Supplementary configuration is now read by the security module.

That allows sec-mod to handle both authentication and accounting.
That deprecates the session-control configuration option.
This commit is contained in:
Nikos Mavrogiannopoulos
2014-12-08 12:56:16 +01:00
parent 8365449e9b
commit baa3e4701e
18 changed files with 289 additions and 170 deletions

View File

@@ -73,7 +73,7 @@ ocserv_SOURCES = main.c main-auth.c worker-vpn.c worker-auth.c tlslib.c \
sec-mod.c sec-mod-db.c sec-mod-auth.c sec-mod-auth.h sec-mod.h sec-mod-ban.c \ sec-mod.c sec-mod-db.c sec-mod-auth.c sec-mod-auth.h sec-mod.h sec-mod-ban.c \
script-list.h $(COMMON_SOURCES) $(AUTH_SOURCES) \ script-list.h $(COMMON_SOURCES) $(AUTH_SOURCES) \
icmp-ping.c icmp-ping.h \ icmp-ping.c icmp-ping.h \
main-sup-config.c main-sup-config.h \ sec-mod-sup-config.c sec-mod-sup-config.h \
sup-config/file.c sup-config/file.h \ sup-config/file.c sup-config/file.h \
worker-bandwidth.c worker-bandwidth.h ctl.h main-ctl.h \ worker-bandwidth.c worker-bandwidth.h ctl.h main-ctl.h \
vasprintf.c vasprintf.h \ vasprintf.c vasprintf.h \

View File

@@ -1,5 +1,6 @@
/* /*
* Copyright (C) 2013 Nikos Mavrogiannopoulos * Copyright (C) 2013, 2014 Nikos Mavrogiannopoulos
* Copyright (C) 2014 Red Hat, Inc.
* *
* Author: Nikos Mavrogiannopoulos * Author: Nikos Mavrogiannopoulos
* *

View File

@@ -452,8 +452,9 @@ unsigned force_cert_auth;
if (config->occtl_socket_file == NULL) if (config->occtl_socket_file == NULL)
config->occtl_socket_file = talloc_strdup(config, OCCTL_UNIX_SOCKET); config->occtl_socket_file = talloc_strdup(config, OCCTL_UNIX_SOCKET);
if (config->auth_types & AUTH_TYPE_USERNAME_PASS) { val = get_option("session-control", NULL);
READ_TF("session-control", config->session_control, 0); if (val != NULL) {
fprintf(stderr, "The option 'session-control' is deprecated\n");
} }
READ_STRING("banner", config->banner); READ_STRING("banner", config->banner);

View File

@@ -141,7 +141,34 @@ int get_ipv4_lease(main_server_st* s, struct proc_st* proc)
int ret; int ret;
const char* c_network, *c_netmask; const char* c_network, *c_netmask;
char buf[64]; char buf[64];
if (proc->config.explicit_ipv4) {
/* if an explicit IP is given for that client, then
* don't do any IP accounting */
ret =
inet_pton(AF_INET, proc->config.explicit_ipv4, SA_IN_P(&network));
if (ret != 1) {
mslog(s, NULL, LOG_ERR, "error reading explicit IP: %s", proc->config.explicit_ipv4);
return -1;
}
proc->ipv4 = talloc_zero(proc, struct ip_lease_st);
if (proc->ipv4 == NULL)
return ERR_MEM;
((struct sockaddr_in*)&network)->sin_family = AF_INET;
((struct sockaddr_in*)&network)->sin_port = 0;
memcpy(&proc->ipv4->lip, &network, sizeof(struct sockaddr_in));
proc->ipv4->lip_len = sizeof(struct sockaddr_in);
memcpy(&proc->ipv4->rip, &network, sizeof(struct sockaddr_in));
proc->ipv4->rip_len = sizeof(struct sockaddr_in);
return 0;
}
/* Our IP accounting */
if (proc->config.ipv4_network && proc->config.ipv4_netmask) { if (proc->config.ipv4_network && proc->config.ipv4_netmask) {
c_network = proc->config.ipv4_network; c_network = proc->config.ipv4_network;
c_netmask = proc->config.ipv4_netmask; c_netmask = proc->config.ipv4_netmask;
@@ -277,6 +304,32 @@ int get_ipv6_lease(main_server_st* s, struct proc_st* proc)
char *c_netmask = NULL; char *c_netmask = NULL;
char buf[64]; char buf[64];
if (proc->config.explicit_ipv6) {
/* if an explicit IP is given for that client, then
* don't do any IP accounting */
ret =
inet_pton(AF_INET6, proc->config.explicit_ipv6, SA_IN6_P(&network));
if (ret != 1) {
mslog(s, NULL, LOG_ERR, "error reading explicit IP: %s", proc->config.explicit_ipv6);
return -1;
}
proc->ipv6 = talloc_zero(proc, struct ip_lease_st);
if (proc->ipv6 == NULL)
return ERR_MEM;
((struct sockaddr_in6*)&network)->sin6_family = AF_INET6;
((struct sockaddr_in6*)&network)->sin6_port = 0;
memcpy(&proc->ipv6->lip, &network, sizeof(struct sockaddr_in6));
proc->ipv6->lip_len = sizeof(struct sockaddr_in6);
memcpy(&proc->ipv6->rip, &network, sizeof(struct sockaddr_in6));
proc->ipv6->rip_len = sizeof(struct sockaddr_in6);
return 0;
}
if (proc->config.ipv6_network && proc->config.ipv6_prefix) { if (proc->config.ipv6_network && proc->config.ipv6_prefix) {
c_network = proc->config.ipv6_network; c_network = proc->config.ipv6_network;
c_netmask = ipv6_prefix_to_mask(proc, proc->config.ipv6_prefix); c_netmask = ipv6_prefix_to_mask(proc, proc->config.ipv6_prefix);
@@ -401,7 +454,7 @@ fail:
} }
static static
int unref_ip_lease(struct ip_lease_st * lease) int unref_ip_lease(struct ip_lease_st *lease)
{ {
if (lease->db) { if (lease->db) {
htable_del(&lease->db->ht, rehash(lease, NULL), lease); htable_del(&lease->db->ht, rehash(lease, NULL), lease);
@@ -409,7 +462,7 @@ int unref_ip_lease(struct ip_lease_st * lease)
return 0; return 0;
} }
int get_ip_leases(main_server_st* s, struct proc_st* proc) int get_ip_leases(main_server_st *s, struct proc_st *proc)
{ {
int ret; int ret;
char buf[128]; char buf[128];
@@ -419,7 +472,7 @@ char buf[128];
if (ret < 0) if (ret < 0)
return ret; return ret;
if (proc->ipv4) { if (proc->ipv4 && proc->ipv4->db) {
if (htable_add(&s->ip_leases.ht, rehash(proc->ipv4, NULL), proc->ipv4) == 0) { if (htable_add(&s->ip_leases.ht, rehash(proc->ipv4, NULL), proc->ipv4) == 0) {
mslog(s, proc, LOG_ERR, "could not add IPv4 lease to hash table."); mslog(s, proc, LOG_ERR, "could not add IPv4 lease to hash table.");
return -1; return -1;
@@ -433,7 +486,7 @@ char buf[128];
if (ret < 0) if (ret < 0)
return ret; return ret;
if (proc->ipv6) { if (proc->ipv6 && proc->ipv4->db) {
if (htable_add(&s->ip_leases.ht, rehash(proc->ipv6, NULL), proc->ipv6) == 0) { if (htable_add(&s->ip_leases.ht, rehash(proc->ipv6, NULL), proc->ipv6) == 0) {
mslog(s, proc, LOG_ERR, "could not add IPv6 lease to hash table."); mslog(s, proc, LOG_ERR, "could not add IPv6 lease to hash table.");
return -1; return -1;

View File

@@ -192,4 +192,24 @@ message sec_auth_session_msg
message sec_auth_session_reply_msg message sec_auth_session_reply_msg
{ {
required AUTH_REP reply = 1; required AUTH_REP reply = 1;
/* sup - config */
optional bool no_udp = 10;
optional bool deny_roaming = 11;
optional bool require_cert = 12;
repeated string routes = 13;
repeated string iroutes = 14;
repeated string dns = 15;
repeated string nbns = 16;
optional string ipv4_net = 17;
optional string ipv4_netmask = 18;
optional string ipv6_net = 19;
optional uint32 ipv6_prefix = 20;
optional string cgroup = 21;
optional string xml_config_file = 22;
optional uint32 rx_per_sec = 23;
optional uint32 tx_per_sec = 24;
optional uint32 net_priority = 25;
optional string explicit_ipv4 = 26;
optional string explicit_ipv6 = 27;
} }

View File

@@ -36,7 +36,6 @@
#include <script-list.h> #include <script-list.h>
#include <ip-lease.h> #include <ip-lease.h>
#include <proc-search.h> #include <proc-search.h>
#include <main-sup-config.h>
#include "str.h" #include "str.h"
#include <vpn.h> #include <vpn.h>
@@ -209,17 +208,16 @@ struct cookie_entry_st *old;
memset(&proc->config, 0, sizeof(proc->config)); memset(&proc->config, 0, sizeof(proc->config));
apply_default_sup_config(s->config, proc); apply_default_sup_config(s->config, proc);
if (s->config_module) { /* loads sup config */
ret = s->config_module->get_sup_config(s->config, proc); ret = session_open(s, proc);
if (ret < 0) { if (ret < 0) {
mslog(s, proc, LOG_ERR, mslog(s, proc, LOG_INFO, "could not open session");
"error reading additional configuration"); return -1;
return ERR_READ_CONFIG; }
}
if (proc->config.cgroup != NULL) { /* Put into right cgroup */
put_into_cgroup(s, proc->config.cgroup, proc->pid); if (proc->config.cgroup != NULL) {
} put_into_cgroup(s, proc->config.cgroup, proc->pid);
} }
/* check whether the cookie IP matches */ /* check whether the cookie IP matches */
@@ -283,12 +281,6 @@ struct cookie_entry_st *old;
memcpy(proc->ipv4_seed, &cmsg->ipv4_seed, sizeof(proc->ipv4_seed)); memcpy(proc->ipv4_seed, &cmsg->ipv4_seed, sizeof(proc->ipv4_seed));
ret = session_open(s, proc);
if (ret < 0) {
mslog(s, proc, LOG_INFO, "could not open session");
return -1;
}
/* add the links to proc hash */ /* add the links to proc hash */
proc_table_add(s, proc); proc_table_add(s, proc);

View File

@@ -46,7 +46,6 @@
#include <proc-search.h> #include <proc-search.h>
#include <ipc.pb-c.h> #include <ipc.pb-c.h>
#include <script-list.h> #include <script-list.h>
#include <main-sup-config.h>
#ifdef HAVE_MALLOC_TRIM #ifdef HAVE_MALLOC_TRIM
# include <malloc.h> # include <malloc.h>
@@ -168,10 +167,8 @@ int session_cmd(main_server_st * s, struct proc_st *proc, unsigned open)
int sd, ret, e; int sd, ret, e;
SecAuthSessionMsg ireq = SEC_AUTH_SESSION_MSG__INIT; SecAuthSessionMsg ireq = SEC_AUTH_SESSION_MSG__INIT;
SecAuthSessionReplyMsg *msg = NULL; SecAuthSessionReplyMsg *msg = NULL;
unsigned type; unsigned type, i;
PROTOBUF_ALLOCATOR(pa, proc);
if (s->config->session_control == 0)
return 0;
if (open) if (open)
type = SM_CMD_AUTH_SESSION_OPEN; type = SM_CMD_AUTH_SESSION_OPEN;
@@ -227,6 +224,86 @@ int session_cmd(main_server_st * s, struct proc_st *proc, unsigned open)
mslog(s, proc, LOG_INFO, "could not initiate session for '%s'", proc->username); mslog(s, proc, LOG_INFO, "could not initiate session for '%s'", proc->username);
return -1; return -1;
} }
/* fill in group_cfg_st */
if (msg->has_no_udp)
proc->config.no_udp = msg->no_udp;
if (msg->has_deny_roaming)
proc->config.deny_roaming = msg->deny_roaming;
if (msg->has_require_cert)
proc->config.require_cert = msg->require_cert;
if (msg->has_ipv6_prefix)
proc->config.ipv6_prefix = msg->ipv6_prefix;
if (msg->rx_per_sec)
proc->config.rx_per_sec = msg->rx_per_sec;
if (msg->tx_per_sec)
proc->config.tx_per_sec = msg->tx_per_sec;
if (msg->net_priority)
proc->config.net_priority = msg->net_priority;
if (msg->ipv4_net) {
proc->config.ipv4_network = talloc_strdup(proc, msg->ipv4_net);
}
if (msg->ipv4_netmask) {
proc->config.ipv4_netmask = talloc_strdup(proc, msg->ipv4_netmask);
}
if (msg->ipv6_net) {
proc->config.ipv6_network = talloc_strdup(proc, msg->ipv6_net);
}
if (msg->cgroup) {
proc->config.cgroup = talloc_strdup(proc, msg->cgroup);
}
if (msg->xml_config_file) {
proc->config.xml_config_file = talloc_strdup(proc, msg->xml_config_file);
}
if (msg->explicit_ipv4) {
proc->config.explicit_ipv4 = talloc_strdup(proc, msg->explicit_ipv4);
}
if (msg->explicit_ipv6) {
proc->config.explicit_ipv6 = talloc_strdup(proc, msg->explicit_ipv6);
}
if (msg->n_routes > 0) {
proc->config.routes = talloc_size(proc, sizeof(char*)*msg->n_routes);
for (i=0;i<msg->n_routes;i++) {
proc->config.routes[i] = talloc_strdup(proc, msg->routes[i]);
}
proc->config.routes_size = msg->n_routes;
}
if (msg->n_iroutes > 0) {
proc->config.iroutes = talloc_size(proc, sizeof(char*)*msg->n_iroutes);
for (i=0;i<msg->n_iroutes;i++) {
proc->config.iroutes[i] = talloc_strdup(proc, msg->iroutes[i]);
}
proc->config.iroutes_size = msg->n_iroutes;
}
if (msg->n_dns > 0) {
proc->config.dns = talloc_size(proc, sizeof(char*)*msg->n_dns);
for (i=0;i<msg->n_dns;i++) {
proc->config.dns[i] = talloc_strdup(proc, msg->dns[i]);
}
proc->config.dns_size = msg->n_dns;
}
if (msg->n_nbns > 0) {
proc->config.nbns = talloc_size(proc, sizeof(char*)*msg->n_nbns);
for (i=0;i<msg->n_nbns;i++) {
proc->config.nbns[i] = talloc_strdup(proc, msg->nbns[i]);
}
proc->config.nbns_size = msg->n_nbns;
}
sec_auth_session_reply_msg__free_unpacked(msg, &pa);
} else { } else {
close(sd); close(sd);
} }
@@ -262,7 +339,7 @@ void remove_proc(main_server_st * s, struct proc_st *proc, unsigned k)
} }
/* close any pending sessions */ /* close any pending sessions */
if (s->config->session_control != 0 && proc->active_sid) { if (proc->active_sid) {
session_close(s, proc); session_close(s, proc);
} }
@@ -273,26 +350,17 @@ void remove_proc(main_server_st * s, struct proc_st *proc, unsigned k)
proc->pid = -1; proc->pid = -1;
remove_iroutes(s, proc); remove_iroutes(s, proc);
if (s->config_module) {
s->config_module->clear_sup_config(&proc->config);
}
if (proc->ipv4 || proc->ipv6) if (proc->ipv4 || proc->ipv6)
remove_ip_leases(s, proc); remove_ip_leases(s, proc);
/* expire any available cookies */ /* expire any available cookies */
if (proc->cookie_ptr) { if (proc->cookie_ptr) {
unsigned timeout = s->config->cookie_timeout;
proc->cookie_ptr->proc = NULL; proc->cookie_ptr->proc = NULL;
if (s->config->session_control != 0) { /* if we use session control and we closed the session we
/* if we use session control and we closed the session we * need to invalidate the cookie, so that a new session is
* need to invalidate the cookie, so that a new session is * used on the next connection */
* used on the next connection */ proc->cookie_ptr->expiration = 1;
proc->cookie_ptr->expiration = 1;
} else {
proc->cookie_ptr->expiration = time(0) + timeout;
}
} }
close_tun(s, proc); close_tun(s, proc);

View File

@@ -51,7 +51,6 @@
# include <systemd/sd-daemon.h> # include <systemd/sd-daemon.h>
#endif #endif
#include <main.h> #include <main.h>
#include <main-sup-config.h>
#include <main-ctl.h> #include <main-ctl.h>
#include <route-add.h> #include <route-add.h>
#include <worker.h> #include <worker.h>
@@ -987,8 +986,6 @@ int main(int argc, char** argv)
run_sec_mod(s); run_sec_mod(s);
sup_config_init(s);
ret = ctl_handler_init(s); ret = ctl_handler_init(s);
if (ret < 0) { if (ret < 0) {
fprintf(stderr, "Cannot create command handler\n"); fprintf(stderr, "Cannot create command handler\n");

View File

@@ -213,7 +213,6 @@ typedef struct main_server_st {
time_t start_time; time_t start_time;
void * auth_extra; void * auth_extra;
struct config_mod_st *config_module;
#ifdef HAVE_DBUS #ifdef HAVE_DBUS
void * ctl_ctx; void * ctl_ctx;

View File

@@ -96,12 +96,6 @@ An example configuration file follows.
# to generate password entries. # to generate password entries.
#auth = "plain[/etc/ocserv/ocpasswd]" #auth = "plain[/etc/ocserv/ocpasswd]"
# Whether to enable the authentication method's session control (i.e., PAM).
# That requires more resources on the server, and makes cookies one-time-use;
# thus don't enable unless you need it. That should be used when you have an
# accounting system in place with the PAM modules.
#session-control = true
# Whether to enable seccomp worker isolation. That restricts the number of # Whether to enable seccomp worker isolation. That restricts the number of
# system calls allowed to a worker process, in order to reduce damage from a # system calls allowed to a worker process, in order to reduce damage from a
# bug in the worker process. It is available on Linux systems at a performance cost. # bug in the worker process. It is available on Linux systems at a performance cost.

View File

@@ -49,6 +49,7 @@
#include <auth/pam.h> #include <auth/pam.h>
#include <sec-mod.h> #include <sec-mod.h>
#include <vpn.h> #include <vpn.h>
#include <sec-mod-sup-config.h>
static const struct auth_mod_st *module = NULL; static const struct auth_mod_st *module = NULL;
@@ -106,6 +107,7 @@ int send_sec_auth_reply(sec_mod_st * sec, client_entry_st * entry, AUTHREP r)
{ {
SecAuthReplyMsg msg = SEC_AUTH_REPLY_MSG__INIT; SecAuthReplyMsg msg = SEC_AUTH_REPLY_MSG__INIT;
int ret; int ret;
void *pool = NULL;
if (r == AUTH__REP__OK) { if (r == AUTH__REP__OK) {
/* fill message */ /* fill message */
@@ -135,6 +137,7 @@ int send_sec_auth_reply(sec_mod_st * sec, client_entry_st * entry, AUTHREP r)
(pack_size_func) (pack_size_func)
sec_auth_reply_msg__get_packed_size, sec_auth_reply_msg__get_packed_size,
(pack_func) sec_auth_reply_msg__pack); (pack_func) sec_auth_reply_msg__pack);
talloc_free(pool);
} else { } else {
msg.reply = AUTH__REP__FAILED; msg.reply = AUTH__REP__FAILED;
@@ -279,9 +282,6 @@ int handle_sec_auth_res(sec_mod_st * sec, client_entry_st * e, int result)
} }
ret = 0; ret = 0;
if (module != NULL && (sec->config->session_control == 0 || module->open_session == NULL)) {
del_client_entry(sec, e);
} /* else do nothing, and wait for session close/open messages */
} else { } else {
e->status = PS_AUTH_FAILED; e->status = PS_AUTH_FAILED;
add_ip_to_ban_list(sec, e->ip, time(0) + sec->config->min_reauth_time); add_ip_to_ban_list(sec, e->ip, time(0) + sec->config->min_reauth_time);
@@ -305,19 +305,12 @@ int handle_sec_auth_res(sec_mod_st * sec, client_entry_st * e, int result)
/* opens or closes a session. /* opens or closes a session.
*/ */
int handle_sec_auth_session_cmd(sec_mod_st * sec, const SecAuthSessionMsg * req, unsigned cmd) int handle_sec_auth_session_cmd(sec_mod_st * sec, const SecAuthSessionMsg * req,
unsigned cmd, client_entry_st **r_entry)
{ {
client_entry_st *e; client_entry_st *e;
int ret; int ret;
if (module == NULL || module->open_session == NULL)
return 0;
if (sec->config->session_control == 0) {
seclog(sec, LOG_ERR, "auth session open/close but session control is disabled!");
return 0;
}
if (req->sid.len != SID_SIZE) { if (req->sid.len != SID_SIZE) {
seclog(sec, LOG_ERR, "auth session open/close but with illegal sid size (%d)!", seclog(sec, LOG_ERR, "auth session open/close but with illegal sid size (%d)!",
(int)req->sid.len); (int)req->sid.len);
@@ -331,6 +324,13 @@ int handle_sec_auth_session_cmd(sec_mod_st * sec, const SecAuthSessionMsg * req,
} }
if (cmd == SM_CMD_AUTH_SESSION_OPEN) { if (cmd == SM_CMD_AUTH_SESSION_OPEN) {
if (r_entry) {
*r_entry = e;
}
if (module == NULL || module->open_session == NULL)
return 0;
ret = module->open_session(e->auth_ctx); ret = module->open_session(e->auth_ctx);
if (ret < 0) { if (ret < 0) {
e->status = PS_AUTH_FAILED; e->status = PS_AUTH_FAILED;

View File

@@ -27,11 +27,11 @@
#include <main.h> #include <main.h>
#include <common.h> #include <common.h>
#include <vpn.h> #include <vpn.h>
#include <main-sup-config.h> #include <sec-mod-sup-config.h>
#include <sup-config/file.h> #include <sup-config/file.h>
void sup_config_init(main_server_st *s) void sup_config_init(sec_mod_st *sec)
{ {
s->config_module = &file_sup_config; sec->config_module = &file_sup_config;
} }

View File

@@ -21,16 +21,16 @@
#ifndef SUP_CONFIG_H #ifndef SUP_CONFIG_H
# define SUP_CONFIG_H # define SUP_CONFIG_H
#include <main.h> #include <sec-mod.h>
/* The get_sup_config() should read any additional configuration for /* The get_sup_config() should read any additional configuration for
* proc->username/proc->groupname and save it in proc->config. * proc->username/proc->groupname and save it in proc->config.
*/ */
struct config_mod_st { struct config_mod_st {
int (*get_sup_config)(struct cfg_st *global_config, struct proc_st *proc); int (*get_sup_config)(struct cfg_st *global_config, client_entry_st *entry,
void (*clear_sup_config)(struct group_cfg_st *out); SecAuthSessionReplyMsg *msg, void *pool);
}; };
void sup_config_init(main_server_st *s); void sup_config_init(sec_mod_st *sec);
#endif #endif

View File

@@ -40,6 +40,7 @@
#include <sec-mod.h> #include <sec-mod.h>
#include <tlslib.h> #include <tlslib.h>
#include <ipc.pb-c.h> #include <ipc.pb-c.h>
#include <sec-mod-sup-config.h>
#include <gnutls/gnutls.h> #include <gnutls/gnutls.h>
#include <gnutls/abstract.h> #include <gnutls/abstract.h>
@@ -281,7 +282,9 @@ int process_packet(void *pool, sec_mod_st * sec, cmd_request_t cmd,
case SM_CMD_AUTH_SESSION_OPEN: case SM_CMD_AUTH_SESSION_OPEN:
case SM_CMD_AUTH_SESSION_CLOSE:{ case SM_CMD_AUTH_SESSION_CLOSE:{
SecAuthSessionMsg *msg; SecAuthSessionMsg *msg;
void *lpool = NULL;
SecAuthSessionReplyMsg rep = SEC_AUTH_SESSION_REPLY_MSG__INIT; SecAuthSessionReplyMsg rep = SEC_AUTH_SESSION_REPLY_MSG__INIT;
client_entry_st *e = NULL;
if (uid != 0) { if (uid != 0) {
seclog(sec, LOG_INFO, "received session open/close from unauthorized uid (%u)\n", (unsigned)uid); seclog(sec, LOG_INFO, "received session open/close from unauthorized uid (%u)\n", (unsigned)uid);
@@ -296,21 +299,36 @@ int process_packet(void *pool, sec_mod_st * sec, cmd_request_t cmd,
return -1; return -1;
} }
ret = handle_sec_auth_session_cmd(sec, msg, cmd); ret = handle_sec_auth_session_cmd(sec, msg, cmd, &e);
sec_auth_session_msg__free_unpacked(msg, &pa); sec_auth_session_msg__free_unpacked(msg, &pa);
if (cmd == SM_CMD_AUTH_SESSION_OPEN) { if (cmd == SM_CMD_AUTH_SESSION_OPEN) {
if (ret < 0) if (ret < 0 || e == NULL)
rep.reply = AUTH__REP__FAILED; rep.reply = AUTH__REP__FAILED;
else else
rep.reply = AUTH__REP__OK; rep.reply = AUTH__REP__OK;
if (sec->config_module && e != NULL) {
lpool = talloc_new(e);
if (lpool == NULL) {
return ERR_MEM;
}
ret = sec->config_module->get_sup_config(sec->config, e, &rep, lpool);
if (ret < 0) {
seclog(sec, LOG_ERR, "error reading additional configuration for '%s'", e->username);
talloc_free(lpool);
return ERR_READ_CONFIG;
}
}
ret = send_msg(pool, sec->fd, SM_CMD_AUTH_SESSION_REPLY, &rep, ret = send_msg(pool, sec->fd, SM_CMD_AUTH_SESSION_REPLY, &rep,
(pack_size_func) sec_auth_session_reply_msg__get_packed_size, (pack_size_func) sec_auth_session_reply_msg__get_packed_size,
(pack_func) sec_auth_session_reply_msg__pack); (pack_func) sec_auth_session_reply_msg__pack);
if (ret < 0) { if (ret < 0) {
seclog(sec, LOG_WARNING, "sec-mod error in sending session reply"); seclog(sec, LOG_WARNING, "sec-mod error in sending session reply");
} }
talloc_free(lpool);
} }
return ret; return ret;
@@ -435,6 +453,8 @@ void sec_mod_server(void *main_pool, struct cfg_st *config, const char *socket_f
sec->dcookie_key.size = COOKIE_KEY_SIZE; sec->dcookie_key.size = COOKIE_KEY_SIZE;
sec->config = talloc_steal(sec, config); sec->config = talloc_steal(sec, config);
sup_config_init(sec);
memset(&sa, 0, sizeof(sa)); memset(&sa, 0, sizeof(sa));
sa.sun_family = AF_UNIX; sa.sun_family = AF_UNIX;
snprintf(sa.sun_path, sizeof(sa.sun_path), "%s", socket_file); snprintf(sa.sun_path, sizeof(sa.sun_path), "%s", socket_file);

View File

@@ -19,6 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/> * along with this program. If not, see <http://www.gnu.org/licenses/>
*/ */
#ifndef SEC_MOD_H #ifndef SEC_MOD_H
# define SEC_MOD_H
#include <cookies.h> #include <cookies.h>
#include <gnutls/abstract.h> #include <gnutls/abstract.h>
@@ -34,6 +35,8 @@ typedef struct sec_mod_st {
struct htable *client_db; struct htable *client_db;
struct htable *ban_db; struct htable *ban_db;
struct config_mod_st *config_module;
int fd; int fd;
} sec_mod_st; } sec_mod_st;
@@ -87,7 +90,7 @@ void sec_auth_init(struct cfg_st *config);
int handle_sec_auth_init(sec_mod_st *sec, const SecAuthInitMsg * req); int handle_sec_auth_init(sec_mod_st *sec, const SecAuthInitMsg * req);
int handle_sec_auth_cont(sec_mod_st *sec, const SecAuthContMsg * req); int handle_sec_auth_cont(sec_mod_st *sec, const SecAuthContMsg * req);
int handle_sec_auth_session_cmd(sec_mod_st * sec, const SecAuthSessionMsg * req, unsigned cmd); int handle_sec_auth_session_cmd(sec_mod_st * sec, const SecAuthSessionMsg * req, unsigned cmd, client_entry_st **_e);
void sec_auth_user_deinit(sec_mod_st * sec, client_entry_st * e); void sec_auth_user_deinit(sec_mod_st * sec, client_entry_st * e);
void sec_mod_server(void *main_pool, struct cfg_st *config, const char *socket_file, void sec_mod_server(void *main_pool, struct cfg_st *config, const char *socket_file,

View File

@@ -1,5 +1,6 @@
/* /*
* Copyright (C) 2013 Nikos Mavrogiannopoulos * Copyright (C) 2013 Nikos Mavrogiannopoulos
* Copyright (C) 2014 Red Hat, Inc.
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -33,7 +34,7 @@
#include <vpn.h> #include <vpn.h>
#include <main.h> #include <main.h>
#include <main-sup-config.h> #include <sec-mod-sup-config.h>
struct cfg_options { struct cfg_options {
const char* name; const char* name;
@@ -68,14 +69,14 @@ static struct cfg_options available_options[] = {
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 = talloc_size(proc, sizeof(char*)*MAX_CONFIG_ENTRIES); \ s_name = talloc_size(pool, sizeof(char*)*MAX_CONFIG_ENTRIES); \
} \ } \
do { \ do { \
if (num >= MAX_CONFIG_ENTRIES) \ if (num >= MAX_CONFIG_ENTRIES) \
break; \ break; \
if (val && !strcmp(val->pzName, name)==0) \ if (val && !strcmp(val->pzName, name)==0) \
continue; \ continue; \
s_name[num] = talloc_strdup(proc, val->v.strVal); \ s_name[num] = talloc_strdup(pool, val->v.strVal); \
num++; \ num++; \
} while((val = optionNextValue(pov, val)) != NULL); \ } while((val = optionNextValue(pov, val)) != NULL); \
s_name[num] = NULL; \ s_name[num] = NULL; \
@@ -86,28 +87,33 @@ static struct cfg_options available_options[] = {
if (val != NULL && val->valType == OPARG_TYPE_STRING) { \ if (val != NULL && val->valType == OPARG_TYPE_STRING) { \
if (s_name != NULL) \ if (s_name != NULL) \
talloc_free(s_name); \ talloc_free(s_name); \
s_name = talloc_strdup(proc, val->v.strVal); \ s_name = talloc_strdup(pool, val->v.strVal); \
}} }}
#define READ_RAW_NUMERIC(name, s_name) { \ #define READ_RAW_NUMERIC(name, s_name, def) { \
val = optionGetValue(pov, name); \ val = optionGetValue(pov, name); \
if (val != NULL) { \ if (val != NULL) { \
if (val->valType == OPARG_TYPE_NUMERIC) \ if (val->valType == OPARG_TYPE_NUMERIC) {\
s_name = val->v.longVal; \ s_name = val->v.longVal; \
else if (val->valType == OPARG_TYPE_STRING) \ def = 1; \
} else if (val->valType == OPARG_TYPE_STRING) {\
s_name = atoi(val->v.strVal); \ s_name = atoi(val->v.strVal); \
def = 1; \
} \
}} }}
#define READ_RAW_PRIO_TOS(name, s_name) { \ #define READ_RAW_PRIO_TOS(name, s_name, def) { \
val = optionGetValue(pov, name); \ val = optionGetValue(pov, name); \
if (val != NULL) { \ if (val != NULL) { \
if (val->valType == OPARG_TYPE_STRING) { \ if (val->valType == OPARG_TYPE_STRING) { \
if (strncmp(val->v.strVal, "0x", 2) == 0) { \ if (strncmp(val->v.strVal, "0x", 2) == 0) { \
s_name = strtol(val->v.strVal, NULL, 16); \ s_name = strtol(val->v.strVal, NULL, 16); \
s_name = TOS_PACK(s_name); \ s_name = TOS_PACK(s_name); \
def = 1; \
} else { \ } else { \
s_name = atoi(val->v.strVal); \ s_name = atoi(val->v.strVal); \
s_name++; \ s_name++; \
def = 1; \
} \ } \
} \ } \
}} }}
@@ -115,12 +121,13 @@ static struct cfg_options available_options[] = {
#define READ_TF(name, s_name, def) { \ #define READ_TF(name, s_name, def) { \
{ char* tmp_tf = NULL; \ { char* tmp_tf = NULL; \
READ_RAW_STRING(name, tmp_tf); \ READ_RAW_STRING(name, tmp_tf); \
if (tmp_tf == NULL) s_name = def; \ if (tmp_tf == NULL) { def = 0; \
else { \ } else { \
if (c_strcasecmp(tmp_tf, "true") == 0 || c_strcasecmp(tmp_tf, "yes") == 0) \ if (c_strcasecmp(tmp_tf, "true") == 0 || c_strcasecmp(tmp_tf, "yes") == 0) \
s_name = 1; \ s_name = 1; \
else \ else \
s_name = 0; \ s_name = 0; \
def = 1; \
} \ } \
talloc_free(tmp_tf); \ talloc_free(tmp_tf); \
}} }}
@@ -143,13 +150,13 @@ unsigned j;
* already allocated using this function. * already allocated using this function.
*/ */
static static
int parse_group_cfg_file(struct cfg_st *global_config, struct proc_st *proc, int parse_group_cfg_file(struct cfg_st *global_config,
SecAuthSessionReplyMsg *msg, void *pool,
const char* file) const char* file)
{ {
tOptionValue const * pov; tOptionValue const * pov;
const tOptionValue* val, *prev; const tOptionValue* val, *prev;
unsigned prefix = 0; unsigned prefix = 0;
struct group_cfg_st *sconfig = &proc->config;
pov = configFileLoad(file); pov = configFileLoad(file);
if (pov == NULL) { if (pov == NULL) {
@@ -171,59 +178,58 @@ struct group_cfg_st *sconfig = &proc->config;
prev = val; prev = val;
} while((val = optionNextValue(pov, prev)) != NULL); } while((val = optionNextValue(pov, prev)) != NULL);
READ_TF("no-udp", sconfig->no_udp, (global_config->udp_port!=0)?0:1); READ_TF("no-udp", msg->no_udp, msg->has_no_udp);
READ_TF("deny-roaming", sconfig->deny_roaming, global_config->deny_roaming); READ_TF("deny-roaming", msg->deny_roaming, msg->has_deny_roaming);
READ_TF("require-cert", sconfig->require_cert, 0); READ_TF("require-cert", msg->require_cert, msg->has_require_cert);
READ_RAW_MULTI_LINE("route", sconfig->routes, sconfig->routes_size); READ_RAW_MULTI_LINE("route", msg->routes, msg->n_routes);
READ_RAW_MULTI_LINE("iroute", sconfig->iroutes, sconfig->iroutes_size); READ_RAW_MULTI_LINE("iroute", msg->iroutes, msg->n_iroutes);
READ_RAW_MULTI_LINE("dns", sconfig->dns, sconfig->dns_size); READ_RAW_MULTI_LINE("dns", msg->dns, msg->n_dns);
if (sconfig->dns_size == 0) { if (msg->n_dns == 0) {
/* try aliases */ /* try aliases */
READ_RAW_MULTI_LINE("ipv6-dns", sconfig->dns, sconfig->dns_size); READ_RAW_MULTI_LINE("ipv6-dns", msg->dns, msg->n_dns);
READ_RAW_MULTI_LINE("ipv4-dns", sconfig->dns, sconfig->dns_size); READ_RAW_MULTI_LINE("ipv4-dns", msg->dns, msg->n_dns);
} }
READ_RAW_MULTI_LINE("nbns", sconfig->nbns, sconfig->nbns_size); READ_RAW_MULTI_LINE("nbns", msg->nbns, msg->n_nbns);
if (sconfig->nbns_size == 0) { if (msg->n_nbns == 0) {
/* try aliases */ /* try aliases */
READ_RAW_MULTI_LINE("ipv6-nbns", sconfig->nbns, sconfig->nbns_size); READ_RAW_MULTI_LINE("ipv6-nbns", msg->nbns, msg->n_nbns);
READ_RAW_MULTI_LINE("ipv4-nbns", sconfig->nbns, sconfig->nbns_size); READ_RAW_MULTI_LINE("ipv4-nbns", msg->nbns, msg->n_nbns);
} }
READ_RAW_STRING("cgroup", sconfig->cgroup); READ_RAW_STRING("cgroup", msg->cgroup);
READ_RAW_STRING("ipv4-network", sconfig->ipv4_network); READ_RAW_STRING("ipv4-network", msg->ipv4_net);
READ_RAW_STRING("ipv6-network", sconfig->ipv6_network); READ_RAW_STRING("ipv6-network", msg->ipv6_net);
READ_RAW_STRING("ipv4-netmask", sconfig->ipv4_netmask); READ_RAW_STRING("ipv4-netmask", msg->ipv4_netmask);
READ_RAW_NUMERIC("ipv6-prefix", prefix); READ_RAW_NUMERIC("ipv6-prefix", msg->ipv6_prefix, msg->has_ipv6_prefix);
if (prefix > 0) { if (msg->has_ipv6_prefix != 0) {
sconfig->ipv6_prefix = prefix; if (valid_ipv6_prefix(msg->ipv6_prefix) == 0) {
if (valid_ipv6_prefix(prefix) == 0) {
syslog(LOG_ERR, "unknown ipv6-prefix '%u' in %s", prefix, file); syslog(LOG_ERR, "unknown ipv6-prefix '%u' in %s", prefix, file);
} }
} }
READ_RAW_NUMERIC("rx-data-per-sec", sconfig->rx_per_sec); READ_RAW_NUMERIC("rx-data-per-sec", msg->rx_per_sec, msg->has_rx_per_sec);
READ_RAW_NUMERIC("tx-data-per-sec", sconfig->tx_per_sec); READ_RAW_NUMERIC("tx-data-per-sec", msg->tx_per_sec, msg->has_tx_per_sec);
sconfig->rx_per_sec /= 1000; /* in kb */ msg->rx_per_sec /= 1000; /* in kb */
sconfig->tx_per_sec /= 1000; /* in kb */ msg->tx_per_sec /= 1000; /* in kb */
/* net-priority will contain the actual priority + 1, /* net-priority will contain the actual priority + 1,
* to allow having zero as uninitialized. */ * to allow having zero as uninitialized. */
READ_RAW_PRIO_TOS("net-priority", sconfig->net_priority); READ_RAW_PRIO_TOS("net-priority", msg->net_priority, msg->has_net_priority);
READ_RAW_STRING("user-profile", sconfig->xml_config_file); READ_RAW_STRING("user-profile", msg->xml_config_file);
optionUnloadNested(pov); optionUnloadNested(pov);
return 0; return 0;
} }
static int read_sup_config_file(struct cfg_st *global_config, struct proc_st *proc, static int read_sup_config_file(struct cfg_st *global_config,
const char *file, const char *fallback, const char *type) SecAuthSessionReplyMsg *msg, void *pool,
const char *file, const char *fallback, const char *type)
{ {
int ret; int ret;
@@ -231,44 +237,41 @@ static int read_sup_config_file(struct cfg_st *global_config, struct proc_st *pr
syslog(LOG_DEBUG, "Loading %s configuration '%s'", type, syslog(LOG_DEBUG, "Loading %s configuration '%s'", type,
file); file);
ret = parse_group_cfg_file(global_config, proc, file); ret = parse_group_cfg_file(global_config, msg, pool, file);
if (ret < 0) if (ret < 0)
return ERR_READ_CONFIG; return ERR_READ_CONFIG;
} else { } else {
if (fallback != NULL) { if (fallback != NULL) {
syslog(LOG_DEBUG, "Loading default %s configuration '%s'", type, fallback); syslog(LOG_DEBUG, "Loading default %s configuration '%s'", type, fallback);
ret = parse_group_cfg_file(global_config, proc, fallback); ret = parse_group_cfg_file(global_config, msg, pool, fallback);
if (ret < 0) if (ret < 0)
return ERR_READ_CONFIG; return ERR_READ_CONFIG;
} else {
syslog(LOG_DEBUG, "No %s configuration for '%s'", type,
proc->username);
} }
} }
return 0; return 0;
} }
static int get_sup_config(struct cfg_st *global_config, struct proc_st *proc) static int get_sup_config(struct cfg_st *cfg, client_entry_st *entry,
SecAuthSessionReplyMsg *msg, void *pool)
{ {
char file[_POSIX_PATH_MAX]; char file[_POSIX_PATH_MAX];
int ret; int ret;
if (global_config->per_group_dir != NULL && proc->groupname[0] != 0) { if (cfg->per_group_dir != NULL && entry->groupname[0] != 0) {
snprintf(file, sizeof(file), "%s/%s", global_config->per_group_dir, snprintf(file, sizeof(file), "%s/%s", cfg->per_group_dir,
proc->groupname); entry->groupname);
ret = read_sup_config_file(global_config, proc, file, global_config->default_group_conf, "group"); ret = read_sup_config_file(cfg, msg, pool, file, cfg->default_group_conf, "group");
if (ret < 0) if (ret < 0)
return ret; return ret;
} }
if (global_config->per_user_dir != NULL) { if (cfg->per_user_dir != NULL) {
snprintf(file, sizeof(file), "%s/%s", global_config->per_user_dir, snprintf(file, sizeof(file), "%s/%s", cfg->per_user_dir,
proc->username); entry->username);
ret = read_sup_config_file(cfg, msg, pool, file, cfg->default_user_conf, "user");
ret = read_sup_config_file(global_config, proc, file, global_config->default_user_conf, "user");
if (ret < 0) if (ret < 0)
return ret; return ret;
} }
@@ -276,40 +279,6 @@ static int get_sup_config(struct cfg_st *global_config, struct proc_st *proc)
return 0; return 0;
} }
static
void clear_sup_config(struct group_cfg_st* config)
{
unsigned i;
for(i=0;i<config->routes_size;i++) {
talloc_free(config->routes[i]);
}
talloc_free(config->routes);
for(i=0;i<config->iroutes_size;i++) {
talloc_free(config->iroutes[i]);
}
talloc_free(config->iroutes);
for(i=0;i<config->dns_size;i++) {
talloc_free(config->dns[i]);
}
talloc_free(config->dns);
for(i=0;i<config->nbns_size;i++) {
talloc_free(config->nbns[i]);
}
talloc_free(config->nbns);
talloc_free(config->cgroup);
talloc_free(config->ipv4_network);
talloc_free(config->ipv6_network);
talloc_free(config->ipv4_netmask);
safe_memset(config, 0, sizeof(*config));
}
struct config_mod_st file_sup_config = { struct config_mod_st file_sup_config = {
.get_sup_config = get_sup_config, .get_sup_config = get_sup_config,
.clear_sup_config = clear_sup_config,
}; };

View File

@@ -21,7 +21,7 @@
#ifndef SUP_CONFIG_FILE_H #ifndef SUP_CONFIG_FILE_H
#define SUP_CONFIG_FILE_H #define SUP_CONFIG_FILE_H
#include <main-sup-config.h> #include <sec-mod-sup-config.h>
extern struct config_mod_st file_sup_config; extern struct config_mod_st file_sup_config;

View File

@@ -145,7 +145,10 @@ struct group_cfg_st {
char *ipv6_network; char *ipv6_network;
unsigned ipv6_prefix; unsigned ipv6_prefix;
char *ipv4_netmask; char *ipv4_netmask;
char *explicit_ipv4;
char *explicit_ipv6;
char *cgroup; char *cgroup;
char *xml_config_file; char *xml_config_file;
@@ -202,7 +205,6 @@ struct cfg_st {
char *cert_user_oid; /* The OID that will be used to extract the username */ char *cert_user_oid; /* The OID that will be used to extract the username */
char *cert_group_oid; /* The OID that will be used to extract the groupname */ char *cert_group_oid; /* The OID that will be used to extract the groupname */
unsigned int auth_types; /* or'ed sequence of AUTH_TYPE */ unsigned int auth_types; /* or'ed sequence of AUTH_TYPE */
unsigned session_control; /* whether to use the session control part of authentication (PAM) */
char *auth_additional; /* the additional string specified in the auth methode */ char *auth_additional; /* the additional string specified in the auth methode */
gnutls_certificate_request_t cert_req; gnutls_certificate_request_t cert_req;
char *priorities; char *priorities;