diff --git a/src/http_auth.c b/src/http_auth.c index 7747f79f..29bb2481 100644 --- a/src/http_auth.c +++ b/src/http_auth.c @@ -53,25 +53,25 @@ const char login_msg[] = "\r\n" "\r\n" "\r\n"; -int get_auth_handler(worker_st *server) +int get_auth_handler(worker_st *ws) { int ret; - tls_puts(server->session, "HTTP/1.1 200 OK\r\n"); - tls_puts(server->session, "Connection: close\r\n"); - tls_puts(server->session, "Content-Type: text/xml\r\n"); - tls_printf(server->session, "Content-Length: %u\r\n", sizeof(login_msg)-1); - tls_puts(server->session, "X-Transcend-Version: 1\r\n"); - tls_puts(server->session, "\r\n"); + tls_puts(ws->session, "HTTP/1.1 200 OK\r\n"); + tls_puts(ws->session, "Connection: close\r\n"); + tls_puts(ws->session, "Content-Type: text/xml\r\n"); + tls_printf(ws->session, "Content-Length: %u\r\n", sizeof(login_msg)-1); + tls_puts(ws->session, "X-Transcend-Version: 1\r\n"); + tls_puts(ws->session, "\r\n"); - tls_send(server->session, login_msg, sizeof(login_msg)-1); + tls_send(ws->session, login_msg, sizeof(login_msg)-1); return 0; } static -int get_cert_username(worker_st *server, const gnutls_datum_t* raw, +int get_cert_username(worker_st *ws, const gnutls_datum_t* raw, char* username, size_t username_size) { gnutls_x509_crt_t crt; @@ -79,20 +79,20 @@ int ret; ret = gnutls_x509_crt_init(&crt); if (ret < 0) { - oclog(server, LOG_ERR, "certificate error: %s", gnutls_strerror(ret)); + oclog(ws, LOG_ERR, "certificate error: %s", gnutls_strerror(ret)); goto fail; } ret = gnutls_x509_crt_import(crt, raw, GNUTLS_X509_FMT_DER); if (ret < 0) { - oclog(server, LOG_ERR, "certificate error: %s", gnutls_strerror(ret)); + oclog(ws, LOG_ERR, "certificate error: %s", gnutls_strerror(ret)); goto fail; } - ret = gnutls_x509_crt_get_dn_by_oid (crt, server->config->cert_user_oid, + ret = gnutls_x509_crt_get_dn_by_oid (crt, ws->config->cert_user_oid, 0, 0, username, &username_size); if (ret < 0) { - oclog(server, LOG_ERR, "certificate error: %s", gnutls_strerror(ret)); + oclog(ws, LOG_ERR, "certificate error: %s", gnutls_strerror(ret)); goto fail; } @@ -132,7 +132,7 @@ static int send_auth_req(int fd, const struct cmd_auth_req_st* r) return(sendmsg(fd, &hdr, 0)); } -static int recv_auth_reply(worker_st *server) +static int recv_auth_reply(worker_st *ws) { struct iovec iov[3]; uint8_t cmd = 0; @@ -162,7 +162,7 @@ static int recv_auth_reply(worker_st *server) hdr.msg_control = control_un.control; hdr.msg_controllen = sizeof(control_un.control); - ret = recvmsg( server->cmd_fd, &hdr, 0); + ret = recvmsg( ws->cmd_fd, &hdr, 0); if (ret <= 0) { return -1; } @@ -177,8 +177,8 @@ static int recv_auth_reply(worker_st *server) if (cmptr->cmsg_type != SCM_RIGHTS) return -1; - server->tun_fd = *((int *) CMSG_DATA(cmptr)); - memcpy(server->tun_name, resp.vname, sizeof(server->tun_name)); + ws->tun_fd = *((int *) CMSG_DATA(cmptr)); + memcpy(ws->tun_name, resp.vname, sizeof(ws->tun_name)); } else return -1; break; @@ -191,19 +191,19 @@ static int recv_auth_reply(worker_st *server) /* sends an authentication request to main thread and waits for * a reply */ -static int auth_user(worker_st *server, const struct cmd_auth_req_st* areq) +static int auth_user(worker_st *ws, const struct cmd_auth_req_st* areq) { int ret; - ret = send_auth_req(server->cmd_fd, areq); + ret = send_auth_req(ws->cmd_fd, areq); if (ret < 0) return ret; - return recv_auth_reply(server); + return recv_auth_reply(ws); } static -int get_cert_info(worker_st *server, struct cmd_auth_req_st *areq, const char** reason) +int get_cert_info(worker_st *ws, struct cmd_auth_req_st *areq, const char** reason) { const gnutls_datum_t * cert; unsigned int ncerts; @@ -211,7 +211,7 @@ int ret; /* this is superflous. Verification has already been performed * during handshake. */ - cert = gnutls_certificate_get_peers (server->session, &ncerts); + cert = gnutls_certificate_get_peers (ws->session, &ncerts); if (cert == NULL) { *reason = "No certificate found"; @@ -219,10 +219,10 @@ int ret; } areq->tls_auth_ok = 1; - if (server->config->cert_user_oid) { /* otherwise certificate username is ignored */ - ret = get_cert_username(server, cert, areq->cert_user, sizeof(areq->cert_user)); + if (ws->config->cert_user_oid) { /* otherwise certificate username is ignored */ + ret = get_cert_username(ws, cert, areq->cert_user, sizeof(areq->cert_user)); if (ret < 0) { - oclog(server, LOG_ERR, "Cannot get username (%s) from certificate", server->config->cert_user_oid); + oclog(ws, LOG_ERR, "Cannot get username (%s) from certificate", ws->config->cert_user_oid); *reason = "No username in certificate"; return -1; } @@ -231,10 +231,10 @@ int ret; return 0; } -int post_old_auth_handler(worker_st *server) +int post_old_auth_handler(worker_st *ws) { int ret; -struct req_data_st *req = server->parser->data; +struct req_data_st *req = ws->parser->data; const char* reason = "Authentication failed"; unsigned char cookie[COOKIE_SIZE]; char str_cookie[2*COOKIE_SIZE+1]; @@ -247,15 +247,15 @@ struct cmd_auth_req_st areq; memset(&areq, 0, sizeof(areq)); - if (server->config->auth_types & AUTH_TYPE_CERTIFICATE) { - ret = get_cert_info(server, &areq, &reason); + if (ws->config->auth_types & AUTH_TYPE_CERTIFICATE) { + ret = get_cert_info(ws, &areq, &reason); if (ret < 0) goto auth_fail; username = areq.cert_user; } - if (server->config->auth_types & AUTH_TYPE_USERNAME_PASS) { + if (ws->config->auth_types & AUTH_TYPE_USERNAME_PASS) { /* body should be "username=test&password=test" */ username = strstr(req->body, "username="); if (username == NULL) { @@ -295,11 +295,11 @@ struct cmd_auth_req_st areq; snprintf(areq.pass, sizeof(areq.pass), "%s", password); } - ret = auth_user(server, &areq); + ret = auth_user(ws, &areq); if (ret < 0) goto auth_fail; - oclog(server, LOG_INFO, "User '%s' logged in\n", username); + oclog(ws, LOG_INFO, "User '%s' logged in\n", username); /* generate cookie */ ret = gnutls_rnd(GNUTLS_RND_RANDOM, cookie, sizeof(cookie)); @@ -312,12 +312,12 @@ struct cmd_auth_req_st areq; } memset(&sc, 0, sizeof(sc)); - sc.expiration = time(0) + server->config->cookie_validity; + sc.expiration = time(0) + ws->config->cookie_validity; if (username) snprintf(sc.username, sizeof(sc.username), "%s", username); /* store cookie */ - ret = store_cookie(server, cookie, sizeof(cookie), &sc); + ret = store_cookie(ws, cookie, sizeof(cookie), &sc); if (ret < 0) { reason = "Storage issue"; goto auth_fail; @@ -325,20 +325,20 @@ struct cmd_auth_req_st areq; /* reply */ - tls_puts(server->session, "HTTP/1.1 200 OK\r\n"); - tls_puts(server->session, "Content-Type: text/xml\r\n"); - tls_printf(server->session, "Content-Length: %u\r\n", (unsigned)(sizeof(SUCCESS_MSG)-1)); - tls_puts(server->session, "X-Transcend-Version: 1\r\n"); - tls_printf(server->session, "Set-Cookie: webvpn=%s\r\n", str_cookie); - tls_puts(server->session, "\r\n"SUCCESS_MSG); + tls_puts(ws->session, "HTTP/1.1 200 OK\r\n"); + tls_puts(ws->session, "Content-Type: text/xml\r\n"); + tls_printf(ws->session, "Content-Length: %u\r\n", (unsigned)(sizeof(SUCCESS_MSG)-1)); + tls_puts(ws->session, "X-Transcend-Version: 1\r\n"); + tls_printf(ws->session, "Set-Cookie: webvpn=%s\r\n", str_cookie); + tls_puts(ws->session, "\r\n"SUCCESS_MSG); return 0; auth_fail: - tls_puts(server->session, "HTTP/1.1 503 Service Unavailable\r\n"); - tls_printf(server->session, + tls_puts(ws->session, "HTTP/1.1 503 Service Unavailable\r\n"); + tls_printf(ws->session, "X-Reason: %s\r\n\r\n", reason); - tls_fatal_close(server->session, GNUTLS_A_ACCESS_DENIED); + tls_fatal_close(ws->session, GNUTLS_A_ACCESS_DENIED); exit(1); } @@ -347,10 +347,10 @@ auth_fail: #define XMLUSER_END "" #define XMLPASS_END "" -int post_new_auth_handler(worker_st *server) +int post_new_auth_handler(worker_st *ws) { int ret; -struct req_data_st *req = server->parser->data; +struct req_data_st *req = ws->parser->data; const char* reason = "Authentication failed"; unsigned char cookie[COOKIE_SIZE]; char str_cookie[2*COOKIE_SIZE+1]; @@ -364,15 +364,15 @@ struct cmd_auth_req_st areq; memset(&areq, 0, sizeof(areq)); - if (server->config->auth_types & AUTH_TYPE_CERTIFICATE) { - ret = get_cert_info(server, &areq, &reason); + if (ws->config->auth_types & AUTH_TYPE_CERTIFICATE) { + ret = get_cert_info(ws, &areq, &reason); if (ret < 0) goto auth_fail; username = areq.cert_user; } - if (server->config->auth_types & AUTH_TYPE_USERNAME_PASS) { + if (ws->config->auth_types & AUTH_TYPE_USERNAME_PASS) { /* body should contain testtest */ username = strstr(req->body, XMLUSER); if (username == NULL) { @@ -412,11 +412,11 @@ struct cmd_auth_req_st areq; snprintf(areq.pass, sizeof(areq.pass), "%s", password); } - ret = auth_user(server, &areq); + ret = auth_user(ws, &areq); if (ret < 0) goto auth_fail; - oclog(server, LOG_INFO, "User '%s' logged in\n", username); + oclog(ws, LOG_INFO, "User '%s' logged in\n", username); /* generate cookie */ ret = gnutls_rnd(GNUTLS_RND_RANDOM, cookie, sizeof(cookie)); @@ -429,12 +429,12 @@ struct cmd_auth_req_st areq; } memset(&sc, 0, sizeof(sc)); - sc.expiration = time(0) + server->config->cookie_validity; + sc.expiration = time(0) + ws->config->cookie_validity; if (username) snprintf(sc.username, sizeof(sc.username), "%s", username); /* store cookie */ - ret = store_cookie(server, cookie, sizeof(cookie), &sc); + ret = store_cookie(ws, cookie, sizeof(cookie), &sc); if (ret < 0) { reason = "Storage issue"; goto auth_fail; @@ -442,22 +442,22 @@ struct cmd_auth_req_st areq; /* reply */ - tls_puts(server->session, "HTTP/1.1 200 OK\r\n"); - tls_puts(server->session, "Content-Type: text/xml\r\n"); - tls_printf(server->session, "Content-Length: %u\r\n", (unsigned)(sizeof(SUCCESS_MSG)-1)); - tls_puts(server->session, "X-Transcend-Version: 1\r\n"); - tls_printf(server->session, "Set-Cookie: webvpn=%s\r\n", str_cookie); - tls_puts(server->session, "\r\n"SUCCESS_MSG); + tls_puts(ws->session, "HTTP/1.1 200 OK\r\n"); + tls_puts(ws->session, "Content-Type: text/xml\r\n"); + tls_printf(ws->session, "Content-Length: %u\r\n", (unsigned)(sizeof(SUCCESS_MSG)-1)); + tls_puts(ws->session, "X-Transcend-Version: 1\r\n"); + tls_printf(ws->session, "Set-Cookie: webvpn=%s\r\n", str_cookie); + tls_puts(ws->session, "\r\n"SUCCESS_MSG); return 0; ask_auth: - return get_auth_handler(server); + return get_auth_handler(ws); auth_fail: - tls_puts(server->session, "HTTP/1.1 503 Service Unavailable\r\n"); - tls_printf(server->session, + tls_puts(ws->session, "HTTP/1.1 503 Service Unavailable\r\n"); + tls_printf(ws->session, "X-Reason: %s\r\n\r\n", reason); - tls_fatal_close(server->session, GNUTLS_A_ACCESS_DENIED); + tls_fatal_close(ws->session, GNUTLS_A_ACCESS_DENIED); exit(1); } diff --git a/src/main.c b/src/main.c index 4686134f..4561582f 100644 --- a/src/main.c +++ b/src/main.c @@ -326,6 +326,7 @@ int main(void) int val, n = 0, ret; struct timeval tv; int cmd_fd[2]; + struct worker_st ws; struct sockaddr_storage tmp_addr; socklen_t tmp_addr_len; @@ -395,6 +396,8 @@ int main(void) GNUTLS_FATAL_ERR(ret); + memset(&ws, 0, sizeof(ws)); + alarm(config.cookie_validity + 300); openlog("ocserv", LOG_PID, LOG_LOCAL0); syslog_open = 1; @@ -440,8 +443,8 @@ int main(void) list_for_each(pos, &llist.list) { ltmp = list_entry(pos, struct listen_list_st, list); if (FD_ISSET(ltmp->fd, &rd)) { - tmp_addr_len = sizeof(tmp_addr); - fd = accept(ltmp->fd, (void*)&tmp_addr, &tmp_addr_len); + ws.remote_addr_len = sizeof(ws.remote_addr); + fd = accept(ltmp->fd, (void*)&ws.remote_addr, &ws.remote_addr_len); if (fd < 0) { syslog(LOG_ERR, "Error in accept(): %s", @@ -458,6 +461,7 @@ int main(void) pid = fork(); if (pid == 0) { /* child */ + /* Drop privileges after this point */ drop_privileges(&config); /* close any open descriptors before @@ -466,9 +470,13 @@ int main(void) close(cmd_fd[0]); clear_listen_list(&llist); clear_proc_list(&clist); + + ws.config = &config; + ws.cmd_fd = cmd_fd[1]; + ws.tun_fd = -1; + ws.conn_fd = fd; - vpn_server(&config, &creds, &tmp_addr, - tmp_addr_len, cmd_fd[1], fd); + vpn_server(&ws, &creds); exit(0); } else if (pid == -1) { fork_failed: diff --git a/src/vpn.c b/src/vpn.c index 3face289..c9bf746d 100644 --- a/src/vpn.c +++ b/src/vpn.c @@ -47,7 +47,7 @@ /* HTTP requests prior to disconnection */ #define MAX_HTTP_REQUESTS 8 -static int connect_handler(worker_st *server); +static int connect_handler(worker_st *ws); typedef int (*url_handler_fn)(worker_st*); struct known_urls_st { @@ -183,9 +183,7 @@ char* tmp = malloc(length+1); return 0; } -void vpn_server(struct cfg_st *config, struct tls_st *creds, - struct sockaddr_storage* r_addr, socklen_t r_addr_len, - int cmd_fd, int fd) +void vpn_server(struct worker_st* ws, struct tls_st *creds) { unsigned char buf[2048]; int ret; @@ -194,19 +192,11 @@ void vpn_server(struct cfg_st *config, struct tls_st *creds, http_parser parser; http_parser_settings settings; struct req_data_st req; - worker_st _server; - worker_st *server; url_handler_fn fn; int requests_left = MAX_HTTP_REQUESTS; - memset(&_server, 0, sizeof(_server)); - server = &_server; - - server->remote_addr_len = r_addr_len; - memcpy(&server->remote_addr, r_addr, r_addr_len); - syslog(LOG_INFO, "Accepted connection from %s", - human_addr((void*)&server->remote_addr, server->remote_addr_len, + human_addr((void*)&ws->remote_addr, ws->remote_addr_len, buf, sizeof(buf))); /* initialize the session */ @@ -221,8 +211,8 @@ void vpn_server(struct cfg_st *config, struct tls_st *creds, creds->xcred); GNUTLS_FATAL_ERR(ret); - gnutls_certificate_server_set_request(session, config->cert_req); - gnutls_transport_set_ptr(session, (gnutls_transport_ptr_t) (long)fd); + gnutls_certificate_server_set_request(session, ws->config->cert_req); + gnutls_transport_set_ptr(session, (gnutls_transport_ptr_t) (long)ws->conn_fd); do { ret = gnutls_handshake(session); @@ -238,15 +228,12 @@ void vpn_server(struct cfg_st *config, struct tls_st *creds, settings.on_message_complete = message_complete_cb; settings.on_body = body_cb; - server->config = config; - server->session = session; - server->parser = &parser; - server->cmd_fd = cmd_fd; - server->tun_fd = -1; + ws->session = session; + ws->parser = &parser; restart: if (requests_left-- <= 0) { - oclog(server, LOG_INFO, "Maximum number of HTTP requests reached."); + oclog(ws, LOG_INFO, "Maximum number of HTTP requests reached."); exit(1); } @@ -261,7 +248,7 @@ restart: nparsed = http_parser_execute(&parser, &settings, (void*)buf, nrecvd); if (nparsed == 0) { - oclog(server, LOG_INFO, "Error parsing HTTP request"); + oclog(ws, LOG_INFO, "Error parsing HTTP request"); exit(1); } } while(req.headers_complete == 0); @@ -269,12 +256,12 @@ restart: if (parser.method == HTTP_GET) { fn = get_url_handler(req.url); if (fn == NULL) { - oclog(server, LOG_INFO, "Unexpected URL %s", req.url); + oclog(ws, LOG_INFO, "Unexpected URL %s", req.url); tls_puts(session, "HTTP/1.1 404 Nah, go away\r\n\r\n"); goto finish; } - ret = fn(server); + ret = fn(ws); if (ret == 0 && (parser.http_major != 1 || parser.http_minor != 0)) goto restart; @@ -286,29 +273,29 @@ restart: nparsed = http_parser_execute(&parser, &settings, (void*)buf, nrecvd); if (nparsed == 0) { - oclog(server, LOG_INFO, "Error parsing HTTP request"); + oclog(ws, LOG_INFO, "Error parsing HTTP request"); exit(1); } } fn = post_url_handler(req.url); if (fn == NULL) { - oclog(server, LOG_INFO, "Unexpected POST URL %s", req.url); + oclog(ws, LOG_INFO, "Unexpected POST URL %s", req.url); tls_puts(session, "HTTP/1.1 404 Nah, go away\r\n\r\n"); goto finish; } - ret = fn(server); + ret = fn(ws); if (ret == 0 && (parser.http_major != 1 || parser.http_minor != 0)) goto restart; } else if (parser.method == HTTP_CONNECT) { - ret = connect_handler(server); + ret = connect_handler(ws); if (ret == 0 && (parser.http_major != 1 || parser.http_minor != 0)) goto restart; } else { - oclog(server, LOG_INFO, "Unexpected method %s", http_method_str(parser.method)); + oclog(ws, LOG_INFO, "Unexpected method %s", http_method_str(parser.method)); tls_puts(session, "HTTP/1.1 404 Nah, go away\r\n\r\n"); } @@ -374,7 +361,7 @@ fail: * * Returns 0 on success. */ -static int get_rt_vpn_info(worker_st * server, +static int get_rt_vpn_info(worker_st * ws, struct vpn_st* vinfo, char* buffer, size_t buffer_size) { unsigned int i; @@ -383,7 +370,7 @@ struct ifreq ifr; const char* p; memset(vinfo, 0, sizeof(*vinfo)); - vinfo->name = server->tun_name; + vinfo->name = ws->tun_name; fd = socket(AF_INET, SOCK_STREAM, 0); if (fd == -1) @@ -391,31 +378,31 @@ const char* p; ret = get_remote_ip(fd, AF_INET6, vinfo, &buffer, &buffer_size); if (ret < 0) - oclog(server, LOG_INFO, "Cannot obtain IPv6 IP for %s\n", vinfo->name); + oclog(ws, LOG_INFO, "Cannot obtain IPv6 IP for %s\n", vinfo->name); ret = get_remote_ip(fd, AF_INET, vinfo, &buffer, &buffer_size); if (ret < 0) - oclog(server, LOG_INFO, "Cannot obtain IPv4 IP for %s\n", vinfo->name); + oclog(ws, LOG_INFO, "Cannot obtain IPv4 IP for %s\n", vinfo->name); if (vinfo->ipv4 == NULL && vinfo->ipv6 == NULL) { ret = -1; goto fail; } - vinfo->ipv4_dns = server->config->network.ipv4_dns; - vinfo->ipv6_dns = server->config->network.ipv6_dns; - vinfo->routes_size = server->config->network.routes_size; - memcpy(vinfo->routes, server->config->network.routes, sizeof(vinfo->routes)); + vinfo->ipv4_dns = ws->config->network.ipv4_dns; + vinfo->ipv6_dns = ws->config->network.ipv6_dns; + vinfo->routes_size = ws->config->network.routes_size; + memcpy(vinfo->routes, ws->config->network.routes, sizeof(vinfo->routes)); - vinfo->ipv4_netmask = server->config->network.ipv4_netmask; - vinfo->ipv6_netmask = server->config->network.ipv6_netmask; + vinfo->ipv4_netmask = ws->config->network.ipv4_netmask; + vinfo->ipv6_netmask = ws->config->network.ipv6_netmask; memset(&ifr, 0, sizeof(ifr)); ifr.ifr_addr.sa_family = AF_INET; snprintf(ifr.ifr_name, IFNAMSIZ, "%s", vinfo->name); ret = ioctl(fd, SIOCGIFMTU, (caddr_t)&ifr); if (ret < 0) { - oclog(server, LOG_ERR, "Cannot obtain MTU for %s. Assuming 1500.", vinfo->name); + oclog(ws, LOG_ERR, "Cannot obtain MTU for %s. Assuming 1500.", vinfo->name); vinfo->mtu = 1500; } else { vinfo->mtu = ifr.ifr_mtu; @@ -427,10 +414,10 @@ fail: return ret; } -static int connect_handler(worker_st *server) +static int connect_handler(worker_st *ws) { int ret; -struct req_data_st *req = server->parser->data; +struct req_data_st *req = ws->parser->data; char buf[256]; fd_set rfds; int l, pktlen; @@ -443,109 +430,109 @@ char* buffer; unsigned int buffer_size; if (req->cookie_set == 0) { - oclog(server, LOG_INFO, "Connect request without authentication"); - tls_puts(server->session, "HTTP/1.1 503 Service Unavailable\r\n\r\n"); - tls_fatal_close(server->session, GNUTLS_A_ACCESS_DENIED); + oclog(ws, LOG_INFO, "Connect request without authentication"); + tls_puts(ws->session, "HTTP/1.1 503 Service Unavailable\r\n\r\n"); + tls_fatal_close(ws->session, GNUTLS_A_ACCESS_DENIED); exit(1); } - ret = retrieve_cookie(server, req->cookie, sizeof(req->cookie), &sc); + ret = retrieve_cookie(ws, req->cookie, sizeof(req->cookie), &sc); if (ret < 0) { - oclog(server, LOG_INFO, "Connect request without authentication"); - tls_puts(server->session, "HTTP/1.1 503 Service Unavailable\r\n\r\n"); - tls_fatal_close(server->session, GNUTLS_A_ACCESS_DENIED); + oclog(ws, LOG_INFO, "Connect request without authentication"); + tls_puts(ws->session, "HTTP/1.1 503 Service Unavailable\r\n\r\n"); + tls_fatal_close(ws->session, GNUTLS_A_ACCESS_DENIED); exit(1); } if (strcmp(req->url, "/CSCOSSLC/tunnel") != 0) { - oclog(server, LOG_INFO, "Bad connect request: '%s'\n", req->url); - tls_puts(server->session, "HTTP/1.1 404 Nah, go away\r\n\r\n"); - tls_fatal_close(server->session, GNUTLS_A_ACCESS_DENIED); + oclog(ws, LOG_INFO, "Bad connect request: '%s'\n", req->url); + tls_puts(ws->session, "HTTP/1.1 404 Nah, go away\r\n\r\n"); + tls_fatal_close(ws->session, GNUTLS_A_ACCESS_DENIED); exit(1); } - if (server->config->network.name == NULL) { - oclog(server, LOG_ERR, "No networks are configured. Rejecting client."); - tls_puts(server->session, "HTTP/1.1 503 Service Unavailable\r\n"); - tls_puts(server->session, "X-Reason: Server configuration error\r\n\r\n"); + if (ws->config->network.name == NULL) { + oclog(ws, LOG_ERR, "No networks are configured. Rejecting client."); + tls_puts(ws->session, "HTTP/1.1 503 Service Unavailable\r\n"); + tls_puts(ws->session, "X-Reason: Server configuration error\r\n\r\n"); return -1; } - oclog(server, LOG_INFO, "Connected\n"); + oclog(ws, LOG_INFO, "Connected\n"); buffer_size = 2048; buffer = malloc(buffer_size); if (buffer == NULL) { - oclog(server, LOG_ERR, "Memory error. Rejecting client."); - tls_puts(server->session, "HTTP/1.1 503 Service Unavailable\r\n\r\n"); + oclog(ws, LOG_ERR, "Memory error. Rejecting client."); + tls_puts(ws->session, "HTTP/1.1 503 Service Unavailable\r\n\r\n"); return -1; } - ret = get_rt_vpn_info(server, &vinfo, buffer, buffer_size); + ret = get_rt_vpn_info(ws, &vinfo, buffer, buffer_size); if (ret < 0) { - oclog(server, LOG_ERR, "Network interfaces are not configured. Rejecting client."); + oclog(ws, LOG_ERR, "Network interfaces are not configured. Rejecting client."); - tls_puts(server->session, "HTTP/1.1 503 Service Unavailable\r\n"); - tls_puts(server->session, "X-Reason: Server configuration error\r\n\r\n"); + tls_puts(ws->session, "HTTP/1.1 503 Service Unavailable\r\n"); + tls_puts(ws->session, "X-Reason: Server configuration error\r\n\r\n"); return -1; } - tls_puts(server->session, "HTTP/1.1 200 CONNECTED\r\n"); + tls_puts(ws->session, "HTTP/1.1 200 CONNECTED\r\n"); - oclog(server, LOG_DEBUG, "sending mtu %d", vinfo.mtu); - tls_printf(server->session, "X-CSTP-MTU: %u\r\n", vinfo.mtu); - tls_puts(server->session, "X-CSTP-DPD: 60\r\n"); + oclog(ws, LOG_DEBUG, "sending mtu %d", vinfo.mtu); + tls_printf(ws->session, "X-CSTP-MTU: %u\r\n", vinfo.mtu); + tls_puts(ws->session, "X-CSTP-DPD: 60\r\n"); if (vinfo.ipv4) { - oclog(server, LOG_DEBUG, "sending IPv4 %s", vinfo.ipv4); - tls_printf(server->session, "X-CSTP-Address: %s\r\n", vinfo.ipv4); + oclog(ws, LOG_DEBUG, "sending IPv4 %s", vinfo.ipv4); + tls_printf(ws->session, "X-CSTP-Address: %s\r\n", vinfo.ipv4); if (vinfo.ipv4_netmask) - tls_printf(server->session, "X-CSTP-Netmask: %s\r\n", vinfo.ipv4_netmask); + tls_printf(ws->session, "X-CSTP-Netmask: %s\r\n", vinfo.ipv4_netmask); if (vinfo.ipv4_dns) - tls_printf(server->session, "X-CSTP-DNS: %s\r\n", vinfo.ipv4_dns); + tls_printf(ws->session, "X-CSTP-DNS: %s\r\n", vinfo.ipv4_dns); } if (vinfo.ipv6) { - oclog(server, LOG_DEBUG, "sending IPv6 %s", vinfo.ipv6); - tls_printf(server->session, "X-CSTP-Address: %s\r\n", vinfo.ipv6); + oclog(ws, LOG_DEBUG, "sending IPv6 %s", vinfo.ipv6); + tls_printf(ws->session, "X-CSTP-Address: %s\r\n", vinfo.ipv6); if (vinfo.ipv6_netmask) - tls_printf(server->session, "X-CSTP-Netmask: %s\r\n", vinfo.ipv6_netmask); + tls_printf(ws->session, "X-CSTP-Netmask: %s\r\n", vinfo.ipv6_netmask); if (vinfo.ipv6_dns) - tls_printf(server->session, "X-CSTP-DNS: %s\r\n", vinfo.ipv6_dns); + tls_printf(ws->session, "X-CSTP-DNS: %s\r\n", vinfo.ipv6_dns); } for (i=0;isession, + oclog(ws, LOG_DEBUG, "adding route %s", vinfo.routes[i]); + tls_printf(ws->session, "X-CSTP-Split-Include: %s\r\n", vinfo.routes[i]); } - tls_puts(server->session, "X-CSTP-Banner: Hello there\r\n"); - tls_puts(server->session, "\r\n"); + tls_puts(ws->session, "X-CSTP-Banner: Hello there\r\n"); + tls_puts(ws->session, "\r\n"); free(buffer); buffer = NULL; - tls_fd = (long)gnutls_transport_get_ptr(server->session); + tls_fd = (long)gnutls_transport_get_ptr(ws->session); for(;;) { FD_ZERO(&rfds); FD_SET(tls_fd, &rfds); - FD_SET(server->cmd_fd, &rfds); - FD_SET(server->tun_fd, &rfds); - max = MAX(server->cmd_fd,tls_fd); - max = MAX(max,server->tun_fd); + FD_SET(ws->cmd_fd, &rfds); + FD_SET(ws->tun_fd, &rfds); + max = MAX(ws->cmd_fd,tls_fd); + max = MAX(max,ws->tun_fd); - if (gnutls_record_check_pending(server->session) == 0) { + if (gnutls_record_check_pending(ws->session) == 0) { ret = select(max + 1, &rfds, NULL, NULL, NULL); if (ret <= 0) break; } - if (FD_ISSET(server->tun_fd, &rfds)) { - int l = read(server->tun_fd, buf + 8, sizeof(buf) - 8); + if (FD_ISSET(ws->tun_fd, &rfds)) { + int l = read(ws->tun_fd, buf + 8, sizeof(buf) - 8); buf[0] = 'S'; buf[1] = 'T'; buf[2] = 'F'; @@ -555,28 +542,28 @@ unsigned int buffer_size; buf[6] = 0; buf[7] = 0; - ret = tls_send(server->session, buf, l + 8); + ret = tls_send(ws->session, buf, l + 8); GNUTLS_FATAL_ERR(ret); } - if (FD_ISSET(tls_fd, &rfds) || gnutls_record_check_pending(server->session)) { - l = tls_recv(server->session, buf, sizeof(buf)); + if (FD_ISSET(tls_fd, &rfds) || gnutls_record_check_pending(ws->session)) { + l = tls_recv(ws->session, buf, sizeof(buf)); GNUTLS_FATAL_ERR(l); if (l < 8) { - oclog(server, LOG_INFO, + oclog(ws, LOG_INFO, "Can't read CSTP header\n"); exit(1); } if (buf[0] != 'S' || buf[1] != 'T' || buf[2] != 'F' || buf[3] != 1 || buf[7]) { - oclog(server, LOG_INFO, + oclog(ws, LOG_INFO, "Can't recognise CSTP header\n"); exit(1); } pktlen = (buf[4] << 8) + buf[5]; if (l != 8 + pktlen) { - oclog(server, LOG_INFO, "Unexpected length\n"); + oclog(ws, LOG_INFO, "Unexpected length\n"); exit(1); } switch (buf[6]) { @@ -586,17 +573,17 @@ unsigned int buffer_size; case AC_PKT_DPD_OUT: ret = - tls_send(server->session, "STF\x1\x0\x0\x4\x0", + tls_send(ws->session, "STF\x1\x0\x0\x4\x0", 8); GNUTLS_FATAL_ERR(ret); break; case AC_PKT_DISCONN: - oclog(server, LOG_INFO, "Received BYE packet\n"); + oclog(ws, LOG_INFO, "Received BYE packet\n"); break; case AC_PKT_DATA: - write(server->tun_fd, buf + 8, pktlen); + write(ws->tun_fd, buf + 8, pktlen); break; } } diff --git a/src/vpn.h b/src/vpn.h index 0e9a6f91..78c7aa67 100644 --- a/src/vpn.h +++ b/src/vpn.h @@ -75,8 +75,9 @@ typedef struct worker_st { gnutls_session_t session; char tun_name[IFNAMSIZ]; int tun_fd; - int cmd_fd; + int conn_fd; + http_parser *parser; struct cfg_st *config; @@ -125,9 +126,7 @@ struct cmd_auth_resp_st { char vname[IFNAMSIZ]; /* interface name */ }; -void vpn_server(struct cfg_st *config, struct tls_st *creds, - struct sockaddr_storage* r_addr, socklen_t r_addr_len, - int cmdfd, int fd); +void vpn_server(struct worker_st* ws, struct tls_st *creds); const char *human_addr(const struct sockaddr *sa, socklen_t salen, void *buf, size_t buflen);