Supplementary group/user configuration is now modular.

That will ease the addition of other backends that can be used to
read the user/group configuration. The only backend supported now
is file.
This commit is contained in:
Nikos Mavrogiannopoulos
2014-05-15 11:30:17 +02:00
parent a2ea033f50
commit e7171ac859
8 changed files with 221 additions and 103 deletions

View File

@@ -63,7 +63,7 @@ COMMON_SOURCES=common.c common.h system.c system.h setproctitle.c setproctitle.h
AUTH_SOURCES=auth/pam.c auth/pam.h auth/plain.c auth/plain.h
ocserv_SOURCES = main.c main-auth.c worker-vpn.c worker-auth.c tlslib.c \
cookies.c main-misc.c group-config.c ip-lease.c ip-lease.h \
cookies.c main-misc.c ip-lease.c ip-lease.h \
vpn.h cookies.h tlslib.h log.c tun.c tun.h \
config.c worker-resume.c worker.h main-resume.c main.h \
worker-extras.c main-auth.h html.c html.h \
@@ -71,6 +71,8 @@ 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.h sec-mod-ban.c \
script-list.h $(COMMON_SOURCES) $(AUTH_SOURCES) \
icmp-ping.c icmp-ping.h \
main-sup-config.c main-sup-config.h \
sup-config/file.c sup-config/file.h \
worker-bandwidth.c worker-bandwidth.h ctl.h main-ctl.h \
str.c str.h gettime.h $(CCAN_SOURCES) $(HTTP_PARSER_SOURCES) \
$(PROTOBUF_SOURCES)

View File

@@ -45,6 +45,7 @@
#include <ip-lease.h>
#include <ipc.pb-c.h>
#include <script-list.h>
#include <main-sup-config.h>
#ifdef HAVE_MALLOC_TRIM
# include <malloc.h>
@@ -136,67 +137,6 @@ int handle_script_exit(main_server_st *s, struct proc_st *proc, int code)
return ret;
}
static int read_additional_config_file(main_server_st * s, struct proc_st *proc,
const char *file, const char *fallback, const char *type)
{
int ret;
if (access(file, R_OK) == 0) {
mslog(s, proc, LOG_DEBUG, "Loading %s configuration '%s'", type,
file);
ret = parse_group_cfg_file(s, proc, file);
if (ret < 0)
return ERR_READ_CONFIG;
} else {
if (fallback != NULL) {
mslog(s, proc, LOG_DEBUG, "Loading default %s configuration '%s'", type, fallback);
ret = parse_group_cfg_file(s, proc, fallback);
if (ret < 0)
return ERR_READ_CONFIG;
} else {
mslog(s, proc, LOG_DEBUG, "No %s configuration for '%s'", type,
proc->username);
}
}
return 0;
}
static int read_additional_config(struct main_server_st *s,
struct proc_st *proc)
{
char file[_POSIX_PATH_MAX];
int ret;
memset(&proc->config, 0, sizeof(proc->config));
if (s->config->per_group_dir != NULL && proc->groupname[0] != 0) {
snprintf(file, sizeof(file), "%s/%s", s->config->per_group_dir,
proc->groupname);
ret = read_additional_config_file(s, proc, file, s->config->default_group_conf, "group");
if (ret < 0)
return ret;
}
if (s->config->per_user_dir != NULL) {
snprintf(file, sizeof(file), "%s/%s", s->config->per_user_dir,
proc->username);
ret = read_additional_config_file(s, proc, file, s->config->default_user_conf, "user");
if (ret < 0)
return ret;
}
if (proc->config.cgroup != NULL) {
put_into_cgroup(s, proc->config.cgroup, proc->pid);
}
return 0;
}
struct proc_st *new_proc(main_server_st * s, pid_t pid, int cmd_fd,
struct sockaddr_storage *remote_addr, socklen_t remote_addr_len,
uint8_t *sid, size_t sid_size)
@@ -247,7 +187,9 @@ void remove_proc(main_server_st * s, struct proc_st *proc, unsigned k)
proc->pid = -1;
remove_iroutes(s, proc);
del_additional_config(&proc->config);
if (s->config_module) {
s->config_module->clear_sup_config(&proc->config);
}
if (proc->ipv4 || proc->ipv6)
remove_ip_leases(s, proc);
@@ -272,13 +214,19 @@ static int accept_user(main_server_st * s, struct proc_st *proc, unsigned cmd)
return ret;
}
ret = read_additional_config(s, proc);
if (s->config_module) {
ret = s->config_module->get_sup_config(s->config, proc);
if (ret < 0) {
mslog(s, proc, LOG_ERR,
"error reading additional configuration");
return ERR_READ_CONFIG;
}
if (proc->config.cgroup != NULL) {
put_into_cgroup(s, proc->config.cgroup, proc->pid);
}
}
ret = open_tun(s, proc);
if (ret < 0) {
return -1;

37
src/main-sup-config.c Normal file
View File

@@ -0,0 +1,37 @@
/*
* Copyright (C) 2013, 2014 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, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <vpn.h>
#include <cookies.h>
#include <tun.h>
#include <main.h>
#include <common.h>
#include <vpn.h>
#include <main-sup-config.h>
#include <sup-config/file.h>
void sup_config_init(main_server_st *s)
{
s->config_module = &file_sup_config;
}

36
src/main-sup-config.h Normal file
View File

@@ -0,0 +1,36 @@
/*
* Copyright (C) 2014 Red Hat
*
* Author: Nikos Mavrogiannopoulos
*
* This file is part of ocserv.
*
* The GnuTLS is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#ifndef SUP_CONFIG_H
# define SUP_CONFIG_H
#include <main.h>
/* The get_sup_config() should read any additional configuration for
* proc->username/proc->groupname and save it in proc->config.
*/
struct config_mod_st {
int (*get_sup_config)(struct cfg_st *global_config, struct proc_st *proc);
void (*clear_sup_config)(struct group_cfg_st *out);
};
void sup_config_init(main_server_st *s);
#endif

View File

@@ -49,6 +49,7 @@
# include <systemd/sd-daemon.h>
#endif
#include <main.h>
#include <main-sup-config.h>
#include <main-ctl.h>
#include <route-add.h>
#include <main-auth.h>
@@ -934,7 +935,7 @@ int main(int argc, char** argv)
run_sec_mod(s);
mslog(s, NULL, LOG_INFO, "initialized %s", PACKAGE_STRING);
sup_config_init(s);
ret = ctl_handler_init(s);
if (ret < 0) {
@@ -942,6 +943,8 @@ int main(int argc, char** argv)
exit(1);
}
mslog(s, NULL, LOG_INFO, "initialized %s", PACKAGE_STRING);
/* chdir to our chroot directory, to allow opening the sec-mod
* socket if necessary. */
if (s->config->chroot_dir)

View File

@@ -180,6 +180,7 @@ typedef struct main_server_st {
time_t start_time;
void * auth_extra;
struct config_mod_st *config_module;
#ifdef HAVE_DBUS
void * ctl_ctx;
@@ -240,10 +241,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, struct proc_st *proc, const char* file);
void del_additional_config(struct group_cfg_st* config);
struct proc_st *new_proc(main_server_st * s, pid_t pid, int cmd_fd,
struct sockaddr_storage *remote_addr, socklen_t remote_addr_len,
uint8_t *sid, size_t sid_size);

View File

@@ -33,6 +33,7 @@
#include <vpn.h>
#include <main.h>
#include <main-sup-config.h>
struct cfg_options {
const char* name;
@@ -138,81 +139,142 @@ unsigned j;
* config. The provided config must either be memset to zero, or be
* already allocated using this function.
*/
int parse_group_cfg_file(main_server_st* s, struct proc_st *proc, const char* file)
static
int parse_group_cfg_file(struct cfg_st *global_config, struct proc_st *proc,
const char* file)
{
tOptionValue const * pov;
const tOptionValue* val, *prev;
unsigned prefix = 0;
struct group_cfg_st *config = &proc->config;
struct group_cfg_st *sconfig = &proc->config;
pov = configFileLoad(file);
if (pov == NULL) {
mslog(s, NULL, LOG_ERR, "Cannot load config file %s", file);
syslog(LOG_ERR, "cannot load config file %s", file);
return 0;
}
val = optionGetValue(pov, NULL);
if (val == NULL) {
mslog(s, NULL, LOG_ERR, "No configuration directives found in %s", file);
syslog(LOG_ERR, "no configuration directives found in %s", file);
optionUnloadNested(pov);
return ERR_READ_CONFIG;
}
do {
if (handle_option(val) == 0) {
mslog(s, NULL, LOG_ERR, "Skipping unknown option '%s' in %s", val->pzName, file);
syslog(LOG_ERR, "skipping unknown option '%s' in %s", val->pzName, file);
}
prev = val;
} while((val = optionNextValue(pov, prev)) != NULL);
READ_TF("no-udp", config->no_udp, (s->config->udp_port!=0)?0:1);
READ_TF("no-udp", sconfig->no_udp, (global_config->udp_port!=0)?0:1);
READ_RAW_MULTI_LINE("route", config->routes, config->routes_size);
READ_RAW_MULTI_LINE("iroute", config->iroutes, config->iroutes_size);
READ_RAW_MULTI_LINE("route", sconfig->routes, sconfig->routes_size);
READ_RAW_MULTI_LINE("iroute", sconfig->iroutes, sconfig->iroutes_size);
READ_RAW_MULTI_LINE("dns", config->dns, config->dns_size);
if (config->dns_size == 0) {
READ_RAW_MULTI_LINE("dns", sconfig->dns, sconfig->dns_size);
if (sconfig->dns_size == 0) {
/* try aliases */
READ_RAW_MULTI_LINE("ipv6-dns", config->dns, config->dns_size);
READ_RAW_MULTI_LINE("ipv4-dns", config->dns, config->dns_size);
READ_RAW_MULTI_LINE("ipv6-dns", sconfig->dns, sconfig->dns_size);
READ_RAW_MULTI_LINE("ipv4-dns", sconfig->dns, sconfig->dns_size);
}
READ_RAW_MULTI_LINE("nbns", config->nbns, config->nbns_size);
if (config->nbns_size == 0) {
READ_RAW_MULTI_LINE("nbns", sconfig->nbns, sconfig->nbns_size);
if (sconfig->nbns_size == 0) {
/* try aliases */
READ_RAW_MULTI_LINE("ipv6-nbns", config->nbns, config->nbns_size);
READ_RAW_MULTI_LINE("ipv4-nbns", config->nbns, config->nbns_size);
READ_RAW_MULTI_LINE("ipv6-nbns", sconfig->nbns, sconfig->nbns_size);
READ_RAW_MULTI_LINE("ipv4-nbns", sconfig->nbns, sconfig->nbns_size);
}
READ_RAW_STRING("cgroup", config->cgroup);
READ_RAW_STRING("ipv4-network", config->ipv4_network);
READ_RAW_STRING("ipv6-network", config->ipv6_network);
READ_RAW_STRING("ipv4-netmask", config->ipv4_netmask);
READ_RAW_STRING("cgroup", sconfig->cgroup);
READ_RAW_STRING("ipv4-network", sconfig->ipv4_network);
READ_RAW_STRING("ipv6-network", sconfig->ipv6_network);
READ_RAW_STRING("ipv4-netmask", sconfig->ipv4_netmask);
READ_RAW_NUMERIC("ipv6-prefix", prefix);
if (prefix > 0) {
config->ipv6_netmask = ipv6_prefix_to_mask(proc, prefix);
config->ipv6_prefix = prefix;
sconfig->ipv6_netmask = ipv6_prefix_to_mask(proc, prefix);
sconfig->ipv6_prefix = prefix;
if (config->ipv6_netmask == NULL) {
mslog(s, NULL, LOG_ERR, "unknown ipv6-prefix '%u' in %s", prefix, file);
if (sconfig->ipv6_netmask == NULL) {
syslog(LOG_ERR, "unknown ipv6-prefix '%u' in %s", prefix, file);
}
}
READ_RAW_NUMERIC("rx-data-per-sec", config->rx_per_sec);
READ_RAW_NUMERIC("tx-data-per-sec", config->tx_per_sec);
config->rx_per_sec /= 1000; /* in kb */
config->tx_per_sec /= 1000; /* in kb */
READ_RAW_NUMERIC("rx-data-per-sec", sconfig->rx_per_sec);
READ_RAW_NUMERIC("tx-data-per-sec", sconfig->tx_per_sec);
sconfig->rx_per_sec /= 1000; /* in kb */
sconfig->tx_per_sec /= 1000; /* in kb */
/* net-priority will contain the actual priority + 1,
* to allow having zero as uninitialized. */
READ_RAW_PRIO_TOS("net-priority", config->net_priority);
READ_RAW_PRIO_TOS("net-priority", sconfig->net_priority);
optionUnloadNested(pov);
return 0;
}
void del_additional_config(struct group_cfg_st* config)
static int read_sup_config_file(struct cfg_st *global_config, struct proc_st *proc,
const char *file, const char *fallback, const char *type)
{
int ret;
if (access(file, R_OK) == 0) {
syslog(LOG_DEBUG, "Loading %s configuration '%s'", type,
file);
ret = parse_group_cfg_file(global_config, proc, file);
if (ret < 0)
return ERR_READ_CONFIG;
} else {
if (fallback != NULL) {
syslog(LOG_DEBUG, "Loading default %s configuration '%s'", type, fallback);
ret = parse_group_cfg_file(global_config, proc, fallback);
if (ret < 0)
return ERR_READ_CONFIG;
} else {
syslog(LOG_DEBUG, "No %s configuration for '%s'", type,
proc->username);
}
}
return 0;
}
static int get_sup_config(struct cfg_st *global_config, struct proc_st *proc)
{
char file[_POSIX_PATH_MAX];
int ret;
memset(&proc->config, 0, sizeof(proc->config));
if (global_config->per_group_dir != NULL && proc->groupname[0] != 0) {
snprintf(file, sizeof(file), "%s/%s", global_config->per_group_dir,
proc->groupname);
ret = read_sup_config_file(global_config, proc, file, global_config->default_group_conf, "group");
if (ret < 0)
return ret;
}
if (global_config->per_user_dir != NULL) {
snprintf(file, sizeof(file), "%s/%s", global_config->per_user_dir,
proc->username);
ret = read_sup_config_file(global_config, proc, file, global_config->default_user_conf, "user");
if (ret < 0)
return ret;
}
return 0;
}
static
void clear_sup_config(struct group_cfg_st* config)
{
unsigned i;
@@ -243,3 +305,8 @@ unsigned i;
talloc_free(config->ipv6_netmask);
safe_memset(config, 0, sizeof(*config));
}
struct config_mod_st file_sup_config = {
.get_sup_config = get_sup_config,
.clear_sup_config = clear_sup_config,
};

28
src/sup-config/file.h Normal file
View File

@@ -0,0 +1,28 @@
/*
* Copyright (C) 2014 Red Hat
*
* Author: Nikos Mavrogiannopoulos
*
* This file is part of ocserv.
*
* The GnuTLS is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#ifndef SUP_CONFIG_FILE_H
#define SUP_CONFIG_FILE_H
#include <main-sup-config.h>
extern struct config_mod_st file_sup_config;
#endif