Пример #1
0
int
net_write2(net_t * net, char * buf, unsigned int len) {
  uv_write_t * req;
  uv_buf_t uvbuf;
  int read = 0;
  req = (uv_write_t *) malloc(sizeof(uv_write_t));
  req->data = net;

  switch (net->use_ssl) {
  case USE_SSL:
    tls_write(net->tls, buf, (int)len);
    do {
      read = tls_bio_read(net->tls, 0);
      if (read > 0) {
        uvbuf = uv_buf_init(net->tls->buf, read);
        uv_write(req, (uv_stream_t*)net->handle,
                              &uvbuf,
                              1,
                              net_write_cb);
      }
    } while (read > 0);
    break;

  case NOT_SSL:
    uvbuf = uv_buf_init(buf, len);
    uv_write(req, (uv_stream_t*)net->handle,
                          &uvbuf,
                          1,
                          net_write_cb);
    break;
  }

  return NET_OK;
}
Пример #2
0
void tls_write_buffer(TLS_CONTEXT ctx, unsigned char *buf, int size)
{
  int ret, err;
  int pos = 0;

  while (pos < size) {
    int bytes = pos + 30000 < size ? 30000 : size - pos;

    printf("writing %d bytes\n", bytes);

    ret = tls_write(ctx, buf + pos, bytes);
    err = tls_get_error(ctx, ret);

    switch(err) {
    case SSL_ERROR_NONE:
      pos += ret;
      printf("%d bytes written\n", ret);
      break;

    case SSL_ERROR_WANT_WRITE:
      printf("want write\n");
      break;

    case SSL_ERROR_WANT_READ:
      printf("want read\n");
      break;

    default:
      printf("TLS error code %d\n", err);
    }
  }
}
Пример #3
0
int rpch_in_write(rdpRpch* rpch, uint8* data, int length)
{
	rdpRpchHTTP* http_in = rpch->http_in;
	rdpTls* tls_in = rpch->tls_in;
	int status = -1;
	int sent = 0;

	LLOGLN(10, ("rpch_in_write:"));

	if (http_in->remContentLength < length)
	{
		printf("RPCH Error: HTTP frame is over.\n");
		return -1;/* TODO ChannelRecycling */
	}
#ifdef WITH_DEBUG_RPCH
	printf("\nrpch_in_send(): length: %d, remaining content length: %d\n", length, http_in->remContentLength);
	freerdp_hexdump(data, length);
	printf("\n");
#endif
	while (sent < length)
	{
		status = tls_write(tls_in, data+sent, length-sent);

		if (status <= 0)
			return status;/* TODO no idea how to handle errors */

		sent += status;
	}

	rpch->BytesSent += sent;
	http_in->remContentLength -= sent;

	return sent;
}
Пример #4
0
static const char *done_handshake(struct Worker *w)
{
	int res;
	size_t outlen = 0;
	const char *emsg;

	emsg = check_fp(w, "sha1", w->peer_fingerprint_sha1, 20);
	if (emsg)
		return emsg;
	emsg = check_fp(w, "sha256", w->peer_fingerprint_sha256, 32);
	if (emsg)
		return emsg;

	if (w->show) {
		if (strcmp(w->show, "ciphers") == 0) {
			tls_get_connection_info(w->ctx, w->showbuf, sizeof w->showbuf);
		} else if (strcmp(w->show, "peer-cert") == 0) {
			struct tls_cert *cert = NULL;
			tls_get_peer_cert(w->ctx, &cert, NULL);
			show_cert(cert, w->showbuf, sizeof w->showbuf);
			tls_cert_free(cert);
		} else {
			snprintf(w->showbuf, sizeof w->showbuf, "bad kw: show=%s", w->show);
		}
	}

	if (!w->is_server) {
		res = tls_write(w->ctx, "PKT", 3, &outlen);
		if (res != 0 && outlen != 3)
			return "write!=3";
	}
	return wait_for_event(w, EV_READ);
}
Пример #5
0
static void copy_from_stdin_to_tls(struct tls *ctx, int *fd)
{
	static size_t buf[BUFSIZE];
	ssize_t n;
	int i = 0;
	dbg("DEBUG: data from STDIN\n");
	do {
		n = read(STDIN_FILENO, buf, sizeof(buf));
		dbg("read %zu\n", n);
	} while (n < 0 && errno == EINTR);

	if (n < 1) {
		*fd = -1;
		return;
	}

	while (n > 0) {
		ssize_t r = tls_write(ctx, &buf[i], n);
		if (r == TLS_WANT_POLLIN || r == TLS_WANT_POLLOUT)
			continue;
		if (r < 0)
			err(1, "tls_write: %s", tls_error(ctx));
		i += r;
		n -= r;
	}
}
Пример #6
0
static void
https_vprintf(struct tls *tls, const char *fmt, ...)
{
	va_list	 ap, ap2;
	char	*string;
	ssize_t	 nw;
	int	 len;

	va_start(ap, fmt);
	if (ftp_debug) {
		va_copy(ap2, ap);
		fprintf(stderr, ">>> ");
		vfprintf(stderr, fmt, ap2);
		va_end(ap2);
	}

	if ((len = vasprintf(&string, fmt, ap)) == -1)
		errx(1, "%s: vasprintf failed", __func__);
	va_end(ap);
again:
	nw = tls_write(tls, string, len);
	if (nw == TLS_WANT_POLLIN || nw == TLS_WANT_POLLOUT)
		goto again;
	else if (nw < 0)
		errx(1, "%s: tls_write: %s", __func__, tls_error(tls));

	free(string);
}
Пример #7
0
int tls_want_write(tls_t *tls, int events)
{
  if (tls && (events & tls->write_events)) {
    int ret;
    void *buf = tls->write_buffer;
    size_t size = tls->write_buffer_len;

    tls->write_events = 0;

    /* remove buf */
    tls->write_buffer = NULL;
    tls->write_buffer_len = 0;

    ret = tls_write(tls, buf, size);

    if (ret >= 0)
      /* Restore buf */
      return tls->write_buffer = buf, tls->write_buffer_len = ret;
    else if (errno == EAGAIN)
      return 0;
    else
      return -1;
  }
  return 0;
}
Пример #8
0
void
connection_send(Client *client, char *buffer)
{
    uv_write_t *req;
    uv_buf_t buf;
    size_t len;

    len = strlen(buffer);
    if(len > IRC_MAXLEN - 2)
    {
        len = IRC_MAXLEN - 2;
    }

    buffer[len++] = '\r';
    buffer[len++] = '\n';
    buffer[len] = '\0';

    buf.base = buffer;
    buf.len = len;

    if(client->TlsContext != NULL)
    {
        tls_write(client->TlsContext, buffer, len, &len);
    }
    else
    {
        req = Malloc(sizeof(uv_write_t));

        uv_write(req, (uv_stream_t *)client->handle, &buf, 1,
                 connection_write_callback);
    }
}
Пример #9
0
void credssp_send(rdpCredssp* credssp)
{
	STREAM* s;
	int length;
	int ts_request_length;
	int nego_tokens_length;
	int pub_key_auth_length;
	int auth_info_length;

	nego_tokens_length = (credssp->negoToken.cbBuffer > 0) ? credssp_skip_nego_tokens(credssp->negoToken.cbBuffer) : 0;
	pub_key_auth_length = (credssp->pubKeyAuth.cbBuffer > 0) ? credssp_skip_pub_key_auth(credssp->pubKeyAuth.cbBuffer) : 0;
	auth_info_length = (credssp->authInfo.cbBuffer > 0) ? credssp_skip_auth_info(credssp->authInfo.cbBuffer) : 0;

	length = nego_tokens_length + pub_key_auth_length + auth_info_length;
	ts_request_length = credssp_skip_ts_request(length);

	s = stream_new(ts_request_length);

	/* TSRequest */
	length = der_get_content_length(ts_request_length);
	der_write_sequence_tag(s, length); /* SEQUENCE */

	/* [0] version */
	ber_write_contextual_tag(s, 0, 3, true);
	ber_write_integer(s, 2); /* INTEGER */

	/* [1] negoTokens (NegoData) */
	if (nego_tokens_length > 0)
	{
		length = der_get_content_length(nego_tokens_length);
		length -= der_write_contextual_tag(s, 1, length, true); /* NegoData */
		length -= der_write_sequence_tag(s, length); /* SEQUENCE OF NegoDataItem */
		length -= der_write_sequence_tag(s, length); /* NegoDataItem */
		length -= der_write_contextual_tag(s, 0, length, true); /* [0] negoToken */
		der_write_octet_string(s, (uint8*) credssp->negoToken.pvBuffer, length); /* OCTET STRING */
	}

	/* [2] authInfo (OCTET STRING) */
	if (auth_info_length > 0)
	{
		length = ber_get_content_length(auth_info_length);
		length -= ber_write_contextual_tag(s, 2, length, true);
		ber_write_octet_string(s, credssp->authInfo.pvBuffer, credssp->authInfo.cbBuffer);
	}

	/* [3] pubKeyAuth (OCTET STRING) */
	if (pub_key_auth_length > 0)
	{
		length = ber_get_content_length(pub_key_auth_length);
		length -= ber_write_contextual_tag(s, 3, length, true);
		ber_write_octet_string(s, credssp->pubKeyAuth.pvBuffer, length);
	}

	//printf("Sending TSRequest: (%d)\n", stream_get_length(s));
	//freerdp_hexdump(s->data, stream_get_length(s));

	tls_write(credssp->tls, s->data, stream_get_length(s));
	stream_free(s);
}
Пример #10
0
int transport_write(rdpTransport* transport, STREAM* s)
{
	int status = -1;
	int length;

	length = stream_get_length(s);
	stream_set_pos(s, 0);

#ifdef WITH_DEBUG_TRANSPORT
	if (length > 0)
	{
		printf("Local > Remote\n");
		winpr_HexDump(s->data, length);
	}
#endif

	while (length > 0)
	{
		if (transport->layer == TRANSPORT_LAYER_TLS)
			status = tls_write(transport->TlsOut, stream_get_tail(s), length);
		else if (transport->layer == TRANSPORT_LAYER_TCP)
			status = tcp_write(transport->TcpOut, stream_get_tail(s), length);
		else if (transport->layer == TRANSPORT_LAYER_TSG)
			status = tsg_write(transport->tsg, stream_get_tail(s), length);

		if (status < 0)
			break; /* error occurred */

		if (status == 0)
		{
			/* when sending is blocked in nonblocking mode, the receiving buffer should be checked */
			if (!transport->blocking)
			{
				/* and in case we do have buffered some data, we set the event so next loop will get it */
				if (transport_read_nonblocking(transport) > 0)
					SetEvent(transport->ReceiveEvent);
			}

			if (transport->layer == TRANSPORT_LAYER_TLS)
				tls_wait_write(transport->TlsOut);
			else if (transport->layer == TRANSPORT_LAYER_TCP)
				tcp_wait_write(transport->TcpOut);
			else
				USleep(transport->SleepInterval);
		}

		length -= status;
		stream_seek(s, status);
	}

	if (status < 0)
	{
		/* A write error indicates that the peer has dropped the connection */
		transport->layer = TRANSPORT_LAYER_CLOSED;
	}

	return status;
}
Пример #11
0
static void worker_cb(int fd, short flags, void *arg)
{
	struct Worker *w = arg;
	const char *err;
	char buf[128];
	int res;
	size_t outlen;

	w->pending = 0;

	if (w->wstate == HANDSHAKE) {
		err = do_handshake(w, fd);
		add_error(w, err);
	} else if (w->wstate == CONNECTED) {
		if (flags & EV_READ) {
			res = tls_read(w->ctx, buf, sizeof buf, &outlen);
			if (res == TLS_READ_AGAIN) {
				wait_for_event(w, EV_READ);
			} else if (res == TLS_WRITE_AGAIN) {
				wait_for_event(w, EV_WRITE);
			} else if (res == 0) {
				if (outlen > 0 && w->is_server) {
					tls_write(w->ctx, "END", 3, &outlen);
					w->wstate = CLOSED;
				} else if (outlen == 0) {
					w->wstate = CLOSED;
				} else {
					wait_for_event(w, EV_READ);
				}
			} else {
				add_error(w, "bad pkt");
			}
		} else {
			add_error(w, "EV_WRITE?");
		}
	}
	if (w->wstate == CLOSED && w->ctx) {
		res = tls_close(w->ctx);
		if (res == 0) {
			tls_free(w->ctx);
			w->ctx = NULL;
		} else if (res == TLS_READ_AGAIN) {
			wait_for_event(w, EV_READ);
		} else if (res == TLS_WRITE_AGAIN) {
			wait_for_event(w, EV_WRITE);
		} else {
			tls_free(w->ctx);
			w->ctx = NULL;
		}
	}
	if (!w->pending && w->ctx) {
		errx(1, "missed event setup: %s flags=%d state=%d", w->is_server ? "S":"C", flags, w->wstate);
	}
	return;
}
Пример #12
0
int transport_write(rdpTransport* transport, STREAM* s)
{
    int status = -1;

    if (transport->layer == TRANSPORT_LAYER_TLS)
        status = tls_write(transport->tls, s->data, stream_get_length(s));
    else if (transport->layer == TRANSPORT_LAYER_TCP)
        status = tcp_write(transport->tcp, s->data, stream_get_length(s));

    return status;
}
Пример #13
0
void credssp_send(rdpCredssp* credssp, SEC_BUFFER* negoToken, SEC_BUFFER* authInfo, SEC_BUFFER* pubKeyAuth)
{
	STREAM* s;
	int length;
	int ts_request_length;
	int nego_tokens_length;
	int pub_key_auth_length;
	int auth_info_length;

	nego_tokens_length = (negoToken != NULL) ? credssp_skip_nego_tokens(negoToken->cbBuffer) : 0;
	pub_key_auth_length = (pubKeyAuth != NULL) ? credssp_skip_pub_key_auth(pubKeyAuth->cbBuffer) : 0;
	auth_info_length = (authInfo != NULL) ? credssp_skip_auth_info(authInfo->cbBuffer) : 0;

	length = nego_tokens_length + pub_key_auth_length + auth_info_length;
	ts_request_length = credssp_skip_ts_request(length);

	s = stream_new(ts_request_length);

	/* TSRequest */
	length = ber_get_content_length(ts_request_length);
	ber_write_sequence_tag(s, length); /* SEQUENCE */
	ber_write_contextual_tag(s, 0, 3, true); /* [0] version */
	ber_write_integer(s, 2); /* INTEGER */

	/* [1] negoTokens (NegoData) */
	if (nego_tokens_length > 0)
	{
		length = ber_get_content_length(nego_tokens_length);
		length -= ber_write_contextual_tag(s, 1, length, true); /* NegoData */
		length -= ber_write_sequence_tag(s, length); /* SEQUENCE OF NegoDataItem */
		length -= ber_write_sequence_tag(s, length); /* NegoDataItem */
		length -= ber_write_contextual_tag(s, 0, length, true); /* [0] negoToken */
		ber_write_octet_string(s, negoToken->pvBuffer, length); /* OCTET STRING */
	}

	/* [2] authInfo (OCTET STRING) */
	if (auth_info_length > 0)
	{
		length = ber_get_content_length(auth_info_length);
		length -= ber_write_contextual_tag(s, 2, length, true);
		ber_write_octet_string(s, authInfo->pvBuffer, authInfo->cbBuffer);
	}

	/* [3] pubKeyAuth (OCTET STRING) */
	if (pub_key_auth_length > 0)
	{
		length = ber_get_content_length(pub_key_auth_length);
		length -= ber_write_contextual_tag(s, 3, length, true);
		ber_write_octet_string(s, pubKeyAuth->pvBuffer, length);
	}

	tls_write(credssp->tls, s->data, stream_get_length(s));
	stream_free(s);
}
Пример #14
0
int
evtls_write(struct evbuffer *buffer, int fd, struct tls *ctx)
{
	int n;

	n = tls_write(ctx, buffer->buffer, buffer->off);
	if (n <= 0)
		return (n);
	evbuffer_drain(buffer, n);

	return (n);
}
Пример #15
0
int transport_write(rdpTransport* transport, STREAM* s)
{
	int status = -1;
	int length;
	int sent = 0;

	length = stream_get_length(s);
	stream_set_pos(s, 0);

#ifdef WITH_DEBUG_TRANSPORT
	if (length > 0)
	{
		printf("Local > Remote\n");
		freerdp_hexdump(s->data, length);
	}
#endif

	while (sent < length)
	{
		if (transport->layer == TRANSPORT_LAYER_TLS)
			status = tls_write(transport->tls, stream_get_tail(s), length);
		else if (transport->layer == TRANSPORT_LAYER_TCP)
			status = tcp_write(transport->tcp, stream_get_tail(s), length);

		if (status < 0)
			break; /* error occurred */

		if (status == 0)
		{
			/* blocking while sending */
			freerdp_usleep(transport->usleep_interval);

			/* when sending is blocked in nonblocking mode, the receiving buffer should be checked */
			if (!transport->blocking)
			{
				/* and in case we do have buffered some data, we set the event so next loop will get it */
				if (transport_read_nonblocking(transport) > 0)
					wait_obj_set(transport->recv_event);
			}
		}

		sent += status;
		stream_seek(s, status);
	}

	if (status < 0)
	{
		/* A write error indicates that the peer has dropped the connection */
		transport->layer = TRANSPORT_LAYER_CLOSED;
	}

	return status;
}
Пример #16
0
/**
 * @brief	Write formatted data to an TLS connection.
 * @param	tls		the SSL connection to which the data will be written.
 * @param	format	a format string specifying the data to be written to the SSL connection.
 * @param	va_list	a variable argument list containing the data parameters associated with the format string.
 * @return	-1 on error, or the number of bytes written to the SSL connection.
 */
int tls_print(TLS *tls, const char *format, va_list args) {

	va_list copy;
	size_t length = 0;
	chr_t *buffer = NULL;
	int result = 0, counter = 0, bytes = 0, position = 0;

	if (!tls || !format) {
		return (!tls ? -1 : 0);
	}

	// We need to make a copy of the arguments so we can run vsnprintf twice.
	va_copy(copy, args);

	// Calculate the length of the result so we can allocate an appropriately sized buffer.
	length = vsnprintf(NULL, 0, format, copy);
	va_end(copy);

	// Make sure the print function succeeded.
	if (length <= 0) {
		return length;
	}

	// Allocate a large enough buffer.
	else if (!(buffer = mm_alloc(length + 1))) {
		return -1;
	}

	// Build the output string.
	else if (vsnprintf(buffer, length + 1, format, args) != length) {
		mm_free(buffer);
		return -1;
	}

	do {

		if ((bytes = tls_write(tls, buffer + position, length - position, true)) < 0) {
			mm_free(buffer);
			return -1;
		}

		position += bytes;

	} while (position != length && counter++ < 128 && status());

	mm_free(buffer);

	return result;
}
Пример #17
0
static int sock_write(SocketRef const socket, uv_buf_t const *const buf) {
	if(!socket->secure) return async_write((uv_stream_t *)socket->stream, buf, 1);
	size_t total = 0;
	for(;;) {
		size_t partial = 0;
		int event = tls_write(socket->secure,
			buf->base + total,
			buf->len - total, &partial);
		total += partial;
		if(0 == event) break;
		int rc = tls_poll((uv_stream_t *)socket->stream, event);
		if(rc < 0) return rc;
	}
	return 0;
}
Пример #18
0
void sendOverTLS(struct tls* ctx, const char *buf) {
    size_t sent;

    // send Length of buf
    size_t length = strlen(buf);

    size_t len = sizeof(length);
    while (len > 0) {
        int ret = tls_write(ctx, &length, len, &sent); 
 
        if (ret == TLS_READ_AGAIN || ret == TLS_WRITE_AGAIN) { 
            syslog(LOG_DEBUG, "READ/WRITE AGAIN\n");
        } else if (ret < 0) { 
            syslog(LOG_ERR, "%s\n", tls_error(ctx));
            break;
        } else { 
            len -= sent;
        }
    }

    // send actual buf
    size_t toSend = length;
    while (toSend > 0) {
        int ret = tls_write(ctx, buf, toSend, &sent); 
 
        if (ret == TLS_READ_AGAIN || ret == TLS_WRITE_AGAIN) { 
            syslog(LOG_DEBUG, "READ/WRITE AGAIN\n");
        } else if (ret < 0) { 
            syslog(LOG_ERR, "%s\n", tls_error(ctx));
            break;
        } else { 
            buf += sent;
            toSend -= sent;
        }
    }
}
Пример #19
0
int transport_write(rdpTransport* transport, STREAM* s)
{
	int status = -1;
	int length;
	int sent = 0;

	length = stream_get_length(s);
	stream_set_pos(s, 0);

#ifdef WITH_DEBUG_TRANSPORT
	if (length > 0)
	{
		printf("Client > Server\n");
		freerdp_hexdump(s->data, length);
	}
#endif

	while (sent < length)
	{
		if (transport->layer == TRANSPORT_LAYER_TLS)
			status = tls_write(transport->tls, stream_get_tail(s), length);
		else if (transport->layer == TRANSPORT_LAYER_TCP)
			status = tcp_write(transport->tcp, stream_get_tail(s), length);

		if (status < 0)
			break; /* error occurred */

		if (status == 0)
		{
			/* blocking while sending */
			nanosleep(&transport->ts, NULL);

			/* when sending is blocked in nonblocking mode, the receiving buffer should be checked */
			if (!transport->blocking)
				transport_read_nonblocking(transport);
		}

		sent += status;
		stream_seek(s, status);
	}

	if (!transport->blocking)
		transport_check_fds(transport);

	return status;
}
Пример #20
0
int transport_write(rdpTransport* transport, STREAM* s)
{
    int status = -1;
    int length;

    length = stream_get_length(s);
    stream_set_pos(s, 0);

#ifdef WITH_DEBUG_TRANSPORT
    if (length > 0)
    {
        printf("Local > Remote\n");
        freerdp_hexdump(s->data, length);
    }
#endif

    while (length > 0)
    {
        if (transport->layer == TRANSPORT_LAYER_TLS)
            status = tls_write(transport->tls, stream_get_tail(s), length);
        else if (transport->layer == TRANSPORT_LAYER_TCP)
            status = tcp_write(transport->tcp, stream_get_tail(s), length);

        if (status < 0)
            break; /* error occurred */

        if (status == 0)
        {
            /* blocking while sending */
            freerdp_usleep(transport->usleep_interval);

        }

        length -= status;
        stream_seek(s, status);
    }

    if (status < 0)
    {
        /* A write error indicates that the peer has dropped the connection */
        transport->layer = TRANSPORT_LAYER_CLOSED;
    }

    return status;
}
Пример #21
0
static const char *done_handshake(struct Worker *w)
{
	int res;
	const char *emsg;

	emsg = check_fp(w, "sha1", w->peer_fingerprint_sha1, 20);
	if (emsg)
		return emsg;
	emsg = check_fp(w, "sha256", w->peer_fingerprint_sha256, 32);
	if (emsg)
		return emsg;

	if (w->show) {
		if (strcmp(w->show, "ciphers") == 0) {
			tls_get_connection_info(w->ctx, w->showbuf, sizeof w->showbuf);
		} else if (strcmp(w->show, "peer-cert") == 0) {
			struct tls_cert *cert = NULL;
			tls_get_peer_cert(w->ctx, &cert, NULL);
			show_cert(cert, w->showbuf, sizeof w->showbuf);
			tls_cert_free(cert);
		} else {
			snprintf(w->showbuf, sizeof w->showbuf, "bad kw: show=%s", w->show);
		}
	}
	if (w->aggressive_close) {
		close(w->socket);
		tls_close(w->ctx);
		w->wstate = CLOSED;
		return "OK";
	}

	if (!w->is_server) {
		res = tls_write(w->ctx, "PKT", 3);
		if (res < 0) {
			return tls_error(w->ctx);
		} else if (res == 0) {
			return "write==0";
		} else if (res != 3) {
			return "write!=3";
		}
	}
	return wait_for_event(w, EV_READ);
}
Пример #22
0
static void tls_handler(process_event_t ev, process_data_t data){

	if (ev == tls_event){
		if (tls_connected()){
			//raven_lcd_show_text("conn");
			connection = (Connection*)data;
			//TLS_Write(connection, "1", 1);
			//etimer_set(&et, CLOCK_CONF_SECOND);
		} /*else if (tls_newdata()){
			tls_appdata[5] = 0;
			TLS_Write(connection, "1", 1);
		}*/
	} else if (ev == PROCESS_EVENT_TIMER){
		if (etimer_expired(&et)){
			tls_write(connection, "1",1);
			etimer_set(&et, CLOCK_CONF_SECOND);
		}
	}

}
Пример #23
0
int tls_write_all(rdpTls* tls, uint8* data, int length)
{
	int status;
	int sent = 0;

	do
	{
		status = tls_write(tls, &data[sent], length - sent);

		if (status > 0)
			sent += status;

		if (sent >= length)
			break;
	}
	while (status >= 0);

	if (status > 0)
		return length;
	else
		return status;
}
Пример #24
0
VMINT vm_tls_write(VMINT res_id, const void* buf, VMINT32 len)
{
    kal_int32 ret;
    vm_tls_context_t * ctx_p = NULL;
    
    MMI_TRACE(TRACE_GROUP_8, TRC_MRE_SSL_S, 6, __LINE__);
    ctx_p = vm_tls_get_ctx_by_res(res_id);
    if (NULL == ctx_p)
    {
        MMI_TRACE(TRACE_GROUP_8, TRC_MRE_SSL_E1, 6, __LINE__);
        return VM_TLS_RET_BASE -2;
    }
    
    ret = tls_write((kal_int8)(ctx_p->soc_id), (const void *)buf, (kal_int32)len);
    if (TLS_ERR_NONE != ret)
    {
        MMI_TRACE(TRACE_GROUP_8, TRC_MRE_SSL_E2, 6, ret);
        return ret;
    }
    MMI_TRACE(TRACE_GROUP_8, TRC_MRE_SSL_E, 6, __LINE__);
    return 0;
}
Пример #25
0
int rpch_out_write(rdpRpch* rpch, uint8* data, int length)
{
	rdpRpchHTTP* http_out = rpch->http_out;
	rdpTls* tls_out = rpch->tls_out;
	int status = -1;
	int sent = 0;

	LLOGLN(10, ("rpch_out_write: in length %d", length));

	if (http_out->remContentLength < length)
	{
		LLOGLN(0, ("rpch_out_write: RPCH Error: HTTP frame is over."));
		return -1;/* TODO ChannelRecycling */
	}

#ifdef WITH_DEBUG_RPCH
	printf("rpch_out_write(): length: %d\n", length);
	freerdp_hexdump(data, length);
	printf("\n");
#endif
	while (sent < length)
	{
		status = tls_write(tls_out, data + sent, length - sent);

		if (status <= 0)
		{
			LLOGLN(0, ("rpch_out_write: error"));
			return status; /* TODO no idea how to handle errors */
		}

		sent += status;
	}

	http_out->remContentLength -= sent;

	LLOGLN(10, ("rpch_out_write: out sent %d", sent));

	return sent;
}
Пример #26
0
/* Send data from stream to tcp socket.
 * Will block until all data has been sent. */
void
tcp_send(rdpTcp * tcp, STREAM s)
{
	int sent = 0;
	int total = 0;
	int length = s->end - s->data;

#ifndef DISABLE_TLS
	if (tcp->iso->mcs->sec->tls_connected)
	{
		tls_write(tcp->iso->mcs->sec->ssl, (char*) s->data, length);
	}
	else
#endif
	{
		while (total < length)
		{
			while (total < length)
			{
				sent = send(tcp->sock, s->data + total, length - total, MSG_NOSIGNAL);
				if (sent <= 0)
				{
					if (sent == -1 && TCP_BLOCKS)
					{
						tcp_can_send(tcp->sock, 100);
						sent = 0;
					}
					else
					{
						ui_error(tcp->iso->mcs->sec->rdp->inst, "send: %s\n", TCP_STRERROR);
						return;
					}
				}
				total += sent;
			}
		}
	}
}
Пример #27
0
/* Write data over TLS connection */
int tls_write(SSL *ssl, char* b, int length)
{
	int write_status;
	int bytesWritten = 0;

	write_status = SSL_write(ssl, b, length);

	switch (SSL_get_error(ssl, write_status))
	{
		case SSL_ERROR_NONE:
			bytesWritten += write_status;
			break;

		default:
			tls_printf("SSL_write", ssl, write_status);
			break;
	}

	if (bytesWritten < length)
		return bytesWritten += tls_write(ssl, &b[bytesWritten], length - bytesWritten);
	else
		return bytesWritten;
}
Пример #28
0
static void test_context(struct tls *ctx)
{
	char buf[2*1024*1024], *ptr = buf;
	ssize_t ret, len = sizeof buf;

	ignore_sigpipe();

	memset(buf, 'X', len);

	buf[len - 4] = ':';
	buf[len - 3] = 'x';
	buf[len - 2] = '\r';
	buf[len - 1] = '\n';
loop:
	len = sizeof buf;
	ptr = buf;

	while (len > 0) {
		ret = tls_write(ctx, ptr, len);
		if (ret <= 0)
			printf("tls_write(%d) = %d\n", (int)len, (int)ret);
		if (ret > 0) {
			len -= ret;
			ptr += ret;
		} else if (ret == TLS_WANT_POLLIN) {
			continue;
		} else if (ret == TLS_WANT_POLLOUT) {
			continue;
		} else {
			printf("tls_write: %s\n", tls_error(ctx));
			break;
		}
	}
	if (len == 0)
		goto loop;
	printf("final len: %d\n", (int)len);
}
Пример #29
0
static ssize_t
tls_writev(struct wrap_io *wio, const iovec_t *iov, int iovcnt)
{
    struct gnutella_socket *s = wio->ctx;
    ssize_t ret, done;
    int i;

    g_assert(socket_uses_tls(s));
    g_assert(iovcnt > 0);

    done = 0;
    ret = 0;
    for (i = 0; i < iovcnt; i++) {
        const size_t size = iovec_len(&iov[i]);

        ret = tls_write(wio, iovec_base(&iov[i]), size);
        if ((ssize_t) -1 == ret)
            break;
        done += (size_t) ret;
        if (size != (size_t) ret)
            break;
    }
    return done > 0 ? done : ret;
}
Пример #30
0
/** Run the event loop once.
 *  This function will run send any data that has been queued by
 *  xmpp_send and related functions and run through the Strophe even
 *  loop a single time, and will not wait more than timeout
 *  milliseconds for events.  This is provided to support integration
 *  with event loops outside the library, and if used, should be
 *  called regularly to achieve low latency event handling.
 *
 *  @param ctx a Strophe context object
 *  @param timeout time to wait for events in milliseconds
 *
 *  @ingroup EventLoop
 */
void xmpp_run_once(xmpp_ctx_t *ctx, const unsigned long timeout)
{
    xmpp_connlist_t *connitem;
    xmpp_conn_t *conn;
    fd_set rfds, wfds;
    sock_t max = 0;
    int ret;
    struct timeval tv;
    xmpp_send_queue_t *sq, *tsq;
    int towrite;
    char buf[4096];
    uint64_t next;
    long usec;
    int tls_read_bytes = 0;

    if (ctx->loop_status == XMPP_LOOP_QUIT) return;
    ctx->loop_status = XMPP_LOOP_RUNNING;

    /* send queued data */
    connitem = ctx->connlist;
    while (connitem) {
	conn = connitem->conn;
	if (conn->state != XMPP_STATE_CONNECTED) {
	    connitem = connitem->next;
	    continue;
	}

	/* if we're running tls, there may be some remaining data waiting to
	 * be sent, so push that out */
	if (conn->tls) {
	    ret = tls_clear_pending_write(conn->tls);

	    if (ret < 0 && !tls_is_recoverable(tls_error(conn->tls))) {
		/* an error occured */
		xmpp_debug(ctx, "xmpp", "Send error occured, disconnecting.");
		conn->error = ECONNABORTED;
		conn_disconnect(conn);
	    }
	}

	/* write all data from the send queue to the socket */
	sq = conn->send_queue_head;
	while (sq) {
	    towrite = sq->len - sq->written;

	    if (conn->tls) {
		ret = tls_write(conn->tls, &sq->data[sq->written], towrite);

		if (ret < 0 && !tls_is_recoverable(tls_error(conn->tls))) {
		    /* an error occured */
		    conn->error = tls_error(conn->tls);
		    break;
		} else if (ret < towrite) {
		    /* not all data could be sent now */
		    if (ret >= 0) sq->written += ret;
		    break;
		}

	    } else {
		ret = sock_write(conn->sock, &sq->data[sq->written], towrite);

		if (ret < 0 && !sock_is_recoverable(sock_error())) {
		    /* an error occured */
		    conn->error = sock_error();
		    break;
		} else if (ret < towrite) {
		    /* not all data could be sent now */
		    if (ret >= 0) sq->written += ret;
		    break;
		}
	    }

	    /* all data for this queue item written, delete and move on */
	    xmpp_free(ctx, sq->data);
	    tsq = sq;
	    sq = sq->next;
	    xmpp_free(ctx, tsq);

	    /* pop the top item */
	    conn->send_queue_head = sq;
	    /* if we've sent everything update the tail */
	    if (!sq) conn->send_queue_tail = NULL;
	}

	/* tear down connection on error */
	if (conn->error) {
	    /* FIXME: need to tear down send queues and random other things
	     * maybe this should be abstracted */
	    xmpp_debug(ctx, "xmpp", "Send error occured, disconnecting.");
	    conn->error = ECONNABORTED;
	    conn_disconnect(conn);
	}

	connitem = connitem->next;
    }

    /* reset parsers if needed */
    for (connitem = ctx->connlist; connitem; connitem = connitem->next) {
	if (connitem->conn->reset_parser)
	    conn_parser_reset(connitem->conn);
    }


    /* fire any ready timed handlers, then
       make sure we don't wait past the time when timed handlers need
       to be called */
    next = handler_fire_timed(ctx);

    usec = ((next < timeout) ? next : timeout) * 1000;
    tv.tv_sec = usec / 1000000;
    tv.tv_usec = usec % 1000000;

    FD_ZERO(&rfds);
    FD_ZERO(&wfds);

    /* find events to watch */
    connitem = ctx->connlist;
    while (connitem) {
	conn = connitem->conn;

	switch (conn->state) {
	case XMPP_STATE_CONNECTING:
	    /* connect has been called and we're waiting for it to complete */
	    /* connection will give us write or error events */

	    /* make sure the timeout hasn't expired */
	    if (time_elapsed(conn->timeout_stamp, time_stamp()) <=
		conn->connect_timeout)
		FD_SET(conn->sock, &wfds);
	    else {
		conn->error = ETIMEDOUT;
		xmpp_info(ctx, "xmpp", "Connection attempt timed out.");
		conn_disconnect(conn);
	    }
	    break;
	case XMPP_STATE_CONNECTED:
	    FD_SET(conn->sock, &rfds);
	    break;
	case XMPP_STATE_DISCONNECTED:
	    /* do nothing */
	default:
	    break;
	}

	/* Check if there is something in the SSL buffer. */
	if (conn->tls) {
	    tls_read_bytes += tls_pending(conn->tls);
	}

	if (conn->state != XMPP_STATE_DISCONNECTED && conn->sock > max)
	    max = conn->sock;

	connitem = connitem->next;
    }

    /* check for events */
    if (max > 0)
        ret = select(max + 1, &rfds,  &wfds, NULL, &tv);
    else {
        if (timeout > 0)
            _sleep(timeout);
        return;
    }

    /* select errored */
    if (ret < 0) {
	if (!sock_is_recoverable(sock_error()))
	    xmpp_error(ctx, "xmpp", "event watcher internal error %d",
		       sock_error());
	return;
    }

    /* no events happened */
    if (ret == 0 && tls_read_bytes == 0) return;

    /* process events */
    connitem = ctx->connlist;
    while (connitem) {
	conn = connitem->conn;

	switch (conn->state) {
	case XMPP_STATE_CONNECTING:
	    if (FD_ISSET(conn->sock, &wfds)) {
		/* connection complete */

		/* check for error */
                ret = sock_connect_error(conn->sock);
		if (ret != 0) {
		    /* connection failed */
		    xmpp_debug(ctx, "xmpp", "connection failed, error %d", ret);
		    conn_disconnect(conn);
		    break;
		}

		conn->state = XMPP_STATE_CONNECTED;
		xmpp_debug(ctx, "xmpp", "connection successful");

        if (conn->tls_legacy_ssl) {
            xmpp_debug(ctx, "xmpp", "using legacy SSL connection");
            ret = conn_tls_start(conn);
            if (ret != 0) {
                conn_disconnect(conn);
                break;
            }
        }

		/* send stream init */
		conn_open_stream(conn);
	    }

	    break;
	case XMPP_STATE_CONNECTED:
	    if (FD_ISSET(conn->sock, &rfds) || (conn->tls && tls_pending(conn->tls))) {
		if (conn->tls) {
		    ret = tls_read(conn->tls, buf, 4096);
		} else {
		    ret = sock_read(conn->sock, buf, 4096);
		}

		if (ret > 0) {
		    ret = parser_feed(conn->parser, buf, ret);
		    if (!ret) {
			/* parse error, we need to shut down */
			/* FIXME */
			xmpp_debug(ctx, "xmpp", "parse error, disconnecting");
			conn_disconnect(conn);
		    }
		} else {
		    if (conn->tls) {
			if (!tls_is_recoverable(tls_error(conn->tls)))
			{
			    xmpp_debug(ctx, "xmpp", "Unrecoverable TLS error, %d.", tls_error(conn->tls));
			    conn->error = tls_error(conn->tls);
			    conn_disconnect(conn);
			}
		    } else {
			/* return of 0 means socket closed by server */
			xmpp_debug(ctx, "xmpp", "Socket closed by remote host.");
			conn->error = ECONNRESET;
			conn_disconnect(conn);
		    }
		}
	    }

	    break;
	case XMPP_STATE_DISCONNECTED:
	    /* do nothing */
	default:
	    break;
	}

	connitem = connitem->next;
    }

    /* fire any ready handlers */
    handler_fire_timed(ctx);
}