From 0242b464e71ac05086042364038764ef7fcb491d Mon Sep 17 00:00:00 2001 From: Roberto De Ioris Date: Sat, 20 Oct 2012 17:29:45 +0200 Subject: [PATCH] another step for https porting --- healthcheck/http.c | 9 -- healthcheck/libpg.c | 0 healthcheck/memcached.c | 0 healthcheck/pg.c | 0 healthcheck/tcp.c | 0 healthcheck/uwsgi.c | 1 - plugins/http/http.c | 189 +++++++++++++++++++++++++++++++++++++++- 7 files changed, 186 insertions(+), 13 deletions(-) delete mode 100644 healthcheck/http.c delete mode 100644 healthcheck/libpg.c delete mode 100644 healthcheck/memcached.c delete mode 100644 healthcheck/pg.c delete mode 100644 healthcheck/tcp.c delete mode 100644 healthcheck/uwsgi.c diff --git a/healthcheck/http.c b/healthcheck/http.c deleted file mode 100644 index 58a439b0..00000000 --- a/healthcheck/http.c +++ /dev/null @@ -1,9 +0,0 @@ -// http:3:GET / HTTP/1.1:192.168.173.10:80,192.168.173.11:80,192.168.173.12:80,192.168.173.13:80 - -/* -write(arg1); - -wait_for_fd() - -get_data() == 200 -*/ diff --git a/healthcheck/libpg.c b/healthcheck/libpg.c deleted file mode 100644 index e69de29b..00000000 diff --git a/healthcheck/memcached.c b/healthcheck/memcached.c deleted file mode 100644 index e69de29b..00000000 diff --git a/healthcheck/pg.c b/healthcheck/pg.c deleted file mode 100644 index e69de29b..00000000 diff --git a/healthcheck/tcp.c b/healthcheck/tcp.c deleted file mode 100644 index e69de29b..00000000 diff --git a/healthcheck/uwsgi.c b/healthcheck/uwsgi.c deleted file mode 100644 index c9ebfec5..00000000 --- a/healthcheck/uwsgi.c +++ /dev/null @@ -1 +0,0 @@ -// uwsgi:3::192.168.173.1:3031,192.168.173.2:3031,192.168.173.3:3031,192.168.173.4:3031 diff --git a/plugins/http/http.c b/plugins/http/http.c index 16ff11dc..b587bd96 100644 --- a/plugins/http/http.c +++ b/plugins/http/http.c @@ -33,13 +33,77 @@ struct uwsgi_http { } uhttp; +#ifdef UWSGI_SSL +void uwsgi_opt_https(char *opt, char *value, void *cr) { + struct uwsgi_corerouter *ucr = (struct uwsgi_corerouter *) cr; + char *client_ca = NULL; + + // build socket, certificate and key file + char *sock = uwsgi_str(value); + char *crt = strchr(sock, ','); + if (!crt) { + uwsgi_log("invalid https syntax must be socket,crt,key\n"); + exit(1); + } + *crt = '\0'; crt++; + char *key = strchr(crt, ','); + if (!key) { + uwsgi_log("invalid https syntax must be socket,crt,key\n"); + exit(1); + } + *key = '\0'; key++; + + char *ciphers = strchr(key, ','); + if (ciphers) { + *ciphers = '\0'; ciphers++; + client_ca = strchr(ciphers, ','); + if (client_ca) { + *client_ca = '\0'; client_ca++; + } + } + + struct uwsgi_gateway_socket *ugs = uwsgi_new_gateway_socket(sock, ucr->name); + // ok we have the socket, initialize ssl if required + if (!uwsgi.ssl_initialized) { + uwsgi_ssl_init(); + } + + // initialize ssl context + ugs->ctx = uwsgi_ssl_new_server_context(uwsgi_concat3(ucr->short_name, "-", ugs->name),crt, key, ciphers, client_ca); + // set the ssl mode + ugs->mode = UWSGI_HTTP_SSL; + + ucr->has_sockets++; +} + +void uwsgi_opt_http_to_https(char *opt, char *value, void *cr) { + struct uwsgi_corerouter *ucr = (struct uwsgi_corerouter *) cr; + + char *sock = uwsgi_str(value); + char *port = strchr(sock, ','); + if (port) { + *port = '\0'; + port++; + } + + struct uwsgi_gateway_socket *ugs = uwsgi_new_gateway_socket(sock, ucr->name); + + // set context to the port + ugs->ctx = port; + // force SSL mode + ugs->mode = UWSGI_HTTP_FORCE_SSL; + + ucr->has_sockets++; +} + +#endif struct uwsgi_option http_options[] = { {"http", required_argument, 0, "add an http router/server on the specified address", uwsgi_opt_corerouter, &uhttp, 0}, #ifdef UWSGI_SSL - //{"https", required_argument, 0, "add an https router/server on the specified address with specified certificate and key", uwsgi_opt_https, &uhttp, 0}, + {"https", required_argument, 0, "add an https router/server on the specified address with specified certificate and key", uwsgi_opt_https, &uhttp, 0}, {"https-export-cert", no_argument, 0, "export uwsgi variable HTTPS_CC containing the raw client certificate", uwsgi_opt_true, &uhttp.https_export_cert, 0}, - //{"http-to-https", required_argument, 0, "add an http router/server on the specified address and redirect all of the requests to https", uwsgi_opt_http_to_https, &uhttp, 0}, + {"http-to-https", required_argument, 0, "add an http router/server on the specified address and redirect all of the requests to https", uwsgi_opt_http_to_https, &uhttp, 0}, #endif {"http-processes", required_argument, 0, "set the number of http processes to spawn", uwsgi_opt_set_int, &uhttp.cr.processes, 0}, {"http-workers", required_argument, 0, "set the number of http processes to spawn", uwsgi_opt_set_int, &uhttp.cr.processes, 0}, @@ -420,6 +484,59 @@ ssize_t hr_read_body(struct corerouter_session * cs) { return len; } +#ifdef UWSGI_SSL +ssize_t hr_write_ssl_response(struct corerouter_session * cs) { + struct http_session *hs = (struct http_session *) cs; + int ret = SSL_write(hs->ssl, cs->buffer->buf + cs->buffer_pos, cs->buffer_len - cs->buffer_pos); + + if (ret > 0) { + cs->buffer_pos += ret; + if (cs->event_hook_read) { + uwsgi_cr_hook_read(cs, NULL); + } + // could be a partial write + uwsgi_cr_hook_write(cs, hr_write_ssl_response); + // ok this response chunk is sent, let's wait for another one + if (cs->buffer_pos == cs->buffer_len) { + uwsgi_cr_hook_write(cs, NULL); + uwsgi_cr_hook_instance_read(cs, hr_instance_read_response); + } + return ret; + } + + int err = SSL_get_error(hs->ssl, ret); + if (err == SSL_ERROR_WANT_READ) { + if (cs->event_hook_write) { + uwsgi_cr_hook_write(cs, NULL); + uwsgi_cr_hook_read(cs, hr_write_ssl_response); + } + errno = EINPROGRESS; + return -1; + } + else if (err == SSL_ERROR_WANT_WRITE) { + if (cs->event_hook_read) { + uwsgi_cr_hook_read(cs, NULL); + uwsgi_cr_hook_write(cs, hr_write_ssl_response); + } + errno = EINPROGRESS; + return -1; + } + + else if (err == SSL_ERROR_SYSCALL) { + uwsgi_error("hr_write_ssl_response()"); + } + + else if (err == SSL_ERROR_SSL && uwsgi.ssl_verbose) { + ERR_print_errors_fp(stderr); + } + + else if (err == SSL_ERROR_ZERO_RETURN) { + return 0; + } + + return -1; +} +#endif ssize_t hr_write_response(struct corerouter_session * cs) { ssize_t len = write(cs->fd, cs->buffer->buf + cs->buffer_pos, cs->buffer_len - cs->buffer_pos); @@ -458,7 +575,17 @@ ssize_t hr_instance_read_response(struct corerouter_session * cs) { cs->buffer_len = len; // ok stop reading from the instance, and start writing to the client uwsgi_cr_hook_instance_read(cs, NULL); - uwsgi_cr_hook_write(cs, hr_write_response); +#ifdef UWSGI_SSL + struct http_session *hs = (struct http_session *) cs; + if (!hs->ssl) { + uwsgi_cr_hook_write(cs, hr_write_response); + } + else { +#endif + uwsgi_cr_hook_write(cs, hr_write_ssl_response); +#ifdef UWSGI_SSL + } +#endif return len; } @@ -546,6 +673,57 @@ ssize_t hr_instance_connected(struct corerouter_session * cs) { return 1; } +ssize_t hs_http_manage(struct corerouter_session *, ssize_t); + +#ifdef UWSGI_SSL +ssize_t hr_recv_http_ssl(struct corerouter_session * cs) { + // be sure buffer does not grow over 64k + cs->buffer->limit = UMAX16; + // try to always leave 4k available + if (uwsgi_buffer_ensure(cs->buffer, uwsgi.page_size)) return -1; + struct http_session *hs = (struct http_session *) cs; + int ret = SSL_read(hs->ssl, cs->buffer->buf + cs->buffer_pos, cs->buffer->len - cs->buffer_pos); + if (ret > 0) { + // fix waiting + if (cs->event_hook_write) { + uwsgi_cr_hook_write(cs, NULL); + uwsgi_cr_hook_read(cs, hr_recv_http_ssl); + } + return hs_http_manage(cs, ret); + } + if (ret == 0) return 0; + int err = SSL_get_error(hs->ssl, ret); + + if (err == SSL_ERROR_WANT_READ) { + if (cs->event_hook_write) { + uwsgi_cr_hook_write(cs, NULL); + uwsgi_cr_hook_read(cs, hr_recv_http_ssl); + } + errno = EINPROGRESS; + return -1; + } + + else if (err == SSL_ERROR_WANT_WRITE) { + if (cs->event_hook_read) { + uwsgi_cr_hook_read(cs, NULL); + uwsgi_cr_hook_write(cs, hr_recv_http_ssl); + } + errno = EINPROGRESS; + return -1; + } + + else if (err == SSL_ERROR_SYSCALL) { + uwsgi_error("hr_recv_http_ssl()"); + } + + else if (err == SSL_ERROR_SSL && uwsgi.ssl_verbose) { + ERR_print_errors_fp(stderr); + } + + return -1; +} +#endif + ssize_t hr_recv_http(struct corerouter_session * cs) { // be sure buffer does not grow over 64k cs->buffer->limit = UMAX16; @@ -557,6 +735,10 @@ ssize_t hr_recv_http(struct corerouter_session * cs) { uwsgi_error("hr_recv_http()"); return -1; } + return hs_http_manage(cs, len); +} + +ssize_t hs_http_manage(struct corerouter_session * cs, ssize_t len) { // fix buffer usage (TODO a bit ugly...) cs->buffer->pos += len; @@ -640,6 +822,7 @@ void http_alloc_session(struct uwsgi_corerouter *ucr, struct uwsgi_gateway_socke hs->ssl = SSL_new(ugs->ctx); SSL_set_fd(hs->ssl, cs->fd); SSL_set_accept_state(hs->ssl); + uwsgi_cr_hook_read(cs, hr_recv_http_ssl); } else { #endif