From 3e82a965a8a8d7e886a3e0ec48ef425f6447d4e0 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Mon, 21 Dec 2015 23:56:35 +0200 Subject: [PATCH] Prior to sending profile files, perform cookie authentication That allows to read the per-user config file, and prevent a null pointer dereference. Reported by Yick Xie. --- src/worker-auth.c | 39 ++++++++++++++++++++++++++++++++++++++ src/worker-http-handlers.c | 3 +++ src/worker-http.c | 3 +++ src/worker-vpn.c | 29 ++-------------------------- src/worker.h | 2 ++ 5 files changed, 49 insertions(+), 27 deletions(-) diff --git a/src/worker-auth.c b/src/worker-auth.c index b5a9a38d..47769b39 100644 --- a/src/worker-auth.c +++ b/src/worker-auth.c @@ -792,6 +792,45 @@ int get_cert_info(worker_st * ws) return 0; } +/* This makes sure that the provided cookie is valid, + * and fills in the ws->user_config. + */ +void cookie_authenticate_or_exit(worker_st *ws) +{ + int ret; + + if (ws->auth_state == S_AUTH_COMPLETE) + return; + + /* we must be in S_AUTH_COOKIE state */ + if (ws->auth_state != S_AUTH_COOKIE || ws->cookie_set == 0) { + oclog(ws, LOG_WARNING, "no cookie found"); + cstp_puts(ws, + "HTTP/1.1 503 Service Unavailable\r\n\r\n"); + cstp_fatal_close(ws, GNUTLS_A_ACCESS_DENIED); + exit_worker(ws); + } + + /* we have authenticated against sec-mod, we need to complete + * our authentication by forwarding our cookie to main. */ + ret = auth_cookie(ws, ws->cookie, ws->cookie_size); + if (ret < 0) { + oclog(ws, LOG_WARNING, "failed cookie authentication attempt"); + if (ret == ERR_AUTH_FAIL) { + cstp_puts(ws, + "HTTP/1.1 401 Unauthorized\r\n\r\n"); + cstp_puts(ws, + "X-Reason: Cookie is not acceptable\r\n\r\n"); + } else { + cstp_puts(ws, + "HTTP/1.1 503 Service Unavailable\r\n\r\n"); + } + cstp_fatal_close(ws, GNUTLS_A_ACCESS_DENIED); + exit_worker(ws); + } + ws->auth_state = S_AUTH_COMPLETE; +} + /* sends a cookie authentication request to main thread and waits for * a reply. * Returns 0 on success. diff --git a/src/worker-http-handlers.c b/src/worker-http-handlers.c index 02281db5..57f77ed7 100644 --- a/src/worker-http-handlers.c +++ b/src/worker-http-handlers.c @@ -48,6 +48,9 @@ int ret; struct stat st; oclog(ws, LOG_HTTP_DEBUG, "requested config: %s", ws->req.url); + + cookie_authenticate_or_exit(ws); + if (ws->user_config->xml_config_file == NULL) { oclog(ws, LOG_INFO, "requested config but no config file is set"); cstp_printf(ws, "HTTP/1.%u 404 Not found\r\n", http_ver); diff --git a/src/worker-http.c b/src/worker-http.c index 2ccdf67d..000c1e5e 100644 --- a/src/worker-http.c +++ b/src/worker-http.c @@ -345,6 +345,9 @@ void header_value_check(struct worker_st *ws, struct http_req_st *req) ws->full_ipv6 = 1; break; case HEADER_COOKIE: + /* don't bother parsing cookies if we are already authenticated */ + if (ws->auth_state > S_AUTH_COOKIE) + break; str = (char *)value; while ((token = strtok(str, ";")) != NULL) { diff --git a/src/worker-vpn.c b/src/worker-vpn.c index 4067c930..765e2a6c 100644 --- a/src/worker-vpn.c +++ b/src/worker-vpn.c @@ -1312,6 +1312,7 @@ static int send_routes(worker_st *ws, struct http_req_st *req, return 0; } + /* connect_handler: * @ws: an initialized worker structure * @@ -1350,33 +1351,7 @@ static int connect_handler(worker_st * ws) ws->buffer_size = sizeof(ws->buffer); - /* we must be in S_AUTH_COOKIE state */ - if (ws->auth_state != S_AUTH_COOKIE || ws->cookie_set == 0) { - oclog(ws, LOG_WARNING, "no cookie found"); - cstp_puts(ws, - "HTTP/1.1 503 Service Unavailable\r\n\r\n"); - cstp_fatal_close(ws, GNUTLS_A_ACCESS_DENIED); - exit_worker(ws); - } - - /* we have authenticated against sec-mod, we need to complete - * our authentication by forwarding our cookie to main. */ - ret = auth_cookie(ws, ws->cookie, ws->cookie_size); - if (ret < 0) { - oclog(ws, LOG_WARNING, "failed cookie authentication attempt"); - if (ret == ERR_AUTH_FAIL) { - cstp_puts(ws, - "HTTP/1.1 401 Unauthorized\r\n\r\n"); - cstp_puts(ws, - "X-Reason: Cookie is not acceptable\r\n\r\n"); - } else { - cstp_puts(ws, - "HTTP/1.1 503 Service Unavailable\r\n\r\n"); - } - cstp_fatal_close(ws, GNUTLS_A_ACCESS_DENIED); - exit_worker(ws); - } - ws->auth_state = S_AUTH_COMPLETE; + cookie_authenticate_or_exit(ws); if (strcmp(req->url, "/CSCOSSLC/tunnel") != 0) { oclog(ws, LOG_INFO, "bad connect request: '%s'\n", req->url); diff --git a/src/worker.h b/src/worker.h index a5904f4d..ced3bbb0 100644 --- a/src/worker.h +++ b/src/worker.h @@ -359,6 +359,8 @@ int send_msg_to_main(worker_st *ws, uint8_t cmd, int parse_proxy_proto_header(struct worker_st *ws, int fd); +void cookie_authenticate_or_exit(worker_st *ws); + /* after that time (secs) of inactivity in the UDP part, connection switches to * TCP (if activity occurs there). */