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);