int create_http_socket(char* http_request, sock_t* server_sock, sock_t* client_sock, ssl_context_t* ssl_ctx) { http_request_t http_infos; int retcode; char* err; char sport[7] = {0, }; err = NULL; proxenet_xzero(&http_infos, sizeof(http_request_t)); http_infos.method = NULL; http_infos.hostname = NULL; http_infos.request_uri = NULL; /* get target from string and establish client socket to dest */ if (get_url_information(http_request, &http_infos) == false) { xlog(LOG_ERROR, "%s\n", "Failed to extract valid parameters from URL."); return -1; } ssl_ctx->use_ssl = http_infos.is_ssl; snprintf(sport, 6, "%d", http_infos.port); retcode = create_connect_socket(http_infos.hostname, sport, &err); if (retcode < 0) { if (err) generic_http_error_page(*server_sock, err); else generic_http_error_page(*server_sock, "Unknown error in <i>create_connect_socket</i>"); retcode = -1; } else { *client_sock = retcode; /* if ssl, set up ssl interception */ if (http_infos.is_ssl) { /* 1. set up proxy->server ssl session */ if(proxenet_ssl_init_client_context(&(ssl_ctx->client)) < 0) { retcode = -1; goto http_sock_end; } proxenet_ssl_wrap_socket(&(ssl_ctx->client.context), client_sock); if (proxenet_ssl_handshake(&(ssl_ctx->client.context)) < 0) { xlog(LOG_ERROR, "%s\n", "proxy->server: handshake"); retcode = -1; goto http_sock_end; } #ifdef DEBUG xlog(LOG_DEBUG, "%s\n", "SSL handshake with server done"); #endif proxenet_write(*server_sock, "HTTP/1.0 200 Connection established\r\n\r\n", 39); /* 2.set up proxy->browser ssl session */ if(proxenet_ssl_init_server_context(&(ssl_ctx->server)) < 0) { retcode = -1; goto http_sock_end; } proxenet_ssl_wrap_socket(&(ssl_ctx->server.context), server_sock); if (proxenet_ssl_handshake(&(ssl_ctx->server.context)) < 0) { xlog(LOG_ERROR, "handshake proxy->client '%s:%d' failed\n", http_infos.hostname, http_infos.port); retcode = -1; goto http_sock_end; } #ifdef DEBUG xlog(LOG_DEBUG, "%s\n", "SSL Handshake with client done"); #endif } } http_sock_end: proxenet_xfree(http_infos.method); proxenet_xfree(http_infos.hostname); proxenet_xfree(http_infos.request_uri); return retcode; }
/** * Establish a connection from proxenet -> server. If proxy forwarding configured, then process * request to other proxy. * */ int create_http_socket(request_t* req, sock_t* server_sock, sock_t* client_sock, ssl_context_t* ssl_ctx) { int retcode; char *host, *port; char sport[6] = {0, }; http_request_t* http_infos = &req->http_infos; bool use_proxy = (cfg->proxy.host != NULL) ; /* get target from string and establish client socket to dest */ if (get_url_information(req->data, http_infos) == false) { xlog(LOG_ERROR, "%s\n", "Failed to extract valid parameters from URL."); return -1; } #ifdef DEBUG char* full_uri = get_request_full_uri(req); xlog(LOG_DEBUG, "URL: %s\n", full_uri); proxenet_xfree(full_uri); #endif ssl_ctx->use_ssl = http_infos->is_ssl; snprintf(sport, 5, "%u", http_infos->port); /* do we forward to another proxy ? */ if (use_proxy) { host = cfg->proxy.host; port = cfg->proxy.port; } else { host = http_infos->hostname; port = sport; } retcode = create_connect_socket(host, port); if (retcode < 0) { if (errno) generic_http_error_page(*server_sock, strerror(errno)); else generic_http_error_page(*server_sock, "Unknown error in <i>create_connect_socket</i>"); retcode = -1; } else { *client_sock = retcode; /* if ssl, set up ssl interception */ if (http_infos->is_ssl) { if (use_proxy) { char *connect_buf = NULL; /* 0. set up proxy->proxy ssl session (i.e. forward CONNECT request) */ retcode = proxenet_write(*client_sock, req->data, req->size); if (retcode < 0) { xlog(LOG_ERROR, "%s failed to CONNECT to proxy\n", PROGNAME); return -1; } /* read response */ retcode = proxenet_read_all(*client_sock, &connect_buf, NULL); if (retcode < 0) { xlog(LOG_ERROR, "%s Failed to read from proxy\n", PROGNAME); return -1; } /* expect HTTP 200 */ if ( (strncmp(connect_buf, "HTTP/1.0 200", 12) != 0) && (strncmp(connect_buf, "HTTP/1.1 200", 12) != 0)) { xlog(LOG_ERROR, "%s->proxy: bad HTTP version\n", PROGNAME); if (cfg->verbose) xlog(LOG_ERROR, "Received %s\n", connect_buf); return -1; } } /* 1. set up proxy->server ssl session */ if(proxenet_ssl_init_client_context(&(ssl_ctx->client)) < 0) { return -1; } proxenet_ssl_wrap_socket(&(ssl_ctx->client.context), client_sock); if (proxenet_ssl_handshake(&(ssl_ctx->client.context)) < 0) { xlog(LOG_ERROR, "%s->server: handshake\n", PROGNAME); return -1; } #ifdef DEBUG xlog(LOG_DEBUG, "%s %d %d\n", "SSL handshake with server done", *client_sock, *server_sock); #endif if (proxenet_write(*server_sock, "HTTP/1.0 200 Connection established\r\n\r\n", 39) < 0){ return -1; } /* 2. set up proxy->browser ssl session */ if(proxenet_ssl_init_server_context(&(ssl_ctx->server)) < 0) { return -1; } proxenet_ssl_wrap_socket(&(ssl_ctx->server.context), server_sock); if (proxenet_ssl_handshake(&(ssl_ctx->server.context)) < 0) { xlog(LOG_ERROR, "handshake %s->client '%s:%d' failed\n", PROGNAME, http_infos->hostname, http_infos->port); return -1; } #ifdef DEBUG xlog(LOG_DEBUG, "%s\n", "SSL Handshake with client done"); #endif } } return retcode; }