int rts_recv_pdu(rdpRpc* rpc, RTS_PDU* rts_pdu) { STREAM* s; int status; int length; BYTE header_buffer[20]; rdpTls* tls_out = rpc->tls_out; /* read first 20 bytes to get RTS PDU Header */ status = tls_read(tls_out, (BYTE*) &header_buffer, 20); if (status <= 0) { printf("rts_recv error\n"); return status; } s = stream_new(0); stream_attach(s, header_buffer, 20); rts_pdu_header_read(s, &(rts_pdu->header)); stream_detach(s); stream_free(s); length = rts_pdu->header.frag_length - 20; rts_pdu->content = (BYTE*) malloc(length); status = tls_read(tls_out, rts_pdu->content, length); if (status < 0) { printf("rts_recv error\n"); return status; } if (rts_pdu->header.ptype != PTYPE_RTS) { printf("rts_recv error: unexpected ptype:%d\n", rts_pdu->header.ptype); return -1; } #ifdef WITH_DEBUG_RTS printf("rts_recv(): length: %d\n", length); freerdp_hexdump(rts_pdu->content, length); printf("\n"); #endif rts_recv_pdu_commands(rpc, rts_pdu); return rts_pdu->header.frag_length; }
static ssize_t tls_readv(struct wrap_io *wio, 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_read(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; }
int transport_read(rdpTransport* transport, STREAM* s) { int status = -1; while (True) { if (transport->layer == TRANSPORT_LAYER_TLS) status = tls_read(transport->tls, s->data, s->size); else if (transport->layer == TRANSPORT_LAYER_TCP) status = tcp_read(transport->tcp, s->data, s->size); if (status == 0 && transport->blocking) { nanosleep(&transport->ts, NULL); continue; } break; } #ifdef WITH_DEBUG_TRANSPORT if (status > 0) { printf("Server > Client\n"); freerdp_hexdump(s->data, status); } #endif return status; }
int force_read(rdpTls* tls, uint8* data, int bytes) { int total_read; int read; LLOGLN(10, ("force_read:")); total_read = 0; while (total_read < bytes) { LLOGLN(10, ("force_read: reading %d bytes", bytes - total_read)); read = tls_read(tls, data + total_read, bytes - total_read); if (read < 0) { /* disconnect or other error */ return -1; } if (read == 0) { LLOGLN(0, ("force_read: read == 0, sleeping and reading again")); tcp_can_recv(tls->sockfd, 100); continue; } total_read += read; } return total_read; }
static void connection_poll_callback(uv_poll_t *handle, int status, int events) { Client *client = handle->data; uv_buf_t buffer = { 0 }; size_t len; int ret; if(status != 0) { client_free(client); return; } connection_allocate_buffer_callback((uv_handle_t *)handle, DEFAULT_READ_SIZE, &buffer); while((ret = tls_read(client->TlsContext, buffer.base, buffer.len, &len)) != 0) { if(ret == -1) { client_free(client); return; } } connection_on_read_callback((uv_stream_t *)handle, len, &buffer); }
int transport_read(rdpTransport* transport, STREAM* s) { int status = -1; while (True) { if (transport->layer == TRANSPORT_LAYER_TLS) status = tls_read(transport->tls, stream_get_tail(s), stream_get_left(s)); else if (transport->layer == TRANSPORT_LAYER_TCP) status = tcp_read(transport->tcp, stream_get_tail(s), stream_get_left(s)); if (status == 0 && transport->blocking) { freerdp_usleep(transport->usleep_interval); continue; } break; } #ifdef WITH_DEBUG_TRANSPORT if (status > 0) { printf("Local < Remote\n"); freerdp_hexdump(s->data, status); } #endif return status; }
static int copy_from_tls_to_stdout(struct tls *ctx) { static size_t buf[BUFSIZE]; ssize_t n,r; int i = 0; dbg("DEBUG: data from TLS\n"); do { n = tls_read(ctx, buf, sizeof(buf)); } while (n == TLS_WANT_POLLIN || r == TLS_WANT_POLLOUT); if (n < 0) err(1, "tls read: %s", tls_error(ctx)); if (n == 0) return 1; while (n) { r = write(STDOUT_FILENO, &buf[i], n); if (r < 0) err(1, "write"); i += r; n -= r; } return 0; }
int rpc_out_read(rdpRpc* rpc, BYTE* data, int length) { int status; status = tls_read(rpc->TlsOut, data, length); return status; }
json_t* recvOverTLS(struct tls*ctx) { json_error_t error; size_t getSize, size; size_t len = sizeof(getSize); // read length while (len > 0) { int ret = tls_read(ctx, &getSize, len, &size); if (ret == TLS_READ_AGAIN || ret == TLS_WRITE_AGAIN) { /* retry. May use select to wait for nonblocking */ } else if (ret < 0) { syslog(LOG_ERR, "%s\n", tls_error(ctx)); break; } else { len -= size; } } // create buffer char* buffer = (char*)malloc((getSize +1) *sizeof(char)); char* buf = buffer; while (getSize > 0) { int ret = tls_read(ctx, buf, getSize, &size); if (ret == TLS_READ_AGAIN || ret == TLS_WRITE_AGAIN) { /* retry. May use select to wait for nonblocking */ } else if (ret < 0) { syslog(LOG_ERR, "%s\n", tls_error(ctx)); break; } else { buf += size; getSize -= size; } } // Process buffer to json json_t *json = json_loads(buffer, JSON_DISABLE_EOF_CHECK, &error); if (verbose_flag) { syslog(LOG_DEBUG, "%s\n", buffer); } return json; }
int transport_read_layer(rdpTransport* transport, BYTE* data, int bytes) { int read = 0; int status = -1; while (read < bytes) { if (transport->layer == TRANSPORT_LAYER_TLS) status = tls_read(transport->TlsIn, data + read, bytes - read); else if (transport->layer == TRANSPORT_LAYER_TCP) status = tcp_read(transport->TcpIn, data + read, bytes - read); else if (transport->layer == TRANSPORT_LAYER_TSG) status = tsg_read(transport->tsg, data + read, bytes - read); else if (transport->layer == TRANSPORT_LAYER_TSG_TLS) { status = tls_read(transport->TsgTls, data + read, bytes - read); } /* blocking means that we can't continue until this is read */ if (!transport->blocking) return status; if (status < 0) { /* A read error indicates that the peer has dropped the connection */ transport->layer = TRANSPORT_LAYER_CLOSED; return status; } read += status; if (status == 0) { /* * instead of sleeping, we should wait timeout on the * socket but this only happens on initial connection */ USleep(transport->SleepInterval); } } return read; }
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; }
int transport_read(rdpTransport* transport, STREAM* s) { int status = -1; if (transport->layer == TRANSPORT_LAYER_TLS) status = tls_read(transport->tls, s->data, s->size); else if (transport->layer == TRANSPORT_LAYER_TCP) status = tcp_read(transport->tcp, s->data, s->size); return status; }
int tls_read_all(rdpTls* tls, uint8* data, int length) { int status; do { status = tls_read(tls, data, length); } while (status == 0); return status; }
int credssp_recv(rdpCredssp* credssp) { STREAM* s; int length; int status; uint32 version; s = stream_new(2048); status = tls_read(credssp->tls, s->data, stream_get_left(s)); if (status < 0) return -1; /* TSRequest */ ber_read_sequence_tag(s, &length); ber_read_contextual_tag(s, 0, &length, true); ber_read_integer(s, &version); /* [1] negoTokens (NegoData) */ if (ber_read_contextual_tag(s, 1, &length, true) != false) { ber_read_sequence_tag(s, &length); /* SEQUENCE OF NegoDataItem */ ber_read_sequence_tag(s, &length); /* NegoDataItem */ ber_read_contextual_tag(s, 0, &length, true); /* [0] negoToken */ ber_read_octet_string(s, &length); /* OCTET STRING */ sspi_SecBufferAlloc(&credssp->negoToken, length); stream_read(s, credssp->negoToken.pvBuffer, length); credssp->negoToken.cbBuffer = length; } /* [2] authInfo (OCTET STRING) */ if (ber_read_contextual_tag(s, 2, &length, true) != false) { ber_read_octet_string(s, &length); /* OCTET STRING */ sspi_SecBufferAlloc(&credssp->authInfo, length); stream_read(s, credssp->authInfo.pvBuffer, length); credssp->authInfo.cbBuffer = length; } /* [3] pubKeyAuth (OCTET STRING) */ if (ber_read_contextual_tag(s, 3, &length, true) != false) { ber_read_octet_string(s, &length); /* OCTET STRING */ sspi_SecBufferAlloc(&credssp->pubKeyAuth, length); stream_read(s, credssp->pubKeyAuth.pvBuffer, length); credssp->pubKeyAuth.cbBuffer = length; } stream_free(s); return 0; }
static void https_retr_file(const char *fn, off_t file_sz, off_t offset) { size_t wlen; ssize_t i, r; char *cp; static char *buf; int fd, flags; if (buf == NULL) { buf = malloc(TMPBUF_LEN); /* allocate once */ if (buf == NULL) err(1, "%s: malloc", __func__); } flags = O_CREAT | O_WRONLY; if (offset) flags |= O_APPEND; if (strcmp(fn, "-") == 0) fd = STDOUT_FILENO; else if ((fd = open(fn, flags, 0666)) == -1) err(1, "%s: open %s", __func__, fn); start_progress_meter(file_sz, &offset); while (1) { r = tls_read(ctx, buf, TMPBUF_LEN); if (r == TLS_WANT_POLLIN || r == TLS_WANT_POLLOUT) continue; else if (r < 0) { errx(1, "%s: tls_read: %s", __func__, tls_error(ctx)); } if (r == 0) break; offset += r; for (cp = buf, wlen = r; wlen > 0; wlen -= i, cp += i) { if ((i = write(fd, cp, wlen)) == -1) { if (errno != EINTR) err(1, "%s: write", __func__); } else if (i == 0) break; } } if (strcmp(fn, "-") != 0) close(fd); stop_progress_meter(); }
int tls_read_all(rdpTls* tls, BYTE* data, int length) { int status; do { status = tls_read(tls, data, length); if (status == 0) tls_wait_read(tls); } while (status == 0); return status; }
/** Check if data is available in TCP connection. * * * * @retval -1 upon an error * @retval 0 end-of-stream * @retval 1 nothing to read * @retval 2 there is data to read */ int tls_want_read(tls_t *tls, int events) { if (tls && (events & tls->read_events)) { int ret = tls_read(tls); if (ret > 0) return 2; else if (ret == 0) return 0; else if (errno == EAGAIN) return 3; /* ??? */ else return -1; } return 1; }
int evtls_read(struct evbuffer *buf, int fd, int howmuch, struct tls *ctx) { u_char *p; size_t oldoff = buf->off; int n = EVBUFFER_MAX_READ; if (ioctl(fd, FIONREAD, &n) == -1 || n <= 0) { n = EVBUFFER_MAX_READ; } else if (n > EVBUFFER_MAX_READ && n > howmuch) { /* * It's possible that a lot of data is available for * reading. We do not want to exhaust resources * before the reader has a chance to do something * about it. If the reader does not tell us how much * data we should read, we artifically limit it. */ if ((size_t)n > buf->totallen << 2) n = buf->totallen << 2; if (n < EVBUFFER_MAX_READ) n = EVBUFFER_MAX_READ; } if (howmuch < 0 || howmuch > n) howmuch = n; /* If we don't have FIONREAD, we might waste some space here */ if (evbuffer_expand(buf, howmuch) == -1) return (-1); /* We can append new data at this point */ p = buf->buffer + buf->off; n = tls_read(ctx, p, howmuch); if (n <= 0) return (n); buf->off += n; /* Tell someone about changes in this buffer */ if (buf->off != oldoff && buf->cb != NULL) (*buf->cb)(buf, oldoff, buf->off, buf->cbarg); return (n); }
static char * https_parseln(size_t *lenp) { size_t i, len; char *buf, *q, c; ssize_t nr; len = 128; if ((buf = calloc(1, len)) == NULL) errx(1, "Can't allocate memory for transfer buffer"); for (i = 0; ; i++) { if (i >= len - 1) { if ((q = reallocarray(buf, len, 2)) == NULL) errx(1, "Can't expand transfer buffer"); buf = q; len *= 2; } again: nr = tls_read(ctx, &c, 1); if (nr == TLS_WANT_POLLIN || nr == TLS_WANT_POLLOUT) goto again; if (nr < 0) errx(1, "TLS read error: %ld", nr); buf[i] = c; if (c == '\n') break; } buf[i] = '\0'; if (i && buf[i - 1] == '\r') buf[--i] = '\0'; if (lenp) *lenp = i; return buf; }
VMINT vm_tls_read(VMINT res_id, void* buf, VMINT32 len) { kal_int32 ret; vm_tls_context_t * ctx_p = NULL; MMI_TRACE(TRACE_GROUP_8, TRC_MRE_SSL_S, 7, __LINE__); ctx_p = vm_tls_get_ctx_by_res(res_id); if (NULL == ctx_p) { MMI_TRACE(TRACE_GROUP_8, TRC_MRE_SSL_E1, 7, __LINE__); return VM_TLS_RET_BASE -2; } ret = tls_read((kal_int8)(ctx_p->soc_id), (void *)buf, (kal_int32)len); if (TLS_ERR_NONE != ret) { MMI_TRACE(TRACE_GROUP_8, TRC_MRE_SSL_E2, 7, ret); return ret; } MMI_TRACE(TRACE_GROUP_8, TRC_MRE_SSL_E, 7, __LINE__); return 0; }
int transport_read_layer(rdpTransport* transport, uint8* data, int bytes) { int read = 0; int status = -1; while (read < bytes) { if (transport->layer == TRANSPORT_LAYER_TLS) status = tls_read(transport->tls, data + read, bytes - read); else if (transport->layer == TRANSPORT_LAYER_TCP) status = tcp_read(transport->tcp, data + read, bytes - read); //else if (transport->layer == TRANSPORT_LAYER_TSG) // status = tsg_read(transport->tsg, data + read, bytes - read); /* blocking means that we can't continue until this is read */ if (!transport->blocking) return status; if (status < 0) return status; read += status; if (status == 0) { /* * instead of sleeping, we should wait timeout on the * socket but this only happens on initial connection */ freerdp_usleep(transport->usleep_interval); } } return read; }
static int sock_read(SocketRef const socket, size_t const size, uv_buf_t *const out) { if(!socket->secure) return async_read((uv_stream_t *)socket->stream, size, out); out->base = malloc(size); if(!out->base) return UV_ENOMEM; size_t total = 0; for(;;) { size_t partial = 0; int event = tls_read(socket->secure, out->base+total, size-total, &partial); total += partial; if(0 == event) break; int rc = tls_poll((uv_stream_t *)socket->stream, event); if(rc < 0) { FREE(&out->base); return rc; } } if(0 == total) { FREE(&out->base); return UV_EOF; } out->len = total; return 0; }
int tls_read(tls_t *tls, void * const buff, const size_t len) { int bytes; /* first, if we've got some ready data, put that in the buffer */ if (tls->readybufferpos < tls->readybufferlen) { if (len < tls->readybufferlen - tls->readybufferpos) { bytes = len; } else { bytes = tls->readybufferlen - tls->readybufferpos; } memcpy(buff, tls->readybuffer + tls->readybufferpos, bytes); if (len < tls->readybufferlen - tls->readybufferpos) { tls->readybufferpos += bytes; return bytes; } else { unsigned char *newbuff = buff; int read; tls->readybufferpos += bytes; newbuff += bytes; read = tls_read(tls, newbuff, len - bytes); if (read == -1) { if (tls_is_recoverable(tls->lasterror)) { return bytes; } return -1; } return bytes + read; } } /* next, top up our recv buffer */ bytes = sock_read(tls->sock, tls->recvbuffer + tls->recvbufferpos, tls->recvbuffermaxlen - tls->recvbufferpos); if (bytes == 0) { tls->lasterror = WSAECONNRESET; return -1; } if (bytes == -1) { if (!tls_is_recoverable(sock_error())) { tls->lasterror = sock_error(); return -1; } } if (bytes > 0) { tls->recvbufferpos += bytes; } /* next, try to decrypt the recv buffer */ if (tls->recvbufferpos > 0) { SecBufferDesc sbddec; SecBuffer sbdec[4]; int ret; memset(&sbddec, 0, sizeof(sbddec)); sbddec.ulVersion = SECBUFFER_VERSION; sbddec.cBuffers = 4; sbddec.pBuffers = sbdec; memset(&(sbdec[0]), 0, sizeof(sbdec[0])); sbdec[0].BufferType = SECBUFFER_DATA; sbdec[0].pvBuffer = tls->recvbuffer; sbdec[0].cbBuffer = tls->recvbufferpos; memset(&(sbdec[1]), 0, sizeof(sbdec[1])); sbdec[1].BufferType = SECBUFFER_EMPTY; memset(&(sbdec[2]), 0, sizeof(sbdec[2])); sbdec[2].BufferType = SECBUFFER_EMPTY; memset(&(sbdec[3]), 0, sizeof(sbdec[3])); sbdec[3].BufferType = SECBUFFER_EMPTY; ret = tls->sft->DecryptMessage(&(tls->hctxt), &sbddec, 0, NULL); if (ret == SEC_E_OK) { memcpy(tls->readybuffer, sbdec[1].pvBuffer, sbdec[1].cbBuffer); tls->readybufferpos = 0; tls->readybufferlen = sbdec[1].cbBuffer; /* have we got some data left over? If so, copy it to the start * of the recv buffer */ if (sbdec[3].BufferType == SECBUFFER_EXTRA) { memcpy(tls->recvbuffer, sbdec[3].pvBuffer, sbdec[3].cbBuffer); tls->recvbufferpos = sbdec[3].cbBuffer; } else { tls->recvbufferpos = 0; } return tls_read(tls, buff, len); } else if (ret == SEC_E_INCOMPLETE_MESSAGE) { tls->lasterror = SEC_E_INCOMPLETE_MESSAGE; return -1; } else if (ret == SEC_I_RENEGOTIATE) { ret = tls_start(tls); if (!ret) { return -1; } /* fake an incomplete message so we're called again */ tls->lasterror = SEC_E_INCOMPLETE_MESSAGE; return -1; } /* something bad happened, so we bail */ tls->lasterror = ret; return -1; } tls->lasterror = SEC_E_INCOMPLETE_MESSAGE; return -1; }
HttpResponse* http_response_recv(rdpTls* tls) { uint8* p; int nbytes; int length; int status; uint8* buffer; char* content; char* header_end; HttpResponse* http_response; nbytes = 0; length = 0xFFFF; buffer = xmalloc(length); http_response = http_response_new(); p = buffer; while (true) { status = tls_read(tls, p, length - nbytes); if (status > 0) { nbytes += status; p = (uint8*) &buffer[nbytes]; } else if (status == 0) { continue; } else { return NULL; break; } header_end = strstr((char*) buffer, "\r\n\r\n") + 2; if (header_end != NULL) { int count; char* line; header_end[0] = '\0'; header_end[1] = '\0'; content = &header_end[2]; count = 0; line = (char*) buffer; while ((line = strstr(line, "\r\n")) != NULL) { line++; count++; } http_response->count = count; http_response->lines = (char**) xmalloc(sizeof(char*) * http_response->count); count = 0; line = strtok((char*) buffer, "\r\n"); while (line != NULL) { http_response->lines[count] = xstrdup(line); line = strtok(NULL, "\r\n"); count++; } http_response_parse_header(http_response); if (http_response->ContentLength > 0) { http_response->Content = xstrdup(content); } break; } if ((length - nbytes) <= 0) { length *= 2; buffer = xrealloc(buffer, length); p = (uint8*) &buffer[nbytes]; } } return http_response; }
int main(int argc, char *argv[], char *envp[]) { struct tls *tls = NULL; int ch; environ = envp; /* pipes to communicate with the front end */ int in = -1; int out = -1; bool no_name_verification = false; bool no_cert_verification = false; bool no_time_verification = false; char *host = getenv("TCPREMOTEHOST"); struct tls_config *tls_config; if (getenv("TLSC_NO_VERIFICATION") != NULL) { no_name_verification = true; no_cert_verification = true; no_time_verification = true; } if (getenv("TLSC_NO_HOST_VERIFICATION") != NULL) no_name_verification = true; if (getenv("TLSC_NO_CERT_VERIFICATION") != NULL) no_cert_verification = true; if (getenv("TLSC_NO_TIME_VERIFICATION") != NULL) no_time_verification = true; if ((tls_config = tls_config_new()) == NULL) err(EXIT_FAILURE, "tls_config_new"); char *str = NULL; if ((str = getenv("TLSC_CERT_FILE")) != NULL) if (tls_config_set_cert_file(tls_config, str) == -1) err(EXIT_FAILURE, "tls_config_set_cert_file"); if ((str = getenv("TLSC_KEY_FILE")) != NULL) if (tls_config_set_key_file(tls_config, str) == -1) err(EXIT_FAILURE, "tls_config_set_key_file"); if ((str = getenv("TLSC_CA_FILE")) != NULL) if (tls_config_set_ca_file(tls_config, str) == -1) err(EXIT_FAILURE, "tls_config_set_ca_file"); if ((str = getenv("TLSC_CA_PATH")) != NULL) if (tls_config_set_ca_path(tls_config, str) == -1) err(EXIT_FAILURE, "tls_config_set_ca_path"); while ((ch = getopt(argc, argv, "c:k:f:p:n:HCTVh")) != -1) { switch (ch) { case 'c': if (tls_config_set_cert_file(tls_config, optarg) == -1) err(EXIT_FAILURE, "tls_config_set_cert_file"); break; case 'k': if (tls_config_set_key_file(tls_config, optarg) == -1) err(EXIT_FAILURE, "tls_config_set_key_file"); break; case 'f': if (tls_config_set_ca_file(tls_config, optarg) == -1) err(EXIT_FAILURE, "tls_config_set_ca_file"); break; case 'p': if (tls_config_set_ca_path(tls_config, optarg) == -1) err(EXIT_FAILURE, "tls_config_set_ca_path"); break; case 'n': if ((host = strdup(optarg)) == NULL) goto err; break; case 'H': no_name_verification = true; break; case 'C': no_cert_verification = true; break; case 'T': no_time_verification = true; break; case 'V': no_name_verification = true; no_cert_verification = true; no_time_verification = true; break; case 'h': default: usage(); /* NOTREACHED */ } } argc -= optind; argv += optind; if (argc < 1) usage(); /* verification settings */ if (no_cert_verification) tls_config_insecure_noverifycert(tls_config); if (no_name_verification) tls_config_insecure_noverifyname(tls_config); if (no_time_verification) tls_config_insecure_noverifytime(tls_config); /* libtls setup */ if (tls_init() != 0) err(EXIT_FAILURE, "tls_init"); if ((tls = tls_client()) == NULL) err(EXIT_FAILURE, "tls_client"); if (tls_configure(tls, tls_config) != 0) err(EXIT_FAILURE, "tls_configure"); if (tls_connect_fds(tls, READ_FD, WRITE_FD, host) == -1) goto err; if (tls_handshake(tls) == -1) goto err; /* overide PROTO to signal the application layer that the communication * channel is save. */ if (setenv("PROTO", "SSL", 1) == -1) err(EXIT_FAILURE, "setenv"); /* fork front end program */ char *prog = argv[0]; # define PIPE_READ 0 # define PIPE_WRITE 1 int pi[2]; /* input pipe */ int po[2]; /* output pipe */ if (pipe(pi) == -1) err(EXIT_FAILURE, "pipe"); if (pipe(po) == -1) err(EXIT_FAILURE, "pipe"); switch (fork()) { case -1: err(EXIT_FAILURE, "fork"); case 0: /* client program */ /* close non-using ends of pipes */ if (close(pi[PIPE_READ]) == -1) err(EXIT_FAILURE, "close"); if (close(po[PIPE_WRITE]) == -1) err(EXIT_FAILURE, "close"); /* * We have to move one descriptor cause po[] may * overlaps with descriptor 6 and 7. */ int po_read = 0; if ((po_read = dup(po[PIPE_READ])) == -1) err(EXIT_FAILURE, "dup"); if (close(po[PIPE_READ]) < 0) err(EXIT_FAILURE, "close"); if (dup2(pi[PIPE_WRITE], WRITE_FD) < 0) err(EXIT_FAILURE, "dup2"); if (dup2(po_read, READ_FD) < 0) err(EXIT_FAILURE, "dup2"); if (close(pi[PIPE_WRITE]) < 0) err(EXIT_FAILURE, "close"); if (close(po_read) < 0) err(EXIT_FAILURE, "close"); execvpe(prog, argv, environ); err(EXIT_FAILURE, "execvpe"); default: break; /* parent */ } /* close non-using ends of pipes */ if (close(pi[PIPE_WRITE]) == -1) err(EXIT_FAILURE, "close"); if (close(po[PIPE_READ]) == -1) err(EXIT_FAILURE, "close"); in = pi[PIPE_READ]; out = po[PIPE_WRITE]; /* communication loop */ for (;;) { int ret; char buf[BUFSIZ]; ssize_t sn = 0; fd_set readfds; FD_ZERO(&readfds); FD_SET(in, &readfds); FD_SET(READ_FD, &readfds); int max_fd = MAX(in, READ_FD); ret = select(max_fd+1, &readfds, NULL, NULL, NULL); if (ret == -1) err(EXIT_FAILURE, "select"); if (FD_ISSET(READ_FD, &readfds)) { do { again: sn = tls_read(tls, buf, sizeof buf); if (sn == TLS_WANT_POLLIN || sn == TLS_WANT_POLLOUT) goto again; if (sn == -1) goto err; if (sn == 0) return EXIT_SUCCESS; if (write(out, buf, sn) == -1) err(EXIT_FAILURE, "write()"); } while (sn == sizeof buf); } else if (FD_ISSET(in, &readfds)) { if ((sn = read(in, buf, sizeof buf)) == -1) err(EXIT_FAILURE, "read()"); if (sn == 0) goto out; if ((sn = tls_write(tls, buf, sn)) == -1) goto out; } } out: tls_close(tls); return EXIT_SUCCESS; err: errx(EXIT_FAILURE, "tls_error: %s", tls_error(tls)); }
int rpc_out_read(rdpRpc* rpc, uint8* data, int length) { STREAM* s; int status; uint8* pdu; int content_length; RPC_PDU_HEADER header; if (rpc->VirtualConnection->DefaultOutChannel->ReceiverAvailableWindow < 0x00008FFF) /* Just a simple workaround */ rts_send_flow_control_ack_pdu(rpc); /* Send FlowControlAck every time AvailableWindow reaches the half */ pdu = xmalloc(0xFFFF); if (pdu == NULL) { printf("rpc_out_read error: memory allocation failed") ; return -1 ; } status = tls_read(rpc->tls_out, pdu, 16); /* read first 16 bytes to get RPC PDU Header */ if (status <= 0) { xfree(pdu); return status; } s = stream_new(0); stream_attach(s, pdu, 16); rpc_pdu_header_read(s, &header); stream_detach(s); stream_free(s); content_length = header.frag_length - 16; status = tls_read(rpc->tls_out, pdu + 16, content_length); if (status < 0) { xfree(pdu); return status; } if (header.ptype == PTYPE_RTS) /* RTS PDU */ { printf("rpc_out_read error: Unexpected RTS PDU\n"); xfree(pdu); return -1; } else { /* RTS PDUs are not subject to flow control */ rpc->VirtualConnection->DefaultOutChannel->BytesReceived += header.frag_length; rpc->VirtualConnection->DefaultOutChannel->ReceiverAvailableWindow -= header.frag_length; } if (length < header.frag_length) { printf("rpc_out_read error! receive buffer is not large enough\n"); xfree(pdu); return -1; } memcpy(data, pdu, header.frag_length); #ifdef WITH_DEBUG_RPC printf("rpc_out_read(): length: %d\n", header.frag_length); freerdp_hexdump(data, header.frag_length); printf("\n"); #endif xfree(pdu); return header.frag_length; }
HttpResponse* http_response_recv(rdpTls* tls) { BYTE* p; int nbytes; int length; int status; BYTE* buffer; char* content; char* header_end; HttpResponse* http_response; nbytes = 0; length = 10000; content = NULL; buffer = malloc(length); if (!buffer) return NULL; http_response = http_response_new(); if (!http_response) goto out_free; p = buffer; http_response->ContentLength = 0; while (TRUE) { while (nbytes < 5) { status = tls_read(tls, p, length - nbytes); if (status < 0) goto out_error; if (!status) continue; nbytes += status; p = (BYTE*) &buffer[nbytes]; } header_end = strstr((char*) buffer, "\r\n\r\n"); if (!header_end) { fprintf(stderr, "http_response_recv: invalid response:\n"); winpr_HexDump(buffer, status); goto out_error; } header_end += 2; if (header_end != NULL) { int count; char* line; header_end[0] = '\0'; header_end[1] = '\0'; content = &header_end[2]; count = 0; line = (char*) buffer; while ((line = strstr(line, "\r\n")) != NULL) { line++; count++; } http_response->count = count; if (count) { http_response->lines = (char **)calloc(http_response->count, sizeof(char *)); if (!http_response->lines) goto out_error; } count = 0; line = strtok((char*) buffer, "\r\n"); while (line != NULL) { http_response->lines[count] = _strdup(line); if (!http_response->lines[count]) goto out_error; line = strtok(NULL, "\r\n"); count++; } if (!http_response_parse_header(http_response)) goto out_error; if (http_response->ContentLength > 0) { http_response->Content = _strdup(content); if (!http_response->Content) goto out_error; } break; } if ((length - nbytes) <= 0) { length *= 2; buffer = realloc(buffer, length); p = (BYTE*) &buffer[nbytes]; } } free(buffer); return http_response; out_error: http_response_free(http_response); out_free: free(buffer); return NULL; }
int ip_recv(int sock, uschar *buffer, int buffsize, int timeout) { fd_set select_inset; struct timeval tv; int start_recv = time(NULL); int rc; /* Wait until the socket is ready */ for (;;) { FD_ZERO (&select_inset); FD_SET (sock, &select_inset); tv.tv_sec = timeout; tv.tv_usec = 0; DEBUG(D_transport) debug_printf("waiting for data on socket\n"); rc = select(sock + 1, (SELECT_ARG2_TYPE *)&select_inset, NULL, NULL, &tv); /* If some interrupt arrived, just retry. We presume this to be rare, but it can happen (e.g. the SIGUSR1 signal sent by exiwhat causes select() to exit). Aug 2004: Somebody set up a cron job that ran exiwhat every 2 minutes, making the interrupt not at all rare. Since the timeout is typically more than 2 minutes, the effect was to block the timeout completely. To prevent this happening again, we do an explicit time test. */ if (rc < 0 && errno == EINTR) { DEBUG(D_transport) debug_printf("EINTR while waiting for socket data\n"); if (time(NULL) - start_recv < timeout) continue; DEBUG(D_transport) debug_printf("total wait time exceeds timeout\n"); } /* Handle a timeout, and treat any other select error as a timeout, including an EINTR when we have been in this loop for longer than timeout. */ if (rc <= 0) { errno = ETIMEDOUT; return -1; } /* If the socket is ready, break out of the loop. */ if (FD_ISSET(sock, &select_inset)) break; } /* The socket is ready, read from it (via TLS if it's active). On EOF (i.e. close down of the connection), set errno to zero; otherwise leave it alone. */ #ifdef SUPPORT_TLS if (tls_active == sock) rc = tls_read(buffer, buffsize); else #endif rc = recv(sock, buffer, buffsize, 0); if (rc > 0) return rc; if (rc == 0) errno = 0; return -1; }
/** 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); }
/* Read length bytes from tcp socket to stream and return it. * Appends to stream s if specified, otherwise it uses stream from tcp layer. * Will block until data available. * Returns NULL on error. */ STREAM tcp_recv(rdpTcp * tcp, STREAM s, uint32 length) { int rcvd = 0; uint32 p_offset; uint32 new_length; uint32 end_offset; if (s == NULL) { /* read into "new" stream */ if (length > tcp->in.size) { tcp->in.data = (uint8 *) xrealloc(tcp->in.data, length); tcp->in.size = length; } tcp->in.end = tcp->in.p = tcp->in.data; s = &(tcp->in); } else { /* append to existing stream */ new_length = (s->end - s->data) + length; if (new_length > s->size) { p_offset = s->p - s->data; end_offset = s->end - s->data; s->data = (uint8 *) xrealloc(s->data, new_length); s->size = new_length; s->p = s->data + p_offset; s->end = s->data + end_offset; } } while (length > 0) { #ifndef DISABLE_TLS if (tcp->iso->mcs->sec->tls_connected) { rcvd = tls_read(tcp->iso->mcs->sec->ssl, (char*) s->end, length); if (rcvd < 0) return NULL; } else #endif { if (!ui_select(tcp->iso->mcs->sec->rdp->inst, tcp->sock)) return NULL; /* user quit */ rcvd = recv(tcp->sock, s->end, length, 0); if (rcvd < 0) { if (rcvd == -1 && TCP_BLOCKS) { tcp_can_recv(tcp->sock, 1); rcvd = 0; } else { ui_error(tcp->iso->mcs->sec->rdp->inst, "recv: %s\n", TCP_STRERROR); return NULL; } } else if (rcvd == 0) { ui_error(tcp->iso->mcs->sec->rdp->inst, "Connection closed\n"); return NULL; } } s->end += rcvd; length -= rcvd; } return s; }