Allow loading additional configuration files per user or per group.

The directives currently allowed are: ipv4/6_dns and route.
This commit is contained in:
Nikos Mavrogiannopoulos
2013-10-28 11:43:05 +01:00
parent 99e7978f99
commit 00554b2f28
18 changed files with 555 additions and 60 deletions
+7
View File
@@ -1,3 +1,10 @@
* Version 0.1.8 (unreleased)
- Added configuration directives 'config-per-user' and 'config-per-group'.
They allow loading an additional configuration client per user or per
group from the setup directory.
* Version 0.1.7 (released 2013-10-25)
- Instead of suggesting different DTLS and CSTP MTU values, suggest a single
+6
View File
@@ -169,6 +169,12 @@ output-buffer = 10
route = 192.168.1.0/255.255.255.0
#route = 192.168.5.0/255.255.255.0
# Configuration files that will be applied per user connection or
# per group. Each file name on these directories must match the username
# or the groupname.
config-per-user = /etc/ocserv/config-per-user/
config-per-group = /etc/ocserv/config-per-group/
#
# The following options are for (experimental) AnyConnect client
# compatibility.
+1
View File
@@ -16,6 +16,7 @@ CCAN_SOURCES = ccan/build_assert/build_assert.h ccan/check_type/check_type.h \
ocserv_SOURCES = main.c main-auth.c worker-vpn.c worker-auth.c tlslib.c \
http-parser/http_parser.c ipc.h cookies.c worker-tun.c main-misc.c \
main-config.c \
vpn.h cookies.h tlslib.h http-parser/http_parser.h log.c tun.c tun.h \
config.c pam.c pam.h worker-resume.c worker.h main-resume.c main.h \
worker-extras.c main-auth.h html.c html.h \
+22
View File
@@ -42,3 +42,25 @@ const uint8_t * p = buf;
return len;
}
ssize_t force_read(int sockfd, void *buf, size_t len)
{
int left = len;
int ret;
uint8_t * p = buf;
while(left > 0) {
ret = read(sockfd, p, left);
if (ret == -1) {
if (errno != EAGAIN && errno != EINTR)
return ret;
}
if (ret > 0) {
left -= ret;
p += ret;
}
}
return len;
}
+1
View File
@@ -1,6 +1,7 @@
#ifndef COMMON_H
# define COMMON_H
ssize_t force_write(int sockfd, const void *buf, size_t len);
ssize_t force_read(int sockfd, void *buf, size_t len);
#endif
+10 -6
View File
@@ -39,10 +39,6 @@
static const char* pid_file = NULL;
static const char* cfg_file = DEFAULT_CFG_FILE;
#define MAX_ENTRIES 64
enum option_types { OPTION_NUMERIC, OPTION_STRING, OPTION_BOOLEAN, OPTION_MULTI_LINE };
struct cfg_options {
const char* name;
unsigned type;
@@ -102,6 +98,8 @@ static struct cfg_options available_options[] = {
{ .name = "ipv6-netmask", .type = OPTION_STRING, .mandatory = 0 },
{ .name = "ipv6-dns", .type = OPTION_STRING, .mandatory = 0 },
{ .name = "ipv6-nbns", .type = OPTION_STRING, .mandatory = 0 },
{ .name = "config-per-user", .type = OPTION_STRING, .mandatory = 0 },
{ .name = "config-per-group", .type = OPTION_STRING, .mandatory = 0 },
};
static const tOptionValue* get_option(const char* name, unsigned * mand)
@@ -124,13 +122,13 @@ unsigned j;
if (val != NULL && val->valType == OPARG_TYPE_STRING) { \
if (s_name == NULL) { \
num = 0; \
s_name = malloc(sizeof(char*)*MAX_ENTRIES); \
s_name = malloc(sizeof(char*)*MAX_CONFIG_ENTRIES); \
do { \
if (val && !strcmp(val->pzName, name)==0) \
continue; \
s_name[num] = strdup(val->v.strVal); \
num++; \
if (num>=MAX_ENTRIES) \
if (num>=MAX_CONFIG_ENTRIES) \
break; \
} while((val = optionNextValue(pov, val)) != NULL); \
s_name[num] = NULL; \
@@ -354,6 +352,9 @@ unsigned auth_size = 0;
READ_STRING("ipv6-nbns", config->network.ipv6_nbns);
READ_MULTI_LINE("route", config->network.routes, config->network.routes_size);
READ_STRING("config-per-user", config->per_user_dir);
READ_STRING("config-per-group", config->per_group_dir);
optionUnloadNested(pov);
}
@@ -480,6 +481,8 @@ unsigned i;
DEL(config->xml_config_hash);
DEL(config->cert_hash);
#endif
DEL(config->per_user_dir);
DEL(config->per_group_dir);
DEL(config->socket_file_prefix);
DEL(config->default_domain);
DEL(config->plain_passwd);
@@ -514,6 +517,7 @@ unsigned i;
DEL(config->cert[i]);
DEL(config->cert);
DEL(config->network.routes);
memset(config, 0, sizeof(*config));
parse_cfg_file(cfg_file, config);
+57 -25
View File
@@ -39,20 +39,9 @@ typedef enum {
REP_RESUME_FAILED = 1,
} cmd_resume_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];
char cert_group[MAX_GROUPNAME_SIZE];
};
/* AUTH_REQ */
struct __attribute__ ((__packed__)) cmd_auth_req_st {
uint8_t pass_size;
char pass[MAX_PASSWORD_SIZE];
};
/* AUTH_INIT:
* Message sent by worker to main to initialize authentication process.
*/
struct __attribute__ ((__packed__)) cmd_auth_init_st {
uint8_t user_present;
char user[MAX_USERNAME_SIZE];
@@ -62,23 +51,62 @@ struct __attribute__ ((__packed__)) cmd_auth_init_st {
char hostname[MAX_HOSTNAME_SIZE];
};
/* AUTH_REP */
struct __attribute__ ((__packed__)) cmd_auth_reply_st {
uint8_t reply;
/* AUTH_COOKIE_REQ:
* Message sent by worker to main to follow up authentication (after AUTH_INIT).
* Sent if the client tried to authenticate using cookie.
*/
struct __attribute__ ((__packed__)) cmd_auth_cookie_req_st {
uint8_t cookie[COOKIE_SIZE];
uint8_t session_id[GNUTLS_MAX_SESSION_ID];
char vname[IFNAMSIZ]; /* interface name */
char user[MAX_USERNAME_SIZE];
char msg[MAX_MSG_SIZE]; /* in case of REP_AUTH_CONTINUE */
uint8_t tls_auth_ok;
char cert_user[MAX_USERNAME_SIZE];
char cert_group[MAX_GROUPNAME_SIZE];
};
/* RESUME_FETCH_REQ + RESUME_DELETE_REQ */
/* AUTH_REQ:
* Message sent by worker to main to follow up authentication (after AUTH_INIT).
* Sent if the client tried to authenticate using password.
*/
struct __attribute__ ((__packed__)) cmd_auth_req_st {
uint8_t pass_size;
char pass[MAX_PASSWORD_SIZE];
};
/* AUTH_REP:
* Message sent by main to worker to follow up authentication (after AUTH_*REQ).
* Sent if the client tried to authenticate using password.
*/
struct __attribute__ ((__packed__)) cmd_auth_reply_st {
uint8_t reply; /* REP_AUTH_OK, REP_AUTH_MSG or REP_AUTH_FAILED */
/* These fields are not filled on REP_AUTH_FAILED */
union {
struct {
uint8_t cookie[COOKIE_SIZE];
uint8_t session_id[GNUTLS_MAX_SESSION_ID];
char vname[IFNAMSIZ]; /* interface name */
char user[MAX_USERNAME_SIZE];
uint8_t routes_size; /* up to MAX_ROUTES */
/* routes_size routes of cmd_auth_reply_route_st follow */
} ok;
/* in case of REP_AUTH_MSG */
char msg[MAX_MSG_SIZE];
} data;
};
/* RESUME_FETCH_REQ + RESUME_DELETE_REQ:
* Message sent by worker to main to ask for TLS resumption data, or
* to delete such data.
*/
struct __attribute__ ((__packed__)) cmd_resume_fetch_req_st {
uint8_t session_id_size;
uint8_t session_id[GNUTLS_MAX_SESSION_ID];
};
/* RESUME_STORE_REQ */
/* RESUME_STORE_REQ:
* Message sent by worker to main to store TLS resumption data.
*/
struct __attribute__ ((__packed__)) cmd_resume_store_req_st {
uint8_t session_id_size;
uint8_t session_id[GNUTLS_MAX_SESSION_ID];
@@ -86,14 +114,18 @@ struct __attribute__ ((__packed__)) cmd_resume_store_req_st {
uint8_t session_data[MAX_SESSION_DATA_SIZE];
};
/* RESUME_FETCH_REP */
/* RESUME_FETCH_REP:
* Message sent by main to worker to return stored TLS resumption data.
*/
struct __attribute__ ((__packed__)) cmd_resume_fetch_reply_st {
uint8_t reply;
uint16_t session_data_size;
uint8_t session_data[MAX_SESSION_DATA_SIZE];
};
/* TUN_MTU */
/* TUN_MTU:
* Message sent by worker to main to alter the MTU of the TUN device.
*/
struct __attribute__ ((__packed__)) cmd_tun_mtu_st {
uint16_t mtu;
};
+72 -8
View File
@@ -43,6 +43,7 @@
#include <ccan/list/list.h>
#include <main-auth.h>
#include <plain.h>
#include <common.h>
#include <pam.h>
static const struct auth_mod_st *module;
@@ -61,7 +62,7 @@ void main_auth_init(main_server_st *s)
}
int send_auth_reply(main_server_st* s, struct proc_st* proc,
cmd_auth_reply_t r)
cmd_auth_reply_t r, struct group_cfg_st* cfg)
{
struct iovec iov[2];
uint8_t cmd[2];
@@ -71,7 +72,14 @@ int send_auth_reply(main_server_st* s, struct proc_st* proc,
char control[CMSG_SPACE(sizeof(int))];
} control_un;
struct cmd_auth_reply_st resp;
struct cmsghdr *cmptr;
struct cmsghdr *cmptr;
unsigned i;
int ret;
if (cfg->routes_size > MAX_ROUTES) {
mslog(s, proc, LOG_INFO, "Note that the routes sent to the client (%d) exceed the maximum allowed (%d). Truncating.", (int)cfg->routes_size, (int)MAX_ROUTES);
cfg->routes_size = MAX_ROUTES;
}
memset(&control_un, 0, sizeof(control_un));
memset(&hdr, 0, sizeof(hdr));
@@ -86,15 +94,17 @@ int send_auth_reply(main_server_st* s, struct proc_st* proc,
hdr.msg_iovlen++;
resp.reply = r;
memcpy(resp.cookie, proc->cookie, COOKIE_SIZE);
memcpy(resp.session_id, proc->session_id, sizeof(resp.session_id));
memcpy(resp.vname, proc->lease->name, sizeof(resp.vname));
memcpy(resp.user, proc->username, sizeof(resp.user));
memcpy(resp.data.ok.cookie, proc->cookie, COOKIE_SIZE);
memcpy(resp.data.ok.session_id, proc->session_id, sizeof(resp.data.ok.session_id));
memcpy(resp.data.ok.vname, proc->lease->name, sizeof(resp.data.ok.vname));
memcpy(resp.data.ok.user, proc->username, sizeof(resp.data.ok.user));
iov[1].iov_base = &resp;
iov[1].iov_len = sizeof(resp);
hdr.msg_iovlen++;
resp.data.ok.routes_size = cfg->routes_size;
/* Send the tun fd */
hdr.msg_control = control_un.control;
hdr.msg_controllen = sizeof(control_un.control);
@@ -113,7 +123,61 @@ int send_auth_reply(main_server_st* s, struct proc_st* proc,
hdr.msg_iovlen++;
}
return(sendmsg(proc->fd, &hdr, 0));
ret = sendmsg(proc->fd, &hdr, 0);
if (ret < 0)
return ret;
if (r == REP_AUTH_OK) {
uint8_t len;
if (cfg->ipv4_dns) {
len = strlen(cfg->ipv4_dns);
mslog(s, proc, LOG_INFO, "sending DNS '%s' with size %d", cfg->ipv4_dns, len);
ret = force_write(proc->fd, &len, 1);
if (ret < 0)
return ret;
ret = force_write(proc->fd, cfg->ipv4_dns, len);
if (ret < 0)
return ret;
} else {
len = 0;
ret = force_write(proc->fd, &len, 1);
if (ret < 0)
return ret;
}
if (cfg->ipv6_dns) {
len = strlen(cfg->ipv6_dns);
mslog(s, proc, LOG_INFO, "sending DNS '%s' with size %d", cfg->ipv6_dns, len);
ret = force_write(proc->fd, &len, 1);
if (ret < 0)
return ret;
ret = force_write(proc->fd, cfg->ipv6_dns, len);
if (ret < 0)
return ret;
} else {
len = 0;
ret = force_write(proc->fd, &len, 1);
if (ret < 0)
return ret;
}
for (i=0;i<cfg->routes_size;i++) {
len = strlen(cfg->routes[i]);
mslog(s, proc, LOG_INFO, "sending route '%s' with size %d", cfg->routes[i], len);
ret = force_write(proc->fd, &len, 1);
if (ret < 0)
return ret;
ret = force_write(proc->fd, cfg->routes[i], len);
if (ret < 0)
return ret;
}
}
return 0;
}
int send_auth_reply_msg(main_server_st* s, struct proc_st* proc)
@@ -128,7 +192,7 @@ int send_auth_reply_msg(main_server_st* s, struct proc_st* proc)
return -1;
memset(&resp, 0, sizeof(resp));
ret = module->auth_msg(proc->auth_ctx, resp.msg, sizeof(resp.msg));
ret = module->auth_msg(proc->auth_ctx, resp.data.msg, sizeof(resp.data.msg));
if (ret < 0)
return ret;
+122
View File
@@ -0,0 +1,122 @@
/*
* 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 <pwd.h>
#include <grp.h>
#include <fcntl.h>
#include <ocserv-args.h>
#include <autoopts/options.h>
#include <limits.h>
#include <c-strcase.h>
#include <vpn.h>
#include <main.h>
struct cfg_options {
const char* name;
unsigned type;
};
static struct cfg_options available_options[] = {
{ .name = "route", .type = OPTION_MULTI_LINE },
{ .name = "ipv4-dns", .type = OPTION_STRING },
{ .name = "ipv6-dns", .type = OPTION_STRING },
};
#define READ_RAW_MULTI_LINE(name, s_name, num) \
val = optionGetValue(pov, name); \
if (val != NULL && val->valType == OPARG_TYPE_STRING) { \
if (s_name == NULL) { \
num = 0; \
s_name = malloc(sizeof(char*)*MAX_CONFIG_ENTRIES); \
do { \
if (val && !strcmp(val->pzName, name)==0) \
continue; \
s_name[num] = strdup(val->v.strVal); \
num++; \
if (num>=MAX_CONFIG_ENTRIES) \
break; \
} while((val = optionNextValue(pov, val)) != NULL); \
s_name[num] = NULL; \
} \
}
#undef READ_RAW_STRING
#define READ_RAW_STRING(name, s_name) \
val = optionGetValue(pov, name); \
if (val != NULL && val->valType == OPARG_TYPE_STRING) { \
s_name = strdup(val->v.strVal); \
}
static int handle_option(const tOptionValue* val)
{
unsigned j;
for (j=0;j<sizeof(available_options)/sizeof(available_options[0]);j++) {
if (strcasecmp(val->pzName, available_options[j].name) == 0) {
return 1;
}
}
return 0;
}
int parse_group_cfg_file(main_server_st* s, const char* file, struct group_cfg_st *config)
{
tOptionValue const * pov;
const tOptionValue* val, *prev;
memset(config, 0, sizeof(*config));
pov = configFileLoad(file);
if (pov == NULL) {
mslog(s, NULL, LOG_ERR, "Error loading config file %s", file);
return ERR_READ_CONFIG;
}
val = optionGetValue(pov, NULL);
if (val == NULL) {
mslog(s, NULL, LOG_ERR, "No configuration directives found in %s", file);
return ERR_READ_CONFIG;
}
do {
if (handle_option(val) == 0) {
mslog(s, NULL, LOG_ERR, "Skipping unknown option '%s' in %s", val->pzName, file);
}
prev = val;
} while((val = optionNextValue(pov, prev)) != NULL);
READ_RAW_MULTI_LINE("route", config->routes, config->routes_size);
READ_RAW_STRING("ipv4-dns", config->ipv4_dns);
READ_RAW_STRING("ipv6-dns", config->ipv6_dns);
optionUnloadNested(pov);
return 0;
}
+109 -2
View File
@@ -112,12 +112,119 @@ int send_udp_fd(main_server_st* s, struct proc_st * proc, int fd)
return(sendmsg(proc->fd, &hdr, 0));
}
static void del_additional_config(struct group_cfg_st* config)
{
unsigned i;
for(i=0;i<config->routes_size;i++) {
free(config->routes[i]);
}
free(config->routes);
free(config->ipv4_dns);
free(config->ipv6_dns);
}
static int read_additional_config(main_server_st* s, struct proc_st* proc,
struct group_cfg_st *config)
{
struct group_cfg_st u_cfg;
struct group_cfg_st g_cfg;
char file[_POSIX_PATH_MAX];
int ret;
unsigned i;
memset(config, 0, sizeof(*config));
if (s->config->per_user_dir != NULL) {
snprintf(file, sizeof(file), "%s/%s", s->config->per_user_dir, proc->username);
if (access(file, R_OK) == 0) {
mslog(s, proc, LOG_INFO, "Loading user configuration '%s'", file);
ret = parse_group_cfg_file(s, file, &u_cfg);
if (ret < 0)
return ERR_READ_CONFIG;
if (u_cfg.routes_size > 0) {
config->routes = u_cfg.routes;
config->routes_size = u_cfg.routes_size;
u_cfg.routes = NULL;
u_cfg.routes_size = 0;
}
config->ipv4_dns = u_cfg.ipv4_dns;
u_cfg.ipv4_dns = NULL;
config->ipv6_dns = u_cfg.ipv6_dns;
u_cfg.ipv6_dns = NULL;
del_additional_config(&u_cfg);
} else
mslog(s, proc, LOG_INFO, "No user configuration for '%s'", proc->username);
}
if (s->config->per_group_dir != NULL) {
snprintf(file, sizeof(file), "%s/%s", s->config->per_group_dir, proc->groupname);
if (access(file, R_OK) == 0) {
mslog(s, proc, LOG_INFO, "Loading group configuration '%s'", file);
ret = parse_group_cfg_file(s, file, &g_cfg);
if (ret < 0)
return ERR_READ_CONFIG;
if (g_cfg.routes_size > 0) {
config->routes = realloc(config->routes, (config->routes_size+g_cfg.routes_size) * sizeof(config->routes[0]));
if (config->routes == NULL)
return ERR_MEM;
for (i=0;i<g_cfg.routes_size;i++) {
config->routes[config->routes_size] = g_cfg.routes[i];
g_cfg.routes[i] = NULL;
config->routes_size++;
}
}
if (config->ipv4_dns == NULL) {
config->ipv4_dns = g_cfg.ipv4_dns;
g_cfg.ipv4_dns = NULL;
}
if (config->ipv6_dns == NULL) {
config->ipv6_dns = g_cfg.ipv6_dns;
g_cfg.ipv6_dns = NULL;
}
del_additional_config(&g_cfg);
} else
mslog(s, proc, LOG_INFO, "No group configuration for '%s'", proc->groupname);
}
return 0;
}
int handle_script_exit(main_server_st *s, struct proc_st* proc, int code)
{
int ret;
if (code == 0) {
ret = send_auth_reply(s, proc, REP_AUTH_OK);
struct group_cfg_st cfg;
ret = read_additional_config(s, proc, &cfg);
if (ret < 0) {
mslog(s, proc, LOG_ERR, "error reading additional routes");
ret = ERR_READ_ROUTES;
goto fail;
}
ret = send_auth_reply(s, proc, REP_AUTH_OK, &cfg);
del_additional_config(&cfg);
if (ret < 0) {
mslog(s, proc, LOG_ERR, "could not send reply auth cmd.");
ret = ERR_BAD_COMMAND;
@@ -125,7 +232,7 @@ int ret;
}
} else {
mslog(s, proc, LOG_INFO, "failed authentication attempt for user '%s'", proc->username);
ret = send_auth_reply( s, proc, REP_AUTH_FAILED);
ret = send_auth_reply( s, proc, REP_AUTH_FAILED, NULL);
if (ret < 0) {
mslog(s, proc, LOG_ERR, "could not send reply auth cmd.");
ret = ERR_BAD_COMMAND;
+5 -1
View File
@@ -155,8 +155,10 @@ int open_tun(main_server_st* s, struct proc_st* proc);
int set_tun_mtu(main_server_st* s, struct proc_st * proc, unsigned mtu);
int send_auth_reply_msg(main_server_st* s, struct proc_st* proc);
int send_auth_reply(main_server_st* s, struct proc_st* proc,
cmd_auth_reply_t r);
cmd_auth_reply_t r, struct group_cfg_st*);
int handle_auth_cookie_req(main_server_st* s, struct proc_st* proc,
const struct cmd_auth_cookie_req_st * req);
int generate_cookie(main_server_st *s, struct proc_st* proc);
@@ -175,4 +177,6 @@ int handle_script_exit(main_server_st *s, struct proc_st* proc, int code);
void run_sec_mod(main_server_st * s);
int parse_group_cfg_file(main_server_st* s, const char* file, struct group_cfg_st *config);
#endif
+4 -4
View File
@@ -2,7 +2,7 @@
*
* DO NOT EDIT THIS FILE (ocserv-args.c)
*
* It has been AutoGen-ed October 20, 2013 at 05:44:06 PM by AutoGen 5.17
* It has been AutoGen-ed October 28, 2013 at 11:41:39 AM by AutoGen 5.17
* From the definitions ocserv-args.def
* and the template file options
*
@@ -66,7 +66,7 @@ extern FILE * option_usage_fp;
* ocserv option static const strings
*/
static char const ocserv_opt_strs[1834] =
/* 0 */ "ocserv 0.1.6\n"
/* 0 */ "ocserv 0.1.7\n"
"Copyright (C) 2013 Nikos Mavrogiannopoulos, all rights reserved.\n"
"This is free software. It is licensed for use, modification and\n"
"redistribution under the terms of the\n"
@@ -99,7 +99,7 @@ static char const ocserv_opt_strs[1834] =
/* 1129 */ "Output version information and exit\0"
/* 1165 */ "version\0"
/* 1173 */ "OCSERV\0"
/* 1180 */ "ocserv - OpenConnect server - Ver. 0.1.6\n"
/* 1180 */ "ocserv - OpenConnect server - Ver. 0.1.7\n"
"USAGE: %s [ -<flag> [<val>] | --<name>[{=| }<val>] ]...\n\0"
/* 1279 */ "openconnect-devel@lists.infradead.org\0"
/* 1317 */ "\n\n\0"
@@ -111,7 +111,7 @@ static char const ocserv_opt_strs[1834] =
"certificate authentication. Authenticated users are assigned an\n"
"unprivileged worker process and obtain a networking (tun) device and an IP\n"
"from a configurable pool of addresses.\n\0"
/* 1746 */ "ocserv 0.1.6\0"
/* 1746 */ "ocserv 0.1.7\0"
/* 1759 */ "Usage: ocserv [options] -c [config]\n"
"ocserv --help for usage instructions.\n";
+7
View File
@@ -260,6 +260,13 @@ output-buffer = 10
route = 192.168.1.0/255.255.255.0
route = 192.168.5.0/255.255.255.0
# Configuration files that will be applied per user connection or
# per group. Each file name on these directories must match the username
# or the groupname.
# The options allow in such configuration files are ipv?-dns, and route.
#config-per-user = /etc/ocserv/config-per-user/
#config-per-group = /etc/ocserv/config-per-group/
#
# The following options are for (experimental) AnyConnect client
# compatibility.
+3 -3
View File
@@ -2,7 +2,7 @@
*
* DO NOT EDIT THIS FILE (ocserv-args.h)
*
* It has been AutoGen-ed October 20, 2013 at 05:44:06 PM by AutoGen 5.17
* It has been AutoGen-ed October 28, 2013 at 11:41:39 AM by AutoGen 5.17
* From the definitions ocserv-args.def
* and the template file options
*
@@ -76,8 +76,8 @@ typedef enum {
} teOptIndex;
#define OPTION_CT 7
#define OCSERV_VERSION "0.1.6"
#define OCSERV_FULL_VERSION "ocserv 0.1.6"
#define OCSERV_VERSION "0.1.7"
#define OCSERV_FULL_VERSION "ocserv 0.1.7"
/*
* Interface defines for all options. Replace "n" with the UPPER_CASED
+27
View File
@@ -47,6 +47,8 @@ extern int syslog_open;
#define ERR_AUTH_CONTINUE -4
#define ERR_WAIT_FOR_SCRIPT -5
#define ERR_MEM -6
#define ERR_READ_ROUTES -7
#define ERR_READ_CONFIG -8
typedef struct
{
@@ -54,6 +56,14 @@ typedef struct
unsigned int entries;
} hash_db_st;
struct group_cfg_st {
char **routes;
unsigned int routes_size;
char *ipv4_dns;
char *ipv6_dns;
};
struct vpn_st {
char *name; /* device name */
char *ipv4_netmask;
@@ -127,6 +137,10 @@ struct cfg_st {
uid_t uid;
gid_t gid;
/* additional configuration files */
char *per_group_dir;
char *per_user_dir;
/* the tun network */
struct vpn_st network;
@@ -144,6 +158,10 @@ struct main_server_st;
#define MAX_GROUPNAME_SIZE MAX_USERNAME_SIZE
#define MAX_SESSION_DATA_SIZE (4*1024)
#define MAX_CONFIG_ENTRIES 64
#define MAX_ROUTES 32
#include <tun.h>
const char *human_addr(const struct sockaddr *sa, socklen_t salen,
@@ -160,4 +178,13 @@ const char *human_addr(const struct sockaddr *sa, socklen_t salen,
#define SA_IN_P_GENERIC(addr, size) ((size==sizeof(struct sockaddr_in))?SA_IN_U8_P(addr):SA_IN6_U8_P(addr))
#define SA_IN_SIZE(size) ((size==sizeof(struct sockaddr_in))?sizeof(struct in_addr):sizeof(struct in6_addr))
/* Helper structures */
struct route_st {
uint8_t size;
char *route;
};
enum option_types { OPTION_NUMERIC, OPTION_STRING, OPTION_BOOLEAN, OPTION_MULTI_LINE };
#endif
+75 -8
View File
@@ -37,6 +37,7 @@
#include "html.h"
#include <worker.h>
#include <cookies.h>
#include <common.h>
#include <tlslib.h>
#include <http-parser/http_parser.h>
@@ -237,7 +238,7 @@ static int send_auth_cookie_req(int fd, const struct cmd_auth_cookie_req_st* r)
static int recv_auth_reply(worker_st *ws, struct cmd_auth_reply_st *resp)
{
struct iovec iov[2];
uint8_t cmd = 0;
uint8_t cmd = 0, len;
struct msghdr hdr;
int ret, cmdlen;
union {
@@ -245,16 +246,17 @@ static int recv_auth_reply(worker_st *ws, struct cmd_auth_reply_st *resp)
char control[CMSG_SPACE(sizeof(int))];
} control_un;
struct cmsghdr *cmptr;
unsigned i;
iov[0].iov_base = &cmd;
iov[0].iov_len = 1;
iov[1].iov_base = resp;
iov[1].iov_len = sizeof(*resp);
memset(&hdr, 0, sizeof(hdr));
hdr.msg_iov = iov;
hdr.msg_iovlen = 2;
hdr.msg_iovlen = 2 + MAX_ROUTES;
hdr.msg_control = control_un.control;
hdr.msg_controllen = sizeof(control_un.control);
@@ -288,10 +290,75 @@ static int recv_auth_reply(worker_st *ws, struct cmd_auth_reply_st *resp)
return ERR_AUTH_FAIL;
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));
memcpy(ws->session_id, resp->session_id, sizeof(ws->session_id));
memcpy(ws->tun_name, resp->data.ok.vname, sizeof(ws->tun_name));
memcpy(ws->username, resp->data.ok.user, sizeof(ws->username));
memcpy(ws->cookie, resp->data.ok.cookie, sizeof(ws->cookie));
memcpy(ws->session_id, resp->data.ok.session_id, sizeof(ws->session_id));
ws->routes_size = resp->data.ok.routes_size;
/* Read any additional data */
/* IPV4 DNS */
ret = force_read(ws->cmd_fd, &len, 1);
if (ret != 1) {
oclog(ws, LOG_ERR, "Error received route size from main (%d)", ret);
return ERR_BAD_COMMAND;
}
if (len > 0) {
ws->ipv4_dns = malloc(len+1);
if (ws->ipv4_dns == NULL)
return ERR_MEM;
ret = force_read(ws->cmd_fd, ws->ipv4_dns, len);
if (ret != len) {
oclog(ws, LOG_ERR, "Error received routes from main (%d)", ret);
return ERR_BAD_COMMAND;
}
ws->ipv4_dns[len] = 0;
}
/* IPV6 DNS */
ret = force_read(ws->cmd_fd, &len, 1);
if (ret != 1) {
oclog(ws, LOG_ERR, "Error received route size from main (%d)", ret);
return ERR_BAD_COMMAND;
}
if (len > 0) {
ws->ipv6_dns = malloc(len+1);
if (ws->ipv6_dns == NULL)
return ERR_MEM;
ret = force_read(ws->cmd_fd, ws->ipv6_dns, len);
if (ret != len) {
oclog(ws, LOG_ERR, "Error received routes from main (%d)", ret);
return ERR_BAD_COMMAND;
}
ws->ipv6_dns[len] = 0;
}
/* routes */
for (i=0;i<ws->routes_size;i++) {
ret = force_read(ws->cmd_fd, &ws->routes[i].size, 1);
if (ret != 1) {
oclog(ws, LOG_ERR, "Error received route size from main (%d)", ret);
return ERR_BAD_COMMAND;
}
ws->routes[i].route = malloc(ws->routes[i].size+1);
if (ws->routes[i].route == NULL)
return ERR_MEM;
ret = force_read(ws->cmd_fd, ws->routes[i].route, ws->routes[i].size);
if (ret != ws->routes[i].size) {
oclog(ws, LOG_ERR, "Error received routes from main (%d)", ret);
return ERR_BAD_COMMAND;
}
ws->routes[i].route[ws->routes[i].size] = 0;
}
} else
return ERR_AUTH_FAIL;
break;
@@ -655,7 +722,7 @@ struct cmd_auth_reply_st resp;
ret = recv_auth_reply(ws, &resp);
if (ret == ERR_AUTH_CONTINUE) {
ws->auth_state = S_AUTH_REQ;
return get_auth_handler2(ws, http_ver, resp.msg);
return get_auth_handler2(ws, http_ver, resp.data.msg);
} else if (ret < 0)
goto auth_fail;
+21 -2
View File
@@ -853,7 +853,11 @@ socklen_t sl;
ret = tls_printf(ws->session, "X-CSTP-Netmask: %s\r\n", vinfo.ipv4_netmask);
SEND_ERR(ret);
}
if (vinfo.ipv4_dns) {
if (ws->ipv4_dns) {
ret = tls_printf(ws->session, "X-CSTP-DNS: %s\r\n", ws->ipv4_dns);
SEND_ERR(ret);
} else if (vinfo.ipv4_dns) {
ret = tls_printf(ws->session, "X-CSTP-DNS: %s\r\n", vinfo.ipv4_dns);
SEND_ERR(ret);
}
@@ -872,7 +876,11 @@ socklen_t sl;
ret = tls_printf(ws->session, "X-CSTP-Netmask: %s\r\n", vinfo.ipv6_netmask);
SEND_ERR(ret);
}
if (vinfo.ipv6_dns) {
if (ws->ipv6_dns) {
ret = tls_printf(ws->session, "X-CSTP-DNS: %s\r\n", ws->ipv6_dns);
SEND_ERR(ret);
} else if (vinfo.ipv6_dns) {
ret = tls_printf(ws->session, "X-CSTP-DNS: %s\r\n", vinfo.ipv6_dns);
SEND_ERR(ret);
}
@@ -892,6 +900,17 @@ socklen_t sl;
"X-CSTP-Split-Include: %s\r\n", vinfo.routes[i]);
SEND_ERR(ret);
}
for (i=0;i<ws->routes_size;i++) {
if (req->no_ipv6 != 0 && strchr(ws->routes[i].route, ':') != 0)
continue;
if (req->no_ipv4 != 0 && strchr(ws->routes[i].route, '.') != 0)
continue;
oclog(ws, LOG_DEBUG, "adding route %s", ws->routes[i].route);
ret = tls_printf(ws->session,
"X-CSTP-Split-Include: %s\r\n", ws->routes[i].route);
SEND_ERR(ret);
}
ret = tls_printf(ws->session, "X-CSTP-Keepalive: %u\r\n", ws->config->keepalive);
SEND_ERR(ret);
+6 -1
View File
@@ -118,6 +118,12 @@ typedef struct worker_st {
unsigned cert_auth_ok;
int tun_fd;
/* additional data - received per user or per group */
char *ipv4_dns;
char *ipv6_dns;
unsigned routes_size;
struct route_st routes[MAX_ROUTES];
struct http_req_st req;
} worker_st;
@@ -142,7 +148,6 @@ void __attribute__ ((format(printf, 3, 4)))
int get_rt_vpn_info(worker_st * ws,
struct vpn_st* vinfo, char* buffer, size_t buffer_size);
ssize_t tun_write(int sockfd, const void *buf, size_t len);
int send_tun_mtu(worker_st *ws, unsigned int mtu);
int handle_worker_commands(struct worker_st *ws);