mirror of
https://gitlab.com/openconnect/ocserv.git
synced 2026-10-14 02:22:03 +08:00
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:
@@ -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)
|
* Version 0.1.7 (released 2013-10-25)
|
||||||
|
|
||||||
- Instead of suggesting different DTLS and CSTP MTU values, suggest a single
|
- Instead of suggesting different DTLS and CSTP MTU values, suggest a single
|
||||||
|
|||||||
@@ -169,6 +169,12 @@ output-buffer = 10
|
|||||||
route = 192.168.1.0/255.255.255.0
|
route = 192.168.1.0/255.255.255.0
|
||||||
#route = 192.168.5.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
|
# The following options are for (experimental) AnyConnect client
|
||||||
# compatibility.
|
# compatibility.
|
||||||
|
|||||||
@@ -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 \
|
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 \
|
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 \
|
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 \
|
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 \
|
worker-extras.c main-auth.h html.c html.h \
|
||||||
|
|||||||
@@ -42,3 +42,25 @@ const uint8_t * p = buf;
|
|||||||
|
|
||||||
return len;
|
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,6 +1,7 @@
|
|||||||
#ifndef COMMON_H
|
#ifndef COMMON_H
|
||||||
# define COMMON_H
|
# define COMMON_H
|
||||||
ssize_t force_write(int sockfd, const void *buf, size_t len);
|
ssize_t force_write(int sockfd, const void *buf, size_t len);
|
||||||
|
ssize_t force_read(int sockfd, void *buf, size_t len);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
+10
-6
@@ -39,10 +39,6 @@
|
|||||||
static const char* pid_file = NULL;
|
static const char* pid_file = NULL;
|
||||||
static const char* cfg_file = DEFAULT_CFG_FILE;
|
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 {
|
struct cfg_options {
|
||||||
const char* name;
|
const char* name;
|
||||||
unsigned type;
|
unsigned type;
|
||||||
@@ -102,6 +98,8 @@ static struct cfg_options available_options[] = {
|
|||||||
{ .name = "ipv6-netmask", .type = OPTION_STRING, .mandatory = 0 },
|
{ .name = "ipv6-netmask", .type = OPTION_STRING, .mandatory = 0 },
|
||||||
{ .name = "ipv6-dns", .type = OPTION_STRING, .mandatory = 0 },
|
{ .name = "ipv6-dns", .type = OPTION_STRING, .mandatory = 0 },
|
||||||
{ .name = "ipv6-nbns", .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)
|
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 (val != NULL && val->valType == OPARG_TYPE_STRING) { \
|
||||||
if (s_name == NULL) { \
|
if (s_name == NULL) { \
|
||||||
num = 0; \
|
num = 0; \
|
||||||
s_name = malloc(sizeof(char*)*MAX_ENTRIES); \
|
s_name = malloc(sizeof(char*)*MAX_CONFIG_ENTRIES); \
|
||||||
do { \
|
do { \
|
||||||
if (val && !strcmp(val->pzName, name)==0) \
|
if (val && !strcmp(val->pzName, name)==0) \
|
||||||
continue; \
|
continue; \
|
||||||
s_name[num] = strdup(val->v.strVal); \
|
s_name[num] = strdup(val->v.strVal); \
|
||||||
num++; \
|
num++; \
|
||||||
if (num>=MAX_ENTRIES) \
|
if (num>=MAX_CONFIG_ENTRIES) \
|
||||||
break; \
|
break; \
|
||||||
} while((val = optionNextValue(pov, val)) != NULL); \
|
} while((val = optionNextValue(pov, val)) != NULL); \
|
||||||
s_name[num] = NULL; \
|
s_name[num] = NULL; \
|
||||||
@@ -354,6 +352,9 @@ unsigned auth_size = 0;
|
|||||||
READ_STRING("ipv6-nbns", config->network.ipv6_nbns);
|
READ_STRING("ipv6-nbns", config->network.ipv6_nbns);
|
||||||
|
|
||||||
READ_MULTI_LINE("route", config->network.routes, config->network.routes_size);
|
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);
|
optionUnloadNested(pov);
|
||||||
}
|
}
|
||||||
@@ -480,6 +481,8 @@ unsigned i;
|
|||||||
DEL(config->xml_config_hash);
|
DEL(config->xml_config_hash);
|
||||||
DEL(config->cert_hash);
|
DEL(config->cert_hash);
|
||||||
#endif
|
#endif
|
||||||
|
DEL(config->per_user_dir);
|
||||||
|
DEL(config->per_group_dir);
|
||||||
DEL(config->socket_file_prefix);
|
DEL(config->socket_file_prefix);
|
||||||
DEL(config->default_domain);
|
DEL(config->default_domain);
|
||||||
DEL(config->plain_passwd);
|
DEL(config->plain_passwd);
|
||||||
@@ -514,6 +517,7 @@ unsigned i;
|
|||||||
DEL(config->cert[i]);
|
DEL(config->cert[i]);
|
||||||
DEL(config->cert);
|
DEL(config->cert);
|
||||||
DEL(config->network.routes);
|
DEL(config->network.routes);
|
||||||
|
|
||||||
memset(config, 0, sizeof(*config));
|
memset(config, 0, sizeof(*config));
|
||||||
|
|
||||||
parse_cfg_file(cfg_file, config);
|
parse_cfg_file(cfg_file, config);
|
||||||
|
|||||||
@@ -39,20 +39,9 @@ typedef enum {
|
|||||||
REP_RESUME_FAILED = 1,
|
REP_RESUME_FAILED = 1,
|
||||||
} cmd_resume_reply_t;
|
} cmd_resume_reply_t;
|
||||||
|
|
||||||
/* AUTH_COOKIE_REQ */
|
/* AUTH_INIT:
|
||||||
struct __attribute__ ((__packed__)) cmd_auth_cookie_req_st {
|
* Message sent by worker to main to initialize authentication process.
|
||||||
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];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct __attribute__ ((__packed__)) cmd_auth_init_st {
|
struct __attribute__ ((__packed__)) cmd_auth_init_st {
|
||||||
uint8_t user_present;
|
uint8_t user_present;
|
||||||
char user[MAX_USERNAME_SIZE];
|
char user[MAX_USERNAME_SIZE];
|
||||||
@@ -62,23 +51,62 @@ struct __attribute__ ((__packed__)) cmd_auth_init_st {
|
|||||||
char hostname[MAX_HOSTNAME_SIZE];
|
char hostname[MAX_HOSTNAME_SIZE];
|
||||||
};
|
};
|
||||||
|
|
||||||
/* AUTH_REP */
|
/* AUTH_COOKIE_REQ:
|
||||||
struct __attribute__ ((__packed__)) cmd_auth_reply_st {
|
* Message sent by worker to main to follow up authentication (after AUTH_INIT).
|
||||||
uint8_t reply;
|
* Sent if the client tried to authenticate using cookie.
|
||||||
|
*/
|
||||||
|
struct __attribute__ ((__packed__)) cmd_auth_cookie_req_st {
|
||||||
uint8_t cookie[COOKIE_SIZE];
|
uint8_t cookie[COOKIE_SIZE];
|
||||||
uint8_t session_id[GNUTLS_MAX_SESSION_ID];
|
uint8_t tls_auth_ok;
|
||||||
char vname[IFNAMSIZ]; /* interface name */
|
char cert_user[MAX_USERNAME_SIZE];
|
||||||
char user[MAX_USERNAME_SIZE];
|
char cert_group[MAX_GROUPNAME_SIZE];
|
||||||
char msg[MAX_MSG_SIZE]; /* in case of REP_AUTH_CONTINUE */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* 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 {
|
struct __attribute__ ((__packed__)) cmd_resume_fetch_req_st {
|
||||||
uint8_t session_id_size;
|
uint8_t session_id_size;
|
||||||
uint8_t session_id[GNUTLS_MAX_SESSION_ID];
|
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 {
|
struct __attribute__ ((__packed__)) cmd_resume_store_req_st {
|
||||||
uint8_t session_id_size;
|
uint8_t session_id_size;
|
||||||
uint8_t session_id[GNUTLS_MAX_SESSION_ID];
|
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];
|
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 {
|
struct __attribute__ ((__packed__)) cmd_resume_fetch_reply_st {
|
||||||
uint8_t reply;
|
uint8_t reply;
|
||||||
uint16_t session_data_size;
|
uint16_t session_data_size;
|
||||||
uint8_t session_data[MAX_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 {
|
struct __attribute__ ((__packed__)) cmd_tun_mtu_st {
|
||||||
uint16_t mtu;
|
uint16_t mtu;
|
||||||
};
|
};
|
||||||
|
|||||||
+72
-8
@@ -43,6 +43,7 @@
|
|||||||
#include <ccan/list/list.h>
|
#include <ccan/list/list.h>
|
||||||
#include <main-auth.h>
|
#include <main-auth.h>
|
||||||
#include <plain.h>
|
#include <plain.h>
|
||||||
|
#include <common.h>
|
||||||
#include <pam.h>
|
#include <pam.h>
|
||||||
|
|
||||||
static const struct auth_mod_st *module;
|
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,
|
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];
|
struct iovec iov[2];
|
||||||
uint8_t cmd[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))];
|
char control[CMSG_SPACE(sizeof(int))];
|
||||||
} control_un;
|
} control_un;
|
||||||
struct cmd_auth_reply_st resp;
|
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(&control_un, 0, sizeof(control_un));
|
||||||
memset(&hdr, 0, sizeof(hdr));
|
memset(&hdr, 0, sizeof(hdr));
|
||||||
@@ -86,15 +94,17 @@ int send_auth_reply(main_server_st* s, struct proc_st* proc,
|
|||||||
hdr.msg_iovlen++;
|
hdr.msg_iovlen++;
|
||||||
|
|
||||||
resp.reply = r;
|
resp.reply = r;
|
||||||
memcpy(resp.cookie, proc->cookie, COOKIE_SIZE);
|
memcpy(resp.data.ok.cookie, proc->cookie, COOKIE_SIZE);
|
||||||
memcpy(resp.session_id, proc->session_id, sizeof(resp.session_id));
|
memcpy(resp.data.ok.session_id, proc->session_id, sizeof(resp.data.ok.session_id));
|
||||||
memcpy(resp.vname, proc->lease->name, sizeof(resp.vname));
|
memcpy(resp.data.ok.vname, proc->lease->name, sizeof(resp.data.ok.vname));
|
||||||
memcpy(resp.user, proc->username, sizeof(resp.user));
|
memcpy(resp.data.ok.user, proc->username, sizeof(resp.data.ok.user));
|
||||||
|
|
||||||
iov[1].iov_base = &resp;
|
iov[1].iov_base = &resp;
|
||||||
iov[1].iov_len = sizeof(resp);
|
iov[1].iov_len = sizeof(resp);
|
||||||
hdr.msg_iovlen++;
|
hdr.msg_iovlen++;
|
||||||
|
|
||||||
|
resp.data.ok.routes_size = cfg->routes_size;
|
||||||
|
|
||||||
/* Send the tun fd */
|
/* Send the tun fd */
|
||||||
hdr.msg_control = control_un.control;
|
hdr.msg_control = control_un.control;
|
||||||
hdr.msg_controllen = sizeof(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++;
|
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)
|
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;
|
return -1;
|
||||||
|
|
||||||
memset(&resp, 0, sizeof(resp));
|
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)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|||||||
@@ -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
@@ -112,12 +112,119 @@ int send_udp_fd(main_server_st* s, struct proc_st * proc, int fd)
|
|||||||
return(sendmsg(proc->fd, &hdr, 0));
|
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 handle_script_exit(main_server_st *s, struct proc_st* proc, int code)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (code == 0) {
|
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) {
|
if (ret < 0) {
|
||||||
mslog(s, proc, LOG_ERR, "could not send reply auth cmd.");
|
mslog(s, proc, LOG_ERR, "could not send reply auth cmd.");
|
||||||
ret = ERR_BAD_COMMAND;
|
ret = ERR_BAD_COMMAND;
|
||||||
@@ -125,7 +232,7 @@ int ret;
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mslog(s, proc, LOG_INFO, "failed authentication attempt for user '%s'", proc->username);
|
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) {
|
if (ret < 0) {
|
||||||
mslog(s, proc, LOG_ERR, "could not send reply auth cmd.");
|
mslog(s, proc, LOG_ERR, "could not send reply auth cmd.");
|
||||||
ret = ERR_BAD_COMMAND;
|
ret = ERR_BAD_COMMAND;
|
||||||
|
|||||||
+5
-1
@@ -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 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_msg(main_server_st* s, struct proc_st* proc);
|
||||||
|
|
||||||
int send_auth_reply(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,
|
int handle_auth_cookie_req(main_server_st* s, struct proc_st* proc,
|
||||||
const struct cmd_auth_cookie_req_st * req);
|
const struct cmd_auth_cookie_req_st * req);
|
||||||
int generate_cookie(main_server_st *s, struct proc_st* proc);
|
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);
|
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
|
#endif
|
||||||
|
|||||||
+4
-4
@@ -2,7 +2,7 @@
|
|||||||
*
|
*
|
||||||
* DO NOT EDIT THIS FILE (ocserv-args.c)
|
* 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
|
* From the definitions ocserv-args.def
|
||||||
* and the template file options
|
* and the template file options
|
||||||
*
|
*
|
||||||
@@ -66,7 +66,7 @@ extern FILE * option_usage_fp;
|
|||||||
* ocserv option static const strings
|
* ocserv option static const strings
|
||||||
*/
|
*/
|
||||||
static char const ocserv_opt_strs[1834] =
|
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"
|
"Copyright (C) 2013 Nikos Mavrogiannopoulos, all rights reserved.\n"
|
||||||
"This is free software. It is licensed for use, modification and\n"
|
"This is free software. It is licensed for use, modification and\n"
|
||||||
"redistribution under the terms of the\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"
|
/* 1129 */ "Output version information and exit\0"
|
||||||
/* 1165 */ "version\0"
|
/* 1165 */ "version\0"
|
||||||
/* 1173 */ "OCSERV\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"
|
"USAGE: %s [ -<flag> [<val>] | --<name>[{=| }<val>] ]...\n\0"
|
||||||
/* 1279 */ "openconnect-devel@lists.infradead.org\0"
|
/* 1279 */ "openconnect-devel@lists.infradead.org\0"
|
||||||
/* 1317 */ "\n\n\0"
|
/* 1317 */ "\n\n\0"
|
||||||
@@ -111,7 +111,7 @@ static char const ocserv_opt_strs[1834] =
|
|||||||
"certificate authentication. Authenticated users are assigned an\n"
|
"certificate authentication. Authenticated users are assigned an\n"
|
||||||
"unprivileged worker process and obtain a networking (tun) device and an IP\n"
|
"unprivileged worker process and obtain a networking (tun) device and an IP\n"
|
||||||
"from a configurable pool of addresses.\n\0"
|
"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"
|
/* 1759 */ "Usage: ocserv [options] -c [config]\n"
|
||||||
"ocserv --help for usage instructions.\n";
|
"ocserv --help for usage instructions.\n";
|
||||||
|
|
||||||
|
|||||||
@@ -260,6 +260,13 @@ output-buffer = 10
|
|||||||
route = 192.168.1.0/255.255.255.0
|
route = 192.168.1.0/255.255.255.0
|
||||||
route = 192.168.5.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
|
# The following options are for (experimental) AnyConnect client
|
||||||
# compatibility.
|
# compatibility.
|
||||||
|
|||||||
+3
-3
@@ -2,7 +2,7 @@
|
|||||||
*
|
*
|
||||||
* DO NOT EDIT THIS FILE (ocserv-args.h)
|
* 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
|
* From the definitions ocserv-args.def
|
||||||
* and the template file options
|
* and the template file options
|
||||||
*
|
*
|
||||||
@@ -76,8 +76,8 @@ typedef enum {
|
|||||||
} teOptIndex;
|
} teOptIndex;
|
||||||
|
|
||||||
#define OPTION_CT 7
|
#define OPTION_CT 7
|
||||||
#define OCSERV_VERSION "0.1.6"
|
#define OCSERV_VERSION "0.1.7"
|
||||||
#define OCSERV_FULL_VERSION "ocserv 0.1.6"
|
#define OCSERV_FULL_VERSION "ocserv 0.1.7"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Interface defines for all options. Replace "n" with the UPPER_CASED
|
* Interface defines for all options. Replace "n" with the UPPER_CASED
|
||||||
|
|||||||
@@ -47,6 +47,8 @@ extern int syslog_open;
|
|||||||
#define ERR_AUTH_CONTINUE -4
|
#define ERR_AUTH_CONTINUE -4
|
||||||
#define ERR_WAIT_FOR_SCRIPT -5
|
#define ERR_WAIT_FOR_SCRIPT -5
|
||||||
#define ERR_MEM -6
|
#define ERR_MEM -6
|
||||||
|
#define ERR_READ_ROUTES -7
|
||||||
|
#define ERR_READ_CONFIG -8
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@@ -54,6 +56,14 @@ typedef struct
|
|||||||
unsigned int entries;
|
unsigned int entries;
|
||||||
} hash_db_st;
|
} hash_db_st;
|
||||||
|
|
||||||
|
struct group_cfg_st {
|
||||||
|
char **routes;
|
||||||
|
unsigned int routes_size;
|
||||||
|
|
||||||
|
char *ipv4_dns;
|
||||||
|
char *ipv6_dns;
|
||||||
|
};
|
||||||
|
|
||||||
struct vpn_st {
|
struct vpn_st {
|
||||||
char *name; /* device name */
|
char *name; /* device name */
|
||||||
char *ipv4_netmask;
|
char *ipv4_netmask;
|
||||||
@@ -127,6 +137,10 @@ struct cfg_st {
|
|||||||
|
|
||||||
uid_t uid;
|
uid_t uid;
|
||||||
gid_t gid;
|
gid_t gid;
|
||||||
|
|
||||||
|
/* additional configuration files */
|
||||||
|
char *per_group_dir;
|
||||||
|
char *per_user_dir;
|
||||||
|
|
||||||
/* the tun network */
|
/* the tun network */
|
||||||
struct vpn_st network;
|
struct vpn_st network;
|
||||||
@@ -144,6 +158,10 @@ struct main_server_st;
|
|||||||
#define MAX_GROUPNAME_SIZE MAX_USERNAME_SIZE
|
#define MAX_GROUPNAME_SIZE MAX_USERNAME_SIZE
|
||||||
#define MAX_SESSION_DATA_SIZE (4*1024)
|
#define MAX_SESSION_DATA_SIZE (4*1024)
|
||||||
|
|
||||||
|
#define MAX_CONFIG_ENTRIES 64
|
||||||
|
|
||||||
|
#define MAX_ROUTES 32
|
||||||
|
|
||||||
#include <tun.h>
|
#include <tun.h>
|
||||||
|
|
||||||
const char *human_addr(const struct sockaddr *sa, socklen_t salen,
|
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_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))
|
#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
|
#endif
|
||||||
|
|||||||
+75
-8
@@ -37,6 +37,7 @@
|
|||||||
#include "html.h"
|
#include "html.h"
|
||||||
#include <worker.h>
|
#include <worker.h>
|
||||||
#include <cookies.h>
|
#include <cookies.h>
|
||||||
|
#include <common.h>
|
||||||
#include <tlslib.h>
|
#include <tlslib.h>
|
||||||
|
|
||||||
#include <http-parser/http_parser.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)
|
static int recv_auth_reply(worker_st *ws, struct cmd_auth_reply_st *resp)
|
||||||
{
|
{
|
||||||
struct iovec iov[2];
|
struct iovec iov[2];
|
||||||
uint8_t cmd = 0;
|
uint8_t cmd = 0, len;
|
||||||
struct msghdr hdr;
|
struct msghdr hdr;
|
||||||
int ret, cmdlen;
|
int ret, cmdlen;
|
||||||
union {
|
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))];
|
char control[CMSG_SPACE(sizeof(int))];
|
||||||
} control_un;
|
} control_un;
|
||||||
struct cmsghdr *cmptr;
|
struct cmsghdr *cmptr;
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
iov[0].iov_base = &cmd;
|
iov[0].iov_base = &cmd;
|
||||||
iov[0].iov_len = 1;
|
iov[0].iov_len = 1;
|
||||||
|
|
||||||
iov[1].iov_base = resp;
|
iov[1].iov_base = resp;
|
||||||
iov[1].iov_len = sizeof(*resp);
|
iov[1].iov_len = sizeof(*resp);
|
||||||
|
|
||||||
memset(&hdr, 0, sizeof(hdr));
|
memset(&hdr, 0, sizeof(hdr));
|
||||||
hdr.msg_iov = iov;
|
hdr.msg_iov = iov;
|
||||||
hdr.msg_iovlen = 2;
|
hdr.msg_iovlen = 2 + MAX_ROUTES;
|
||||||
|
|
||||||
hdr.msg_control = control_un.control;
|
hdr.msg_control = control_un.control;
|
||||||
hdr.msg_controllen = sizeof(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;
|
return ERR_AUTH_FAIL;
|
||||||
|
|
||||||
memcpy(&ws->tun_fd, CMSG_DATA(cmptr), sizeof(int));
|
memcpy(&ws->tun_fd, CMSG_DATA(cmptr), sizeof(int));
|
||||||
memcpy(ws->tun_name, resp->vname, sizeof(ws->tun_name));
|
memcpy(ws->tun_name, resp->data.ok.vname, sizeof(ws->tun_name));
|
||||||
memcpy(ws->username, resp->user, sizeof(ws->username));
|
memcpy(ws->username, resp->data.ok.user, sizeof(ws->username));
|
||||||
memcpy(ws->cookie, resp->cookie, sizeof(ws->cookie));
|
memcpy(ws->cookie, resp->data.ok.cookie, sizeof(ws->cookie));
|
||||||
memcpy(ws->session_id, resp->session_id, sizeof(ws->session_id));
|
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
|
} else
|
||||||
return ERR_AUTH_FAIL;
|
return ERR_AUTH_FAIL;
|
||||||
break;
|
break;
|
||||||
@@ -655,7 +722,7 @@ struct cmd_auth_reply_st resp;
|
|||||||
ret = recv_auth_reply(ws, &resp);
|
ret = recv_auth_reply(ws, &resp);
|
||||||
if (ret == ERR_AUTH_CONTINUE) {
|
if (ret == ERR_AUTH_CONTINUE) {
|
||||||
ws->auth_state = S_AUTH_REQ;
|
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)
|
} else if (ret < 0)
|
||||||
goto auth_fail;
|
goto auth_fail;
|
||||||
|
|
||||||
|
|||||||
+21
-2
@@ -853,7 +853,11 @@ socklen_t sl;
|
|||||||
ret = tls_printf(ws->session, "X-CSTP-Netmask: %s\r\n", vinfo.ipv4_netmask);
|
ret = tls_printf(ws->session, "X-CSTP-Netmask: %s\r\n", vinfo.ipv4_netmask);
|
||||||
SEND_ERR(ret);
|
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);
|
ret = tls_printf(ws->session, "X-CSTP-DNS: %s\r\n", vinfo.ipv4_dns);
|
||||||
SEND_ERR(ret);
|
SEND_ERR(ret);
|
||||||
}
|
}
|
||||||
@@ -872,7 +876,11 @@ socklen_t sl;
|
|||||||
ret = tls_printf(ws->session, "X-CSTP-Netmask: %s\r\n", vinfo.ipv6_netmask);
|
ret = tls_printf(ws->session, "X-CSTP-Netmask: %s\r\n", vinfo.ipv6_netmask);
|
||||||
SEND_ERR(ret);
|
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);
|
ret = tls_printf(ws->session, "X-CSTP-DNS: %s\r\n", vinfo.ipv6_dns);
|
||||||
SEND_ERR(ret);
|
SEND_ERR(ret);
|
||||||
}
|
}
|
||||||
@@ -892,6 +900,17 @@ socklen_t sl;
|
|||||||
"X-CSTP-Split-Include: %s\r\n", vinfo.routes[i]);
|
"X-CSTP-Split-Include: %s\r\n", vinfo.routes[i]);
|
||||||
SEND_ERR(ret);
|
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);
|
ret = tls_printf(ws->session, "X-CSTP-Keepalive: %u\r\n", ws->config->keepalive);
|
||||||
SEND_ERR(ret);
|
SEND_ERR(ret);
|
||||||
|
|
||||||
|
|||||||
+6
-1
@@ -118,6 +118,12 @@ typedef struct worker_st {
|
|||||||
unsigned cert_auth_ok;
|
unsigned cert_auth_ok;
|
||||||
int tun_fd;
|
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;
|
struct http_req_st req;
|
||||||
} worker_st;
|
} worker_st;
|
||||||
|
|
||||||
@@ -142,7 +148,6 @@ void __attribute__ ((format(printf, 3, 4)))
|
|||||||
|
|
||||||
int get_rt_vpn_info(worker_st * ws,
|
int get_rt_vpn_info(worker_st * ws,
|
||||||
struct vpn_st* vinfo, char* buffer, size_t buffer_size);
|
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 send_tun_mtu(worker_st *ws, unsigned int mtu);
|
||||||
int handle_worker_commands(struct worker_st *ws);
|
int handle_worker_commands(struct worker_st *ws);
|
||||||
|
|||||||
Reference in New Issue
Block a user