CAMLprim value ocaml_ssl_get_mode(value socket) { CAMLparam1(socket); CAMLlocal1(ret); long m; ssl_socket_t *ssl = ssl_socket_of_block(socket); m = SSL_get_mode(ssl->handler); ret = alloc_tuple(3); Store_field(ret, 0, Val_bool(m & SSL_MODE_ENABLE_PARTIAL_WRITE)); Store_field(ret, 1, Val_bool(m & SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER)); Store_field(ret, 2, Val_bool(m & SSL_MODE_AUTO_RETRY)); CAMLreturn(ret); }
int ssl3_setup_read_buffer(SSL *s) { unsigned char *p; size_t len,align=0,headerlen; if (SSL_version(s) == DTLS1_VERSION || SSL_version(s) == DTLS1_BAD_VER) headerlen = DTLS1_RT_HEADER_LENGTH; else headerlen = SSL3_RT_HEADER_LENGTH; #if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0 align = (-SSL3_RT_HEADER_LENGTH)&(SSL3_ALIGN_PAYLOAD-1); #endif if (s->s3->rbuf.buf == NULL) { if (SSL_get_mode(s) & SSL_MODE_SMALL_BUFFERS) { len = SSL3_RT_DEFAULT_PACKET_SIZE; } else { len = SSL3_RT_MAX_PLAIN_LENGTH + SSL3_RT_MAX_ENCRYPTED_OVERHEAD + headerlen + align; if (s->options & SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER) { s->s3->init_extra = 1; len += SSL3_RT_MAX_EXTRA; } } #ifndef OPENSSL_NO_COMP if (!(s->options & SSL_OP_NO_COMPRESSION)) len += SSL3_RT_MAX_COMPRESSED_OVERHEAD; #endif if ((p=freelist_extract(s->ctx, 1, len)) == NULL) goto err; s->s3->rbuf.buf = p; s->s3->rbuf.len = len; } s->packet= &(s->s3->rbuf.buf[0]); return 1; err: SSLerr(SSL_F_SSL3_SETUP_READ_BUFFER,ERR_R_MALLOC_FAILURE); return 0; }
int ssl3_setup_write_buffer(SSL *s) { unsigned char *p; size_t len,align=0,headerlen; if (SSL_version(s) == DTLS1_VERSION || SSL_version(s) == DTLS1_BAD_VER) headerlen = DTLS1_RT_HEADER_LENGTH + 1; else headerlen = SSL3_RT_HEADER_LENGTH; #if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0 align = (-SSL3_RT_HEADER_LENGTH)&(SSL3_ALIGN_PAYLOAD-1); #endif if (s->s3->wbuf.buf == NULL) { if (SSL_get_mode(s) & SSL_MODE_SMALL_BUFFERS) { len = SSL3_RT_DEFAULT_PACKET_SIZE; } else { len = s->max_send_fragment; } len += 0 + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD + headerlen + align; #ifndef OPENSSL_NO_COMP if (!(s->options & SSL_OP_NO_COMPRESSION)) len += SSL3_RT_MAX_COMPRESSED_OVERHEAD; #endif if (!(s->options & SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)) len += headerlen + align + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD; if ((p=freelist_extract(s->ctx, 0, len)) == NULL) goto err; s->s3->wbuf.buf = p; s->s3->wbuf.len = len; } return 1; err: SSLerr(SSL_F_SSL3_SETUP_WRITE_BUFFER,ERR_R_MALLOC_FAILURE); return 0; }
// establish connection to the ChromeCast device, m_init is set to indicate that // the protocol needs to be bootstrapped. bool ChromeCast::connect() { m_s = socket(PF_INET, SOCK_STREAM, 0); if (m_s == -1) { syslog(LOG_CRIT, "socket() failed: %m"); return false; } struct sockaddr_in inaddr; memset(&inaddr, 0, sizeof inaddr); inaddr.sin_family = AF_INET; inaddr.sin_port = htons(8009); inaddr.sin_addr.s_addr = inet_addr(m_ip.c_str()); if (::connect(m_s, (const struct sockaddr *)&inaddr, sizeof inaddr) != 0) { syslog(LOG_CRIT, "connect() failed: %m"); close(m_s); m_s = -1; return false; } m_ssl = SSL_new(m_ssl_ctx); SSL_set_fd(m_ssl, m_s); SSL_set_mode(m_ssl, SSL_get_mode(m_ssl) | SSL_MODE_AUTO_RETRY); SSL_set_connect_state(m_ssl); if (SSL_connect(m_ssl) != 1) { syslog(LOG_CRIT, "SSL_connect() failed"); SSL_free(m_ssl); m_ssl = NULL; close(m_s); m_s = -1; return false; } m_tread = std::thread(&ChromeCast::_read, this); m_init = false; return true; }
static struct mailstream_ssl_data * ssl_data_new_full(int fd, time_t timeout, const SSL_METHOD * method, void (* callback)(struct mailstream_ssl_context * ssl_context, void * cb_data), void * cb_data) { struct mailstream_ssl_data * ssl_data; SSL * ssl_conn; int r; SSL_CTX * tmp_ctx; struct mailstream_cancel * cancel; struct mailstream_ssl_context * ssl_context = NULL; #if SSL_MODE_RELEASE_BUFFERS long mode = 0; #endif mailstream_ssl_init(); tmp_ctx = SSL_CTX_new(method); if (tmp_ctx == NULL) goto err; if (callback != NULL) { ssl_context = mailstream_ssl_context_new(tmp_ctx, fd); callback(ssl_context, cb_data); } SSL_CTX_set_app_data(tmp_ctx, ssl_context); SSL_CTX_set_client_cert_cb(tmp_ctx, mailstream_openssl_client_cert_cb); ssl_conn = (SSL *) SSL_new(tmp_ctx); #if SSL_MODE_RELEASE_BUFFERS mode = SSL_get_mode(ssl_conn); SSL_set_mode(ssl_conn, mode | SSL_MODE_RELEASE_BUFFERS); #endif if (ssl_conn == NULL) goto free_ctx; #if (OPENSSL_VERSION_NUMBER >= 0x10000000L) if (ssl_context != NULL && ssl_context->server_name != NULL) { SSL_set_tlsext_host_name(ssl_conn, ssl_context->server_name); free(ssl_context->server_name); ssl_context->server_name = NULL; } #endif /* (OPENSSL_VERSION_NUMBER >= 0x10000000L) */ if (SSL_set_fd(ssl_conn, fd) == 0) goto free_ssl_conn; again: r = SSL_connect(ssl_conn); switch(SSL_get_error(ssl_conn, r)) { case SSL_ERROR_WANT_READ: r = wait_SSL_connect(fd, 1, timeout); if (r < 0) goto free_ssl_conn; else goto again; break; case SSL_ERROR_WANT_WRITE: r = wait_SSL_connect(fd, 0, timeout); if (r < 0) goto free_ssl_conn; else goto again; break; } if (r <= 0) goto free_ssl_conn; cancel = mailstream_cancel_new(); if (cancel == NULL) goto free_ssl_conn; r = mailstream_prepare_fd(fd); if (r < 0) goto free_cancel; ssl_data = malloc(sizeof(* ssl_data)); if (ssl_data == NULL) goto free_cancel; ssl_data->fd = fd; ssl_data->ssl_conn = ssl_conn; ssl_data->ssl_ctx = tmp_ctx; ssl_data->cancel = cancel; mailstream_ssl_context_free(ssl_context); return ssl_data; free_cancel: mailstream_cancel_free(cancel); free_ssl_conn: SSL_free(ssl_conn); free_ctx: SSL_CTX_free(tmp_ctx); mailstream_ssl_context_free(ssl_context); err: return NULL; }
void bud_client_create(bud_config_t* config, uv_stream_t* stream) { int r; bud_client_t* client; bud_client_error_t cerr; BIO* enc_in; BIO* enc_out; #ifdef SSL_MODE_RELEASE_BUFFERS long mode; #endif /* SSL_MODE_RELEASE_BUFFERS */ client = malloc(sizeof(*client)); if (client == NULL) return; client->config = config; client->ssl = NULL; client->last_handshake = 0; client->handshakes = 0; client->connect = kBudProgressNone; client->close = kBudProgressNone; client->cycle = kBudProgressNone; client->recycle = 0; client->destroy_waiting = 0; client->id = bud_config_get_client_id(config); client->async_hello = kBudProgressDone; if (config->sni.enabled || config->stapling.enabled) client->async_hello = kBudProgressNone; /* SNI */ client->sni_req = NULL; client->sni_ctx.ctx = NULL; /* Stapling */ client->stapling_cache_req = NULL; client->stapling_req = NULL; client->stapling_ocsp_resp = NULL; /* Availability */ client->retry = kBudProgressNone; client->retry_count = 0; client->retry_timer.data = client; client->backend_list = NULL; client->selected_backend = NULL; /* Proxyline */ client->proxyline_waiting = 2; /* X-Forward */ client->xforward.skip = 0; client->xforward.crlf = 0; r = uv_timer_init(config->loop, &client->retry_timer); if (r != 0) goto failed_timer_init; client->destroy_waiting++; /* Initialize buffers */ bud_client_side_init(&client->frontend, kBudFrontend, client); bud_client_side_init(&client->backend, kBudBackend, client); /** * Accept client on frontend */ r = uv_tcp_init(config->loop, &client->frontend.tcp); if (r != 0) goto failed_tcp_in_init; client->destroy_waiting++; r = uv_accept(stream, (uv_stream_t*) &client->frontend.tcp); if (r != 0) goto failed_accept; cerr = bud_client_read_start(client, &client->frontend); if (!bud_is_ok(cerr.err)) goto failed_accept; client->frontend.reading = kBudProgressRunning; /* Fill hosts */ cerr = bud_client_fill_host(client, &client->local); if (!bud_is_ok(cerr.err)) goto failed_accept; cerr = bud_client_fill_host(client, &client->remote); if (!bud_is_ok(cerr.err)) goto failed_accept; /* * Select a backend and connect to it, or wait for a backend to become * alive again. */ /* SNI backend comes from `backend` or sni callback */ client->backend_list = &config->contexts[0].backend; client->balance = config->balance_e; if (client->balance == kBudBalanceSNI) { client->selected_backend = NULL; client->connect = kBudProgressRunning; } else { client->selected_backend = bud_select_backend(client); } /* No backend can be selected yet, wait for SNI */ if (client->selected_backend == NULL) { client->backend.close = kBudProgressDone; cerr = bud_client_ok(&client->backend); /* No backend alive, try reconnecting */ } else if (client->selected_backend->dead) { DBG_LN(&client->backend, "all backends dead, scheduling reconnection"); cerr = bud_client_retry(client); /* Backend alive - connect immediately */ } else { cerr = bud_client_connect(client); } if (!bud_is_ok(cerr.err)) goto failed_accept; /* Adjust sockets */ r = uv_tcp_nodelay(&client->frontend.tcp, 1); if (r == 0 && config->frontend.keepalive > 0) r = uv_tcp_keepalive(&client->frontend.tcp, 1, config->frontend.keepalive); if (r != 0) goto failed_connect; /* Initialize SSL */ /* First context is always default */ client->ssl = SSL_new(config->contexts[0].ctx); if (client->ssl == NULL) goto failed_connect; if (!SSL_set_ex_data(client->ssl, kBudSSLClientIndex, client)) goto failed_connect; SSL_set_cert_cb(client->ssl, bud_client_ssl_cert_cb, client); SSL_set_info_callback(client->ssl, bud_client_ssl_info_cb); enc_in = bud_bio_new(&client->frontend.input); if (enc_in == NULL) goto failed_connect; enc_out = bud_bio_new(&client->frontend.output); if (enc_out == NULL) { BIO_free_all(enc_in); goto failed_connect; } SSL_set_bio(client->ssl, enc_in, enc_out); #ifdef SSL_MODE_RELEASE_BUFFERS mode = SSL_get_mode(client->ssl); SSL_set_mode(client->ssl, mode | SSL_MODE_RELEASE_BUFFERS); #endif /* SSL_MODE_RELEASE_BUFFERS */ SSL_set_accept_state(client->ssl); bud_trace_frontend_accept(client); DBG_LN(&client->frontend, "new"); return; failed_connect: client->connect = kBudProgressDone; client->close = kBudProgressDone; uv_close((uv_handle_t*) &client->backend.tcp, bud_client_close_cb); failed_accept: uv_close((uv_handle_t*) &client->frontend.tcp, bud_client_close_cb); failed_tcp_in_init: uv_close((uv_handle_t*) &client->retry_timer, bud_client_close_cb); return; failed_timer_init: free(client); }