X-Git-Url: https://ruderich.org/simon/gitweb/?a=blobdiff_plain;f=src%2Fconnection.c;h=3254982b32b22f6dc2b2bf0c8dfcdece12fcc7cb;hb=f7b1d8eb6ee068e7562553c00cd9998300ee5311;hp=e83bc864975403198bf792701f01e1f7f850b576;hpb=112cce261d537006fd97ab43512bca2ffbbb3c7d;p=tlsproxy%2Ftlsproxy.git diff --git a/src/connection.c b/src/connection.c index e83bc86..3254982 100644 --- a/src/connection.c +++ b/src/connection.c @@ -59,6 +59,10 @@ static int initialize_tls_session_client(int peer_socket, static int initialize_tls_session_server(int peer_socket, gnutls_session_t *session, gnutls_certificate_credentials_t *x509_cred); +static int initialize_tls_session_both(int flags, + int peer_socket, + gnutls_session_t *session, + gnutls_certificate_credentials_t *x509_cred); static int fdopen_read_write(int socket, FILE **read_fd, FILE **write_fd); static int read_http_request(FILE *client_fd, char *request, size_t length); @@ -106,7 +110,7 @@ void handle_connection(int client_socket) { * certificate. */ int validation_failed; - LOG(DEBUG, "new connection"); + LOG(DEBUG1, "new connection"); server_socket = -1; client_fd_read = NULL; @@ -134,26 +138,26 @@ void handle_connection(int client_socket) { send_bad_request(client_fd_write); goto out; } else if (result == -3) { - LOG(DEBUG, "read_http_request(): proxy authentication failed"); + LOG(DEBUG1, "read_http_request(): proxy authentication failed"); send_authentication_required(client_fd_write); goto out; } if (parse_request(buffer, host, port, &version_minor) != 0) { - LOG(WARNING, "bad request: %s", buffer); + LOG(WARNING, "bad request: >%s<", buffer); send_bad_request(client_fd_write); goto out; } - LOG(DEBUG, "target: %s:%s (HTTP 1.%d)", host, port, version_minor); + LOG(DEBUG1, "target: %s:%s (HTTP 1.%d)", host, port, version_minor); /* Connect to proxy server or directly to server. */ if (global_proxy_host != NULL && global_proxy_port != NULL) { - LOG(DEBUG, "connecting to %s:%s", global_proxy_host, - global_proxy_port); + LOG(DEBUG1, "connecting to %s:%s", global_proxy_host, + global_proxy_port); server_socket = connect_to_host(global_proxy_host, global_proxy_port); } else { - LOG(DEBUG, "connecting to %s:%s", host, port); + LOG(DEBUG1, "connecting to %s:%s", host, port); server_socket = connect_to_host(host, port); } @@ -194,7 +198,7 @@ void handle_connection(int client_socket) { } } - LOG(DEBUG, "connection to server established"); + LOG(DEBUG1, "connection to server established"); /* If the -u option is used and we don't know this hostname's server * certificate then just pass through the connection and let the client @@ -209,13 +213,13 @@ void handle_connection(int client_socket) { fprintf(client_fd_write, "\r\n"); fflush(client_fd_write); - LOG(DEBUG, "transferring data"); + LOG(DEBUG1, "transferring data"); /* Proxy data between client and server until one side is done * (EOF or error). */ transfer_data(client_socket, server_socket); - LOG(DEBUG, "finished transferring data"); + LOG(DEBUG1, "finished transferring data"); goto out; } @@ -235,7 +239,7 @@ void handle_connection(int client_socket) { } server_session_init = 1; - LOG(DEBUG, "starting server TLS handshake"); + LOG(DEBUG1, "starting server TLS handshake"); /* Try to establish TLS handshake between us and server. */ result = gnutls_handshake(server_session); @@ -247,7 +251,7 @@ void handle_connection(int client_socket) { } server_session_started = 1; - LOG(DEBUG, "server TLS handshake finished"); + LOG(DEBUG1, "server TLS handshake finished"); /* Make sure the server certificate is valid and known. */ if (verify_tls_connection(server_session, host) != 0) { @@ -278,7 +282,7 @@ void handle_connection(int client_socket) { fprintf(client_fd_write, "\r\n"); fflush(client_fd_write); - LOG(DEBUG, "starting client TLS handshake"); + LOG(DEBUG1, "starting client TLS handshake"); /* Try to establish TLS handshake between client and us. */ result = gnutls_handshake(client_session); @@ -290,7 +294,7 @@ void handle_connection(int client_socket) { } client_session_started = 1; - LOG(DEBUG, "client TLS handshake finished"); + LOG(DEBUG1, "client TLS handshake finished"); /* Tell the client that the verification failed. Shouldn't be necessary as * the client should terminate the connection because he received the @@ -300,20 +304,29 @@ void handle_connection(int client_socket) { goto out; } - LOG(DEBUG, "transferring TLS data"); + LOG(DEBUG1, "transferring TLS data"); /* Proxy data between client and server until one side is done (EOF or * error). */ transfer_data_tls(client_socket, server_socket, client_session, server_session); - LOG(DEBUG, "finished transferring TLS data"); + LOG(DEBUG1, "finished transferring TLS data"); out: /* Close TLS sessions if necessary. Use GNUTLS_SHUT_RDWR so the data is * reliable transmitted. */ if (server_session_started) { - gnutls_bye(server_session, GNUTLS_SHUT_RDWR); + /* Recent gnutls-serv (used in the test-suite) won't terminate the + * connection when gnutls_bye(session, GNUTLS_SHUT_RDWR) is used + * before any other data was received. If the validation failed just + * close the connection without waiting for data, we won't read it + * anyway. + * + * For verified connections GNUTLS_SHUT_RDWR is important or we might + * lose data. */ + gnutls_bye(server_session, validation_failed ? GNUTLS_SHUT_WR + : GNUTLS_SHUT_RDWR); } if (client_session_started) { gnutls_bye(client_session, GNUTLS_SHUT_RDWR); @@ -338,7 +351,7 @@ out: } else if (server_socket != -1) { close(server_socket); } - LOG(DEBUG, "connection to server closed"); + LOG(DEBUG1, "connection to server closed"); /* Close connection to client. */ if (client_fd_read != NULL) { if (client_fd_write != NULL) { @@ -348,9 +361,9 @@ out: } else { close(client_socket); } - LOG(DEBUG, "connection to client closed"); + LOG(DEBUG1, "connection to client closed"); - LOG(DEBUG, "connection finished"); + LOG(DEBUG1, "connection finished"); } @@ -385,12 +398,12 @@ static int initialize_tls_session_client(int peer_socket, /* Load proxy CA file, this CA "list" is send to the client. */ if (!use_invalid_cert) { result = gnutls_certificate_set_x509_trust_file(*x509_cred, - PROXY_CA_FILE, + PROXY_CA_PATH, GNUTLS_X509_FMT_PEM); if (result <= 0) { LOG(ERROR, "initialize_tls_session_client(): can't read CA file: '%s'", - PROXY_CA_FILE); + PROXY_CA_PATH); gnutls_certificate_free_credentials(*x509_cred); return -1; } @@ -401,21 +414,22 @@ static int initialize_tls_session_client(int peer_socket, /* And certificate for this website and proxy's private key. */ if (!use_invalid_cert) { result = gnutls_certificate_set_x509_key_file(*x509_cred, - path, PROXY_KEY_FILE, + path, + PROXY_KEY_PATH, GNUTLS_X509_FMT_PEM); /* If the invalid hostname was specified load our special "invalid" * certificate. */ } else { result = gnutls_certificate_set_x509_key_file(*x509_cred, - PROXY_INVALID_CERT_FILE, - PROXY_KEY_FILE, + PROXY_INVALID_CERT_PATH, + PROXY_KEY_PATH, GNUTLS_X509_FMT_PEM); } if (result != GNUTLS_E_SUCCESS) { LOG(ERROR, "initialize_tls_session_client(): " "can't read server certificate ('%s') or key file ('%s'): %s", - path, PROXY_KEY_FILE, gnutls_strerror(result)); + path, PROXY_KEY_PATH, gnutls_strerror(result)); gnutls_certificate_free_credentials(*x509_cred); /* Could be a missing certificate. */ return -2; @@ -423,37 +437,8 @@ static int initialize_tls_session_client(int peer_socket, gnutls_certificate_set_dh_params(*x509_cred, global_tls_dh_params); - result = gnutls_init(session, GNUTLS_SERVER); - if (result != GNUTLS_E_SUCCESS) { - LOG(ERROR, - "initialize_tls_session_client(): gnutls_init(): %s", - gnutls_strerror(result)); - gnutls_certificate_free_credentials(*x509_cred); - return -1; - } - result = gnutls_priority_set(*session, global_tls_priority_cache); - if (result != GNUTLS_E_SUCCESS) { - LOG(ERROR, - "initialize_tls_session_client(): gnutls_priority_set(): %s", - gnutls_strerror(result)); - gnutls_deinit(*session); - gnutls_certificate_free_credentials(*x509_cred); - return -1; - } - result = gnutls_credentials_set(*session, - GNUTLS_CRD_CERTIFICATE, *x509_cred); - if (result != GNUTLS_E_SUCCESS) { - LOG(ERROR, - "initialize_tls_session_client(): gnutls_credentials_set(): %s", - gnutls_strerror(result)); - gnutls_deinit(*session); - gnutls_certificate_free_credentials(*x509_cred); - return -1; - } - - gnutls_transport_set_ptr(*session, (gnutls_transport_ptr_t)peer_socket); - - return 0; + return initialize_tls_session_both(GNUTLS_SERVER, + peer_socket, session, x509_cred); } static int initialize_tls_session_server(int peer_socket, gnutls_session_t *session, @@ -469,10 +454,19 @@ static int initialize_tls_session_server(int peer_socket, return -1; } - result = gnutls_init(session, GNUTLS_CLIENT); + return initialize_tls_session_both(GNUTLS_CLIENT, + peer_socket, session, x509_cred); +} +static int initialize_tls_session_both(int flags, + int peer_socket, + gnutls_session_t *session, + gnutls_certificate_credentials_t *x509_cred) { + int result; + + result = gnutls_init(session, flags); if (result != GNUTLS_E_SUCCESS) { LOG(ERROR, - "initialize_tls_session_server(): gnutls_init(): %s", + "initialize_tls_session_both(): gnutls_init(): %s", gnutls_strerror(result)); gnutls_certificate_free_credentials(*x509_cred); return -1; @@ -480,7 +474,7 @@ static int initialize_tls_session_server(int peer_socket, result = gnutls_priority_set(*session, global_tls_priority_cache); if (result != GNUTLS_E_SUCCESS) { LOG(ERROR, - "initialize_tls_session_server(): gnutls_priority_set(): %s", + "initialize_tls_session_both(): gnutls_priority_set(): %s", gnutls_strerror(result)); gnutls_deinit(*session); gnutls_certificate_free_credentials(*x509_cred); @@ -490,14 +484,19 @@ static int initialize_tls_session_server(int peer_socket, GNUTLS_CRD_CERTIFICATE, *x509_cred); if (result != GNUTLS_E_SUCCESS) { LOG(ERROR, - "initialize_tls_session_server(): gnutls_credentials_set(): %s", + "initialize_tls_session_both(): gnutls_credentials_set(): %s", gnutls_strerror(result)); gnutls_deinit(*session); gnutls_certificate_free_credentials(*x509_cred); return -1; } +#ifdef HAVE_GNUTLS_TRANSPORT_SET_INT2 + /* gnutls_transport_set_int() is a macro. */ + gnutls_transport_set_int(*session, peer_socket); +#else gnutls_transport_set_ptr(*session, (gnutls_transport_ptr_t)peer_socket); +#endif return 0; } @@ -543,14 +542,14 @@ static int read_http_request(FILE *client_fd, char *request, size_t length) { while (fgets(buffer, sizeof(buffer), client_fd) != NULL) { const char *authentication = "Proxy-Authorization: Basic "; - if (http_digest_authorization != NULL + if (global_http_digest_authorization != NULL && !strncmp(buffer, authentication, strlen(authentication))) { found_proxy_authorization = 1; /* Check if the passphrase matches. */ strtok(buffer, "\r\n"); if (strcmp(buffer + strlen(authentication), - http_digest_authorization)) { + global_http_digest_authorization)) { return -3; } } @@ -565,7 +564,7 @@ static int read_http_request(FILE *client_fd, char *request, size_t length) { return -1; } - if (http_digest_authorization != NULL && !found_proxy_authorization) { + if (global_http_digest_authorization != NULL && !found_proxy_authorization) { return -3; } @@ -618,7 +617,7 @@ static void transfer_data(int client, int server) { fds[1].events = POLLIN | POLLPRI | POLLHUP | POLLERR; fds[1].revents = 0; - LOG(DEBUG, "transfer_data(): %d -> %d", client, server); + LOG(DEBUG1, "transfer_data(): %d -> %d", client, server); for (;;) { int result = poll(fds, 2 /* fd count */, -1 /* no timeout */); @@ -703,8 +702,8 @@ static void transfer_data_tls(int client, int server, if (gnutls_record_get_max_size(server_session) < buffer_size) { buffer_size = gnutls_record_get_max_size(server_session); } - LOG(DEBUG, "transfer_data_tls(): suggested buffer size: %ld", - (long int)buffer_size); + LOG(DEBUG1, "transfer_data_tls(): suggested buffer size: %ld", + (long int)buffer_size); for (;;) { int result = poll(fds, 2 /* fd count */, -1 /* no timeout */); @@ -819,14 +818,14 @@ static int connect_to_host(const char *hostname, const char *port) { server->ai_socktype, server->ai_protocol); if (server_socket < 0) { - LOG_PERROR(DEBUG, "connect_to_host(): socket(), trying next"); + LOG_PERROR(DEBUG1, "connect_to_host(): socket(), trying next"); continue; } if (connect(server_socket, server->ai_addr, server->ai_addrlen) == 0) { break; } - LOG_PERROR(DEBUG, "connect_to_host(): connect(), trying next"); + LOG_PERROR(DEBUG1, "connect_to_host(): connect(), trying next"); close(server_socket); }