int MaOpenSslSocket::write(char *buf, int len) { int rc, written, totalWritten; if (bio == 0 || ssl == 0 || len <= 0) { return -1; } BIO_clear_retry_flags(bio); totalWritten = 0; do { written = BIO_write(bio, buf, len); mprLog(7, "written %d, len %d\n", written, len); if (written >= 0) { do { rc = BIO_flush(bio); mprLog(7, "BIO_flush rc %d\n", rc); if (rc > 0) { // Success break; } // // Nap to prevent busy waiting. // mprSleep(10); } while (rc <= 0 && BIO_should_retry(bio)); totalWritten += written; buf += written; len -= written; } mprLog(7, "write: len %d, written %d, total %d, should_retry %d\n", len, written, totalWritten, BIO_should_retry(bio)); /* * If written is < 0 and an error occurred, then BIO_should_retry * will return false. */ } while (len > 0 && (written > 0 || BIO_should_retry(bio))); if (totalWritten <= 0 && BIO_should_retry(bio) == 0) { mprLog(7, "connection closed\n"); /* * If totalWritten is not Zero, then we don't return an Error. * Next time this function is called, it will return an Error. */ return -1; // return Error ( connection closed ) } return totalWritten; }
int MaOpenSslSocket::read(char *buf, int len) { int rc; if (bio == 0 || ssl == 0) { return -1; } rc = BIO_read(bio, buf, len); #if DEBUG if (rc > 0 && !connTraced) { X509_NAME *xSubject; X509 *cert; char subject[260], issuer[260], peer[260]; mprLog(4, "%d: SSL Connected using: \"%s\"\n", sock, SSL_get_cipher(ssl)); cert = SSL_get_peer_certificate(ssl); if (cert == 0) { mprLog(4, "%d: SSL Details: client supplied no certificate\n", sock); } else { xSubject = X509_get_subject_name(cert); X509_NAME_oneline(xSubject, subject, sizeof(subject) -1); X509_NAME_oneline(X509_get_issuer_name(cert), issuer, sizeof(issuer) -1); X509_NAME_get_text_by_NID(xSubject, NID_commonName, peer, sizeof(peer) - 1); mprLog(4, "%d: SSL Subject %s\n", sock, subject); mprLog(4, "%d: SSL Issuer: %s\n", sock, issuer); mprLog(4, "%d: SSL Peer: %s\n", sock, peer); X509_free(cert); } connTraced = 1; } #endif if (rc > 0) { return rc; } else if (rc == 0) { if (BIO_should_retry(bio)) { return 0; } flags |= MPR_SOCKET_EOF; return 0; } if (BIO_should_retry(bio)) { return 0; } return rc; }
static int ok_write(BIO *b, const char *in, int inl) { int ret = 0, n, i; BIO_OK_CTX *ctx; if (inl <= 0) return inl; ctx = (BIO_OK_CTX *)b->ptr; ret = inl; if ((ctx == NULL) || (b->next_bio == NULL) || (b->init == 0)) return (0); if (ctx->sigio) sig_out(b); do { BIO_clear_retry_flags(b); n = ctx->buf_len - ctx->buf_off; while (ctx->blockout && n > 0) { i = BIO_write(b->next_bio, &(ctx->buf[ctx->buf_off]), n); if (i <= 0) { BIO_copy_next_retry(b); if (!BIO_should_retry(b)) ctx->cont = 0; return (i); } ctx->buf_off += i; n -= i; } /* at this point all pending data has been written */ ctx->blockout = 0; if (ctx->buf_len == ctx->buf_off) { ctx->buf_len = OK_BLOCK_BLOCK; ctx->buf_off = 0; } if ((in == NULL) || (inl <= 0)) return (0); n = (inl + ctx->buf_len > OK_BLOCK_SIZE + OK_BLOCK_BLOCK) ? (int)(OK_BLOCK_SIZE + OK_BLOCK_BLOCK - ctx->buf_len) : inl; memcpy((unsigned char *)(&(ctx->buf[ctx->buf_len])), (unsigned char *)in, n); ctx->buf_len += n; inl -= n; in += n; if (ctx->buf_len >= OK_BLOCK_SIZE + OK_BLOCK_BLOCK) { block_out(b); } } while (inl > 0); BIO_clear_retry_flags(b); BIO_copy_next_retry(b); return (ret); }
unsigned char *Client::encode64(std::string data, int *lenoutput){ const char *c_data = data.c_str(); unsigned char *u_data = (unsigned char *) c_data; int len = data.size(); BIO *b64, *bmem; b64 = BIO_new(BIO_f_base64()); BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); bmem = BIO_new(BIO_s_mem()); BIO_push(b64, bmem); bool done = false; int res = 0; while(!done){ res = BIO_write(b64, u_data, len); if(res <= 0){ if(BIO_should_retry(b64)) continue; else return NULL; } else done = true; } BIO_flush(b64); unsigned char *output; *lenoutput = BIO_get_mem_data(bmem, &output); return output; }
OCSP_RESPONSE *OCSP_sendreq_bio (BIO * b, char *path, OCSP_REQUEST * req) { OCSP_RESPONSE *resp = NULL; OCSP_REQ_CTX *ctx; int rv; ctx = OCSP_sendreq_new (b, path, req, -1); if (!ctx) return NULL; do { rv = OCSP_sendreq_nbio (&resp, ctx); } while ((rv == -1) && BIO_should_retry (b)); OCSP_REQ_CTX_free (ctx); if (rv) return resp; return NULL; }
int tls_write_all(rdpTls* tls, const BYTE* data, int length) { int status; int offset = 0; BIO* bio = tls->bio; while (offset < length) { status = BIO_write(bio, &data[offset], length - offset); if (status > 0) { offset += status; } else { if (!BIO_should_retry(bio)) return -1; if (BIO_write_blocked(bio)) status = BIO_wait_write(bio, 100); else if (BIO_read_blocked(bio)) status = BIO_wait_read(bio, 100); else USleep(100); if (status < 0) return -1; } } return length; }
static enum pbpal_resolv_n_connect_result resolv_and_connect_wout_SSL(pubnub_t *pb) { PUBNUB_LOG_TRACE("resolv_and_connect_wout_SSL\n"); if (NULL == pb->pal.socket) { char const*origin = PUBNUB_ORIGIN_SETTABLE ? pb->origin : PUBNUB_ORIGIN; PUBNUB_LOG_TRACE("pb=%p: Don't have BIO\n", pb); pb->pal.socket = BIO_new_connect((char*)origin); } if (NULL == pb->pal.socket) { return pbpal_resolv_resource_failure; } BIO_set_conn_port(pb->pal.socket, "http"); BIO_set_nbio(pb->pal.socket, !pb->options.use_blocking_io); WATCH_ENUM(pb->options.use_blocking_io); if (BIO_do_connect(pb->pal.socket) <= 0) { if (BIO_should_retry(pb->pal.socket)) { return pbpal_connect_wouldblock; } ERR_print_errors_cb(print_to_pubnub_log, NULL); PUBNUB_LOG_ERROR("BIO_do_connect failed\n"); return pbpal_connect_failed; } PUBNUB_LOG_TRACE("pb=%p: BIO connected\n", pb); { int fd = BIO_get_fd(pb->pal.socket, NULL); socket_set_rcv_timeout(fd, pb->transaction_timeout_ms); } return pbpal_connect_success; }
static LUA_FUNCTION(openssl_bio_puts) { BIO* bio = CHECK_OBJECT(1, BIO, "openssl.bio"); const char* s = luaL_checkstring(L, 2); int ret = 1; int len = BIO_puts(bio, s); if (len > 0) { lua_pushinteger(L, len); ret = 1; } else if (BIO_should_retry(bio)) { lua_pushinteger(L, 0); ret = 1; } else { lua_pushnil(L); lua_pushinteger(L, len); ret = 2; }; return ret; }
static int transport_bio_buffered_read(BIO* bio, char* buf, int size) { int status; rdpTcp* tcp = (rdpTcp*) bio->ptr; tcp->readBlocked = FALSE; BIO_clear_flags(bio, BIO_FLAGS_READ); status = BIO_read(bio->next_bio, buf, size); if (status <= 0) { if (!BIO_should_retry(bio->next_bio)) { BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY); status = -1; goto out; } BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY); if (BIO_should_read(bio->next_bio)) { BIO_set_flags(bio, BIO_FLAGS_READ); tcp->readBlocked = TRUE; goto out; } } out: return status; }
int write_to_BIO( BIO *bio, char *out, int len ) { int total, written; int errcode; /* This loop writes the data to the file. It checks for errors as if the underlying file were non-blocking */ for (total = 0; total < len; total += written) { if ((written = BIO_write (bio, out + total, len - total)) <= 0) { if (BIO_should_retry (bio)) { written = 0; } else { /* return the error */ errcode = ERR_get_error(); /* FIXME - do something with errcode? */ return written; } } } /* Ensure all of our data is pushed all the way out to the destination */ BIO_flush( bio ); return total; }
int __bro_openssl_read(BroConn *bc, uchar *buf, uint buf_size) { int n; D_ENTER; /* It's important here to use <= for comparison, since, as the * invaluable O'Reilly OpenSSL book reports, "for each of the four * reading and writing functions, a 0 or -1 return value may or may * not necessarily indicate that an error has occurred." This may or * may not necessarily be indicative of the incredible PITA that * OpenSSL is. --cpk */ if ( (n = BIO_read(bc->bio, buf, buf_size)) <= 0) { if (BIO_should_retry(bc->bio)) D_RETURN_(0); __bro_openssl_shutdown(bc); D(("Connection closed, BIO_read() returned %i.\n", n)); print_errors(); D_RETURN_(-1); } D_RETURN_(n); }
/* Returns the amount written. */ static int bio_bucket_write(BIO *bio, const char *in, int inl) { serf_ssl_context_t *ctx = bio->ptr; serf_bucket_t *tmp; #ifdef SSL_VERBOSE printf("bio_bucket_write called for %d bytes\n", inl); #endif if (ctx->encrypt.status == SERF_ERROR_WAIT_CONN && !BIO_should_read(ctx->bio)) { #ifdef SSL_VERBOSE printf("bio_bucket_write waiting: (%d %d %d)\n", BIO_should_retry(ctx->bio), BIO_should_read(ctx->bio), BIO_get_retry_flags(ctx->bio)); #endif /* Falling back... */ ctx->encrypt.exhausted_reset = 1; BIO_clear_retry_flags(bio); } tmp = serf_bucket_simple_copy_create(in, inl, ctx->encrypt.pending->allocator); serf_bucket_aggregate_append(ctx->encrypt.pending, tmp); return inl; }
static LUA_FUNCTION(openssl_bio_gets) { BIO* bio = CHECK_OBJECT(1, BIO, "openssl.bio"); int len = luaL_optint(L, 2, BIO_pending(bio)); char* buf; int ret = 1; len = len > 0 ? len : 1024; buf = malloc(len); len = BIO_gets(bio, buf, len); if (len > 0) { lua_pushlstring(L, buf, len); ret = 1; } else if (BIO_should_retry(bio)) { lua_pushstring(L, ""); ret = 1; } else { lua_pushnil(L); lua_pushinteger(L, len); ret = 2; }; free(buf); return ret; }
/** * Receive data package though the ssl connection * @param ssl ssl connection * @param buffer array to hold the data * @param len size of the data container * @param timeout Seconds to wait for data to be available * @return number of bytes transmitted, -1 in case of an error */ int recv_ssl_socket(ssl_connection *ssl, void *buffer, int len, int timeout) { #ifdef HAVE_OPENSSL int n= 0; ASSERT(ssl); do { n= SSL_read(ssl->handler, buffer, len); } while(n <= 0 && BIO_should_retry(ssl->socket_bio) && can_read(ssl->socket, timeout)); if(n <= 0) { return -1; } return n; #else return -1; #endif }
/** * Read a from a stream and handle restarts if nessecary */ ssize_t read_from_stream(BIO* bio, char* buffer, ssize_t length) { ssize_t r = -1; while (r < 0) { r = BIO_read(bio, buffer, length); if (r == 0) { print_ssl_error("Reached the end of the data stream.\n", stdout); continue; } else if (r < 0) { if (!BIO_should_retry(bio)) { print_ssl_error("BIO_read should retry test failed.\n", stdout); continue; } /* It would be prudent to check the reason for the retry and handle * it appropriately here */ } }; return r; }
void SSLClient::process(bool bInRead) { for (;;){ switch (state){ case SSLWrite: write(); break; case SSLConnect: connect(); break; case SSLAccept: accept(); break; case SSLShutdown: shutdown(); break; case SSLConnected: if (!bInRead && (SSL_pending(pSSL) > 0)) notify->read_ready(); break; } char b[2048]; int i = BIO_read(wBIO, b, sizeof(b)); if (i == 0) return; if (i > 0){ sock->write(b, i); continue; } if (i < 0){ if (!BIO_should_retry(wBIO)) notify->error_state(I18N_NOOP("SSL write error")); return; } } }
static int transport_bio_buffered_read(BIO* bio, char* buf, int size) { int status; WINPR_BIO_BUFFERED_SOCKET* ptr = (WINPR_BIO_BUFFERED_SOCKET*) BIO_get_data(bio); BIO* next_bio = BIO_next(bio); ptr->readBlocked = FALSE; BIO_clear_flags(bio, BIO_FLAGS_READ); status = BIO_read(next_bio, buf, size); if (status <= 0) { if (!BIO_should_retry(next_bio)) { BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY); goto out; } BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY); if (BIO_should_read(next_bio)) { BIO_set_flags(bio, BIO_FLAGS_READ); ptr->readBlocked = TRUE; goto out; } } out: return status; }
static LUA_FUNCTION(openssl_bio_write) { BIO* bio = CHECK_OBJECT(1, BIO, "openssl.bio"); size_t size = 0; const char* d = luaL_checklstring(L, 2, &size); int ret = 1; int len = luaL_optint(L, 3, size); len = BIO_write(bio, d, len); if (len > 0) { lua_pushinteger(L, len); ret = 1; } else if (BIO_should_retry(bio)) { lua_pushinteger(L, 0); ret = 1; } else { lua_pushnil(L); lua_pushinteger(L, len); ret = 2; }; return ret; }
static int transport_bio_buffered_write(BIO* bio, const char* buf, int num) { int i, ret; int status; int nchunks; int committedBytes; DataChunk chunks[2]; WINPR_BIO_BUFFERED_SOCKET* ptr = (WINPR_BIO_BUFFERED_SOCKET*) bio->ptr; ret = num; ptr->writeBlocked = FALSE; BIO_clear_flags(bio, BIO_FLAGS_WRITE); /* we directly append extra bytes in the xmit buffer, this could be prevented * but for now it makes the code more simple. */ if (buf && num && !ringbuffer_write(&ptr->xmitBuffer, (const BYTE*) buf, num)) { WLog_ERR(TAG, "an error occured when writing (num: %d)", num); return -1; } committedBytes = 0; nchunks = ringbuffer_peek(&ptr->xmitBuffer, chunks, ringbuffer_used(&ptr->xmitBuffer)); for (i = 0; i < nchunks; i++) { while (chunks[i].size) { status = BIO_write(bio->next_bio, chunks[i].data, chunks[i].size); if (status <= 0) { if (!BIO_should_retry(bio->next_bio)) { BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY); ret = -1; /* fatal error */ goto out; } if (BIO_should_write(bio->next_bio)) { BIO_set_flags(bio, BIO_FLAGS_WRITE); ptr->writeBlocked = TRUE; goto out; /* EWOULDBLOCK */ } } committedBytes += status; chunks[i].size -= status; chunks[i].data += status; } } out: ringbuffer_commit_read_bytes(&ptr->xmitBuffer, committedBytes); return ret; }
/** * Embeds a socket in a ssl connection. * @param socket the socket to be used. * @return The ssl connection or NULL if an error occured. */ int embed_ssl_socket(ssl_connection *ssl, int socket) { int ssl_error; time_t ssl_time; if (!ssl) return FALSE; if (!ssl_initialized) start_ssl(); if (socket >= 0) { ssl->socket = socket; } else { LogError("%s: Socket error!\n", prog); goto sslerror; } if ((ssl->handler = SSL_new (ssl->ctx)) == NULL) { LogError("%s: Cannot initialize the SSL handler -- %s\n", prog, SSLERROR); goto sslerror; } set_noblock(ssl->socket); if ((ssl->socket_bio = BIO_new_socket(ssl->socket, BIO_NOCLOSE)) == NULL) { LogError("%s: Cannot generate IO buffer -- %s\n", prog, SSLERROR); goto sslerror; } SSL_set_bio(ssl->handler, ssl->socket_bio, ssl->socket_bio); ssl_time = time(NULL); while ((ssl_error = SSL_connect (ssl->handler)) < 0) { if ((time(NULL) - ssl_time) > SSL_TIMEOUT) { LogError("%s: SSL service timeout!\n", prog); goto sslerror; } if (!handle_error(ssl_error, ssl)) goto sslerror; if (!BIO_should_retry(ssl->socket_bio)) goto sslerror; } ssl->cipher = (char *) SSL_get_cipher(ssl->handler); if (! update_ssl_cert_data(ssl)) { LogError("%s: Cannot get the SSL server certificate!\n", prog); goto sslerror; } return TRUE; sslerror: cleanup_ssl_socket(ssl); return FALSE; }
static BOOL rdg_process_control_packet(rdpRdg* rdg, int type, size_t packetLength) { wStream* s = NULL; size_t readCount = 0; int status; size_t payloadSize = packetLength - sizeof(RdgPacketHeader); if (payloadSize) { s = Stream_New(NULL, payloadSize); if (!s) return FALSE; while (readCount < payloadSize) { status = BIO_read(rdg->tlsOut->bio, Stream_Pointer(s), sizeof(RdgPacketHeader) - readCount); if (status <= 0) { if (!BIO_should_retry(rdg->tlsOut->bio)) { Stream_Free(s, TRUE); return FALSE; } continue; } Stream_Seek(s, status); readCount += status; } } switch (type) { case PKT_TYPE_CLOSE_CHANNEL: EnterCriticalSection(&rdg->writeSection); status = rdg_process_close_packet(rdg); LeaveCriticalSection(&rdg->writeSection); break; case PKT_TYPE_KEEPALIVE: EnterCriticalSection(&rdg->writeSection); status = rdg_process_keep_alive_packet(rdg); LeaveCriticalSection(&rdg->writeSection); break; default: status = rdg_process_unknown_packet(rdg, type); break; } Stream_Free(s, TRUE); return status; }
static int transport_bio_buffered_write(BIO* bio, const char* buf, int num) { int status, ret; rdpTcp* tcp = (rdpTcp*) bio->ptr; int nchunks, committedBytes, i; DataChunk chunks[2]; ret = num; tcp->writeBlocked = FALSE; BIO_clear_flags(bio, BIO_FLAGS_WRITE); /* we directly append extra bytes in the xmit buffer, this could be prevented * but for now it makes the code more simple. */ if (buf && num && !ringbuffer_write(&tcp->xmitBuffer, (const BYTE*) buf, num)) { fprintf(stderr, "%s: an error occured when writing(toWrite=%d)\n", __FUNCTION__, num); return -1; } committedBytes = 0; nchunks = ringbuffer_peek(&tcp->xmitBuffer, chunks, ringbuffer_used(&tcp->xmitBuffer)); for (i = 0; i < nchunks; i++) { while (chunks[i].size) { status = BIO_write(bio->next_bio, chunks[i].data, chunks[i].size); if (status <= 0) { if (!BIO_should_retry(bio->next_bio)) { BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY); ret = -1; /* fatal error */ goto out; } if (BIO_should_write(bio->next_bio)) { BIO_set_flags(bio, BIO_FLAGS_WRITE); tcp->writeBlocked = TRUE; goto out; /* EWOULDBLOCK */ } } committedBytes += status; chunks[i].size -= status; chunks[i].data += status; } } out: ringbuffer_commit_read_bytes(&tcp->xmitBuffer, committedBytes); return ret; }
/* * Read from an OpenSSL BIO in non-blocking mode. */ static int bio_read (BIO *bio, struct buffer *buf, int maxlen, const char *desc) { int i; int ret = 0; ASSERT (buf->len >= 0); if (buf->len) { ; } else { int len = buf_forward_capacity (buf); if (maxlen < len) len = maxlen; /* * BIO_read brackets most of the serious RSA * key negotiation number crunching. */ i = BIO_read (bio, BPTR (buf), len); VALGRIND_MAKE_READABLE ((void *) &i, sizeof (i)); #ifdef BIO_DEBUG bio_debug_data ("read", bio, BPTR (buf), i, desc); #endif if (i < 0) { if (BIO_should_retry (bio)) { ; } else { msg (D_TLS_ERRORS | M_SSL, "TLS_ERROR: BIO read %s error", desc); buf->len = 0; ret = -1; ERR_clear_error (); } } else if (!i) { buf->len = 0; } else { /* successful read */ dmsg (D_HANDSHAKE_VERBOSE, "BIO read %s %d bytes", desc, i); buf->len = i; ret = 1; VALGRIND_MAKE_READABLE ((void *) BPTR (buf), BLEN (buf)); } } return ret; }
const char *dbapi_lookup(const char *key) { long res = 1; SSL_CTX* ctx = NULL; BIO *web = NULL, *out = NULL; SSL *ssl = NULL; const SSL_METHOD* method; char *token, *tmpout, *buf; int hlen=0, len=0, maxlen=2048; (void)SSL_library_init(); SSL_load_error_strings(); OPENSSL_config(NULL); method = SSLv23_method(); if(method==NULL) return NULL; ctx = SSL_CTX_new(method); if(ctx==NULL) return NULL; SSL_CTX_set_verify_depth(ctx, 4); SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_TLSv1| SSL_OP_NO_COMPRESSION); web = BIO_new_ssl_connect(ctx); if(web==NULL) return NULL; res = BIO_set_conn_hostname(web, DB_API_SERVER); if(res!=1) return NULL; BIO_get_ssl(web, &ssl); if(ssl==NULL) return NULL; res = SSL_set_cipher_list(ssl, SECURE_CIPHER_LIST); if(res!=1) return NULL; res = SSL_set_tlsext_host_name(ssl, DB_API_HOST); if(res!=1) return NULL; out = BIO_new_fp(stdout, BIO_NOCLOSE); if(NULL==out) return NULL; res = BIO_do_connect(web); if(res!=1) return NULL; res = BIO_do_handshake(web); if(res!=1) return NULL; len=(60+strlen(key)+strlen(DB_API_HOST)+strlen(DB_API_AUTH)); char *request=malloc(sizeof(char)*(len+1)); snprintf(request,len, "GET %s HTTP/1.1\nHost: %s\nx-api-key: %s\nConnection: close\n\n", key, DB_API_HOST, DB_API_AUTH); request[len]='\0'; BIO_puts(web, request); BIO_puts(out, "\n"); buf = malloc(sizeof(char)*maxlen); do { char buff[1536] = {}; len=BIO_read(web, buff, sizeof(buff)); hlen+=len; if(hlen<maxlen&&len>0) strncat(buf,buff,len); } while (len>0 || BIO_should_retry(web)); buf[maxlen]='\0'; tmpout = malloc(sizeof(char)*(HASH_MAXLENGTH+1)); token = strtok(buf, "\n"); while (token) { snprintf(tmpout,HASH_MAXLENGTH,"%s",token); token = strtok(NULL, "\n"); } tmpout[strlen(tmpout)]='\0'; free(buf); free(request); if(out) BIO_free(out); if(web != NULL) BIO_free_all(web); if(NULL != ctx) SSL_CTX_free(ctx); return tmpout; }
/** * Send data package though the ssl connection * @param ssl ssl connection * @param buffer array containg the data * @param len size of the data container * @param timeout Seconds to wait for data to be written * @return number of bytes transmitted, -1 in case of an error */ int send_ssl_socket(ssl_connection *ssl, void *buffer, size_t len, int timeout) { int n = 0; ASSERT(ssl); do { n = SSL_write(ssl->handler, buffer, (int)len); } while (n <= 0 && BIO_should_retry(ssl->socket_bio) && can_write(ssl->socket, timeout)); return (n > 0) ? n : -1; }
/** * Receive data package though the ssl connection * @param ssl ssl connection * @param buffer array to hold the data * @param len size of the data container * @param timeout Seconds to wait for data to be available * @return number of bytes transmitted, -1 in case of an error */ int recv_ssl_socket(ssl_connection *ssl, void *buffer, int len, int timeout) { int n = 0; ASSERT(ssl); do { n = SSL_read(ssl->handler, buffer, len); } while (n < 0 && BIO_should_retry(ssl->socket_bio) && can_read(ssl->socket, timeout)); return (n >= 0) ? n : -1; }
int transport_read_layer(rdpTransport* transport, BYTE* data, int bytes) { int read = 0; int status = -1; if (!transport->frontBio) { transport->layer = TRANSPORT_LAYER_CLOSED; return -1; } while (read < bytes) { status = BIO_read(transport->frontBio, data + read, bytes - read); if (status <= 0) { if (!transport->frontBio || !BIO_should_retry(transport->frontBio)) { /* something unexpected happened, let's close */ if (!transport->frontBio) { WLog_Print(transport->log, WLOG_ERROR, "BIO_read: transport->frontBio null"); return -1; } WLog_ERR_BIO(transport, "BIO_read", transport->frontBio); transport->layer = TRANSPORT_LAYER_CLOSED; return -1; } /* non blocking will survive a partial read */ if (!transport->blocking) return read; /* blocking means that we can't continue until we have read the number of requested bytes */ if (BIO_wait_read(transport->frontBio, 100) < 0) { WLog_ERR_BIO(transport, "BIO_wait_read", transport->frontBio); return -1; } continue; } #ifdef HAVE_VALGRIND_MEMCHECK_H VALGRIND_MAKE_MEM_DEFINED(data + read, bytes - read); #endif read += status; } return read; }
BOOL CSSLSession::WriteRecvChannel(const BYTE* pData, int iLength) { ASSERT(pData && iLength > 0); BOOL isOK = TRUE; int bytes = BIO_write(m_bioRecv, pData, iLength); if(bytes > 0) ASSERT(bytes == iLength); else if(!BIO_should_retry(m_bioRecv)) isOK = FALSE; return isOK; }
BIO *BIO_get_retry_BIO(BIO *bio, int *reason) { BIO *b,*last; b=last=bio; for (;;) { if (!BIO_should_retry(b)) break; last=b; b=b->next_bio; if (b == NULL) break; } if (reason != NULL) *reason=last->retry_reason; return(last); }
/* * Write to an OpenSSL BIO in non-blocking mode. */ static int bio_write (BIO *bio, const uint8_t *data, int size, const char *desc) { int i; int ret = 0; ASSERT (size >= 0); if (size) { /* * Free the L_TLS lock prior to calling BIO routines * so that foreground thread can still call * tls_pre_decrypt or tls_pre_encrypt, * allowing tunnel packet forwarding to continue. */ #ifdef BIO_DEBUG bio_debug_data ("write", bio, data, size, desc); #endif i = BIO_write (bio, data, size); if (i < 0) { if (BIO_should_retry (bio)) { ; } else { msg (D_TLS_ERRORS | M_SSL, "TLS ERROR: BIO write %s error", desc); ret = -1; ERR_clear_error (); } } else if (i != size) { msg (D_TLS_ERRORS | M_SSL, "TLS ERROR: BIO write %s incomplete %d/%d", desc, i, size); ret = -1; ERR_clear_error (); } else { /* successful write */ dmsg (D_HANDSHAKE_VERBOSE, "BIO write %s %d bytes", desc, i); ret = 1; } } return ret; }