void hr_session_ssl_close(struct corerouter_session *cs) { hr_session_close(cs); struct http_session *hr = (struct http_session *) cs; if (hr->ssl_client_dn) { OPENSSL_free(hr->ssl_client_dn); } if (hr->ssl_cc) { free(hr->ssl_cc); } if (hr->ssl_bio) { BIO_free(hr->ssl_bio); } if (hr->ssl_client_cert) { X509_free(hr->ssl_client_cert); } #ifdef UWSGI_SPDY if (hr->spdy_ping) { uwsgi_buffer_destroy(hr->spdy_ping); } if (hr->spdy) { deflateEnd(&hr->spdy_z_in); deflateEnd(&hr->spdy_z_out); } #endif // clear the errors (otherwise they could be propagated) hr_ssl_clear_errors(); SSL_free(hr->ssl); }
ssize_t hr_ssl_read(struct corerouter_peer *main_peer) { struct corerouter_session *cs = main_peer->session; struct http_session *hr = (struct http_session *) cs; hr_ssl_clear_errors(); // try to always leave 4k available if (uwsgi_buffer_ensure(main_peer->in, uwsgi.page_size)) return -1; int ret = SSL_read(hr->ssl, main_peer->in->buf + main_peer->in->pos, main_peer->in->len - main_peer->in->pos); if (ret > 0) { // fix the buffer main_peer->in->pos += ret; // check for pending data int ret2 = SSL_pending(hr->ssl); if (ret2 > 0) { if (uwsgi_buffer_fix(main_peer->in, main_peer->in->len + ret2 )) { uwsgi_cr_log(main_peer, "cannot fix the buffer to %d\n", main_peer->in->len + ret2); return -1; } if (SSL_read(hr->ssl, main_peer->in->buf + main_peer->in->pos, ret2) != ret2) { uwsgi_cr_log(main_peer, "SSL_read() on %d bytes of pending data failed\n", ret2); return -1; } // fix the buffer main_peer->in->pos += ret2; } #ifdef UWSGI_SPDY if (hr->spdy) { //uwsgi_log("RUNNING THE SPDY PARSER FOR %d bytes\n", main_peer->in->pos); return spdy_parse(main_peer); } #endif return http_parse(main_peer); } int err = SSL_get_error(hr->ssl, ret); if (err == SSL_ERROR_ZERO_RETURN || err == 0) return 0; if (err == SSL_ERROR_WANT_READ) { cr_reset_hooks_and_read(main_peer, hr_ssl_read); return 1; } else if (err == SSL_ERROR_WANT_WRITE) { cr_write_to_main(main_peer, hr_ssl_read); return 1; } else if (err == SSL_ERROR_SYSCALL) { if (errno != 0) uwsgi_cr_error(main_peer, "hr_ssl_read()"); } else if (err == SSL_ERROR_SSL && uwsgi.ssl_verbose) { ERR_print_errors_fp(stderr); } return -1; }
ssize_t hr_ssl_write(struct corerouter_peer *main_peer) { struct corerouter_session *cs = main_peer->session; struct http_session *hr = (struct http_session *) cs; hr_ssl_clear_errors(); int ret = SSL_write(hr->ssl, main_peer->out->buf + main_peer->out_pos, main_peer->out->pos - main_peer->out_pos); if (ret > 0) { main_peer->out_pos += ret; if (main_peer->out->pos == main_peer->out_pos) { // reset the buffer (if needed) main_peer->out->pos = 0; if (main_peer->session->wait_full_write) { main_peer->session->wait_full_write = 0; return 0; } if (main_peer->session->connect_peer_after_write) { cr_connect(main_peer->session->connect_peer_after_write, hr_instance_connected); main_peer->session->connect_peer_after_write = NULL; return ret; } cr_reset_hooks(main_peer); #ifdef UWSGI_SPDY if (hr->spdy) { return spdy_parse(main_peer); } #endif } return ret; } int err = SSL_get_error(hr->ssl, ret); if (err == SSL_ERROR_ZERO_RETURN || err == 0) return 0; if (err == SSL_ERROR_WANT_READ) { cr_reset_hooks_and_read(main_peer, hr_ssl_write); return 1; } else if (err == SSL_ERROR_WANT_WRITE) { cr_write_to_main(main_peer, hr_ssl_write); return 1; } else if (err == SSL_ERROR_SYSCALL) { if (errno != 0) uwsgi_cr_error(main_peer, "hr_ssl_write()"); } else if (err == SSL_ERROR_SSL && uwsgi.ssl_verbose) { ERR_print_errors_fp(stderr); } return -1; }
ssize_t hr_ssl_shutdown(struct corerouter_peer *peer) { // ensure no hooks are set if (uwsgi_cr_set_hooks(peer, NULL, NULL)) return -1; struct corerouter_session *cs = peer->session; struct http_session *hr = (struct http_session *) cs; hr_ssl_clear_errors(); int ret = SSL_shutdown(hr->ssl); int err = 0; if (ret != 1 && ERR_peek_error()) { err = SSL_get_error(hr->ssl, ret); } // no error, close the connection if (ret == 1 || err == 0 || err == SSL_ERROR_ZERO_RETURN) return 0; if (err == SSL_ERROR_WANT_READ) { if (uwsgi_cr_set_hooks(peer, hr_ssl_shutdown, NULL)) return -1; return 1; } else if (err == SSL_ERROR_WANT_WRITE) { if (uwsgi_cr_set_hooks(peer, NULL, hr_ssl_shutdown)) return -1; return 1; } else if (err == SSL_ERROR_SYSCALL) { if (errno != 0) uwsgi_cr_error(peer, "hr_ssl_shutdown()"); } else if (err == SSL_ERROR_SSL && uwsgi.ssl_verbose) { ERR_print_errors_fp(stderr); } return -1; }