mirror of
https://gitlab.com/openconnect/ocserv.git
synced 2026-02-10 08:46:58 +08:00
Merge branch 'radius'
That merges all the changes needed for radius support.
This commit is contained in:
3
README
3
README
@@ -30,6 +30,9 @@ libopts25-dev / autogen-libopts-devel
|
||||
autogen / autogen
|
||||
|
||||
|
||||
For radius support the freeradius-client library is required. Currently
|
||||
(2014-12-10) the best would be to use the version from the git repository
|
||||
at: https://github.com/FreeRADIUS/freeradius-client
|
||||
|
||||
=== Build instructions ===
|
||||
|
||||
|
||||
5
TODO
5
TODO
@@ -1,8 +1,7 @@
|
||||
Short term items:
|
||||
|
||||
* Enhance the current accounting modules to allow, native radius support
|
||||
with real-time accounting (e.g., sending periodically the transferred
|
||||
bytes). Use radius for testing it.
|
||||
* Use the UDP address to report the client's IP when sniproxy or haproxy
|
||||
are being used.
|
||||
|
||||
* When a user (IP) gets into the BAN list multiple times, disable it for
|
||||
longer time (or should we drop this functionality altogether and rely
|
||||
|
||||
27
configure.ac
27
configure.ac
@@ -188,6 +188,32 @@ AC_LINK_IFELSE([AC_LANG_PROGRAM([
|
||||
LIBS="$oldlibs"
|
||||
fi
|
||||
|
||||
AC_ARG_WITH(radius,
|
||||
AS_HELP_STRING([--without-radius], [do not include Radius support]),
|
||||
test_for_radius=$withval,
|
||||
test_for_radius=yes)
|
||||
|
||||
radius_enabled=no
|
||||
|
||||
if test "$test_for_radius" = yes;then
|
||||
LIBS="$oldlibs -lfreeradius-client"
|
||||
AC_MSG_CHECKING([for freeradius client library])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([
|
||||
#include <freeradius-client.h>],[
|
||||
rc_read_config(0);])],
|
||||
[AC_MSG_RESULT(yes)
|
||||
AC_SUBST([FREERADIUS_CLIENT_LIBS], [-lfreeradius-client])
|
||||
AC_SUBST([FREERADIUS_CLIENT_CFLAGS], [])
|
||||
radius_enabled=yes
|
||||
AC_DEFINE([HAVE_RADIUS], 1, [Enable the Radius library])],
|
||||
[AC_MSG_RESULT(no)
|
||||
AC_MSG_WARN([[
|
||||
***
|
||||
*** libfreeradius-client was not found. Radius support will be disabled.
|
||||
*** ]])])
|
||||
LIBS="$oldlibs"
|
||||
fi
|
||||
|
||||
gl_INIT
|
||||
|
||||
AC_LIB_HAVE_LINKFLAGS(crypt,, [#define _XOPEN_SOURCE
|
||||
@@ -381,6 +407,7 @@ Summary of build options:
|
||||
CFlags: ${CFLAGS}
|
||||
|
||||
PAM auth backend: ${pam_enabled}
|
||||
Radius auth backend: ${radius_enabled}
|
||||
TCP wrappers: ${libwrap_enabled}
|
||||
systemd: ${systemd_enabled}
|
||||
(socket activation)
|
||||
|
||||
@@ -22,6 +22,14 @@ auth = "plain[./sample.passwd]"
|
||||
# to generate password entries.
|
||||
#auth = "plain[/etc/ocserv/ocpasswd]"
|
||||
|
||||
# The radius option requires specifying freeradius-client configuration
|
||||
# file. If the groupconfig option is set, then config-per-user will be overriden,
|
||||
# and all configuration will be read from radius. The supported atributes for
|
||||
# radius configuration are:
|
||||
# Group-Name, Framed-IPv6-Address, DNS-Server-IPv6-Address, Framed-IP-Address,
|
||||
# Framed-IP-Netmask, MS-Primary-DNS-Server, MS-Secondary-DNS-Server
|
||||
#auth = "radius[/usr/local/etc/radiusclient/radiusclient.conf,groupconfig]"
|
||||
|
||||
# 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
|
||||
# bug in the worker process. It is available on Linux systems at a performance cost.
|
||||
@@ -56,6 +64,12 @@ max-same-clients = 2
|
||||
# reconnects.
|
||||
#listen-host-is-dyndns = true
|
||||
|
||||
# Stats report time. The number of seconds after which each
|
||||
# worker process will report its usage statistics (number of
|
||||
# bytes transferred etc). This is useful when accounting like
|
||||
# radius is in use.
|
||||
#stats-report-time = 360
|
||||
|
||||
# TCP and UDP port number
|
||||
tcp-port = 443
|
||||
udp-port = 443
|
||||
|
||||
@@ -62,7 +62,8 @@ endif
|
||||
COMMON_SOURCES=common.c common.h system.c system.h setproctitle.c setproctitle.h
|
||||
|
||||
# Authentication module sources
|
||||
AUTH_SOURCES=auth/pam.c auth/pam.h auth/plain.c auth/plain.h
|
||||
AUTH_SOURCES=auth/pam.c auth/pam.h auth/plain.c auth/plain.h auth/radius.c auth/radius.h \
|
||||
auth/common.c auth/common.h
|
||||
|
||||
ocserv_SOURCES = main.c main-auth.c worker-vpn.c worker-auth.c tlslib.c \
|
||||
cookies.c main-misc.c ip-lease.c ip-lease.h \
|
||||
@@ -73,8 +74,9 @@ 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 \
|
||||
script-list.h $(COMMON_SOURCES) $(AUTH_SOURCES) \
|
||||
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/radius.c sup-config/radius.h \
|
||||
worker-bandwidth.c worker-bandwidth.h ctl.h main-ctl.h \
|
||||
vasprintf.c vasprintf.h \
|
||||
proc-search.c proc-search.h \
|
||||
@@ -87,7 +89,8 @@ ocserv_SOURCES += ipc.pb-c.h ipc.pb-c.c ctl.pb-c.c ctl.pb-c.h
|
||||
ocserv_LDADD = ../gl/libgnu.a $(NEEDED_LIBOPTS) libcmd-ocserv.a
|
||||
ocserv_LDADD += $(LIBGNUTLS_LIBS) $(PAM_LIBS) $(LIBUTIL) \
|
||||
$(LIBSECCOMP) $(LIBWRAP) $(LIBCRYPT) $(NEEDED_HTTP_PARSER_LIBS) \
|
||||
$(LIBPROTOBUF_C_LIBS) $(LIBSYSTEMD_DAEMON) $(LIBTALLOC_LIBS)
|
||||
$(LIBPROTOBUF_C_LIBS) $(LIBSYSTEMD_DAEMON) $(LIBTALLOC_LIBS) \
|
||||
$(FREERADIUS_CLIENT_LIBS)
|
||||
|
||||
|
||||
if PCL
|
||||
|
||||
26
src/auth/common.c
Normal file
26
src/auth/common.c
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Red Hat, Inc.
|
||||
*
|
||||
* This file is part of ocserv.
|
||||
*
|
||||
* ocserv 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.
|
||||
*
|
||||
* ocserv 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 <auth/common.h>
|
||||
|
||||
const char* pass_msg_first = "Please enter your password.";
|
||||
const char* pass_msg_second = "Please enter your challenge password.";
|
||||
const char* pass_msg_failed = "Login failed.\nPlease enter your password.";
|
||||
|
||||
10
src/auth/common.h
Normal file
10
src/auth/common.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#ifndef AUTH_COMMON_H
|
||||
# define AUTH_COMMON_H
|
||||
|
||||
#define MAX_TRIES 3
|
||||
|
||||
extern const char* pass_msg_first;
|
||||
extern const char* pass_msg_second;
|
||||
extern const char* pass_msg_failed;
|
||||
|
||||
#endif
|
||||
@@ -348,7 +348,7 @@ struct pam_ctx_st * pctx = ctx;
|
||||
talloc_free(pctx);
|
||||
}
|
||||
|
||||
static int pam_auth_open_session(void* ctx)
|
||||
static int pam_auth_open_session(void* ctx, const void *sid, unsigned sid_size)
|
||||
{
|
||||
struct pam_ctx_st * pctx = ctx;
|
||||
int pret;
|
||||
|
||||
@@ -29,14 +29,11 @@
|
||||
#include <vpn.h>
|
||||
#include <c-ctype.h>
|
||||
#include "plain.h"
|
||||
#include "auth/common.h"
|
||||
#include <ccan/htable/htable.h>
|
||||
#include <ccan/hash/hash.h>
|
||||
|
||||
#define MAX_CPASS_SIZE 128
|
||||
#define MAX_TRIES 3
|
||||
|
||||
const char* pass_msg_first = "Please enter your password.";
|
||||
const char* pass_msg_failed = "Login failed.\nPlease enter your password.";
|
||||
|
||||
struct plain_ctx_st {
|
||||
char username[MAX_USERNAME_SIZE];
|
||||
|
||||
425
src/auth/radius.c
Normal file
425
src/auth/radius.c
Normal file
@@ -0,0 +1,425 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Red Hat, Inc.
|
||||
*
|
||||
* This file is part of ocserv.
|
||||
*
|
||||
* ocserv 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.
|
||||
*
|
||||
* ocserv 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 <syslog.h>
|
||||
#include <unistd.h>
|
||||
#include <vpn.h>
|
||||
#include <c-ctype.h>
|
||||
#include <arpa/inet.h> /* inet_ntop */
|
||||
#include "radius.h"
|
||||
#include "auth/common.h"
|
||||
|
||||
#ifdef HAVE_RADIUS
|
||||
|
||||
#include <freeradius-client.h>
|
||||
|
||||
#if !defined(PW_FRAMED_IPV6_ADDRESS) && defined(PW_TYPE_IPV6ADDR)
|
||||
#define PW_FRAMED_IPV6_ADDRESS 168
|
||||
#define PW_DNS_SERVER_IPV6_ADDRESS 169
|
||||
#endif
|
||||
|
||||
#define RAD_GROUP_NAME 1030
|
||||
#define RAD_IPV4_DNS1 ((311<<16)|(28))
|
||||
#define RAD_IPV4_DNS2 ((311<<16)|(29))
|
||||
|
||||
int rc_aaa(rc_handle *rh, uint32_t client_port, VALUE_PAIR *send, VALUE_PAIR **received,
|
||||
char *msg, int add_nas_port, int request_type);
|
||||
|
||||
static rc_handle *rh = NULL;
|
||||
|
||||
static void radius_global_init(void *pool, void *additional)
|
||||
{
|
||||
rh = rc_read_config(additional);
|
||||
if (rh == NULL) {
|
||||
fprintf(stderr, "radius initialization error\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (rc_read_dictionary(rh, rc_conf_str(rh, "dictionary")) != 0) {
|
||||
fprintf(stderr, "error reading the radius dictionary\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void radius_global_deinit()
|
||||
{
|
||||
if (rh != NULL)
|
||||
rc_destroy(rh);
|
||||
}
|
||||
|
||||
static int radius_auth_init(void **ctx, void *pool, const char *username, const char *ip,
|
||||
void *additional)
|
||||
{
|
||||
struct radius_ctx_st *pctx;
|
||||
char *default_realm;
|
||||
|
||||
pctx = talloc_zero(pool, struct radius_ctx_st);
|
||||
if (pctx == NULL)
|
||||
return ERR_AUTH_FAIL;
|
||||
|
||||
snprintf(pctx->username, sizeof(pctx->username), "%s", username);
|
||||
pctx->config = additional;
|
||||
pctx->pass_msg = pass_msg_first;
|
||||
|
||||
default_realm = rc_conf_str(rh, "default_realm");
|
||||
|
||||
if ((strchr(username, '@') == NULL) && default_realm &&
|
||||
default_realm[0] != 0) {
|
||||
snprintf(pctx->username, sizeof(pctx->username), "%s@%s", username, default_realm);
|
||||
} else {
|
||||
strcpy(pctx->username, username);
|
||||
}
|
||||
|
||||
|
||||
*ctx = pctx;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int radius_auth_group(void *ctx, const char *suggested, char *groupname, int groupname_size)
|
||||
{
|
||||
struct radius_ctx_st *pctx = ctx;
|
||||
|
||||
groupname[0] = 0;
|
||||
|
||||
if (suggested != NULL) {
|
||||
if (strcmp(suggested, pctx->groupname) == 0) {
|
||||
snprintf(groupname, groupname_size, "%s", pctx->groupname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
syslog(LOG_AUTH,
|
||||
"user '%s' requested group '%s' but is not a member",
|
||||
pctx->username, suggested);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pctx->groupname[0] != 0 && groupname[0] == 0) {
|
||||
snprintf(groupname, groupname_size, "%s", pctx->groupname);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int radius_auth_user(void *ctx, char *username, int username_size)
|
||||
{
|
||||
/* do not update username */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Returns 0 if the user is successfully authenticated, and sets the appropriate group name.
|
||||
*/
|
||||
static int radius_auth_pass(void *ctx, const char *pass, unsigned pass_len)
|
||||
{
|
||||
struct radius_ctx_st *pctx = ctx;
|
||||
VALUE_PAIR *send = NULL, *recvd = NULL;
|
||||
uint32_t service;
|
||||
int ret;
|
||||
|
||||
syslog(LOG_DEBUG, "communicating username (%s) and password to radius", pctx->username);
|
||||
if (rc_avpair_add(rh, &send, PW_USER_NAME, pctx->username, -1, 0) == NULL) {
|
||||
syslog(LOG_ERR,
|
||||
"%s:%u: user '%s' auth error", __func__, __LINE__,
|
||||
pctx->username);
|
||||
return ERR_AUTH_FAIL;
|
||||
}
|
||||
|
||||
if (rc_avpair_add(rh, &send, PW_USER_PASSWORD, (char*)pass, -1, 0) == NULL) {
|
||||
syslog(LOG_ERR,
|
||||
"%s:%u: user '%s' auth error", __func__, __LINE__,
|
||||
pctx->username);
|
||||
ret = ERR_AUTH_FAIL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
service = PW_AUTHENTICATE_ONLY;
|
||||
if (rc_avpair_add(rh, &send, PW_SERVICE_TYPE, &service, -1, 0) == NULL) {
|
||||
syslog(LOG_ERR,
|
||||
"%s:%u: user '%s' auth error", __func__, __LINE__,
|
||||
pctx->username);
|
||||
ret = ERR_AUTH_FAIL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = rc_aaa(rh, 0, send, &recvd, pctx->msg, 1, PW_ACCESS_REQUEST);
|
||||
|
||||
if (ret == OK_RC) {
|
||||
VALUE_PAIR *vp = recvd;
|
||||
uint32_t ip;
|
||||
while(vp != NULL) {
|
||||
if (vp->attribute == PW_SERVICE_TYPE && vp->lvalue != PW_FRAMED) {
|
||||
syslog(LOG_ERR,
|
||||
"%s:%u: unknown radius service type '%d'", __func__, __LINE__,
|
||||
(int)vp->lvalue);
|
||||
goto fail;
|
||||
} else if (vp->attribute == RAD_GROUP_NAME && vp->type == PW_TYPE_STRING) {
|
||||
/* Group-Name */
|
||||
snprintf(pctx->groupname, sizeof(pctx->groupname), "%s", vp->strvalue);
|
||||
#ifdef PW_FRAMED_IPV6_ADDRESS
|
||||
} else if (vp->attribute == PW_FRAMED_IPV6_ADDRESS && vp->type == PW_TYPE_IPV6ADDR) {
|
||||
/* Framed-IPv6-Address */
|
||||
inet_ntop(AF_INET6, vp->strvalue, pctx->ipv6, sizeof(pctx->ipv6));
|
||||
} else if (vp->attribute == PW_DNS_SERVER_IPV6_ADDRESS && vp->type == PW_TYPE_IPV6ADDR) {
|
||||
/* DNS-Server-IPv6-Address */
|
||||
if (pctx->ipv6_dns1[0] == 0)
|
||||
inet_ntop(AF_INET6, vp->strvalue, pctx->ipv6_dns1, sizeof(pctx->ipv6_dns1));
|
||||
else
|
||||
inet_ntop(AF_INET6, vp->strvalue, pctx->ipv6_dns2, sizeof(pctx->ipv6_dns2));
|
||||
#endif
|
||||
} else if (vp->attribute == PW_FRAMED_IP_ADDRESS && vp->type == PW_TYPE_IPADDR) {
|
||||
/* Framed-IP-Address */
|
||||
ip = htonl(vp->lvalue);
|
||||
inet_ntop(AF_INET, &ip, pctx->ipv4, sizeof(pctx->ipv4));
|
||||
} else if (vp->attribute == PW_FRAMED_IP_NETMASK && vp->type == PW_TYPE_IPADDR) {
|
||||
/* Framed-IP-Netmask */
|
||||
ip = htonl(vp->lvalue);
|
||||
inet_ntop(AF_INET, &ip, pctx->ipv4_mask, sizeof(pctx->ipv4_mask));
|
||||
} else if (vp->attribute == RAD_IPV4_DNS1 && vp->type == PW_TYPE_IPADDR) {
|
||||
/* MS-Primary-DNS-Server */
|
||||
ip = htonl(vp->lvalue);
|
||||
inet_ntop(AF_INET, &ip, pctx->ipv4_dns1, sizeof(pctx->ipv4_dns1));
|
||||
} else if (vp->attribute == RAD_IPV4_DNS2 && vp->type == PW_TYPE_IPADDR) {
|
||||
/* MS-Secondary-DNS-Server */
|
||||
ip = htonl(vp->lvalue);
|
||||
inet_ntop(AF_INET, &ip, pctx->ipv4_dns2, sizeof(pctx->ipv4_dns2));
|
||||
} else {
|
||||
syslog(LOG_DEBUG, "radius: ignoring server's value %u of type %u", (int)vp->attribute, (int)vp->type);
|
||||
}
|
||||
vp = vp->next;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
cleanup:
|
||||
rc_avpair_free(send);
|
||||
if (recvd != NULL)
|
||||
rc_avpair_free(recvd);
|
||||
return ret;
|
||||
} else {
|
||||
fail:
|
||||
if (send != NULL)
|
||||
rc_avpair_free(send);
|
||||
|
||||
if (recvd != NULL)
|
||||
rc_avpair_free(recvd);
|
||||
|
||||
if (ret == PW_ACCESS_CHALLENGE) {
|
||||
pctx->pass_msg = pass_msg_second;
|
||||
return ERR_AUTH_CONTINUE;
|
||||
} else if (pctx->retries++ < MAX_TRIES) {
|
||||
pctx->pass_msg = pass_msg_failed;
|
||||
return ERR_AUTH_CONTINUE;
|
||||
} else {
|
||||
syslog(LOG_AUTH,
|
||||
"radius-auth: error authenticating user '%s'",
|
||||
pctx->username);
|
||||
return ERR_AUTH_FAIL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int radius_auth_msg(void *ctx, char *msg, size_t msg_size)
|
||||
{
|
||||
struct radius_ctx_st *pctx = ctx;
|
||||
|
||||
snprintf(msg, msg_size, "%s", pctx->pass_msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void radius_auth_deinit(void *ctx)
|
||||
{
|
||||
struct radius_ctx_st *pctx = ctx;
|
||||
talloc_free(pctx);
|
||||
}
|
||||
|
||||
|
||||
static void radius_auth_session_stats(void* ctx, uint64_t bytes_in, uint64_t bytes_out)
|
||||
{
|
||||
struct radius_ctx_st * pctx = ctx;
|
||||
int ret;
|
||||
uint32_t status_type;
|
||||
VALUE_PAIR *send = NULL, *recvd = NULL;
|
||||
uint32_t uin, uout;
|
||||
|
||||
status_type = PW_STATUS_ALIVE;
|
||||
|
||||
syslog(LOG_DEBUG, "sending radius session interim update");
|
||||
|
||||
if (rc_avpair_add(rh, &send, PW_ACCT_STATUS_TYPE, &status_type, -1, 0) == NULL) {
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (rc_avpair_add(rh, &send, PW_USER_NAME, pctx->username, -1, 0) == NULL) {
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (rc_avpair_add(rh, &send, PW_ACCT_SESSION_ID, pctx->sid, -1, 0) == NULL) {
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
uin = bytes_in;
|
||||
uout = bytes_out;
|
||||
|
||||
if (rc_avpair_add(rh, &send, PW_ACCT_INPUT_OCTETS, &uin, -1, 0) == NULL) {
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (rc_avpair_add(rh, &send, PW_ACCT_OUTPUT_OCTETS, &uout, -1, 0) == NULL) {
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
uin = bytes_in / 4294967296;
|
||||
if (rc_avpair_add(rh, &send, PW_ACCT_INPUT_GIGAWORDS, &uin, -1, 0) == NULL) {
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
uout = bytes_in / 4294967296;
|
||||
if (rc_avpair_add(rh, &send, PW_ACCT_OUTPUT_GIGAWORDS, &uout, -1, 0) == NULL) {
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = rc_aaa(rh, 0, send, &recvd, pctx->msg, 1, PW_ACCOUNTING_REQUEST);
|
||||
|
||||
if (recvd != NULL)
|
||||
rc_avpair_free(recvd);
|
||||
|
||||
if (ret != OK_RC) {
|
||||
syslog(LOG_AUTH, "radius-auth: radius_open_session: %d", ret);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
rc_avpair_free(send);
|
||||
return;
|
||||
}
|
||||
|
||||
static int radius_auth_open_session(void* ctx, const void *sid, unsigned sid_size)
|
||||
{
|
||||
struct radius_ctx_st * pctx = ctx;
|
||||
int ret;
|
||||
uint32_t status_type;
|
||||
VALUE_PAIR *send = NULL, *recvd = NULL;
|
||||
|
||||
status_type = PW_STATUS_START;
|
||||
|
||||
if (sid_size != SID_SIZE) {
|
||||
syslog(LOG_DEBUG, "incorrect sid size");
|
||||
return -1;
|
||||
}
|
||||
|
||||
base64_encode((char *)sid, sid_size, (char *)pctx->sid, sizeof(pctx->sid));
|
||||
|
||||
syslog(LOG_DEBUG, "opening session %s with radius", pctx->sid);
|
||||
|
||||
if (rc_avpair_add(rh, &send, PW_USER_NAME, pctx->username, -1, 0) == NULL) {
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (rc_avpair_add(rh, &send, PW_ACCT_SESSION_ID, pctx->sid, -1, 0) == NULL) {
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (rc_avpair_add(rh, &send, PW_ACCT_STATUS_TYPE, &status_type, -1, 0) == NULL) {
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = rc_aaa(rh, 0, send, &recvd, pctx->msg, 1, PW_ACCOUNTING_REQUEST);
|
||||
|
||||
if (recvd != NULL)
|
||||
rc_avpair_free(recvd);
|
||||
|
||||
if (ret != OK_RC) {
|
||||
syslog(LOG_AUTH, "radius-auth: radius_open_session: %d", ret);
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
cleanup:
|
||||
rc_avpair_free(send);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void radius_auth_close_session(void* ctx)
|
||||
{
|
||||
struct radius_ctx_st * pctx = ctx;
|
||||
int ret;
|
||||
uint32_t status_type;
|
||||
VALUE_PAIR *send = NULL, *recvd = NULL;
|
||||
|
||||
status_type = PW_STATUS_STOP;
|
||||
|
||||
syslog(LOG_DEBUG, "closing session with radius");
|
||||
if (rc_avpair_add(rh, &send, PW_ACCT_STATUS_TYPE, &status_type, -1, 0) == NULL)
|
||||
return;
|
||||
|
||||
if (rc_avpair_add(rh, &send, PW_USER_NAME, pctx->username, -1, 0) == NULL) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (rc_avpair_add(rh, &send, PW_ACCT_SESSION_ID, pctx->sid, -1, 0) == NULL) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
||||
ret = rc_aaa(rh, 0, send, &recvd, pctx->msg, 1, PW_ACCOUNTING_REQUEST);
|
||||
if (recvd != NULL)
|
||||
rc_avpair_free(recvd);
|
||||
|
||||
if (ret != OK_RC) {
|
||||
syslog(LOG_INFO, "radius-auth: radius_close_session: %d", ret);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
rc_avpair_free(send);
|
||||
return;
|
||||
}
|
||||
|
||||
const struct auth_mod_st radius_auth_funcs = {
|
||||
.type = AUTH_TYPE_RADIUS | AUTH_TYPE_USERNAME_PASS,
|
||||
.global_init = radius_global_init,
|
||||
.global_deinit = radius_global_deinit,
|
||||
.auth_init = radius_auth_init,
|
||||
.auth_deinit = radius_auth_deinit,
|
||||
.auth_msg = radius_auth_msg,
|
||||
.auth_pass = radius_auth_pass,
|
||||
.auth_user = radius_auth_user,
|
||||
.auth_group = radius_auth_group,
|
||||
.open_session = radius_auth_open_session,
|
||||
.close_session = radius_auth_close_session,
|
||||
.session_stats = radius_auth_session_stats,
|
||||
.group_list = NULL
|
||||
};
|
||||
|
||||
#endif
|
||||
52
src/auth/radius.h
Normal file
52
src/auth/radius.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Red Hat, Inc.
|
||||
*
|
||||
* 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 RADIUS_H
|
||||
#define RADIUS_H
|
||||
|
||||
#include <sec-mod-auth.h>
|
||||
#include <base64.h>
|
||||
|
||||
struct radius_ctx_st {
|
||||
char username[MAX_USERNAME_SIZE*2];
|
||||
char groupname[MAX_GROUPNAME_SIZE];
|
||||
char sid[BASE64_LENGTH(SID_SIZE) + 1];
|
||||
|
||||
char msg[4096];
|
||||
|
||||
/* variables for configuration */
|
||||
char ipv4[MAX_IP_STR];
|
||||
char ipv4_mask[MAX_IP_STR];
|
||||
char ipv4_dns1[MAX_IP_STR];
|
||||
char ipv4_dns2[MAX_IP_STR];
|
||||
|
||||
char ipv6[MAX_IP_STR];
|
||||
uint16_t ipv6_prefix;
|
||||
char ipv6_dns1[MAX_IP_STR];
|
||||
char ipv6_dns2[MAX_IP_STR];
|
||||
|
||||
const char *config; /* radius config file */
|
||||
const char *pass_msg;
|
||||
unsigned retries;
|
||||
};
|
||||
|
||||
extern const struct auth_mod_st radius_auth_funcs;
|
||||
|
||||
#endif
|
||||
@@ -56,6 +56,8 @@ static char tmp[32];
|
||||
case CMD_CLI_STATS:
|
||||
return "cli stats";
|
||||
|
||||
case SM_CMD_CLI_STATS:
|
||||
return "sm: cli stats";
|
||||
case SM_CMD_AUTH_INIT:
|
||||
return "sm: auth init";
|
||||
case SM_CMD_AUTH_CONT:
|
||||
|
||||
19
src/common.h
19
src/common.h
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Nikos Mavrogiannopoulos
|
||||
* Copyright (C) 2013, 2014 Nikos Mavrogiannopoulos
|
||||
* Copyright (C) 2014 Red Hat, Inc.
|
||||
*
|
||||
* Author: Nikos Mavrogiannopoulos
|
||||
*
|
||||
@@ -42,6 +43,22 @@ ssize_t force_read_timeout(int sockfd, void *buf, size_t len, unsigned sec);
|
||||
ssize_t recv_timeout(int sockfd, void *buf, size_t len, unsigned sec);
|
||||
int ip_cmp(const struct sockaddr_storage *s1, const struct sockaddr_storage *s2, size_t n);
|
||||
char* ipv6_prefix_to_mask(void *pool, unsigned prefix);
|
||||
inline static int valid_ipv6_prefix(unsigned prefix)
|
||||
{
|
||||
switch (prefix) {
|
||||
case 16:
|
||||
case 32:
|
||||
case 48:
|
||||
case 64:
|
||||
case 80:
|
||||
case 96:
|
||||
case 112:
|
||||
case 128:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
typedef size_t (*pack_func)(const void*, uint8_t *);
|
||||
typedef size_t (*pack_size_func)(const void*);
|
||||
|
||||
112
src/config.c
112
src/config.c
@@ -32,7 +32,9 @@
|
||||
#include <c-strcase.h>
|
||||
#include <c-ctype.h>
|
||||
#include <auth/pam.h>
|
||||
#include <auth/radius.h>
|
||||
#include <auth/plain.h>
|
||||
#include <sec-mod-sup-config.h>
|
||||
|
||||
#include <vpn.h>
|
||||
#include <cookies.h>
|
||||
@@ -45,6 +47,7 @@
|
||||
|
||||
static char pid_file[_POSIX_PATH_MAX] = "";
|
||||
static const char* cfg_file = DEFAULT_CFG_FILE;
|
||||
static const struct auth_mod_st *amod = NULL;
|
||||
|
||||
struct cfg_options {
|
||||
const char* name;
|
||||
@@ -106,6 +109,7 @@ static struct cfg_options available_options[] = {
|
||||
{ .name = "net-priority", .type = OPTION_STRING, .mandatory = 0 },
|
||||
{ .name = "output-buffer", .type = OPTION_NUMERIC, .mandatory = 0 },
|
||||
{ .name = "cookie-timeout", .type = OPTION_NUMERIC, .mandatory = 0 },
|
||||
{ .name = "stats-report-time", .type = OPTION_NUMERIC, .mandatory = 0 },
|
||||
{ .name = "rekey-time", .type = OPTION_NUMERIC, .mandatory = 0 },
|
||||
{ .name = "rekey-method", .type = OPTION_STRING, .mandatory = 0 },
|
||||
{ .name = "auth-timeout", .type = OPTION_NUMERIC, .mandatory = 0 },
|
||||
@@ -143,7 +147,9 @@ static struct cfg_options available_options[] = {
|
||||
{ .name = "default-group-config", .type = OPTION_STRING, .mandatory = 0 },
|
||||
};
|
||||
|
||||
static char *get_brackets_string(void *pool, const char *str);
|
||||
#define get_brackets_string get_brackets_string1
|
||||
static char *get_brackets_string1(void *pool, const char *str);
|
||||
static char *get_brackets_string2(void *pool, const char *str);
|
||||
|
||||
static const tOptionValue* get_option(const char* name, unsigned * mand)
|
||||
{
|
||||
@@ -300,7 +306,7 @@ unsigned j;
|
||||
}
|
||||
}
|
||||
|
||||
static char *get_brackets_string(void *pool, const char *str)
|
||||
static char *get_brackets_string1(void *pool, const char *str)
|
||||
{
|
||||
char *p, *p2;
|
||||
unsigned len;
|
||||
@@ -313,10 +319,13 @@ static char *get_brackets_string(void *pool, const char *str)
|
||||
while (c_isspace(*p))
|
||||
p++;
|
||||
|
||||
p2 = strchr(p, ']');
|
||||
p2 = strchr(p, ',');
|
||||
if (p2 == NULL) {
|
||||
fprintf(stderr, "error parsing %s\n", str);
|
||||
exit(1);
|
||||
p2 = strchr(p, ']');
|
||||
if (p2 == NULL) {
|
||||
fprintf(stderr, "error parsing %s\n", str);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
len = p2 - p;
|
||||
@@ -324,6 +333,45 @@ static char *get_brackets_string(void *pool, const char *str)
|
||||
return talloc_strndup(pool, p, len);
|
||||
}
|
||||
|
||||
static char *get_brackets_string2(void *pool, const char *str)
|
||||
{
|
||||
char *p, *p2;
|
||||
unsigned len;
|
||||
|
||||
p = strchr(str, '[');
|
||||
if (p == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
p++;
|
||||
|
||||
p = strchr(p, ',');
|
||||
if (p == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
p++;
|
||||
|
||||
while (c_isspace(*p))
|
||||
p++;
|
||||
|
||||
p2 = strchr(p, ',');
|
||||
if (p2 == NULL) {
|
||||
p2 = strchr(p, ']');
|
||||
if (p2 == NULL) {
|
||||
fprintf(stderr, "error parsing %s\n", str);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
len = p2 - p;
|
||||
|
||||
return talloc_strndup(pool, p, len);
|
||||
}
|
||||
|
||||
const struct auth_mod_st *get_auth_mod(void)
|
||||
{
|
||||
return amod;
|
||||
}
|
||||
|
||||
static void parse_cfg_file(const char* file, struct cfg_st *config, unsigned reload)
|
||||
{
|
||||
tOptionValue const * pov;
|
||||
@@ -332,7 +380,6 @@ unsigned j, i, mand;
|
||||
char** auth = NULL;
|
||||
unsigned auth_size = 0;
|
||||
unsigned prefix = 0, auto_select_group = 0;
|
||||
const struct auth_mod_st *amod = NULL;
|
||||
char *tmp;
|
||||
unsigned force_cert_auth;
|
||||
|
||||
@@ -360,6 +407,8 @@ unsigned force_cert_auth;
|
||||
prev = val;
|
||||
} while((val = optionNextValue(pov, prev)) != NULL);
|
||||
|
||||
config->sup_config_type = SUP_CONFIG_FILE;
|
||||
|
||||
READ_MULTI_LINE("auth", auth, auth_size);
|
||||
for (j=0;j<auth_size;j++) {
|
||||
if (c_strncasecmp(auth[j], "pam", 3) == 0) {
|
||||
@@ -369,7 +418,7 @@ unsigned force_cert_auth;
|
||||
exit(1);
|
||||
}
|
||||
#ifdef HAVE_PAM
|
||||
config->auth_types |= AUTH_TYPE_PAM;
|
||||
config->auth_types |= amod->type;
|
||||
amod = &pam_auth_funcs;
|
||||
#else
|
||||
fprintf(stderr, "PAM support is disabled\n");
|
||||
@@ -387,7 +436,35 @@ unsigned force_cert_auth;
|
||||
exit(1);
|
||||
}
|
||||
amod = &plain_auth_funcs;
|
||||
config->auth_types |= AUTH_TYPE_PLAIN;
|
||||
config->auth_types |= amod->type;
|
||||
} else if (strncasecmp(auth[j], "radius", 6) == 0) {
|
||||
const char *p;
|
||||
if ((config->auth_types & AUTH_TYPE_USERNAME_PASS) != 0) {
|
||||
fprintf(stderr, "You cannot mix multiple username/password authentication methods\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#ifdef HAVE_RADIUS
|
||||
config->auth_additional = get_brackets_string1(config, auth[j]+6);
|
||||
if (config->auth_additional == NULL) {
|
||||
fprintf(stderr, "No configuration specified; error in %s\n", auth[j]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
p = get_brackets_string2(config, auth[j]+6);
|
||||
if (p != NULL) {
|
||||
if (strcasecmp(p, "groupconfig") != 0) {
|
||||
fprintf(stderr, "No known configuration option: %s\n", p);
|
||||
exit(1);
|
||||
}
|
||||
config->sup_config_type = SUP_CONFIG_RADIUS;
|
||||
}
|
||||
amod = &radius_auth_funcs;
|
||||
config->auth_types |= amod->type;
|
||||
#else
|
||||
fprintf(stderr, "Radius support is disabled\n");
|
||||
exit(1);
|
||||
#endif
|
||||
} else if (c_strcasecmp(auth[j], "certificate") == 0) {
|
||||
config->auth_types |= AUTH_TYPE_CERTIFICATE;
|
||||
} else if (c_strcasecmp(auth[j], "certificate[optional]") == 0) {
|
||||
@@ -452,8 +529,9 @@ unsigned force_cert_auth;
|
||||
if (config->occtl_socket_file == NULL)
|
||||
config->occtl_socket_file = talloc_strdup(config, OCCTL_UNIX_SOCKET);
|
||||
|
||||
if (config->auth_types & AUTH_TYPE_USERNAME_PASS) {
|
||||
READ_TF("session-control", config->session_control, 0);
|
||||
val = get_option("session-control", NULL);
|
||||
if (val != NULL) {
|
||||
fprintf(stderr, "The option 'session-control' is deprecated\n");
|
||||
}
|
||||
|
||||
READ_STRING("banner", config->banner);
|
||||
@@ -496,6 +574,8 @@ unsigned force_cert_auth;
|
||||
|
||||
READ_TF("deny-roaming", config->deny_roaming, 0);
|
||||
|
||||
READ_NUMERIC("stats-report-time", config->stats_report_time);
|
||||
|
||||
config->rekey_time = -1;
|
||||
READ_NUMERIC("rekey-time", config->rekey_time);
|
||||
if (config->rekey_time == -1) {
|
||||
@@ -561,10 +641,9 @@ unsigned force_cert_auth;
|
||||
|
||||
READ_NUMERIC("ipv6-prefix", prefix);
|
||||
if (prefix > 0) {
|
||||
config->network.ipv6_netmask = ipv6_prefix_to_mask(config, prefix);
|
||||
config->network.ipv6_prefix = prefix;
|
||||
|
||||
if (config->network.ipv6_netmask == NULL) {
|
||||
if (valid_ipv6_prefix(prefix) == 0) {
|
||||
fprintf(stderr, "invalid IPv6 prefix: %u\n", prefix);
|
||||
exit(1);
|
||||
}
|
||||
@@ -642,8 +721,8 @@ static void check_cfg(struct cfg_st *config)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (config->network.ipv6 != NULL && config->network.ipv6_netmask == NULL) {
|
||||
fprintf(stderr, "No mask found for IPv6 network.\n");
|
||||
if (config->network.ipv6 != NULL && config->network.ipv6_prefix == 0) {
|
||||
fprintf(stderr, "No prefix found for IPv6 network.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -775,7 +854,6 @@ unsigned i;
|
||||
DEL(config->network.ipv4);
|
||||
DEL(config->network.ipv4_netmask);
|
||||
DEL(config->network.ipv6);
|
||||
DEL(config->network.ipv6_netmask);
|
||||
for (i=0;i<config->network.routes_size;i++)
|
||||
DEL(config->network.routes[i]);
|
||||
DEL(config->network.routes);
|
||||
@@ -822,6 +900,9 @@ void print_version(tOptions *opts, tOptDesc *desc)
|
||||
#ifdef HAVE_LIBWRAP
|
||||
fprintf(stderr, "tcp-wrappers, ");
|
||||
#endif
|
||||
#ifdef HAVE_RADIUS
|
||||
fprintf(stderr, "radius, ");
|
||||
#endif
|
||||
#ifdef HAVE_PAM
|
||||
fprintf(stderr, "PAM, ");
|
||||
#endif
|
||||
@@ -846,6 +927,7 @@ void print_version(tOptions *opts, tOptDesc *desc)
|
||||
void reload_cfg_file(void *pool, struct cfg_st* config)
|
||||
{
|
||||
clear_cfg_file(config);
|
||||
|
||||
memset(config, 0, sizeof(*config));
|
||||
|
||||
parse_cfg_file(cfg_file, config, 1);
|
||||
|
||||
@@ -141,7 +141,34 @@ int get_ipv4_lease(main_server_st* s, struct proc_st* proc)
|
||||
int ret;
|
||||
const char* c_network, *c_netmask;
|
||||
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) {
|
||||
c_network = proc->config.ipv4_network;
|
||||
c_netmask = proc->config.ipv4_netmask;
|
||||
@@ -273,15 +300,42 @@ int get_ipv6_lease(main_server_st* s, struct proc_st* proc)
|
||||
struct sockaddr_storage tmp, mask, network, rnd;
|
||||
unsigned i, max_loops = MAX_IP_TRIES;
|
||||
int ret;
|
||||
const char* c_network, *c_netmask;
|
||||
const char* c_network;
|
||||
char *c_netmask = NULL;
|
||||
char buf[64];
|
||||
|
||||
if (proc->config.ipv6_network && proc->config.ipv6_netmask) {
|
||||
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) {
|
||||
c_network = proc->config.ipv6_network;
|
||||
c_netmask = proc->config.ipv6_netmask;
|
||||
c_netmask = ipv6_prefix_to_mask(proc, proc->config.ipv6_prefix);
|
||||
} else {
|
||||
c_network = s->config->network.ipv6;
|
||||
c_netmask = s->config->network.ipv6_netmask;
|
||||
c_netmask = ipv6_prefix_to_mask(proc, proc->config.ipv6_prefix);
|
||||
}
|
||||
|
||||
if (c_network && c_netmask) {
|
||||
@@ -392,6 +446,7 @@ int get_ipv6_lease(main_server_st* s, struct proc_st* proc)
|
||||
return 0;
|
||||
fail:
|
||||
talloc_free(proc->ipv6);
|
||||
talloc_free(c_netmask);
|
||||
proc->ipv6 = NULL;
|
||||
|
||||
return ret;
|
||||
@@ -399,7 +454,7 @@ fail:
|
||||
}
|
||||
|
||||
static
|
||||
int unref_ip_lease(struct ip_lease_st * lease)
|
||||
int unref_ip_lease(struct ip_lease_st *lease)
|
||||
{
|
||||
if (lease->db) {
|
||||
htable_del(&lease->db->ht, rehash(lease, NULL), lease);
|
||||
@@ -407,7 +462,7 @@ int unref_ip_lease(struct ip_lease_st * lease)
|
||||
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;
|
||||
char buf[128];
|
||||
@@ -417,7 +472,7 @@ char buf[128];
|
||||
if (ret < 0)
|
||||
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) {
|
||||
mslog(s, proc, LOG_ERR, "could not add IPv4 lease to hash table.");
|
||||
return -1;
|
||||
@@ -431,7 +486,7 @@ char buf[128];
|
||||
if (ret < 0)
|
||||
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) {
|
||||
mslog(s, proc, LOG_ERR, "could not add IPv6 lease to hash table.");
|
||||
return -1;
|
||||
|
||||
@@ -86,6 +86,7 @@ message cli_stats_msg
|
||||
{
|
||||
required uint64 bytes_in = 1;
|
||||
required uint64 bytes_out = 2;
|
||||
optional bytes sid = 3; /* only required by sec-mod */
|
||||
}
|
||||
|
||||
/* UDP_FD */
|
||||
@@ -192,4 +193,24 @@ message sec_auth_session_msg
|
||||
message sec_auth_session_reply_msg
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -36,7 +36,6 @@
|
||||
#include <script-list.h>
|
||||
#include <ip-lease.h>
|
||||
#include <proc-search.h>
|
||||
#include <main-sup-config.h>
|
||||
#include "str.h"
|
||||
|
||||
#include <vpn.h>
|
||||
@@ -85,7 +84,6 @@ int send_cookie_auth_reply(main_server_st* s, struct proc_st* proc,
|
||||
}
|
||||
|
||||
msg.ipv4_netmask = proc->config.ipv4_netmask;
|
||||
msg.ipv6_netmask = proc->config.ipv6_netmask;
|
||||
|
||||
msg.ipv4_network = proc->config.ipv4_network;
|
||||
msg.ipv6_network = proc->config.ipv6_network;
|
||||
@@ -210,17 +208,16 @@ struct cookie_entry_st *old;
|
||||
memset(&proc->config, 0, sizeof(proc->config));
|
||||
apply_default_sup_config(s->config, 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;
|
||||
}
|
||||
/* loads sup config */
|
||||
ret = session_open(s, proc);
|
||||
if (ret < 0) {
|
||||
mslog(s, proc, LOG_INFO, "could not open session");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (proc->config.cgroup != NULL) {
|
||||
put_into_cgroup(s, proc->config.cgroup, proc->pid);
|
||||
}
|
||||
/* Put into right cgroup */
|
||||
if (proc->config.cgroup != NULL) {
|
||||
put_into_cgroup(s, proc->config.cgroup, proc->pid);
|
||||
}
|
||||
|
||||
/* check whether the cookie IP matches */
|
||||
@@ -284,12 +281,6 @@ struct cookie_entry_st *old;
|
||||
|
||||
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 */
|
||||
proc_table_add(s, proc);
|
||||
|
||||
|
||||
106
src/main-misc.c
106
src/main-misc.c
@@ -46,7 +46,6 @@
|
||||
#include <proc-search.h>
|
||||
#include <ipc.pb-c.h>
|
||||
#include <script-list.h>
|
||||
#include <main-sup-config.h>
|
||||
|
||||
#ifdef HAVE_MALLOC_TRIM
|
||||
# include <malloc.h>
|
||||
@@ -168,10 +167,8 @@ int session_cmd(main_server_st * s, struct proc_st *proc, unsigned open)
|
||||
int sd, ret, e;
|
||||
SecAuthSessionMsg ireq = SEC_AUTH_SESSION_MSG__INIT;
|
||||
SecAuthSessionReplyMsg *msg = NULL;
|
||||
unsigned type;
|
||||
|
||||
if (s->config->session_control == 0)
|
||||
return 0;
|
||||
unsigned type, i;
|
||||
PROTOBUF_ALLOCATOR(pa, proc);
|
||||
|
||||
if (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);
|
||||
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 {
|
||||
close(sd);
|
||||
}
|
||||
@@ -262,7 +339,7 @@ void remove_proc(main_server_st * s, struct proc_st *proc, unsigned k)
|
||||
}
|
||||
|
||||
/* close any pending sessions */
|
||||
if (s->config->session_control != 0 && proc->active_sid) {
|
||||
if (proc->active_sid) {
|
||||
session_close(s, proc);
|
||||
}
|
||||
|
||||
@@ -273,26 +350,17 @@ void remove_proc(main_server_st * s, struct proc_st *proc, unsigned k)
|
||||
proc->pid = -1;
|
||||
|
||||
remove_iroutes(s, proc);
|
||||
if (s->config_module) {
|
||||
s->config_module->clear_sup_config(&proc->config);
|
||||
}
|
||||
|
||||
if (proc->ipv4 || proc->ipv6)
|
||||
remove_ip_leases(s, proc);
|
||||
|
||||
/* expire any available cookies */
|
||||
if (proc->cookie_ptr) {
|
||||
unsigned timeout = s->config->cookie_timeout;
|
||||
|
||||
proc->cookie_ptr->proc = NULL;
|
||||
if (s->config->session_control != 0) {
|
||||
/* if we use session control and we closed the session we
|
||||
* need to invalidate the cookie, so that a new session is
|
||||
* used on the next connection */
|
||||
proc->cookie_ptr->expiration = 1;
|
||||
} else {
|
||||
proc->cookie_ptr->expiration = time(0) + timeout;
|
||||
}
|
||||
/* if we use session control and we closed the session we
|
||||
* need to invalidate the cookie, so that a new session is
|
||||
* used on the next connection */
|
||||
proc->cookie_ptr->expiration = 1;
|
||||
}
|
||||
|
||||
close_tun(s, proc);
|
||||
|
||||
@@ -51,7 +51,6 @@
|
||||
# include <systemd/sd-daemon.h>
|
||||
#endif
|
||||
#include <main.h>
|
||||
#include <main-sup-config.h>
|
||||
#include <main-ctl.h>
|
||||
#include <route-add.h>
|
||||
#include <worker.h>
|
||||
@@ -987,8 +986,6 @@ int main(int argc, char** argv)
|
||||
|
||||
run_sec_mod(s);
|
||||
|
||||
sup_config_init(s);
|
||||
|
||||
ret = ctl_handler_init(s);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Cannot create command handler\n");
|
||||
|
||||
@@ -213,7 +213,6 @@ typedef struct main_server_st {
|
||||
time_t start_time;
|
||||
|
||||
void * auth_extra;
|
||||
struct config_mod_st *config_module;
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
void * ctl_ctx;
|
||||
@@ -305,4 +304,6 @@ int send_socket_msg_to_worker(main_server_st* s, struct proc_st* proc, uint8_t c
|
||||
void request_reload(int signo);
|
||||
void request_stop(int signo);
|
||||
|
||||
const struct auth_mod_st *get_auth_mod(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -76,7 +76,7 @@ An example configuration file follows.
|
||||
# User authentication method. Could be set multiple times and in
|
||||
# that case all should succeed. To enable multiple methods use
|
||||
# multiple auth directives. Available options: certificate, certificate[optional],
|
||||
# plain, pam.
|
||||
# plain, pam, radius[configfile,groupconfig].
|
||||
#auth = "certificate"
|
||||
#auth = "pam"
|
||||
|
||||
@@ -96,11 +96,13 @@ An example configuration file follows.
|
||||
# to generate password entries.
|
||||
#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
|
||||
# The radius option requires specifying freeradius-client configuration
|
||||
# file. If the groupconfig option is set, then config-per-user will be overriden,
|
||||
# and all configuration will be read from radius. The supported atributes for
|
||||
# radius configuration are:
|
||||
# Group-Name, Framed-IPv6-Address, DNS-Server-IPv6-Address, Framed-IP-Address,
|
||||
# Framed-IP-Netmask, MS-Primary-DNS-Server, MS-Secondary-DNS-Server
|
||||
#auth = "radius[/etc/radiusclient/radiusclient.conf,groupconfig]"
|
||||
|
||||
# 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
|
||||
@@ -141,6 +143,12 @@ udp-port = 3333
|
||||
# combined with certificate authentication.
|
||||
#listen-clear-file = /var/run/ocserv-conn.socket
|
||||
|
||||
# Stats report time. The number of seconds after which each
|
||||
# worker process will report its usage statistics (number of
|
||||
# bytes transferred etc). This is useful when accounting like
|
||||
# radius is in use.
|
||||
#stats-report-time = 360
|
||||
|
||||
# Keepalive in seconds
|
||||
keepalive = 32400
|
||||
|
||||
|
||||
@@ -49,19 +49,26 @@
|
||||
#include <auth/pam.h>
|
||||
#include <sec-mod.h>
|
||||
#include <vpn.h>
|
||||
#include <sec-mod-sup-config.h>
|
||||
|
||||
static const struct auth_mod_st *module = NULL;
|
||||
|
||||
void sec_auth_init(struct cfg_st *config)
|
||||
void sec_auth_init(sec_mod_st * sec, struct cfg_st *config)
|
||||
{
|
||||
#ifdef HAVE_PAM
|
||||
if ((config->auth_types & pam_auth_funcs.type) == pam_auth_funcs.type)
|
||||
module = &pam_auth_funcs;
|
||||
else
|
||||
#endif
|
||||
if ((config->auth_types & plain_auth_funcs.type) ==
|
||||
plain_auth_funcs.type) {
|
||||
module = &plain_auth_funcs;
|
||||
module = get_auth_mod();
|
||||
|
||||
if (module && module->global_init) {
|
||||
module->global_init(sec, config->auth_additional);
|
||||
}
|
||||
}
|
||||
|
||||
void sec_auth_reinit(sec_mod_st * sec, struct cfg_st *config)
|
||||
{
|
||||
if (module) {
|
||||
if (module != get_auth_mod()) {
|
||||
seclog(sec, LOG_ERR, "Cannot change authentication method on reload");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,7 +109,7 @@ static int generate_cookie(sec_mod_st * sec, client_entry_st * entry)
|
||||
}
|
||||
|
||||
static
|
||||
int send_sec_auth_reply(sec_mod_st * sec, client_entry_st * entry, AUTHREP r)
|
||||
int send_sec_auth_reply(int cfd, sec_mod_st * sec, client_entry_st * entry, AUTHREP r)
|
||||
{
|
||||
SecAuthReplyMsg msg = SEC_AUTH_REPLY_MSG__INIT;
|
||||
int ret;
|
||||
@@ -130,7 +137,7 @@ int send_sec_auth_reply(sec_mod_st * sec, client_entry_st * entry, AUTHREP r)
|
||||
msg.dtls_session_id.data = entry->dtls_session_id;
|
||||
msg.dtls_session_id.len = sizeof(entry->dtls_session_id);
|
||||
|
||||
ret = send_msg(entry, sec->fd, SM_CMD_AUTH_REP,
|
||||
ret = send_msg(entry, cfd, SM_CMD_AUTH_REP,
|
||||
&msg,
|
||||
(pack_size_func)
|
||||
sec_auth_reply_msg__get_packed_size,
|
||||
@@ -138,7 +145,7 @@ int send_sec_auth_reply(sec_mod_st * sec, client_entry_st * entry, AUTHREP r)
|
||||
} else {
|
||||
msg.reply = AUTH__REP__FAILED;
|
||||
|
||||
ret = send_msg(entry, sec->fd, SM_CMD_AUTH_REP,
|
||||
ret = send_msg(entry, cfd, SM_CMD_AUTH_REP,
|
||||
&msg,
|
||||
(pack_size_func)
|
||||
sec_auth_reply_msg__get_packed_size,
|
||||
@@ -155,7 +162,7 @@ int send_sec_auth_reply(sec_mod_st * sec, client_entry_st * entry, AUTHREP r)
|
||||
}
|
||||
|
||||
static
|
||||
int send_sec_auth_reply_msg(sec_mod_st * sec, client_entry_st * e)
|
||||
int send_sec_auth_reply_msg(int cfd, sec_mod_st * sec, client_entry_st * e)
|
||||
{
|
||||
SecAuthReplyMsg msg = SEC_AUTH_REPLY_MSG__INIT;
|
||||
char tmp[MAX_MSG_SIZE] = "";
|
||||
@@ -176,7 +183,7 @@ int send_sec_auth_reply_msg(sec_mod_st * sec, client_entry_st * e)
|
||||
msg.sid.data = e->sid;
|
||||
msg.sid.len = sizeof(e->sid);
|
||||
|
||||
ret = send_msg(e, sec->fd, SM_CMD_AUTH_REP, &msg,
|
||||
ret = send_msg(e, cfd, SM_CMD_AUTH_REP, &msg,
|
||||
(pack_size_func) sec_auth_reply_msg__get_packed_size,
|
||||
(pack_func) sec_auth_reply_msg__pack);
|
||||
if (ret < 0) {
|
||||
@@ -256,12 +263,12 @@ static int check_user_group_status(sec_mod_st * sec, client_entry_st * e,
|
||||
* @result: the auth result
|
||||
*/
|
||||
static
|
||||
int handle_sec_auth_res(sec_mod_st * sec, client_entry_st * e, int result)
|
||||
int handle_sec_auth_res(int cfd, sec_mod_st * sec, client_entry_st * e, int result)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (result == ERR_AUTH_CONTINUE) {
|
||||
ret = send_sec_auth_reply_msg(sec, e);
|
||||
ret = send_sec_auth_reply_msg(cfd, sec, e);
|
||||
if (ret < 0) {
|
||||
e->status = PS_AUTH_FAILED;
|
||||
seclog(sec, LOG_ERR, "could not send reply auth cmd.");
|
||||
@@ -271,7 +278,7 @@ int handle_sec_auth_res(sec_mod_st * sec, client_entry_st * e, int result)
|
||||
} else if (result == 0) {
|
||||
e->status = PS_AUTH_COMPLETED;
|
||||
|
||||
ret = send_sec_auth_reply(sec, e, AUTH__REP__OK);
|
||||
ret = send_sec_auth_reply(cfd, sec, e, AUTH__REP__OK);
|
||||
if (ret < 0) {
|
||||
e->status = PS_AUTH_FAILED;
|
||||
seclog(sec, LOG_ERR, "could not send reply auth cmd.");
|
||||
@@ -279,14 +286,11 @@ int handle_sec_auth_res(sec_mod_st * sec, client_entry_st * e, int result)
|
||||
}
|
||||
|
||||
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 {
|
||||
e->status = PS_AUTH_FAILED;
|
||||
add_ip_to_ban_list(sec, e->ip, time(0) + sec->config->min_reauth_time);
|
||||
|
||||
ret = send_sec_auth_reply(sec, e, AUTH__REP__FAILED);
|
||||
ret = send_sec_auth_reply(cfd, sec, e, AUTH__REP__FAILED);
|
||||
if (ret < 0) {
|
||||
seclog(sec, LOG_ERR, "could not send reply auth cmd.");
|
||||
return ret;
|
||||
@@ -305,19 +309,13 @@ int handle_sec_auth_res(sec_mod_st * sec, client_entry_st * e, int result)
|
||||
|
||||
/* 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(int cfd, sec_mod_st * sec, const SecAuthSessionMsg * req,
|
||||
unsigned cmd)
|
||||
{
|
||||
client_entry_st *e;
|
||||
void *lpool;
|
||||
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) {
|
||||
seclog(sec, LOG_ERR, "auth session open/close but with illegal sid size (%d)!",
|
||||
(int)req->sid.len);
|
||||
@@ -331,14 +329,44 @@ int handle_sec_auth_session_cmd(sec_mod_st * sec, const SecAuthSessionMsg * req,
|
||||
}
|
||||
|
||||
if (cmd == SM_CMD_AUTH_SESSION_OPEN) {
|
||||
ret = module->open_session(e->auth_ctx);
|
||||
if (ret < 0) {
|
||||
e->status = PS_AUTH_FAILED;
|
||||
seclog(sec, LOG_ERR, "could not open session.");
|
||||
del_client_entry(sec, e);
|
||||
return ret;
|
||||
SecAuthSessionReplyMsg rep = SEC_AUTH_SESSION_REPLY_MSG__INIT;
|
||||
|
||||
if (module != NULL && module->open_session != NULL) {
|
||||
ret = module->open_session(e->auth_ctx, req->sid.data, req->sid.len);
|
||||
if (ret < 0) {
|
||||
e->status = PS_AUTH_FAILED;
|
||||
seclog(sec, LOG_ERR, "could not open session.");
|
||||
del_client_entry(sec, e);
|
||||
rep.reply = AUTH__REP__FAILED;
|
||||
} else {
|
||||
e->have_session = 1;
|
||||
rep.reply = AUTH__REP__OK;
|
||||
}
|
||||
} else {
|
||||
rep.reply = AUTH__REP__OK;
|
||||
}
|
||||
e->have_session = 1;
|
||||
|
||||
lpool = talloc_new(e);
|
||||
if (lpool == NULL) {
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
if (sec->config_module && sec->config_module->get_sup_config) {
|
||||
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(lpool, cfd, SM_CMD_AUTH_SESSION_REPLY, &rep,
|
||||
(pack_size_func) sec_auth_session_reply_msg__get_packed_size,
|
||||
(pack_func) sec_auth_session_reply_msg__pack);
|
||||
if (ret < 0) {
|
||||
seclog(sec, LOG_WARNING, "sec-mod error in sending session reply");
|
||||
}
|
||||
talloc_free(lpool);
|
||||
} else {
|
||||
del_client_entry(sec, e);
|
||||
}
|
||||
@@ -346,7 +374,38 @@ int handle_sec_auth_session_cmd(sec_mod_st * sec, const SecAuthSessionMsg * req,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int handle_sec_auth_cont(sec_mod_st * sec, const SecAuthContMsg * req)
|
||||
int handle_sec_auth_stats_cmd(sec_mod_st * sec, const CliStatsMsg * req)
|
||||
{
|
||||
client_entry_st *e;
|
||||
|
||||
if (req->sid.len != SID_SIZE) {
|
||||
seclog(sec, LOG_ERR, "auth session open/close but with illegal sid size (%d)!",
|
||||
(int)req->sid.len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
e = find_client_entry(sec, req->sid.data);
|
||||
if (e == NULL) {
|
||||
seclog(sec, LOG_INFO, "session open/close but with non-existing sid!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (e->status != PS_AUTH_COMPLETED) {
|
||||
seclog(sec, LOG_ERR, "session stats received in unauthenticated client!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
e->bytes_in = req->bytes_in;
|
||||
e->bytes_out = req->bytes_out;
|
||||
|
||||
if (module == NULL || module->session_stats == NULL)
|
||||
return 0;
|
||||
|
||||
module->session_stats(e->auth_ctx, e->bytes_in, e->bytes_out);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int handle_sec_auth_cont(int cfd, sec_mod_st * sec, const SecAuthContMsg * req)
|
||||
{
|
||||
client_entry_st *e;
|
||||
int ret;
|
||||
@@ -391,10 +450,10 @@ int handle_sec_auth_cont(sec_mod_st * sec, const SecAuthContMsg * req)
|
||||
e->username);
|
||||
}
|
||||
|
||||
return handle_sec_auth_res(sec, e, ret);
|
||||
return handle_sec_auth_res(cfd, sec, e, ret);
|
||||
}
|
||||
|
||||
int handle_sec_auth_init(sec_mod_st * sec, const SecAuthInitMsg * req)
|
||||
int handle_sec_auth_init(int cfd, sec_mod_st * sec, const SecAuthInitMsg * req)
|
||||
{
|
||||
int ret = -1;
|
||||
client_entry_st *e;
|
||||
@@ -488,7 +547,7 @@ int handle_sec_auth_init(sec_mod_st * sec, const SecAuthInitMsg * req)
|
||||
|
||||
ret = 0;
|
||||
cleanup:
|
||||
return handle_sec_auth_res(sec, e, ret);
|
||||
return handle_sec_auth_res(cfd, sec, e, ret);
|
||||
}
|
||||
|
||||
void sec_auth_user_deinit(sec_mod_st * sec, client_entry_st * e)
|
||||
|
||||
@@ -28,13 +28,16 @@
|
||||
|
||||
struct auth_mod_st {
|
||||
unsigned int type;
|
||||
void (*global_init)(void *pool, void* additional);
|
||||
void (*global_deinit)(void);
|
||||
int (*auth_init)(void** ctx, void *pool, const char* username, const char* ip, void* additional);
|
||||
int (*auth_msg)(void* ctx, char* msg, size_t msg_size);
|
||||
int (*auth_pass)(void* ctx, const char* pass, unsigned pass_len);
|
||||
int (*auth_group)(void* ctx, const char *suggested, char *groupname, int groupname_size);
|
||||
int (*auth_user)(void* ctx, char *groupname, int groupname_size);
|
||||
|
||||
int (*open_session)(void *ctx); /* optional, may be null */
|
||||
int (*open_session)(void *ctx, const void *sid, unsigned sid_size); /* optional, may be null */
|
||||
void (*session_stats)(void *ctx, uint64_t bytes_in, uint64_t bytes_out); /* optional, may be null */
|
||||
void (*close_session)(void *ctx); /* optional */
|
||||
|
||||
void (*auth_deinit)(void* ctx);
|
||||
|
||||
@@ -27,11 +27,16 @@
|
||||
#include <main.h>
|
||||
#include <common.h>
|
||||
#include <vpn.h>
|
||||
#include <main-sup-config.h>
|
||||
#include <sec-mod-sup-config.h>
|
||||
#include <sup-config/file.h>
|
||||
#include <sup-config/radius.h>
|
||||
|
||||
void sup_config_init(main_server_st *s)
|
||||
void sup_config_init(sec_mod_st *sec)
|
||||
{
|
||||
s->config_module = &file_sup_config;
|
||||
if (sec->config->sup_config_type == SUP_CONFIG_FILE) {
|
||||
sec->config_module = &file_sup_config;
|
||||
} else if (sec->config->sup_config_type == SUP_CONFIG_RADIUS) {
|
||||
sec->config_module = &radius_sup_config;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,16 +21,19 @@
|
||||
#ifndef SUP_CONFIG_H
|
||||
# define SUP_CONFIG_H
|
||||
|
||||
#include <main.h>
|
||||
#include <sec-mod.h>
|
||||
|
||||
#define SUP_CONFIG_FILE 1
|
||||
#define SUP_CONFIG_RADIUS 2
|
||||
|
||||
/* 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);
|
||||
int (*get_sup_config)(struct cfg_st *global_config, client_entry_st *entry,
|
||||
SecAuthSessionReplyMsg *msg, void *pool);
|
||||
};
|
||||
|
||||
void sup_config_init(main_server_st *s);
|
||||
void sup_config_init(sec_mod_st *sec);
|
||||
|
||||
#endif
|
||||
160
src/sec-mod.c
160
src/sec-mod.c
@@ -40,6 +40,7 @@
|
||||
#include <sec-mod.h>
|
||||
#include <tlslib.h>
|
||||
#include <ipc.pb-c.h>
|
||||
#include <sec-mod-sup-config.h>
|
||||
|
||||
#include <gnutls/gnutls.h>
|
||||
#include <gnutls/abstract.h>
|
||||
@@ -166,7 +167,7 @@ int load_pins(struct cfg_st *config, struct pin_st *s)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int handle_op(void *pool, sec_mod_st * sec, uint8_t type, uint8_t * rep,
|
||||
static int handle_op(void *pool, int cfd, sec_mod_st * sec, uint8_t type, uint8_t * rep,
|
||||
size_t rep_size)
|
||||
{
|
||||
SecOpMsg msg = SEC_OP_MSG__INIT;
|
||||
@@ -175,7 +176,7 @@ static int handle_op(void *pool, sec_mod_st * sec, uint8_t type, uint8_t * rep,
|
||||
msg.data.data = rep;
|
||||
msg.data.len = rep_size;
|
||||
|
||||
ret = send_msg(pool, sec->fd, type, &msg,
|
||||
ret = send_msg(pool, cfd, type, &msg,
|
||||
(pack_size_func) sec_op_msg__get_packed_size,
|
||||
(pack_func) sec_op_msg__pack);
|
||||
if (ret < 0) {
|
||||
@@ -186,7 +187,7 @@ static int handle_op(void *pool, sec_mod_st * sec, uint8_t type, uint8_t * rep,
|
||||
}
|
||||
|
||||
static
|
||||
int process_packet(void *pool, sec_mod_st * sec, cmd_request_t cmd,
|
||||
int process_packet(void *pool, int cfd, sec_mod_st * sec, cmd_request_t cmd,
|
||||
uid_t uid, uint8_t * buffer, size_t buffer_size)
|
||||
{
|
||||
unsigned i;
|
||||
@@ -243,11 +244,27 @@ int process_packet(void *pool, sec_mod_st * sec, cmd_request_t cmd,
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = handle_op(pool, sec, cmd, out.data, out.size);
|
||||
ret = handle_op(pool, cfd, sec, cmd, out.data, out.size);
|
||||
gnutls_free(out.data);
|
||||
|
||||
return ret;
|
||||
|
||||
case SM_CMD_CLI_STATS:{
|
||||
CliStatsMsg *tmsg;
|
||||
|
||||
tmsg = cli_stats_msg__unpack(&pa, data.size, data.data);
|
||||
if (tmsg == NULL) {
|
||||
seclog(sec, LOG_ERR, "error unpacking data");
|
||||
ret = ERR_BAD_COMMAND;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = handle_sec_auth_stats_cmd(sec, tmsg);
|
||||
cli_stats_msg__free_unpacked(tmsg, &pa);
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
|
||||
case SM_CMD_AUTH_INIT:{
|
||||
SecAuthInitMsg *auth_init;
|
||||
|
||||
@@ -259,7 +276,7 @@ int process_packet(void *pool, sec_mod_st * sec, cmd_request_t cmd,
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = handle_sec_auth_init(sec, auth_init);
|
||||
ret = handle_sec_auth_init(cfd, sec, auth_init);
|
||||
sec_auth_init_msg__free_unpacked(auth_init, &pa);
|
||||
return ret;
|
||||
}
|
||||
@@ -274,14 +291,13 @@ int process_packet(void *pool, sec_mod_st * sec, cmd_request_t cmd,
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = handle_sec_auth_cont(sec, auth_cont);
|
||||
ret = handle_sec_auth_cont(cfd, sec, auth_cont);
|
||||
sec_auth_cont_msg__free_unpacked(auth_cont, &pa);
|
||||
return ret;
|
||||
}
|
||||
case SM_CMD_AUTH_SESSION_OPEN:
|
||||
case SM_CMD_AUTH_SESSION_CLOSE:{
|
||||
SecAuthSessionMsg *msg;
|
||||
SecAuthSessionReplyMsg rep = SEC_AUTH_SESSION_REPLY_MSG__INIT;
|
||||
|
||||
if (uid != 0) {
|
||||
seclog(sec, LOG_INFO, "received session open/close from unauthorized uid (%u)\n", (unsigned)uid);
|
||||
@@ -296,23 +312,9 @@ int process_packet(void *pool, sec_mod_st * sec, cmd_request_t cmd,
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = handle_sec_auth_session_cmd(sec, msg, cmd);
|
||||
ret = handle_sec_auth_session_cmd(cfd, sec, msg, cmd);
|
||||
sec_auth_session_msg__free_unpacked(msg, &pa);
|
||||
|
||||
if (cmd == SM_CMD_AUTH_SESSION_OPEN) {
|
||||
if (ret < 0)
|
||||
rep.reply = AUTH__REP__FAILED;
|
||||
else
|
||||
rep.reply = AUTH__REP__OK;
|
||||
|
||||
ret = send_msg(pool, sec->fd, SM_CMD_AUTH_SESSION_REPLY, &rep,
|
||||
(pack_size_func) sec_auth_session_reply_msg__get_packed_size,
|
||||
(pack_func) sec_auth_session_reply_msg__pack);
|
||||
if (ret < 0) {
|
||||
seclog(sec, LOG_WARNING, "sec-mod error in sending session reply");
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
default:
|
||||
@@ -356,6 +358,7 @@ static void check_other_work(sec_mod_st *sec)
|
||||
if (need_reload) {
|
||||
seclog(sec, LOG_DEBUG, "reloading configuration");
|
||||
reload_cfg_file(sec, sec->config);
|
||||
sec_auth_reinit(sec, sec->config);
|
||||
need_reload = 0;
|
||||
}
|
||||
|
||||
@@ -371,6 +374,54 @@ static void check_other_work(sec_mod_st *sec)
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void serve_request(sec_mod_st *sec, uid_t uid, int cfd, uint8_t *buffer, unsigned buffer_size)
|
||||
{
|
||||
int ret, e;
|
||||
unsigned cmd, length;
|
||||
uint16_t l16;
|
||||
void *pool = buffer;
|
||||
|
||||
/* read request */
|
||||
ret = force_read_timeout(cfd, buffer, 3, MAX_WAIT_SECS);
|
||||
if (ret == 0)
|
||||
goto leave;
|
||||
else if (ret < 3) {
|
||||
e = errno;
|
||||
seclog(sec, LOG_INFO, "error receiving msg head: %s",
|
||||
strerror(e));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
cmd = buffer[0];
|
||||
memcpy(&l16, &buffer[1], 2);
|
||||
length = l16;
|
||||
|
||||
if (length > buffer_size - 4) {
|
||||
seclog(sec, LOG_INFO, "too big message (%d)", length);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* read the body */
|
||||
ret = force_read_timeout(cfd, buffer, length, MAX_WAIT_SECS);
|
||||
if (ret < 0) {
|
||||
e = errno;
|
||||
seclog(sec, LOG_INFO, "error receiving msg body: %s",
|
||||
strerror(e));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
ret = process_packet(pool, cfd, sec, cmd, uid, buffer, ret);
|
||||
if (ret < 0) {
|
||||
seclog(sec, LOG_INFO, "error processing data for '%s' command (%d)", cmd_request_to_str(cmd), ret);
|
||||
}
|
||||
|
||||
leave:
|
||||
talloc_free(pool);
|
||||
close(cfd);
|
||||
return;
|
||||
}
|
||||
|
||||
/* sec_mod_server:
|
||||
* @config: server configuration
|
||||
* @socket_file: the name of the socket
|
||||
@@ -404,11 +455,9 @@ void sec_mod_server(void *main_pool, struct cfg_st *config, const char *socket_f
|
||||
struct sockaddr_un sa;
|
||||
socklen_t sa_len;
|
||||
int cfd, ret, e;
|
||||
unsigned cmd, length;
|
||||
unsigned i, buffer_size;
|
||||
uid_t uid;
|
||||
uint8_t *buffer, *tpool;
|
||||
uint16_t l16;
|
||||
uint8_t *buffer;
|
||||
struct pin_st pins;
|
||||
int sd;
|
||||
sec_mod_st *sec;
|
||||
@@ -435,6 +484,8 @@ void sec_mod_server(void *main_pool, struct cfg_st *config, const char *socket_f
|
||||
sec->dcookie_key.size = COOKIE_KEY_SIZE;
|
||||
sec->config = talloc_steal(sec, config);
|
||||
|
||||
sup_config_init(sec);
|
||||
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sun_family = AF_UNIX;
|
||||
snprintf(sa.sun_path, sizeof(sa.sun_path), "%s", socket_file);
|
||||
@@ -452,7 +503,7 @@ void sec_mod_server(void *main_pool, struct cfg_st *config, const char *socket_f
|
||||
|
||||
alarm(MAINTAINANCE_TIME);
|
||||
|
||||
sec_auth_init(config);
|
||||
sec_auth_init(sec, config);
|
||||
|
||||
#ifdef HAVE_PKCS11
|
||||
ret = gnutls_pkcs11_reinit();
|
||||
@@ -470,13 +521,6 @@ void sec_mod_server(void *main_pool, struct cfg_st *config, const char *socket_f
|
||||
if (config->min_reauth_time > 0)
|
||||
sec_mod_ban_db_init(sec);
|
||||
|
||||
buffer_size = 8 * 1024;
|
||||
buffer = talloc_size(sec, buffer_size);
|
||||
if (buffer == NULL) {
|
||||
seclog(sec, LOG_ERR, "error in memory allocation");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
sd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (sd == -1) {
|
||||
@@ -578,50 +622,18 @@ void sec_mod_server(void *main_pool, struct cfg_st *config, const char *socket_f
|
||||
ret = check_upeer_id("sec-mod", cfd, config->uid, config->gid, &uid);
|
||||
if (ret < 0) {
|
||||
seclog(sec, LOG_INFO, "rejected unauthorized connection");
|
||||
goto cont;
|
||||
} else {
|
||||
buffer_size = 8 * 1024;
|
||||
buffer = talloc_size(sec, buffer_size);
|
||||
if (buffer == NULL) {
|
||||
seclog(sec, LOG_ERR, "error in memory allocation");
|
||||
close(cfd);
|
||||
} else {
|
||||
serve_request(sec, uid, cfd, buffer, buffer_size);
|
||||
}
|
||||
}
|
||||
|
||||
/* read request */
|
||||
ret = force_read_timeout(cfd, buffer, 3, MAX_WAIT_SECS);
|
||||
if (ret == 0)
|
||||
goto cont;
|
||||
else if (ret < 3) {
|
||||
e = errno;
|
||||
seclog(sec, LOG_INFO, "error receiving msg head: %s",
|
||||
strerror(e));
|
||||
goto cont;
|
||||
}
|
||||
|
||||
cmd = buffer[0];
|
||||
memcpy(&l16, &buffer[1], 2);
|
||||
length = l16;
|
||||
|
||||
if (length > buffer_size - 4) {
|
||||
seclog(sec, LOG_INFO, "too big message (%d)", length);
|
||||
goto cont;
|
||||
}
|
||||
|
||||
/* read the body */
|
||||
ret = force_read_timeout(cfd, buffer, length, MAX_WAIT_SECS);
|
||||
if (ret < 0) {
|
||||
e = errno;
|
||||
seclog(sec, LOG_INFO, "error receiving msg body: %s",
|
||||
strerror(e));
|
||||
goto cont;
|
||||
}
|
||||
|
||||
tpool = talloc_new(sec);
|
||||
sec->fd = cfd;
|
||||
ret = process_packet(tpool, sec, cmd, uid, buffer, ret);
|
||||
if (ret < 0) {
|
||||
seclog(sec, LOG_INFO, "error processing data for '%s' command (%d)", cmd_request_to_str(cmd), ret);
|
||||
}
|
||||
talloc_free(tpool);
|
||||
|
||||
#ifdef DEBUG_LEAKS
|
||||
talloc_report_full(sec, stderr);
|
||||
#endif
|
||||
cont:
|
||||
close(cfd);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
#ifndef SEC_MOD_H
|
||||
# define SEC_MOD_H
|
||||
|
||||
#include <cookies.h>
|
||||
#include <gnutls/abstract.h>
|
||||
@@ -34,7 +35,7 @@ typedef struct sec_mod_st {
|
||||
struct htable *client_db;
|
||||
struct htable *ban_db;
|
||||
|
||||
int fd;
|
||||
struct config_mod_st *config_module;
|
||||
} sec_mod_st;
|
||||
|
||||
|
||||
@@ -49,6 +50,11 @@ typedef struct client_entry_st {
|
||||
unsigned have_session; /* whether an auth session is initialized */
|
||||
unsigned tls_auth_ok;
|
||||
|
||||
/* these are filled in after the worker process dies, using the
|
||||
* Cli stats message. */
|
||||
uint64_t bytes_in;
|
||||
uint64_t bytes_out;
|
||||
|
||||
unsigned status; /* PS_AUTH_ */
|
||||
|
||||
char ip[MAX_IP_STR]; /* the user's IP */
|
||||
@@ -83,11 +89,13 @@ void cleanup_client_entries(sec_mod_st *sec);
|
||||
}
|
||||
#endif
|
||||
|
||||
void sec_auth_init(struct cfg_st *config);
|
||||
void sec_auth_init(sec_mod_st *sec, struct cfg_st *config);
|
||||
void sec_auth_reinit(sec_mod_st *sec, struct cfg_st *config);
|
||||
|
||||
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_session_cmd(sec_mod_st * sec, const SecAuthSessionMsg * req, unsigned cmd);
|
||||
int handle_sec_auth_init(int cfd, sec_mod_st *sec, const SecAuthInitMsg * req);
|
||||
int handle_sec_auth_cont(int cfd, sec_mod_st *sec, const SecAuthContMsg * req);
|
||||
int handle_sec_auth_session_cmd(int cfd, sec_mod_st *sec, const SecAuthSessionMsg *req, unsigned cmd);
|
||||
int handle_sec_auth_stats_cmd(sec_mod_st * sec, const CliStatsMsg * req);
|
||||
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,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Nikos Mavrogiannopoulos
|
||||
* Copyright (C) 2014 Red Hat, Inc.
|
||||
*
|
||||
* 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
|
||||
@@ -33,7 +34,7 @@
|
||||
|
||||
#include <vpn.h>
|
||||
#include <main.h>
|
||||
#include <main-sup-config.h>
|
||||
#include <sec-mod-sup-config.h>
|
||||
|
||||
struct cfg_options {
|
||||
const char* name;
|
||||
@@ -68,14 +69,14 @@ static struct cfg_options available_options[] = {
|
||||
if (val != NULL && val->valType == OPARG_TYPE_STRING) { \
|
||||
if (s_name == NULL) { \
|
||||
num = 0; \
|
||||
s_name = talloc_size(proc, sizeof(char*)*MAX_CONFIG_ENTRIES); \
|
||||
s_name = talloc_size(pool, sizeof(char*)*MAX_CONFIG_ENTRIES); \
|
||||
} \
|
||||
do { \
|
||||
if (num >= MAX_CONFIG_ENTRIES) \
|
||||
break; \
|
||||
if (val && !strcmp(val->pzName, name)==0) \
|
||||
continue; \
|
||||
s_name[num] = talloc_strdup(proc, val->v.strVal); \
|
||||
s_name[num] = talloc_strdup(pool, val->v.strVal); \
|
||||
num++; \
|
||||
} while((val = optionNextValue(pov, val)) != NULL); \
|
||||
s_name[num] = NULL; \
|
||||
@@ -86,28 +87,33 @@ static struct cfg_options available_options[] = {
|
||||
if (val != NULL && val->valType == OPARG_TYPE_STRING) { \
|
||||
if (s_name != NULL) \
|
||||
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); \
|
||||
if (val != NULL) { \
|
||||
if (val->valType == OPARG_TYPE_NUMERIC) \
|
||||
if (val->valType == OPARG_TYPE_NUMERIC) {\
|
||||
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); \
|
||||
def = 1; \
|
||||
} \
|
||||
}}
|
||||
|
||||
#define READ_RAW_PRIO_TOS(name, s_name) { \
|
||||
#define READ_RAW_PRIO_TOS(name, s_name, def) { \
|
||||
val = optionGetValue(pov, name); \
|
||||
if (val != NULL) { \
|
||||
if (val->valType == OPARG_TYPE_STRING) { \
|
||||
if (strncmp(val->v.strVal, "0x", 2) == 0) { \
|
||||
s_name = strtol(val->v.strVal, NULL, 16); \
|
||||
s_name = TOS_PACK(s_name); \
|
||||
def = 1; \
|
||||
} else { \
|
||||
s_name = atoi(val->v.strVal); \
|
||||
s_name++; \
|
||||
def = 1; \
|
||||
} \
|
||||
} \
|
||||
}}
|
||||
@@ -115,12 +121,13 @@ static struct cfg_options available_options[] = {
|
||||
#define READ_TF(name, s_name, def) { \
|
||||
{ char* tmp_tf = NULL; \
|
||||
READ_RAW_STRING(name, tmp_tf); \
|
||||
if (tmp_tf == NULL) s_name = def; \
|
||||
else { \
|
||||
if (tmp_tf == NULL) { def = 0; \
|
||||
} else { \
|
||||
if (c_strcasecmp(tmp_tf, "true") == 0 || c_strcasecmp(tmp_tf, "yes") == 0) \
|
||||
s_name = 1; \
|
||||
else \
|
||||
s_name = 0; \
|
||||
def = 1; \
|
||||
} \
|
||||
talloc_free(tmp_tf); \
|
||||
}}
|
||||
@@ -143,13 +150,13 @@ unsigned j;
|
||||
* already allocated using this function.
|
||||
*/
|
||||
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)
|
||||
{
|
||||
tOptionValue const * pov;
|
||||
const tOptionValue* val, *prev;
|
||||
unsigned prefix = 0;
|
||||
struct group_cfg_st *sconfig = &proc->config;
|
||||
|
||||
pov = configFileLoad(file);
|
||||
if (pov == NULL) {
|
||||
@@ -171,60 +178,58 @@ struct group_cfg_st *sconfig = &proc->config;
|
||||
prev = val;
|
||||
} while((val = optionNextValue(pov, prev)) != NULL);
|
||||
|
||||
READ_TF("no-udp", sconfig->no_udp, (global_config->udp_port!=0)?0:1);
|
||||
READ_TF("deny-roaming", sconfig->deny_roaming, global_config->deny_roaming);
|
||||
READ_TF("require-cert", sconfig->require_cert, 0);
|
||||
READ_TF("no-udp", msg->no_udp, msg->has_no_udp);
|
||||
READ_TF("deny-roaming", msg->deny_roaming, msg->has_deny_roaming);
|
||||
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("iroute", sconfig->iroutes, sconfig->iroutes_size);
|
||||
READ_RAW_MULTI_LINE("route", msg->routes, msg->n_routes);
|
||||
READ_RAW_MULTI_LINE("iroute", msg->iroutes, msg->n_iroutes);
|
||||
|
||||
READ_RAW_MULTI_LINE("dns", sconfig->dns, sconfig->dns_size);
|
||||
if (sconfig->dns_size == 0) {
|
||||
READ_RAW_MULTI_LINE("dns", msg->dns, msg->n_dns);
|
||||
if (msg->n_dns == 0) {
|
||||
/* try aliases */
|
||||
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("ipv6-dns", msg->dns, msg->n_dns);
|
||||
READ_RAW_MULTI_LINE("ipv4-dns", msg->dns, msg->n_dns);
|
||||
}
|
||||
|
||||
READ_RAW_MULTI_LINE("nbns", sconfig->nbns, sconfig->nbns_size);
|
||||
if (sconfig->nbns_size == 0) {
|
||||
READ_RAW_MULTI_LINE("nbns", msg->nbns, msg->n_nbns);
|
||||
if (msg->n_nbns == 0) {
|
||||
/* try aliases */
|
||||
READ_RAW_MULTI_LINE("ipv6-nbns", sconfig->nbns, sconfig->nbns_size);
|
||||
READ_RAW_MULTI_LINE("ipv4-nbns", sconfig->nbns, sconfig->nbns_size);
|
||||
READ_RAW_MULTI_LINE("ipv6-nbns", msg->nbns, msg->n_nbns);
|
||||
READ_RAW_MULTI_LINE("ipv4-nbns", msg->nbns, msg->n_nbns);
|
||||
}
|
||||
|
||||
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_STRING("cgroup", msg->cgroup);
|
||||
READ_RAW_STRING("ipv4-network", msg->ipv4_net);
|
||||
READ_RAW_STRING("ipv6-network", msg->ipv6_net);
|
||||
READ_RAW_STRING("ipv4-netmask", msg->ipv4_netmask);
|
||||
|
||||
READ_RAW_NUMERIC("ipv6-prefix", prefix);
|
||||
if (prefix > 0) {
|
||||
sconfig->ipv6_netmask = ipv6_prefix_to_mask(proc, prefix);
|
||||
sconfig->ipv6_prefix = prefix;
|
||||
|
||||
if (sconfig->ipv6_netmask == NULL) {
|
||||
READ_RAW_NUMERIC("ipv6-prefix", msg->ipv6_prefix, msg->has_ipv6_prefix);
|
||||
if (msg->has_ipv6_prefix != 0) {
|
||||
if (valid_ipv6_prefix(msg->ipv6_prefix) == 0) {
|
||||
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("tx-data-per-sec", sconfig->tx_per_sec);
|
||||
sconfig->rx_per_sec /= 1000; /* in kb */
|
||||
sconfig->tx_per_sec /= 1000; /* in kb */
|
||||
READ_RAW_NUMERIC("rx-data-per-sec", msg->rx_per_sec, msg->has_rx_per_sec);
|
||||
READ_RAW_NUMERIC("tx-data-per-sec", msg->tx_per_sec, msg->has_tx_per_sec);
|
||||
msg->rx_per_sec /= 1000; /* in kb */
|
||||
msg->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", 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);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read_sup_config_file(struct cfg_st *global_config, struct proc_st *proc,
|
||||
const char *file, const char *fallback, const char *type)
|
||||
static int read_sup_config_file(struct cfg_st *global_config,
|
||||
SecAuthSessionReplyMsg *msg, void *pool,
|
||||
const char *file, const char *fallback, const char *type)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@@ -232,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,
|
||||
file);
|
||||
|
||||
ret = parse_group_cfg_file(global_config, proc, file);
|
||||
ret = parse_group_cfg_file(global_config, msg, pool, 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);
|
||||
ret = parse_group_cfg_file(global_config, msg, pool, 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)
|
||||
static int get_sup_config(struct cfg_st *cfg, client_entry_st *entry,
|
||||
SecAuthSessionReplyMsg *msg, void *pool)
|
||||
{
|
||||
char file[_POSIX_PATH_MAX];
|
||||
int ret;
|
||||
|
||||
if (global_config->per_group_dir != NULL && proc->groupname[0] != 0) {
|
||||
snprintf(file, sizeof(file), "%s/%s", global_config->per_group_dir,
|
||||
proc->groupname);
|
||||
if (cfg->per_group_dir != NULL && entry->groupname[0] != 0) {
|
||||
snprintf(file, sizeof(file), "%s/%s", cfg->per_group_dir,
|
||||
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)
|
||||
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 (cfg->per_user_dir != NULL) {
|
||||
snprintf(file, sizeof(file), "%s/%s", cfg->per_user_dir,
|
||||
entry->username);
|
||||
ret = read_sup_config_file(cfg, msg, pool, file, cfg->default_user_conf, "user");
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
@@ -277,41 +279,6 @@ static int get_sup_config(struct cfg_st *global_config, struct proc_st *proc)
|
||||
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);
|
||||
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,
|
||||
};
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#ifndef 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;
|
||||
|
||||
|
||||
100
src/sup-config/radius.c
Normal file
100
src/sup-config/radius.c
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Red Hat, Inc.
|
||||
*
|
||||
* 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 <sys/types.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#include <fcntl.h>
|
||||
#include <ocserv-args.h>
|
||||
#include <autoopts/options.h>
|
||||
#include <limits.h>
|
||||
#include <common.h>
|
||||
#include <c-strcase.h>
|
||||
|
||||
#ifdef HAVE_RADIUS
|
||||
|
||||
#include <vpn.h>
|
||||
#include <main.h>
|
||||
#include <sec-mod-sup-config.h>
|
||||
#include <auth/radius.h>
|
||||
|
||||
static int get_sup_config(struct cfg_st *cfg, client_entry_st *entry,
|
||||
SecAuthSessionReplyMsg *msg, void *pool)
|
||||
{
|
||||
struct radius_ctx_st *pctx = entry->auth_ctx;
|
||||
unsigned dns = 0;
|
||||
|
||||
if (pctx == NULL)
|
||||
return 0;
|
||||
|
||||
if (pctx->ipv4[0] != 0) {
|
||||
msg->explicit_ipv4 = talloc_strdup(pool, pctx->ipv4);
|
||||
}
|
||||
|
||||
if (pctx->ipv4_mask[0] != 0) {
|
||||
msg->ipv4_netmask = talloc_strdup(pool, pctx->ipv4_mask);
|
||||
}
|
||||
|
||||
if (pctx->ipv4_dns1[0] != 0)
|
||||
dns++;
|
||||
if (pctx->ipv4_dns2[0] != 0)
|
||||
dns++;
|
||||
if (pctx->ipv6_dns1[0] != 0)
|
||||
dns++;
|
||||
if (pctx->ipv6_dns2[0] != 0)
|
||||
dns++;
|
||||
|
||||
if (dns > 0) {
|
||||
msg->dns = talloc_size(pool, dns*sizeof(char*));
|
||||
if (msg->dns != NULL) {
|
||||
unsigned pos = 0;
|
||||
if (pctx->ipv4_dns1[0] != 0)
|
||||
msg->dns[pos++] = talloc_strdup(pool, pctx->ipv4_dns1);
|
||||
if (pctx->ipv4_dns2[0] != 0)
|
||||
msg->dns[pos++] = talloc_strdup(pool, pctx->ipv4_dns2);
|
||||
if (pctx->ipv6_dns1[0] != 0)
|
||||
msg->dns[pos++] = talloc_strdup(pool, pctx->ipv6_dns1);
|
||||
if (pctx->ipv6_dns2[0] != 0)
|
||||
msg->dns[pos++] = talloc_strdup(pool, pctx->ipv6_dns2);
|
||||
|
||||
msg->n_dns = dns;
|
||||
}
|
||||
}
|
||||
|
||||
if (pctx->ipv6[0] != 0) {
|
||||
msg->explicit_ipv6 = talloc_strdup(pool, pctx->ipv6);
|
||||
}
|
||||
|
||||
if (pctx->ipv6_prefix != 0) {
|
||||
msg->ipv6_prefix = pctx->ipv6_prefix;
|
||||
msg->has_ipv6_prefix = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct config_mod_st radius_sup_config = {
|
||||
.get_sup_config = get_sup_config,
|
||||
};
|
||||
|
||||
#endif
|
||||
28
src/sup-config/radius.h
Normal file
28
src/sup-config/radius.h
Normal 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_RADIUS_H
|
||||
#define SUP_CONFIG_RADIUS_H
|
||||
|
||||
#include <sec-mod-sup-config.h>
|
||||
|
||||
extern struct config_mod_st radius_sup_config;
|
||||
|
||||
#endif
|
||||
12
src/vpn.h
12
src/vpn.h
@@ -76,6 +76,7 @@ extern int syslog_open;
|
||||
#define AUTH_TYPE_PLAIN (1<<2 | AUTH_TYPE_USERNAME_PASS)
|
||||
#define AUTH_TYPE_CERTIFICATE (1<<3)
|
||||
#define AUTH_TYPE_CERTIFICATE_OPT (1<<4|AUTH_TYPE_CERTIFICATE)
|
||||
#define AUTH_TYPE_RADIUS (1<<5 | AUTH_TYPE_USERNAME_PASS)
|
||||
|
||||
#define ERR_SUCCESS 0
|
||||
#define ERR_BAD_COMMAND -2
|
||||
@@ -122,6 +123,7 @@ typedef enum {
|
||||
SM_CMD_AUTH_SESSION_OPEN,
|
||||
SM_CMD_AUTH_SESSION_CLOSE,
|
||||
SM_CMD_AUTH_SESSION_REPLY,
|
||||
SM_CMD_CLI_STATS,
|
||||
} cmd_request_t;
|
||||
|
||||
#define MAX_IP_STR 46
|
||||
@@ -145,8 +147,10 @@ struct group_cfg_st {
|
||||
char *ipv6_network;
|
||||
unsigned ipv6_prefix;
|
||||
char *ipv4_netmask;
|
||||
char *ipv6_netmask;
|
||||
|
||||
|
||||
char *explicit_ipv4;
|
||||
char *explicit_ipv6;
|
||||
|
||||
char *cgroup;
|
||||
|
||||
char *xml_config_file;
|
||||
@@ -166,7 +170,6 @@ struct vpn_st {
|
||||
char *ipv4_network;
|
||||
char *ipv4;
|
||||
char *ipv4_local; /* local IPv4 address */
|
||||
char *ipv6_netmask;
|
||||
char *ipv6_network;
|
||||
unsigned ipv6_prefix;
|
||||
|
||||
@@ -190,6 +193,8 @@ struct cfg_st {
|
||||
unsigned int udp_port;
|
||||
unsigned int is_dyndns;
|
||||
char* unix_conn_file;
|
||||
unsigned int sup_config_type; /* one of SUP_CONFIG_ */
|
||||
unsigned int stats_report_time;
|
||||
|
||||
char *pin_file;
|
||||
char *srk_pin_file;
|
||||
@@ -204,7 +209,6 @@ struct cfg_st {
|
||||
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 */
|
||||
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 */
|
||||
gnutls_certificate_request_t cert_req;
|
||||
char *priorities;
|
||||
|
||||
@@ -548,12 +548,6 @@ static int recv_cookie_auth_reply(worker_st * ws)
|
||||
talloc_strdup(ws, msg->ipv4_netmask);
|
||||
}
|
||||
|
||||
if (msg->ipv6_netmask != NULL) {
|
||||
talloc_free(ws->config->network.ipv6_netmask);
|
||||
ws->config->network.ipv6_netmask =
|
||||
talloc_strdup(ws, msg->ipv6_netmask);
|
||||
}
|
||||
|
||||
if (msg->ipv4_network != NULL) {
|
||||
talloc_free(ws->config->network.ipv4_network);
|
||||
ws->config->network.ipv4_network =
|
||||
@@ -647,7 +641,7 @@ static int recv_cookie_auth_reply(worker_st * ws)
|
||||
}
|
||||
|
||||
/* returns the fd */
|
||||
static int connect_to_secmod(worker_st * ws)
|
||||
int connect_to_secmod(worker_st * ws)
|
||||
{
|
||||
int sd, ret, e;
|
||||
|
||||
@@ -673,16 +667,6 @@ static int connect_to_secmod(worker_st * ws)
|
||||
return sd;
|
||||
}
|
||||
|
||||
static
|
||||
int send_msg_to_secmod(worker_st * ws, int sd, uint8_t cmd,
|
||||
const void *msg, pack_size_func get_size, pack_func pack)
|
||||
{
|
||||
oclog(ws, LOG_DEBUG, "sending message '%s' to secmod",
|
||||
cmd_request_to_str(cmd));
|
||||
|
||||
return send_msg(ws, sd, cmd, msg, get_size, pack);
|
||||
}
|
||||
|
||||
static int recv_auth_reply(worker_st * ws, int sd, char *txt,
|
||||
size_t max_txt_size)
|
||||
{
|
||||
|
||||
@@ -227,7 +227,6 @@ int complete_vpn_info(worker_st * ws, struct vpn_st *vinfo)
|
||||
vinfo->ipv6_network = ws->config->network.ipv6_network;
|
||||
|
||||
vinfo->ipv4_netmask = ws->config->network.ipv4_netmask;
|
||||
vinfo->ipv6_netmask = ws->config->network.ipv6_netmask;
|
||||
vinfo->ipv6_prefix = ws->config->network.ipv6_prefix;
|
||||
|
||||
if (ws->config->network.mtu != 0) {
|
||||
|
||||
@@ -992,6 +992,34 @@ int periodic_check(worker_st * ws, unsigned mtu_overhead, time_t now,
|
||||
|
||||
}
|
||||
|
||||
if (ws->config->stats_report_time > 0 &&
|
||||
now - ws->last_stats_msg >= ws->config->stats_report_time &&
|
||||
ws->sid_set) {
|
||||
CliStatsMsg msg = CLI_STATS_MSG__INIT;
|
||||
int sd;
|
||||
|
||||
ws->last_stats_msg = now;
|
||||
|
||||
sd = connect_to_secmod(ws);
|
||||
if (sd >= 0) {
|
||||
msg.bytes_in = ws->tun_bytes_in;
|
||||
msg.bytes_out = ws->tun_bytes_out;
|
||||
msg.sid.len = sizeof(ws->sid);
|
||||
msg.sid.data = ws->sid;
|
||||
msg.has_sid = 1;
|
||||
|
||||
send_msg_to_secmod(ws, sd, SM_CMD_CLI_STATS, &msg,
|
||||
(pack_size_func)cli_stats_msg__get_packed_size,
|
||||
(pack_func) cli_stats_msg__pack);
|
||||
close(sd);
|
||||
|
||||
oclog(ws, LOG_DEBUG,
|
||||
"sending periodic stats (in: %lu, out: %lu) to sec-mod",
|
||||
(unsigned long)msg.bytes_in,
|
||||
(unsigned long)msg.bytes_out);
|
||||
}
|
||||
}
|
||||
|
||||
/* check DPD. Otherwise exit */
|
||||
if (ws->udp_state == UP_ACTIVE &&
|
||||
now - ws->last_msg_udp > DPD_TRIES * dpd && dpd > 0) {
|
||||
|
||||
14
src/worker.h
14
src/worker.h
@@ -172,6 +172,9 @@ typedef struct worker_st {
|
||||
time_t last_tls_rehandshake;
|
||||
time_t last_dtls_rehandshake;
|
||||
|
||||
/* the time the last stats message was sent */
|
||||
time_t last_stats_msg;
|
||||
|
||||
/* for mtu trials */
|
||||
unsigned last_good_mtu;
|
||||
unsigned last_bad_mtu;
|
||||
@@ -274,6 +277,17 @@ int handle_worker_commands(struct worker_st *ws);
|
||||
int disable_system_calls(struct worker_st *ws);
|
||||
void ocsigaltstack(struct worker_st *ws);
|
||||
|
||||
int connect_to_secmod(worker_st * ws);
|
||||
inline static
|
||||
int send_msg_to_secmod(worker_st * ws, int sd, uint8_t cmd,
|
||||
const void *msg, pack_size_func get_size, pack_func pack)
|
||||
{
|
||||
oclog(ws, LOG_DEBUG, "sending message '%s' to secmod",
|
||||
cmd_request_to_str(cmd));
|
||||
|
||||
return send_msg(ws, sd, cmd, msg, get_size, pack);
|
||||
}
|
||||
|
||||
inline static
|
||||
int send_msg_to_main(worker_st *ws, uint8_t cmd,
|
||||
const void* msg, pack_size_func get_size, pack_func pack)
|
||||
|
||||
Reference in New Issue
Block a user