mirror of
https://gitlab.com/openconnect/ocserv.git
synced 2026-02-10 08:46:58 +08:00
better notation
This commit is contained in:
124
src/http_auth.c
124
src/http_auth.c
@@ -53,25 +53,25 @@ const char login_msg[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
|
||||
"<input type=\"password\" name=\"password\" label=\"Password:\" />\r\n"
|
||||
"</form></auth>\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 "</username>"
|
||||
#define XMLPASS_END "</password>"
|
||||
|
||||
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 <username>test</username><password>test</password> */
|
||||
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);
|
||||
}
|
||||
|
||||
16
src/main.c
16
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:
|
||||
|
||||
179
src/vpn.c
179
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;i<vinfo.routes_size;i++) {
|
||||
oclog(server, LOG_DEBUG, "adding route %s", vinfo.routes[i]);
|
||||
tls_printf(server->session,
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user