mirror of
https://gitlab.com/openconnect/ocserv.git
synced 2026-10-12 01:26:48 +08:00
several updates and fixes in auth
This commit is contained in:
+3
-2
@@ -5,9 +5,10 @@ EXTRA_DIST = ocserv.1
|
||||
|
||||
bin_PROGRAMS = ocserv
|
||||
|
||||
ocserv_SOURCES = main.c worker-vpn.c worker-auth.c tlslib.c cookies.c http-parser/http_parser.c \
|
||||
ocserv_SOURCES = main.c main-auth.c worker-vpn.c worker-auth.c tlslib.c \
|
||||
cookies.c http-parser/http_parser.c \
|
||||
vpn.h cookies.h tlslib.h http-parser/http_parser.h log.c tun.c tun.h \
|
||||
config.c worker-auth.h
|
||||
config.c worker-auth.h
|
||||
|
||||
ocserv_SOURCES += ocserv-args.def ocserv-args.c ocserv-args.h
|
||||
|
||||
|
||||
+3
-3
@@ -85,9 +85,8 @@ static void parse_cfg_file(const char* file, struct cfg_st *config)
|
||||
{
|
||||
tOptionValue const * pov;
|
||||
const tOptionValue* val;
|
||||
char tmpstr[256];
|
||||
char** auth;
|
||||
unsigned auth_size;
|
||||
char** auth = NULL;
|
||||
unsigned auth_size = 0;
|
||||
unsigned j;
|
||||
|
||||
pov = configFileLoad(file);
|
||||
@@ -127,6 +126,7 @@ unsigned j;
|
||||
READ_STRING("chroot-dir", config->chroot_dir, 0);
|
||||
|
||||
READ_NUMERIC("cookie-validity", config->cookie_validity, 1);
|
||||
READ_NUMERIC("auth-timeout", config->auth_timeout, 0);
|
||||
READ_STRING("cookie-db", config->db_file, 1);
|
||||
|
||||
val = optionGetValue(pov, "run-as-user"); \
|
||||
|
||||
+7
-7
@@ -38,7 +38,7 @@
|
||||
|
||||
/* All the functions return zero on success and a negative value on error */
|
||||
|
||||
int store_cookie(worker_st *server, const void* cookie, unsigned cookie_size,
|
||||
int store_cookie(const struct cfg_st *config, const void* cookie, unsigned cookie_size,
|
||||
const struct stored_cookie_st* sc)
|
||||
{
|
||||
GDBM_FILE dbf;
|
||||
@@ -46,9 +46,9 @@ datum key;
|
||||
datum data;
|
||||
int ret;
|
||||
|
||||
dbf = gdbm_open((char*)server->config->db_file, 0, GDBM_WRCREAT, S_IRUSR|S_IWUSR, NULL);
|
||||
dbf = gdbm_open((char*)config->db_file, 0, GDBM_WRCREAT, S_IRUSR|S_IWUSR, NULL);
|
||||
if (dbf == NULL) {
|
||||
oclog(server, LOG_ERR, "Cannot open cookie database: %s", server->config->db_file);
|
||||
syslog(LOG_ERR, "Cannot open cookie database: %s", config->db_file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ finish:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int retrieve_cookie(worker_st *server, const void* cookie, unsigned cookie_size,
|
||||
int retrieve_cookie(const struct cfg_st *config, const void* cookie, unsigned cookie_size,
|
||||
struct stored_cookie_st* sc)
|
||||
{
|
||||
GDBM_FILE dbf;
|
||||
@@ -78,9 +78,9 @@ datum key;
|
||||
datum data;
|
||||
int ret;
|
||||
|
||||
dbf = gdbm_open((char*)server->config->db_file, 0, GDBM_READER, 0, NULL);
|
||||
dbf = gdbm_open((char*)config->db_file, 0, GDBM_READER, 0, NULL);
|
||||
if (dbf == NULL) {
|
||||
oclog(server, LOG_ERR, "Cannot open cookie database: %s", server->config->db_file);
|
||||
syslog(LOG_ERR, "Cannot open cookie database: %s", config->db_file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ finish:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void expire_cookies(struct cfg_st *cfg)
|
||||
void expire_cookies(const struct cfg_st *cfg)
|
||||
{
|
||||
GDBM_FILE dbf;
|
||||
datum key;
|
||||
|
||||
+3
-4
@@ -5,15 +5,14 @@
|
||||
|
||||
struct __attribute__ ((__packed__)) stored_cookie_st {
|
||||
char username[MAX_USERNAME_SIZE];
|
||||
char tun_name[IFNAMSIZ];
|
||||
time_t expiration;
|
||||
};
|
||||
|
||||
int store_cookie(worker_st *server, const void* cookie, unsigned cookie_size,
|
||||
int store_cookie(const struct cfg_st *, const void* cookie, unsigned cookie_size,
|
||||
const struct stored_cookie_st* sc);
|
||||
void expire_cookies(struct cfg_st *cfg);
|
||||
void expire_cookies(const struct cfg_st *cfg);
|
||||
|
||||
int retrieve_cookie(worker_st *server, const void* cookie, unsigned cookie_size,
|
||||
int retrieve_cookie(const struct cfg_st *, const void* cookie, unsigned cookie_size,
|
||||
struct stored_cookie_st* sc);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <vpn.h>
|
||||
@@ -63,7 +64,7 @@ const char *human_addr(const struct sockaddr *sa, socklen_t salen,
|
||||
return save_buf;
|
||||
}
|
||||
|
||||
int __attribute__ ((format(printf, 3, 4)))
|
||||
void __attribute__ ((format(printf, 3, 4)))
|
||||
oclog(const worker_st * ws, int priority, const char *fmt, ...)
|
||||
{
|
||||
char buf[1024];
|
||||
@@ -83,5 +84,7 @@ int __attribute__ ((format(printf, 3, 4)))
|
||||
if (ip)
|
||||
syslog(priority, "%s %s", ip, buf);
|
||||
else
|
||||
syslog(priority, "[unknown] %s", ip, buf);
|
||||
syslog(priority, "[unknown] %s", buf);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
+261
@@ -0,0 +1,261 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Nikos Mavrogiannopoulos
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/wait.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <gnutls/gnutls.h>
|
||||
#include <gnutls/crypto.h>
|
||||
#include <tlslib.h>
|
||||
#include <worker-auth.h>
|
||||
|
||||
#include <vpn.h>
|
||||
#include <cookies.h>
|
||||
#include <tun.h>
|
||||
#include <list.h>
|
||||
|
||||
static int send_auth_reply(cmd_auth_reply_t r, struct proc_list_st* proc, struct lease_st* lease)
|
||||
{
|
||||
struct iovec iov[4];
|
||||
uint8_t cmd[2];
|
||||
struct msghdr hdr;
|
||||
union {
|
||||
struct cmsghdr cm;
|
||||
char control[CMSG_SPACE(sizeof(int))];
|
||||
} control_un;
|
||||
struct cmsghdr *cmptr;
|
||||
|
||||
memset(&control_un, 0, sizeof(control_un));
|
||||
memset(&hdr, 0, sizeof(hdr));
|
||||
|
||||
cmd[0] = AUTH_REP;
|
||||
cmd[1] = r;
|
||||
|
||||
iov[0].iov_base = cmd;
|
||||
iov[0].iov_len = 2;
|
||||
hdr.msg_iovlen++;
|
||||
|
||||
hdr.msg_iov = iov;
|
||||
|
||||
if (r == REP_AUTH_OK && lease != NULL) {
|
||||
iov[1].iov_base = proc->cookie;
|
||||
iov[1].iov_len = sizeof(proc->cookie);
|
||||
hdr.msg_iovlen++;
|
||||
|
||||
iov[2].iov_base = lease->name;
|
||||
iov[2].iov_len = sizeof(lease->name);
|
||||
hdr.msg_iovlen++;
|
||||
|
||||
iov[3].iov_base = proc->username;
|
||||
iov[3].iov_len = MAX_USERNAME_SIZE;
|
||||
hdr.msg_iovlen++;
|
||||
|
||||
/* Send the tun fd */
|
||||
hdr.msg_control = control_un.control;
|
||||
hdr.msg_controllen = sizeof(control_un.control);
|
||||
|
||||
cmptr = CMSG_FIRSTHDR(&hdr);
|
||||
cmptr->cmsg_len = CMSG_LEN(sizeof(int));
|
||||
cmptr->cmsg_level = SOL_SOCKET;
|
||||
cmptr->cmsg_type = SCM_RIGHTS;
|
||||
memcpy(CMSG_DATA(cmptr), &lease->fd, sizeof(int));
|
||||
}
|
||||
|
||||
return(sendmsg(proc->fd, &hdr, 0));
|
||||
}
|
||||
|
||||
static int handle_auth_cookie_req(const struct cfg_st *config, struct tun_st *tun,
|
||||
const struct cmd_auth_cookie_req_st * req, struct lease_st **lease,
|
||||
char username[MAX_USERNAME_SIZE])
|
||||
{
|
||||
int ret;
|
||||
struct stored_cookie_st sc;
|
||||
|
||||
ret = retrieve_cookie(config, req->cookie, sizeof(req->cookie), &sc);
|
||||
if (ret < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = 0; /* cookie was found and valid */
|
||||
|
||||
memcpy(username, sc.username, MAX_USERNAME_SIZE);
|
||||
|
||||
ret = open_tun(config, tun, lease);
|
||||
if (ret < 0)
|
||||
ret = -1; /* sorry */
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static
|
||||
int generate_and_store_cookie(const struct cfg_st* config, uint8_t *cookie, unsigned cookie_size)
|
||||
{
|
||||
int ret;
|
||||
struct stored_cookie_st sc;
|
||||
|
||||
ret = gnutls_rnd(GNUTLS_RND_RANDOM, cookie, cookie_size);
|
||||
if (ret < 0)
|
||||
return -2;
|
||||
|
||||
memset(&sc, 0, sizeof(sc));
|
||||
sc.expiration = time(0) + config->cookie_validity;
|
||||
|
||||
ret = store_cookie(config, cookie, cookie_size, &sc);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int handle_auth_req(const struct cfg_st *config, struct tun_st *tun,
|
||||
const struct cmd_auth_req_st * req, struct lease_st **lease,
|
||||
char username[MAX_USERNAME_SIZE])
|
||||
{
|
||||
int ret;
|
||||
#warning fix auth
|
||||
if (strcmp(req->user, "test") == 0 && strcmp(req->pass, "test") == 0)
|
||||
ret = 0;
|
||||
else
|
||||
ret = -1;
|
||||
|
||||
memcpy(username, req->user, MAX_USERNAME_SIZE);
|
||||
|
||||
if (ret == 0) { /* open tun */
|
||||
ret = open_tun(config, tun, lease);
|
||||
if (ret < 0)
|
||||
ret = -1; /* sorry */
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int handle_commands(const struct cfg_st *config, struct tun_st *tun,
|
||||
struct proc_list_st* proc)
|
||||
{
|
||||
struct iovec iov[2];
|
||||
char buf[128];
|
||||
uint8_t cmd;
|
||||
struct msghdr hdr;
|
||||
struct lease_st *lease;
|
||||
union {
|
||||
struct cmd_auth_req_st auth;
|
||||
struct cmd_auth_cookie_req_st cauth;
|
||||
} cmd_data;
|
||||
int ret, cmd_data_len;
|
||||
const char* peer_ip;
|
||||
|
||||
peer_ip = human_addr((void*)&proc->remote_addr, proc->remote_addr_len, buf, sizeof(buf));
|
||||
|
||||
memset(&cmd_data, 0, sizeof(cmd_data));
|
||||
|
||||
iov[0].iov_base = &cmd;
|
||||
iov[0].iov_len = 1;
|
||||
|
||||
iov[1].iov_base = &cmd_data;
|
||||
iov[1].iov_len = sizeof(cmd_data);
|
||||
|
||||
memset(&hdr, 0, sizeof(hdr));
|
||||
hdr.msg_iov = iov;
|
||||
hdr.msg_iovlen = 2;
|
||||
|
||||
ret = recvmsg( proc->fd, &hdr, 0);
|
||||
if (ret == -1) {
|
||||
syslog(LOG_ERR, "Cannot obtain data from command socket (pid: %d, peer: %s).", proc->pid, peer_ip);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
cmd_data_len = ret - 1;
|
||||
|
||||
switch(cmd) {
|
||||
case AUTH_REQ:
|
||||
case AUTH_COOKIE_REQ:
|
||||
|
||||
if (cmd == AUTH_REQ) {
|
||||
if (cmd_data_len != sizeof(cmd_data.auth)) {
|
||||
syslog(LOG_ERR, "Error in received message length (pid: %d, peer: %s).", proc->pid, peer_ip);
|
||||
return -2;
|
||||
}
|
||||
|
||||
ret = handle_auth_req(config, tun, &cmd_data.auth, &lease, proc->username);
|
||||
} else {
|
||||
if (cmd_data_len != sizeof(cmd_data.cauth)) {
|
||||
syslog(LOG_ERR, "Error in received message length (pid: %d, peer: %s).", proc->pid, peer_ip);
|
||||
return -2;
|
||||
}
|
||||
|
||||
ret = handle_auth_cookie_req(config, tun, &cmd_data.cauth, &lease, proc->username);
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
if (cmd == AUTH_REQ) {
|
||||
/* generate and store cookie */
|
||||
ret = generate_and_store_cookie(config,
|
||||
proc->cookie,
|
||||
COOKIE_SIZE);
|
||||
if (ret < 0)
|
||||
return -2;
|
||||
} else { /* copy cookie */
|
||||
memcpy(proc->cookie, cmd_data.cauth.cookie,
|
||||
COOKIE_SIZE);
|
||||
}
|
||||
|
||||
syslog(LOG_INFO, "User '%s' authenticated", proc->username);
|
||||
ret = send_auth_reply(REP_AUTH_OK, proc, lease);
|
||||
if (ret < 0) {
|
||||
syslog(LOG_ERR, "Could not send reply cmd (pid: %d, peer: %s).", proc->pid, peer_ip);
|
||||
return -2;
|
||||
}
|
||||
|
||||
proc->lease = lease;
|
||||
proc->lease->in_use = 1;
|
||||
if (lease->fd >= 0)
|
||||
close(lease->fd);
|
||||
lease->fd = -1;
|
||||
} else {
|
||||
syslog(LOG_INFO, "Failed authentication attempt for user '%s'", proc->username);
|
||||
ret = send_auth_reply( REP_AUTH_FAILED, proc, NULL);
|
||||
if (ret < 0) {
|
||||
syslog(LOG_ERR, "Could not send reply cmd (pid: %d, peer: %s).", proc->pid, peer_ip);
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
syslog(LOG_ERR, "Unknown CMD 0x%x (pid: %d, peer: %s).", (unsigned)cmd, proc->pid, peer_ip);
|
||||
return -2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
+7
-176
@@ -49,20 +49,6 @@ struct listen_list_st {
|
||||
int fd;
|
||||
};
|
||||
|
||||
struct proc_list_st {
|
||||
struct list_head list;
|
||||
int fd;
|
||||
pid_t pid;
|
||||
struct sockaddr_storage remote_addr; /* peer address */
|
||||
socklen_t remote_addr_len;
|
||||
|
||||
/* the tun lease this process has */
|
||||
struct lease_st* lease;
|
||||
};
|
||||
|
||||
static int handle_commands(const struct cfg_st *config, struct tun_st *tun,
|
||||
struct proc_list_st* proc);
|
||||
|
||||
static void tls_log_func(int level, const char *str)
|
||||
{
|
||||
syslog(LOG_DEBUG, "Debug[<%d>]: %s", level, str);
|
||||
@@ -209,8 +195,7 @@ worker_st * ws;
|
||||
static int verify_certificate_cb(gnutls_session_t session)
|
||||
{
|
||||
unsigned int status;
|
||||
int ret, type;
|
||||
gnutls_datum_t out;
|
||||
int ret;
|
||||
worker_st * ws;
|
||||
|
||||
ws = gnutls_session_get_ptr(session);
|
||||
@@ -310,7 +295,7 @@ static void clear_proc_list(struct proc_list_st* clist)
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
int fd, pid, e;
|
||||
int fd, pid;
|
||||
struct tls_st creds;
|
||||
struct listen_list_st llist;
|
||||
struct proc_list_st clist;
|
||||
@@ -326,9 +311,6 @@ int main(int argc, char** argv)
|
||||
struct worker_st ws;
|
||||
struct cfg_st config;
|
||||
|
||||
struct sockaddr_storage tmp_addr;
|
||||
socklen_t tmp_addr_len;
|
||||
|
||||
INIT_LIST_HEAD(&clist.list);
|
||||
tun_st_init(&tun);
|
||||
|
||||
@@ -417,7 +399,7 @@ int main(int argc, char** argv)
|
||||
daemon(0, 0);
|
||||
|
||||
alarm(config.cookie_validity + 300);
|
||||
openlog("ocserv", LOG_PID, LOG_LOCAL0);
|
||||
openlog("ocserv", LOG_PID|LOG_NDELAY, LOG_LOCAL0);
|
||||
syslog_open = 1;
|
||||
|
||||
for (;;) {
|
||||
@@ -500,15 +482,14 @@ int main(int argc, char** argv)
|
||||
} else if (pid == -1) {
|
||||
fork_failed:
|
||||
close(cmd_fd[0]);
|
||||
free(ctmp);
|
||||
} else { /* parent */
|
||||
ctmp = calloc(1, sizeof(struct proc_list_st));
|
||||
if (ctmp == NULL) {
|
||||
kill(pid, SIGTERM);
|
||||
goto fork_failed;
|
||||
}
|
||||
memcpy(&ctmp->remote_addr, &tmp_addr, tmp_addr_len);
|
||||
ctmp->remote_addr_len = tmp_addr_len;
|
||||
memcpy(&ctmp->remote_addr, &ws.remote_addr, ws.remote_addr_len);
|
||||
ctmp->remote_addr_len = ws.remote_addr_len;
|
||||
|
||||
ctmp->pid = pid;
|
||||
ctmp->fd = cmd_fd[0];
|
||||
@@ -544,17 +525,8 @@ fork_failed:
|
||||
need_to_expire_cookies = 0;
|
||||
pid = fork();
|
||||
if (pid == 0) { /* child */
|
||||
/* Drop privileges after this point */
|
||||
drop_privileges(&config);
|
||||
|
||||
list_for_each(pos, &llist.list) {
|
||||
ltmp =
|
||||
list_entry(pos,
|
||||
struct
|
||||
listen_list_st,
|
||||
list);
|
||||
close(ltmp->fd);
|
||||
}
|
||||
clear_listen_list(&llist);
|
||||
clear_proc_list(&clist);
|
||||
|
||||
expire_cookies(&config);
|
||||
exit(0);
|
||||
@@ -566,144 +538,3 @@ fork_failed:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int send_auth_reply(int fd, cmd_auth_reply_t r, struct lease_st* lease)
|
||||
{
|
||||
struct iovec iov[2];
|
||||
uint8_t cmd[2];
|
||||
struct msghdr hdr;
|
||||
union {
|
||||
struct cmd_auth_req_st auth;
|
||||
} cmd_data;
|
||||
int ret;
|
||||
union {
|
||||
struct cmsghdr cm;
|
||||
char control[CMSG_SPACE(sizeof(int))];
|
||||
} control_un;
|
||||
struct cmsghdr *cmptr;
|
||||
|
||||
memset(&control_un, 0, sizeof(control_un));
|
||||
memset(&hdr, 0, sizeof(hdr));
|
||||
|
||||
cmd[0] = AUTH_REP;
|
||||
cmd[1] = r;
|
||||
|
||||
iov[0].iov_base = cmd;
|
||||
iov[0].iov_len = 2;
|
||||
hdr.msg_iovlen++;
|
||||
|
||||
hdr.msg_iov = iov;
|
||||
|
||||
if (r == REP_AUTH_OK && lease != NULL) {
|
||||
iov[1].iov_base = lease->name;
|
||||
iov[1].iov_len = sizeof(lease->name);
|
||||
hdr.msg_iovlen++;
|
||||
|
||||
/* Send the tun fd */
|
||||
hdr.msg_control = control_un.control;
|
||||
hdr.msg_controllen = sizeof(control_un.control);
|
||||
|
||||
cmptr = CMSG_FIRSTHDR(&hdr);
|
||||
cmptr->cmsg_len = CMSG_LEN(sizeof(int));
|
||||
cmptr->cmsg_level = SOL_SOCKET;
|
||||
cmptr->cmsg_type = SCM_RIGHTS;
|
||||
*((int *) CMSG_DATA(cmptr)) = lease->fd;
|
||||
}
|
||||
|
||||
return(sendmsg(fd, &hdr, 0));
|
||||
}
|
||||
|
||||
static int handle_auth_req(const struct cfg_st *config, struct tun_st *tun,
|
||||
const struct cmd_auth_req_st * req, struct lease_st **lease)
|
||||
{
|
||||
int ret;
|
||||
#warning fix auth
|
||||
if (strcmp(req->user, "test") == 0 && strcmp(req->pass, "test") == 0)
|
||||
ret = 0;
|
||||
else
|
||||
ret = -1;
|
||||
|
||||
if (ret == 0) { /* open tun */
|
||||
ret = open_tun(config, tun, lease);
|
||||
if (ret < 0)
|
||||
ret = -1; /* sorry */
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int handle_commands(const struct cfg_st *config, struct tun_st *tun,
|
||||
struct proc_list_st* proc)
|
||||
{
|
||||
struct iovec iov[2];
|
||||
char buf[128];
|
||||
uint8_t cmd;
|
||||
struct msghdr hdr;
|
||||
struct lease_st *lease;
|
||||
union {
|
||||
struct cmd_auth_req_st auth;
|
||||
} cmd_data;
|
||||
int ret, cmd_data_len;
|
||||
const char* peer_ip;
|
||||
|
||||
peer_ip = human_addr((void*)&proc->remote_addr, proc->remote_addr_len, buf, sizeof(buf));
|
||||
|
||||
memset(&cmd_data, 0, sizeof(cmd_data));
|
||||
|
||||
iov[0].iov_base = &cmd;
|
||||
iov[0].iov_len = 1;
|
||||
|
||||
iov[1].iov_base = &cmd_data;
|
||||
iov[1].iov_len = sizeof(cmd_data);
|
||||
|
||||
memset(&hdr, 0, sizeof(hdr));
|
||||
hdr.msg_iov = iov;
|
||||
hdr.msg_iovlen = 2;
|
||||
|
||||
ret = recvmsg( proc->fd, &hdr, 0);
|
||||
if (ret == -1) {
|
||||
syslog(LOG_ERR, "Cannot obtain data from command socket (pid: %d, peer: %s).", proc->pid, peer_ip);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
cmd_data_len = ret - 1;
|
||||
|
||||
switch(cmd) {
|
||||
case AUTH_REQ:
|
||||
if (cmd_data_len != sizeof(cmd_data.auth)) {
|
||||
syslog(LOG_ERR, "Error in received message length (pid: %d, peer: %s).", proc->pid, peer_ip);
|
||||
return -2;
|
||||
}
|
||||
|
||||
ret = handle_auth_req(config, tun, &cmd_data.auth, &lease);
|
||||
if (ret == 0) {
|
||||
ret = send_auth_reply(proc->fd, REP_AUTH_OK, lease);
|
||||
if (ret < 0) {
|
||||
syslog(LOG_ERR, "Could not send reply cmd (pid: %d, peer: %s).", proc->pid, peer_ip);
|
||||
return -2;
|
||||
}
|
||||
|
||||
proc->lease = lease;
|
||||
proc->lease->in_use = 1;
|
||||
if (lease->fd >= 0)
|
||||
close(lease->fd);
|
||||
lease->fd = -1;
|
||||
} else {
|
||||
ret = send_auth_reply(proc->fd, REP_AUTH_FAILED, NULL);
|
||||
if (ret < 0) {
|
||||
syslog(LOG_ERR, "Could not send reply cmd (pid: %d, peer: %s).", proc->pid, peer_ip);
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
syslog(LOG_ERR, "Unknown CMD 0x%x (pid: %d, peer: %s).", (unsigned)cmd, proc->pid, peer_ip);
|
||||
return -2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
*
|
||||
* DO NOT EDIT THIS FILE (ocserv-args.c)
|
||||
*
|
||||
* It has been AutoGen-ed January 30, 2013 at 05:50:16 PM by AutoGen 5.16
|
||||
* It has been AutoGen-ed January 30, 2013 at 08:53:35 PM by AutoGen 5.16
|
||||
* From the definitions ocserv-args.def
|
||||
* and the template file options
|
||||
*
|
||||
|
||||
@@ -85,6 +85,10 @@ tls-priorities = "PERFORMANCE:%SERVER_PRECEDENCE"
|
||||
# The default server directory
|
||||
#chroot-dir = /path/to/chroot
|
||||
|
||||
# The time (in seconds) that a client is allowed to stay connected prior
|
||||
# to authentication
|
||||
auth-timeout = 40
|
||||
|
||||
# Cookie validity time (in seconds)
|
||||
# Once a client is authenticated he's provided a cookie with
|
||||
# which he can reconnect. This option sets the maximum lifetime
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
*
|
||||
* DO NOT EDIT THIS FILE (ocserv-args.h)
|
||||
*
|
||||
* It has been AutoGen-ed January 30, 2013 at 05:50:16 PM by AutoGen 5.16
|
||||
* It has been AutoGen-ed January 30, 2013 at 08:53:35 PM by AutoGen 5.16
|
||||
* From the definitions ocserv-args.def
|
||||
* and the template file options
|
||||
*
|
||||
|
||||
@@ -6,6 +6,10 @@ auth = "pam"
|
||||
# Use listen-host to limit to specific IPs or to the IPs of a provided hostname.
|
||||
# listen-host = [IP|HOSTNAME]
|
||||
|
||||
# The time (in seconds) that a client is allowed to stay connected prior
|
||||
# to authentication
|
||||
auth-timeout = 40
|
||||
|
||||
# TCP port number
|
||||
tcp-port = 3333
|
||||
|
||||
|
||||
@@ -112,6 +112,9 @@ static int get_avail_network_addresses(const struct cfg_st *config, const struct
|
||||
memcpy(&lease->rip4, t4, lease->rip4_len);
|
||||
|
||||
} else if (last4 != NULL) {
|
||||
t4 = (void*)&tmp;
|
||||
t4->sin_family = AF_INET;
|
||||
|
||||
ret =
|
||||
inet_pton(AF_INET, config->network.ipv4_netmask, SA_IN_P(&mask));
|
||||
|
||||
@@ -181,6 +184,9 @@ static int get_avail_network_addresses(const struct cfg_st *config, const struct
|
||||
lease->rip6_len = sizeof(struct sockaddr_in6);
|
||||
memcpy(&lease->rip6, t6, lease->rip6_len);
|
||||
} else if (last6 != NULL) {
|
||||
t6 = (void*)&tmp;
|
||||
t6->sin6_family = AF_INET6;
|
||||
|
||||
ret =
|
||||
inet_pton(AF_INET6, config->network.ipv6_netmask, SA_IN6_P(&mask));
|
||||
|
||||
@@ -227,7 +233,6 @@ static int set_network_info( const struct lease_st *lease)
|
||||
{
|
||||
struct ifreq ifr;
|
||||
int fd, ret;
|
||||
void* p;
|
||||
|
||||
fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (fd == -1)
|
||||
@@ -296,7 +301,6 @@ static int set_network_info( const struct lease_st *lease)
|
||||
syslog(LOG_ERR, "%s: Could not bring up interface.\n", lease->name);
|
||||
}
|
||||
|
||||
fail:
|
||||
close(fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -56,6 +56,7 @@ struct cfg_st {
|
||||
const char *priorities;
|
||||
const char *chroot_dir; /* where the xml files are served from */
|
||||
time_t cookie_validity; /* in seconds */
|
||||
unsigned auth_timeout; /* timeout of HTTP auth */
|
||||
const char *db_file;
|
||||
unsigned foreground;
|
||||
|
||||
@@ -68,6 +69,10 @@ struct cfg_st {
|
||||
|
||||
#include <tun.h>
|
||||
|
||||
#define MAX_USERNAME_SIZE 64
|
||||
#define MAX_PASSWORD_SIZE 64
|
||||
#define COOKIE_SIZE 32
|
||||
|
||||
struct tls_st {
|
||||
gnutls_certificate_credentials_t xcred;
|
||||
gnutls_priority_t cprio;
|
||||
@@ -75,8 +80,6 @@ struct tls_st {
|
||||
|
||||
typedef struct worker_st {
|
||||
gnutls_session_t session;
|
||||
char tun_name[IFNAMSIZ];
|
||||
int tun_fd;
|
||||
int cmd_fd;
|
||||
int conn_fd;
|
||||
|
||||
@@ -85,11 +88,15 @@ typedef struct worker_st {
|
||||
|
||||
struct sockaddr_storage remote_addr; /* peer's address */
|
||||
socklen_t remote_addr_len;
|
||||
|
||||
/* the following are set only if authentication is complete */
|
||||
char tun_name[IFNAMSIZ];
|
||||
char username[MAX_USERNAME_SIZE];
|
||||
uint8_t cookie[COOKIE_SIZE];
|
||||
unsigned auth_ok;
|
||||
int tun_fd;
|
||||
} worker_st;
|
||||
|
||||
#define MAX_USERNAME_SIZE 64
|
||||
#define MAX_PASSWORD_SIZE 64
|
||||
#define COOKIE_SIZE 32
|
||||
|
||||
enum {
|
||||
HEADER_COOKIE = 1,
|
||||
@@ -110,11 +117,27 @@ 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);
|
||||
|
||||
int __attribute__ ((format(printf, 3, 4)))
|
||||
void __attribute__ ((format(printf, 3, 4)))
|
||||
oclog(const worker_st * server, int priority, const char *fmt, ...);
|
||||
|
||||
int cmd_parser (int argc, char **argv, struct cfg_st* config);
|
||||
|
||||
struct proc_list_st {
|
||||
struct list_head list;
|
||||
int fd;
|
||||
pid_t pid;
|
||||
struct sockaddr_storage remote_addr; /* peer address */
|
||||
socklen_t remote_addr_len;
|
||||
char username[MAX_USERNAME_SIZE]; /* the owner */
|
||||
uint8_t cookie[COOKIE_SIZE]; /* the cookie associate with the session */
|
||||
|
||||
/* the tun lease this process has */
|
||||
struct lease_st* lease;
|
||||
};
|
||||
|
||||
int handle_commands(const struct cfg_st *config, struct tun_st *tun,
|
||||
struct proc_list_st* proc);
|
||||
|
||||
/* Helper casts */
|
||||
#define SA_IN_P(p) (&((struct sockaddr_in *)(p))->sin_addr)
|
||||
#define SA_IN_U8_P(p) ((uint8_t*)(&((struct sockaddr_in *)(p))->sin_addr))
|
||||
|
||||
+109
-94
@@ -55,12 +55,10 @@ const char login_msg[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
|
||||
|
||||
int get_auth_handler(worker_st *ws)
|
||||
{
|
||||
int ret;
|
||||
|
||||
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_printf(ws->session, "Content-Length: %u\r\n", (unsigned int)sizeof(login_msg)-1);
|
||||
tls_puts(ws->session, "X-Transcend-Version: 1\r\n");
|
||||
tls_puts(ws->session, "\r\n");
|
||||
|
||||
@@ -109,12 +107,6 @@ static int send_auth_req(int fd, const struct cmd_auth_req_st* r)
|
||||
struct iovec iov[2];
|
||||
uint8_t cmd;
|
||||
struct msghdr hdr;
|
||||
int ret;
|
||||
union {
|
||||
struct cmsghdr cm;
|
||||
char control[CMSG_SPACE(sizeof(int))];
|
||||
} control_un;
|
||||
struct cmsghdr *cmptr;
|
||||
|
||||
memset(&hdr, 0, sizeof(hdr));
|
||||
|
||||
@@ -132,11 +124,33 @@ static int send_auth_req(int fd, const struct cmd_auth_req_st* r)
|
||||
return(sendmsg(fd, &hdr, 0));
|
||||
}
|
||||
|
||||
static int send_auth_cookie_req(int fd, const struct cmd_auth_cookie_req_st* r)
|
||||
{
|
||||
struct iovec iov[2];
|
||||
uint8_t cmd;
|
||||
struct msghdr hdr;
|
||||
|
||||
memset(&hdr, 0, sizeof(hdr));
|
||||
|
||||
cmd = AUTH_COOKIE_REQ;
|
||||
|
||||
iov[0].iov_base = &cmd;
|
||||
iov[0].iov_len = 1;
|
||||
|
||||
iov[1].iov_base = (void*)r;
|
||||
iov[1].iov_len = sizeof(*r);
|
||||
|
||||
hdr.msg_iov = iov;
|
||||
hdr.msg_iovlen = 2;
|
||||
|
||||
return(sendmsg(fd, &hdr, 0));
|
||||
}
|
||||
|
||||
static int recv_auth_reply(worker_st *ws)
|
||||
{
|
||||
struct iovec iov[3];
|
||||
struct iovec iov[2];
|
||||
uint8_t cmd = 0;
|
||||
struct cmd_auth_resp_st resp;
|
||||
struct cmd_auth_reply_st resp;
|
||||
struct msghdr hdr;
|
||||
int ret;
|
||||
|
||||
@@ -149,21 +163,19 @@ static int recv_auth_reply(worker_st *ws)
|
||||
iov[0].iov_base = &cmd;
|
||||
iov[0].iov_len = 1;
|
||||
|
||||
iov[1].iov_base = &resp.reply;
|
||||
iov[1].iov_len = 1;
|
||||
|
||||
iov[2].iov_base = resp.vname;
|
||||
iov[2].iov_len = sizeof(resp.vname);
|
||||
iov[1].iov_base = &resp;
|
||||
iov[1].iov_len = sizeof(resp);
|
||||
|
||||
memset(&hdr, 0, sizeof(hdr));
|
||||
hdr.msg_iov = iov;
|
||||
hdr.msg_iovlen = 3;
|
||||
hdr.msg_iovlen = 2;
|
||||
|
||||
hdr.msg_control = control_un.control;
|
||||
hdr.msg_controllen = sizeof(control_un.control);
|
||||
|
||||
ret = recvmsg( ws->cmd_fd, &hdr, 0);
|
||||
if (ret <= 0) {
|
||||
if (ret < sizeof(resp)+1) {
|
||||
oclog(ws, LOG_ERR, "Received incorrect data (%d, expected %d) from main", ret, (int)sizeof(resp)+1);
|
||||
return -1;
|
||||
}
|
||||
if (cmd != AUTH_REP)
|
||||
@@ -177,8 +189,11 @@ static int recv_auth_reply(worker_st *ws)
|
||||
if (cmptr->cmsg_type != SCM_RIGHTS)
|
||||
return -1;
|
||||
|
||||
ws->tun_fd = *((int *) CMSG_DATA(cmptr));
|
||||
memcpy(&ws->tun_fd, CMSG_DATA(cmptr), sizeof(int));
|
||||
memcpy(ws->tun_name, resp.vname, sizeof(ws->tun_name));
|
||||
memcpy(ws->username, resp.user, sizeof(ws->username));
|
||||
memcpy(ws->cookie, resp.cookie, sizeof(ws->cookie));
|
||||
ws->auth_ok = 1;
|
||||
} else
|
||||
return -1;
|
||||
break;
|
||||
@@ -189,21 +204,9 @@ static int recv_auth_reply(worker_st *ws)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* sends an authentication request to main thread and waits for
|
||||
* a reply */
|
||||
static int auth_user(worker_st *ws, const struct cmd_auth_req_st* areq)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = send_auth_req(ws->cmd_fd, areq);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return recv_auth_reply(ws);
|
||||
}
|
||||
|
||||
/* grabs the username from the session certificate */
|
||||
static
|
||||
int get_cert_info(worker_st *ws, struct cmd_auth_req_st *areq, const char** reason)
|
||||
int get_cert_info(worker_st *ws, char* user, unsigned user_size)
|
||||
{
|
||||
const gnutls_datum_t * cert;
|
||||
unsigned int ncerts;
|
||||
@@ -214,16 +217,13 @@ int ret;
|
||||
cert = gnutls_certificate_get_peers (ws->session, &ncerts);
|
||||
|
||||
if (cert == NULL) {
|
||||
*reason = "No certificate found";
|
||||
return -1;
|
||||
}
|
||||
|
||||
areq->tls_auth_ok = 1;
|
||||
if (ws->config->cert_user_oid) { /* otherwise certificate username is ignored */
|
||||
ret = get_cert_username(ws, cert, areq->cert_user, sizeof(areq->cert_user));
|
||||
ret = get_cert_username(ws, cert, user, user_size);
|
||||
if (ret < 0) {
|
||||
oclog(ws, LOG_ERR, "Cannot get username (%s) from certificate", ws->config->cert_user_oid);
|
||||
*reason = "No username in certificate";
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -231,30 +231,75 @@ int ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* sends an authentication request to main thread and waits for
|
||||
* a reply.
|
||||
* Returns 0 on success.
|
||||
*/
|
||||
static int auth_user(worker_st *ws, struct cmd_auth_req_st* areq)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (ws->config->auth_types & AUTH_TYPE_CERTIFICATE) {
|
||||
ret = get_cert_info(ws, areq->cert_user, sizeof(areq->cert_user));
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
||||
areq->tls_auth_ok = 1;
|
||||
}
|
||||
|
||||
oclog(ws, LOG_DEBUG, "Sending authentication request");
|
||||
ret = send_auth_req(ws->cmd_fd, areq);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return recv_auth_reply(ws);
|
||||
}
|
||||
|
||||
/* sends a cookie authentication request to main thread and waits for
|
||||
* a reply.
|
||||
* Returns 0 on success.
|
||||
*/
|
||||
int auth_cookie(worker_st *ws, void* cookie, size_t cookie_size)
|
||||
{
|
||||
int ret;
|
||||
struct cmd_auth_cookie_req_st areq;
|
||||
|
||||
if (cookie_size != sizeof(areq.cookie))
|
||||
return -1;
|
||||
|
||||
if (ws->config->auth_types & AUTH_TYPE_CERTIFICATE) {
|
||||
ret = get_cert_info(ws, areq.cert_user, sizeof(areq.cert_user));
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
||||
areq.tls_auth_ok = 1;
|
||||
}
|
||||
|
||||
memcpy(areq.cookie, cookie, sizeof(areq.cookie));
|
||||
|
||||
oclog(ws, LOG_DEBUG, "Sending cookie authentication request");
|
||||
ret = send_auth_cookie_req(ws->cmd_fd, &areq);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return recv_auth_reply(ws);
|
||||
}
|
||||
|
||||
|
||||
int post_old_auth_handler(worker_st *ws)
|
||||
{
|
||||
int ret;
|
||||
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];
|
||||
char * username = NULL;
|
||||
char * password = NULL;
|
||||
char *p;
|
||||
unsigned int i;
|
||||
struct stored_cookie_st sc;
|
||||
struct cmd_auth_req_st areq;
|
||||
|
||||
memset(&areq, 0, sizeof(areq));
|
||||
|
||||
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 (ws->config->auth_types & AUTH_TYPE_USERNAME_PASS) {
|
||||
/* body should be "username=test&password=test" */
|
||||
username = strstr(req->body, "username=");
|
||||
@@ -296,32 +341,20 @@ struct cmd_auth_req_st areq;
|
||||
}
|
||||
|
||||
ret = auth_user(ws, &areq);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
if (username)
|
||||
oclog(ws, LOG_INFO, "Failed authentication attempt for '%s'", username);
|
||||
else
|
||||
oclog(ws, LOG_INFO, "Failed authentication attempt");
|
||||
goto auth_fail;
|
||||
|
||||
oclog(ws, LOG_INFO, "User '%s' logged in\n", username);
|
||||
|
||||
/* generate cookie */
|
||||
ret = gnutls_rnd(GNUTLS_RND_RANDOM, cookie, sizeof(cookie));
|
||||
GNUTLS_FATAL_ERR(ret);
|
||||
|
||||
p = str_cookie;
|
||||
for (i=0;i<sizeof(cookie);i++) {
|
||||
sprintf(p, "%.2x", (unsigned int)cookie[i]);
|
||||
p+=2;
|
||||
}
|
||||
|
||||
memset(&sc, 0, sizeof(sc));
|
||||
sc.expiration = time(0) + ws->config->cookie_validity;
|
||||
if (username)
|
||||
snprintf(sc.username, sizeof(sc.username), "%s", username);
|
||||
memcpy(sc.tun_name, ws->tun_name, sizeof(sc.tun_name));
|
||||
oclog(ws, LOG_INFO, "User '%s' logged in\n", ws->username);
|
||||
|
||||
/* store cookie */
|
||||
ret = store_cookie(ws, cookie, sizeof(cookie), &sc);
|
||||
if (ret < 0) {
|
||||
reason = "Storage issue";
|
||||
goto auth_fail;
|
||||
p = str_cookie;
|
||||
for (i=0;i<sizeof(ws->cookie);i++) {
|
||||
sprintf(p, "%.2x", (unsigned int)ws->cookie[i]);
|
||||
p+=2;
|
||||
}
|
||||
|
||||
/* reply */
|
||||
@@ -355,24 +388,14 @@ 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];
|
||||
char cert_username[MAX_USERNAME_SIZE];
|
||||
char * username = NULL;
|
||||
char * password = NULL;
|
||||
char *p;
|
||||
unsigned int i;
|
||||
struct stored_cookie_st sc;
|
||||
struct cmd_auth_req_st areq;
|
||||
|
||||
memset(&areq, 0, sizeof(areq));
|
||||
|
||||
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 (ws->config->auth_types & AUTH_TYPE_USERNAME_PASS) {
|
||||
/* body should contain <username>test</username><password>test</password> */
|
||||
username = strstr(req->body, XMLUSER);
|
||||
@@ -414,10 +437,15 @@ struct cmd_auth_req_st areq;
|
||||
}
|
||||
|
||||
ret = auth_user(ws, &areq);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
if (username)
|
||||
oclog(ws, LOG_INFO, "Failed authentication attempt for '%s'", username);
|
||||
else
|
||||
oclog(ws, LOG_INFO, "Failed authentication attempt");
|
||||
goto auth_fail;
|
||||
}
|
||||
|
||||
oclog(ws, LOG_INFO, "User '%s' logged in\n", username);
|
||||
oclog(ws, LOG_INFO, "User '%s' logged in\n", ws->username);
|
||||
|
||||
/* generate cookie */
|
||||
ret = gnutls_rnd(GNUTLS_RND_RANDOM, cookie, sizeof(cookie));
|
||||
@@ -429,19 +457,6 @@ struct cmd_auth_req_st areq;
|
||||
p+=2;
|
||||
}
|
||||
|
||||
memset(&sc, 0, sizeof(sc));
|
||||
sc.expiration = time(0) + ws->config->cookie_validity;
|
||||
if (username)
|
||||
snprintf(sc.username, sizeof(sc.username), "%s", username);
|
||||
memcpy(sc.tun_name, ws->tun_name, sizeof(sc.tun_name));
|
||||
|
||||
/* store cookie */
|
||||
ret = store_cookie(ws, cookie, sizeof(cookie), &sc);
|
||||
if (ret < 0) {
|
||||
reason = "Storage issue";
|
||||
goto auth_fail;
|
||||
}
|
||||
|
||||
/* reply */
|
||||
|
||||
tls_puts(ws->session, "HTTP/1.1 200 OK\r\n");
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
#ifndef WORKER_AUTH_H
|
||||
#define WORKER_AUTH_H
|
||||
|
||||
#include <config.h>
|
||||
#include <syslog.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
#include <net/if.h>
|
||||
#include <vpn.h>
|
||||
#include <cookies.h>
|
||||
|
||||
typedef enum {
|
||||
AUTH_REQ = 1,
|
||||
AUTH_COOKIE_REQ = 2,
|
||||
AUTH_REP = 3,
|
||||
} cmd_request_t;
|
||||
|
||||
typedef enum {
|
||||
REP_AUTH_OK = 0,
|
||||
REP_AUTH_FAILED = 1,
|
||||
} cmd_auth_reply_t;
|
||||
|
||||
/* AUTH_COOKIE_REQ */
|
||||
struct __attribute__ ((__packed__)) cmd_auth_cookie_req_st {
|
||||
uint8_t cookie[COOKIE_SIZE];
|
||||
uint8_t tls_auth_ok;
|
||||
char cert_user[MAX_USERNAME_SIZE];
|
||||
};
|
||||
|
||||
/* AUTH_REQ */
|
||||
struct __attribute__ ((__packed__)) cmd_auth_req_st {
|
||||
uint8_t user_pass_present;
|
||||
char user[MAX_USERNAME_SIZE];
|
||||
char pass[MAX_PASSWORD_SIZE];
|
||||
uint8_t tls_auth_ok;
|
||||
char cert_user[MAX_USERNAME_SIZE];
|
||||
};
|
||||
|
||||
/* AUTH_REP */
|
||||
struct __attribute__ ((__packed__)) cmd_auth_reply_st {
|
||||
uint8_t reply;
|
||||
uint8_t cookie[COOKIE_SIZE];
|
||||
char vname[IFNAMSIZ]; /* interface name */
|
||||
char user[MAX_USERNAME_SIZE];
|
||||
};
|
||||
|
||||
int auth_cookie(worker_st *ws, void* cookie, size_t cookie_size);
|
||||
|
||||
int get_auth_handler(worker_st *server);
|
||||
int post_old_auth_handler(worker_st *server);
|
||||
int post_new_auth_handler(worker_st *server);
|
||||
|
||||
#endif
|
||||
+31
-15
@@ -36,6 +36,7 @@
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <vpn.h>
|
||||
#include <worker-auth.h>
|
||||
@@ -47,6 +48,11 @@
|
||||
/* HTTP requests prior to disconnection */
|
||||
#define MAX_HTTP_REQUESTS 8
|
||||
|
||||
static void handle_alarm(int signo)
|
||||
{
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static int connect_handler(worker_st *ws);
|
||||
|
||||
typedef int (*url_handler_fn)(worker_st*);
|
||||
@@ -195,6 +201,11 @@ void vpn_server(struct worker_st* ws, struct tls_st *creds)
|
||||
url_handler_fn fn;
|
||||
int requests_left = MAX_HTTP_REQUESTS;
|
||||
|
||||
signal(SIGALRM, handle_alarm);
|
||||
|
||||
if (ws->config->auth_timeout)
|
||||
alarm(ws->config->auth_timeout);
|
||||
|
||||
syslog(LOG_INFO, "Accepted connection from %s",
|
||||
human_addr((void*)&ws->remote_addr, ws->remote_addr_len,
|
||||
buf, sizeof(buf)));
|
||||
@@ -245,7 +256,10 @@ restart:
|
||||
/* parse as we go */
|
||||
do {
|
||||
nrecvd = tls_recv(session, buf, sizeof(buf));
|
||||
GNUTLS_FATAL_ERR(nrecvd);
|
||||
if (nrecvd <= 0) {
|
||||
oclog(ws, LOG_INFO, "Error receiving client data");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
nparsed = http_parser_execute(&parser, &settings, (void*)buf, nrecvd);
|
||||
if (nparsed == 0) {
|
||||
@@ -308,10 +322,10 @@ finish:
|
||||
static int get_ip(struct worker_st* ws, int fd, int family, unsigned int local,
|
||||
struct vpn_st* vinfo, char** buffer, size_t* buffer_size)
|
||||
{
|
||||
void* *ptr;
|
||||
void* ptr;
|
||||
const void* p;
|
||||
struct ifreq ifr;
|
||||
unsigned int i, flags;
|
||||
unsigned int flags;
|
||||
int ret, e;
|
||||
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
@@ -374,10 +388,8 @@ fail:
|
||||
static int get_rt_vpn_info(worker_st * ws,
|
||||
struct vpn_st* vinfo, char* buffer, size_t buffer_size)
|
||||
{
|
||||
unsigned int i;
|
||||
int fd, ret;
|
||||
struct ifreq ifr;
|
||||
const char* p;
|
||||
|
||||
memset(vinfo, 0, sizeof(*vinfo));
|
||||
vinfo->name = ws->tun_name;
|
||||
@@ -453,7 +465,6 @@ fd_set rfds;
|
||||
int l, pktlen;
|
||||
int tls_fd, max;
|
||||
unsigned i;
|
||||
struct stored_cookie_st sc;
|
||||
struct vpn_st vinfo;
|
||||
char* buffer;
|
||||
unsigned int buffer_size;
|
||||
@@ -466,14 +477,21 @@ unsigned int buffer_size;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = retrieve_cookie(ws, req->cookie, sizeof(req->cookie), &sc);
|
||||
if (ret < 0) {
|
||||
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 (ws->auth_ok == 0) {
|
||||
/* authentication didn't occur in this session. Use the
|
||||
* cookie */
|
||||
ret = auth_cookie(ws, req->cookie, sizeof(req->cookie));
|
||||
if (ret < 0) {
|
||||
oclog(ws, LOG_INFO, "Failed cookie authentication attempt");
|
||||
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);
|
||||
}
|
||||
}
|
||||
memcpy(ws->tun_name, sc.tun_name, sizeof(ws->tun_name));
|
||||
|
||||
/* turn of the alarm */
|
||||
if (ws->config->auth_timeout)
|
||||
alarm(0);
|
||||
|
||||
if (strcmp(req->url, "/CSCOSSLC/tunnel") != 0) {
|
||||
oclog(ws, LOG_INFO, "Bad connect request: '%s'\n", req->url);
|
||||
@@ -489,8 +507,6 @@ unsigned int buffer_size;
|
||||
return -1;
|
||||
}
|
||||
|
||||
oclog(ws, LOG_INFO, "User '%s' connected.\n", sc.username);
|
||||
|
||||
buffer_size = 2048;
|
||||
buffer = malloc(buffer_size);
|
||||
if (buffer == NULL) {
|
||||
|
||||
Reference in New Issue
Block a user