X-Git-Url: http://git.cascardo.eti.br/?a=blobdiff_plain;f=hcconn_ssl.c;h=aaf8037257167ae315592801d1f08e7d358972ac;hb=1abeb1f8078fe4c3b5b1059ecb043a48310dd0d6;hp=0100757b97e815c3657019799f3cbad409af4971;hpb=5a4d4b0c292c764a8720fd9428937b1b1370aa93;p=cascardo%2Frnetproxy.git diff --git a/hcconn_ssl.c b/hcconn_ssl.c index 0100757..aaf8037 100644 --- a/hcconn_ssl.c +++ b/hcconn_ssl.c @@ -30,9 +30,47 @@ struct ssl_data gnutls_session_t session; GString *buffer; gboolean handshaking; + gboolean failed; gpointer lowconn; }; +#define DH_BITS 1024 +void * +hc_conn_ssl_server_init_credentials (char *certfile, char *keyfile) +{ + static int initialized = 0; + static gnutls_certificate_credentials_t cred; + gnutls_dh_params_t dh_params; + if (initialized) + return cred; + gnutls_dh_params_init (&dh_params); + gnutls_dh_params_generate2 (dh_params, DH_BITS); + gnutls_certificate_allocate_credentials (&cred); + gnutls_certificate_set_x509_key_file (cred, certfile, keyfile, + GNUTLS_X509_FMT_PEM); + gnutls_certificate_set_dh_params (cred, dh_params); + initialized = 1; + return cred; +} + +static void * +ssl_server_get_credentials(void) +{ + return hc_conn_ssl_server_init_credentials (NULL, NULL); +} + +static void +ssl_server_session_new (gnutls_session_t *session) +{ + static void *cred; + cred = ssl_server_get_credentials (); + gnutls_init (session, GNUTLS_SERVER); + gnutls_set_default_priority (*session); + gnutls_credentials_set (*session, GNUTLS_CRD_CERTIFICATE, cred); + gnutls_dh_set_prime_bits (*session, DH_BITS); +} +#undef DH_BITS + static void ssl_client_session_new (gnutls_session_t *session) { @@ -46,13 +84,17 @@ ssl_client_session_new (gnutls_session_t *session) } static struct ssl_data * -ssl_data_new_client (void) +ssl_data_new (int server) { struct ssl_data *ssl; ssl = g_slice_new (struct ssl_data); - ssl_client_session_new (&ssl->session); + if (server) + ssl_server_session_new (&ssl->session); + else + ssl_client_session_new (&ssl->session); ssl->buffer = g_string_sized_new (4096); ssl->handshaking = FALSE; + ssl->failed = FALSE; return ssl; } @@ -98,25 +140,31 @@ ssl_pull (gnutls_transport_ptr_t ptr, void *buffer, size_t len) } if (r == 0) { - gnutls_transport_set_errno (ssl->session, EAGAIN); + errno = (EAGAIN); return -1; } return r; } static void -ssl_server_handshake (struct ssl_data *ssl) +ssl_server_handshake (HCConn *conn) { + struct ssl_data *ssl = conn->layer; int error; if ((error = gnutls_handshake (ssl->session)) < 0) { if (gnutls_error_is_fatal (error)) - g_critical ("Fatal error while doing TLS handshaking: %s\n", - gnutls_strerror (error)); + { + g_critical ("Fatal error while doing TLS handshaking: %s\n", + gnutls_strerror (error)); + ssl->failed = TRUE; + } } else { ssl->handshaking = FALSE; + if (conn->func) + conn->func (conn, HC_EVENT_CONNECT, conn->data); } } @@ -128,7 +176,7 @@ ssl_server_connect (HCConn *conn) gnutls_transport_set_push_function (ssl->session, ssl_push); gnutls_transport_set_pull_function (ssl->session, ssl_pull); ssl->handshaking = TRUE; - ssl_server_handshake (ssl); + ssl_server_handshake (conn); } static void @@ -169,7 +217,10 @@ hc_conn_ssl_watch (HCConn *conn, HCEvent event, gpointer data) case HC_EVENT_READ: if (ssl->handshaking) { - ssl_server_handshake (ssl); + ssl_server_handshake (ssl_conn); + /* FIXME: create HC_CONN_ERROR */ + if (ssl->failed && ssl_conn->func) + ssl_conn->func (ssl_conn, HC_EVENT_CLOSE, ssl_conn->data); return; } while ((r = hc_conn_read (ssl->lowconn, buffer, sizeof (buffer))) > 0) @@ -183,10 +234,13 @@ hc_conn_ssl_watch (HCConn *conn, HCEvent event, gpointer data) } } -void -hc_conn_set_driver_ssl_client (HCConn *conn, HCConn *lowconn) +static int +hc_conn_set_driver_ssl (HCConn *conn, HCConn *lowconn, int server) { - struct ssl_data *ssl = ssl_data_new_client (); + struct ssl_data *ssl; + ssl = ssl_data_new (server); + if (ssl == NULL) + return -1; ssl->lowconn = lowconn; conn->layer = ssl; conn->read = hc_conn_ssl_read; @@ -194,4 +248,17 @@ hc_conn_set_driver_ssl_client (HCConn *conn, HCConn *lowconn) conn->close = hc_conn_ssl_close; hc_conn_set_callback (lowconn, hc_conn_ssl_watch, conn); ssl_server_connect (conn); + return 0; +} + +int +hc_conn_set_driver_ssl_client (HCConn *conn, HCConn *lowconn) +{ + return hc_conn_set_driver_ssl (conn, lowconn, 0); +} + +int +hc_conn_set_driver_ssl_server (HCConn *conn, HCConn *lowconn) +{ + return hc_conn_set_driver_ssl (conn, lowconn, 1); }