Separated accounting from authentication.

This commit is contained in:
Nikos Mavrogiannopoulos
2015-02-23 11:24:14 +01:00
parent 783be933e5
commit 40e96aae45
23 changed files with 662 additions and 332 deletions

View File

@@ -40,6 +40,17 @@ auth = "plain[./sample.passwd]"
#enable-auth = gssapi
#enable-auth = "gssapi[keytab:/etc/key.tab]"
# Accounting methods available:
# pam: can only be combined with PAM authentication method, it provides
# a session opened using PAM.
#
# radius: can be combined with any authentication method, it provides
# radius accounting to available users (see also stats-report-time).
#
# Only one accounting method can be specified.
#acct = "pam"
#acct = "radius[/etc/radiusclient/radiusclient.conf]"
# Whether to enable seccomp/Linux namespaces 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.

View File

@@ -66,6 +66,8 @@ COMMON_SOURCES=common.c common.h system.c system.h setproctitle.c setproctitle.h
AUTH_SOURCES=auth/pam.c auth/pam.h auth/plain.c auth/plain.h auth/radius.c auth/radius.h \
auth/common.c auth/common.h auth/gssapi.h auth/gssapi.c
ACCT_SOURCES=acct/pam.c acct/pam.h acct/radius.c acct/radius.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 \
vpn.h cookies.h tlslib.h log.c tun.c tun.h \
@@ -73,7 +75,7 @@ ocserv_SOURCES = main.c main-auth.c worker-vpn.c worker-auth.c tlslib.c \
worker-extras.c html.c html.h worker-http.c \
main-user.c worker-misc.c route-add.c route-add.h worker-privs.c \
sec-mod.c sec-mod-db.c sec-mod-auth.c sec-mod-auth.h sec-mod.h sec-mod-ban.c \
script-list.h $(COMMON_SOURCES) $(AUTH_SOURCES) \
script-list.h $(COMMON_SOURCES) $(AUTH_SOURCES) $(ACCT_SOURCES) \
icmp-ping.c icmp-ping.h worker-kkdcp.c \
sec-mod-sup-config.c sec-mod-sup-config.h \
sup-config/file.c sup-config/file.h \
@@ -82,7 +84,7 @@ ocserv_SOURCES = main.c main-auth.c worker-vpn.c worker-auth.c tlslib.c \
vasprintf.c vasprintf.h lzs.c lzs.h \
proc-search.c proc-search.h http-heads.h \
str.c str.h gettime.h $(CCAN_SOURCES) $(HTTP_PARSER_SOURCES) \
$(PROTOBUF_SOURCES) kkdcp.asn kkdcp_asn1_tab.c
$(PROTOBUF_SOURCES) kkdcp.asn kkdcp_asn1_tab.c sec-mod-acct.h
ocserv_SOURCES += ipc.pb-c.h ipc.pb-c.c ctl.pb-c.c ctl.pb-c.h

83
src/acct/pam.c Normal file
View File

@@ -0,0 +1,83 @@
/*
* Copyright (C) 2013 Nikos Mavrogiannopoulos
*
* 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 <vpn.h>
#include "pam.h"
#include <sec-mod-acct.h>
#ifdef HAVE_PAM
#include <security/pam_appl.h>
#include <sys/types.h>
#include <pwd.h>
#include <grp.h>
#include <pcl.h>
#include <str.h>
#include "auth/pam.h"
static int pam_acct_open_session(unsigned auth_method, void *ctx, const struct common_auth_info_st *ai, const void *sid, unsigned sid_size)
{
struct pam_ctx_st * pctx = ctx;
int pret;
if (auth_method != AUTH_TYPE_PAM) {
syslog(LOG_AUTH, "PAM-acct: pam_open_session cannot be combined with this authentication method (%x)", auth_method);
return -1;
}
if (pctx->cr != NULL) {
co_delete(pctx->cr);
pctx->cr = NULL;
}
pret = pam_open_session(pctx->ph, PAM_SILENT);
if (pret != PAM_SUCCESS) {
syslog(LOG_AUTH, "PAM-acct: pam_open_session: %s", pam_strerror(pctx->ph, pret));
return -1;
}
return 0;
}
static void pam_acct_close_session(unsigned auth_method, void *ctx, const struct common_auth_info_st *ai, stats_st *stats)
{
struct pam_ctx_st * pctx = ctx;
int pret;
pret = pam_close_session(pctx->ph, PAM_SILENT);
if (pret != PAM_SUCCESS) {
syslog(LOG_AUTH, "PAM-acct: pam_close_session: %s", pam_strerror(pctx->ph, pret));
}
return;
}
const struct acct_mod_st pam_acct_funcs = {
.type = ACCT_TYPE_PAM,
.auth_types = AUTH_TYPE_PAM & (~VIRTUAL_AUTH_TYPES),
.open_session = pam_acct_open_session,
.close_session = pam_acct_close_session,
};
#endif

28
src/acct/pam.h Normal file
View File

@@ -0,0 +1,28 @@
/*
* Copyright (C) 2015 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 ACCT_PAM_H
#define ACCT_PAM_H
#include <sec-mod-acct.h>
extern const struct acct_mod_st pam_acct_funcs;
#endif

282
src/acct/radius.c Normal file
View File

@@ -0,0 +1,282 @@
/*
* 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>
#include <sec-mod-acct.h>
#include "auth/radius.h"
#include "acct/radius.h"
static rc_handle *rh = NULL;
static char nas_identifier[64];
static void acct_radius_global_init(void *pool, const char *server_name, void *additional)
{
rh = rc_read_config(additional);
if (rh == NULL) {
fprintf(stderr, "radius initialization error\n");
exit(1);
}
if (server_name)
strlcpy(nas_identifier, server_name, sizeof(nas_identifier));
else
nas_identifier[0] = 0;
if (rc_read_dictionary(rh, rc_conf_str(rh, "dictionary")) != 0) {
fprintf(stderr, "error reading the radius dictionary\n");
exit(1);
}
return;
}
static void acct_radius_global_deinit(void)
{
if (rh != NULL)
rc_destroy(rh);
}
static void append_stats(rc_handle *rh, VALUE_PAIR **send, stats_st *stats)
{
uint32_t uin, uout;
if (stats->uptime) {
uin = stats->uptime;
if (rc_avpair_add(rh, send, PW_ACCT_SESSION_TIME, &uin, -1, 0) == NULL) {
return;
}
}
uin = stats->bytes_in;
uout = stats->bytes_out;
if (rc_avpair_add(rh, send, PW_ACCT_INPUT_OCTETS, &uin, -1, 0) == NULL) {
return;
}
if (rc_avpair_add(rh, send, PW_ACCT_OUTPUT_OCTETS, &uout, -1, 0) == NULL) {
return;
}
uin = stats->bytes_in / 4294967296;
if (rc_avpair_add(rh, send, PW_ACCT_INPUT_GIGAWORDS, &uin, -1, 0) == NULL) {
return;
}
uout = stats->bytes_in / 4294967296;
if (rc_avpair_add(rh, send, PW_ACCT_OUTPUT_GIGAWORDS, &uout, -1, 0) == NULL) {
return;
}
return;
}
static void append_acct_standard(rc_handle *rh, const common_auth_info_st *ai, VALUE_PAIR **send)
{
int i;
if (nas_identifier[0] != 0) {
if (rc_avpair_add(rh, send, PW_NAS_IDENTIFIER, nas_identifier, -1, 0) == NULL) {
return;
}
}
if (rc_avpair_add(rh, send, PW_USER_NAME, ai->username, -1, 0) == NULL) {
return;
}
i = PW_FRAMED;
if (rc_avpair_add(rh, send, PW_SERVICE_TYPE, &i, -1, 0) == NULL) {
return;
}
i = PW_PPP;
if (rc_avpair_add(rh, send, PW_FRAMED_PROTOCOL, &i, -1, 0) == NULL) {
return;
}
if (ai->ipv4[0] != 0) {
struct in_addr in;
inet_pton(AF_INET, ai->ipv4, &in);
in.s_addr = ntohl(in.s_addr);
if (rc_avpair_add(rh, send, PW_FRAMED_IP_ADDRESS, &in, sizeof(in), 0) == NULL) {
return;
}
}
if (ai->ipv6[0] != 0) {
struct in6_addr in;
inet_pton(AF_INET6, ai->ipv6, &in);
if (rc_avpair_add(rh, send, PW_FRAMED_IPV6_ADDRESS, &in, sizeof(in), 0) == NULL) {
return;
}
}
if (rc_avpair_add(rh, send, PW_CALLING_STATION_ID, ai->remote_ip, -1, 0) == NULL) {
return;
}
if (rc_avpair_add(rh, send, PW_ACCT_SESSION_ID, ai->psid, -1, 0) == NULL) {
return;
}
i = PW_RADIUS;
if (rc_avpair_add(rh, send, PW_ACCT_AUTHENTIC, &i, -1, 0) == NULL) {
return;
}
i = PW_ASYNC;
if (rc_avpair_add(rh, send, PW_NAS_PORT_TYPE, &i, -1, 0) == NULL) {
return;
}
return;
}
static void radius_acct_session_stats(unsigned auth_method, void *ctx, const common_auth_info_st *ai, stats_st *stats)
{
int ret;
uint32_t status_type;
VALUE_PAIR *send = NULL, *recvd = NULL;
status_type = PW_STATUS_ALIVE;
syslog(LOG_DEBUG, "radius-auth: sending session interim update");
if (rc_avpair_add(rh, &send, PW_ACCT_STATUS_TYPE, &status_type, -1, 0) == NULL) {
ret = -1;
goto cleanup;
}
append_acct_standard(rh, ai, &send);
append_stats(rh, &send, stats);
ret = rc_aaa(rh, 0, send, &recvd, NULL, 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_acct_open_session(unsigned auth_method, void *ctx, const common_auth_info_st *ai, const void *sid, unsigned sid_size)
{
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, "radius-auth: incorrect sid size");
return -1;
}
syslog(LOG_DEBUG, "radius-auth: opening session %s", ai->psid);
if (rc_avpair_add(rh, &send, PW_ACCT_STATUS_TYPE, &status_type, -1, 0) == NULL) {
ret = -1;
goto cleanup;
}
append_acct_standard(rh, ai, &send);
ret = rc_aaa(rh, 0, send, &recvd, NULL, 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_acct_close_session(unsigned auth_method, void *ctx, const common_auth_info_st *ai, stats_st *stats)
{
int ret;
uint32_t status_type;
VALUE_PAIR *send = NULL, *recvd = NULL;
status_type = PW_STATUS_STOP;
syslog(LOG_DEBUG, "radius-auth: closing session");
if (rc_avpair_add(rh, &send, PW_ACCT_STATUS_TYPE, &status_type, -1, 0) == NULL)
return;
ret = PW_USER_REQUEST;
if (rc_avpair_add(rh, &send, PW_ACCT_TERMINATE_CAUSE, &ret, -1, 0) == NULL) {
goto cleanup;
}
append_acct_standard(rh, ai, &send);
append_stats(rh, &send, stats);
ret = rc_aaa(rh, 0, send, &recvd, NULL, 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 acct_mod_st radius_acct_funcs = {
.type = ACCT_TYPE_RADIUS,
.auth_types = ALL_AUTH_TYPES,
.global_init = acct_radius_global_init,
.global_deinit = acct_radius_global_deinit,
.open_session = radius_acct_open_session,
.close_session = radius_acct_close_session,
.session_stats = radius_acct_session_stats
};
#endif

28
src/acct/radius.h Normal file
View File

@@ -0,0 +1,28 @@
/*
* Copyright (C) 2015 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 ACCT_RADIUS_H
#define ACCT_RADIUS_H
#include <sec-mod-auth.h>
extern const struct acct_mod_st radius_acct_funcs;
#endif

View File

@@ -42,8 +42,7 @@
#include <sys/types.h>
#include <pwd.h>
#include <grp.h>
#include <pcl.h>
#include <str.h>
#include "auth/pam.h"
#define PAM_STACK_SIZE (96*1024)
@@ -55,20 +54,6 @@ enum {
PAM_S_COMPLETE,
};
struct pam_ctx_st {
char password[MAX_PASSWORD_SIZE];
char username[MAX_USERNAME_SIZE];
pam_handle_t * ph;
struct pam_conv dc;
coroutine_t cr;
int cr_ret;
unsigned changing; /* whether we are entering a new password */
str_st msg;
unsigned sent_msg;
struct pam_response *replies; /* for safety */
unsigned state; /* PAM_S_ */
};
static int ocserv_conv(int msg_size, const struct pam_message **msg,
struct pam_response **resp, void *uptr)
{
@@ -353,38 +338,6 @@ struct pam_ctx_st * pctx = ctx;
talloc_free(pctx);
}
static int pam_auth_open_session(void* ctx, const void *sid, unsigned sid_size)
{
struct pam_ctx_st * pctx = ctx;
int pret;
if (pctx->cr != NULL) {
co_delete(pctx->cr);
pctx->cr = NULL;
}
pret = pam_open_session(pctx->ph, PAM_SILENT);
if (pret != PAM_SUCCESS) {
syslog(LOG_AUTH, "PAM-auth: pam_open_session: %s", pam_strerror(pctx->ph, pret));
return -1;
}
return 0;
}
static void pam_auth_close_session(void* ctx, stats_st *stats)
{
struct pam_ctx_st * pctx = ctx;
int pret;
pret = pam_close_session(pctx->ph, PAM_SILENT);
if (pret != PAM_SUCCESS) {
syslog(LOG_AUTH, "PAM-auth: pam_close_session: %s", pam_strerror(pctx->ph, pret));
}
return;
}
static void pam_group_list(void *pool, void *_additional, char ***groupname, unsigned *groupname_size)
{
struct group *grp;
@@ -430,8 +383,6 @@ const struct auth_mod_st pam_auth_funcs = {
.auth_pass = pam_auth_pass,
.auth_group = pam_auth_group,
.auth_user = pam_auth_user,
.open_session = pam_auth_open_session,
.close_session = pam_auth_close_session,
.group_list = pam_group_list
};

View File

@@ -22,7 +22,25 @@
#define PAM_H
#include <sec-mod-auth.h>
#include <security/pam_appl.h>
#include <str.h>
#include <pcl.h>
extern const struct auth_mod_st pam_auth_funcs;
struct pam_ctx_st {
char password[MAX_PASSWORD_SIZE];
char username[MAX_USERNAME_SIZE];
pam_handle_t * ph;
struct pam_conv dc;
coroutine_t cr;
int cr_ret;
unsigned changing; /* whether we are entering a new password */
str_st msg;
unsigned sent_msg;
struct pam_response *replies; /* for safety */
unsigned state; /* PAM_S_ */
};
#endif

View File

@@ -323,218 +323,6 @@ static void radius_auth_deinit(void *ctx)
talloc_free(pctx);
}
static void append_stats(rc_handle *rh, VALUE_PAIR **send, stats_st *stats)
{
uint32_t uin, uout;
if (stats->uptime) {
uin = stats->uptime;
if (rc_avpair_add(rh, send, PW_ACCT_SESSION_TIME, &uin, -1, 0) == NULL) {
return;
}
}
uin = stats->bytes_in;
uout = stats->bytes_out;
if (rc_avpair_add(rh, send, PW_ACCT_INPUT_OCTETS, &uin, -1, 0) == NULL) {
return;
}
if (rc_avpair_add(rh, send, PW_ACCT_OUTPUT_OCTETS, &uout, -1, 0) == NULL) {
return;
}
uin = stats->bytes_in / 4294967296;
if (rc_avpair_add(rh, send, PW_ACCT_INPUT_GIGAWORDS, &uin, -1, 0) == NULL) {
return;
}
uout = stats->bytes_in / 4294967296;
if (rc_avpair_add(rh, send, PW_ACCT_OUTPUT_GIGAWORDS, &uout, -1, 0) == NULL) {
return;
}
return;
}
static void append_acct_standard(struct radius_ctx_st * pctx, rc_handle *rh,
VALUE_PAIR **send)
{
int i;
if (nas_identifier[0] != 0) {
if (rc_avpair_add(rh, send, PW_NAS_IDENTIFIER, nas_identifier, -1, 0) == NULL) {
return;
}
}
if (rc_avpair_add(rh, send, PW_USER_NAME, pctx->username, -1, 0) == NULL) {
return;
}
i = PW_FRAMED;
if (rc_avpair_add(rh, send, PW_SERVICE_TYPE, &i, -1, 0) == NULL) {
return;
}
i = PW_PPP;
if (rc_avpair_add(rh, send, PW_FRAMED_PROTOCOL, &i, -1, 0) == NULL) {
return;
}
if (pctx->ipv4[0] != 0) {
struct in_addr in;
inet_pton(AF_INET, pctx->ipv4, &in);
in.s_addr = ntohl(in.s_addr);
if (rc_avpair_add(rh, send, PW_FRAMED_IP_ADDRESS, &in, sizeof(in), 0) == NULL) {
return;
}
}
if (pctx->ipv6[0] != 0) {
struct in6_addr in;
inet_pton(AF_INET6, pctx->ipv6, &in);
if (rc_avpair_add(rh, send, PW_FRAMED_IPV6_ADDRESS, &in, sizeof(in), 0) == NULL) {
return;
}
}
if (rc_avpair_add(rh, send, PW_CALLING_STATION_ID, pctx->remote_ip, -1, 0) == NULL) {
return;
}
if (rc_avpair_add(rh, send, PW_ACCT_SESSION_ID, pctx->sid, -1, 0) == NULL) {
return;
}
i = PW_RADIUS;
if (rc_avpair_add(rh, send, PW_ACCT_AUTHENTIC, &i, -1, 0) == NULL) {
return;
}
i = PW_ASYNC;
if (rc_avpair_add(rh, send, PW_NAS_PORT_TYPE, &i, -1, 0) == NULL) {
return;
}
return;
}
static void radius_auth_session_stats(void* ctx, stats_st *stats, const char *ip)
{
struct radius_ctx_st * pctx = ctx;
int ret;
uint32_t status_type;
VALUE_PAIR *send = NULL, *recvd = NULL;
if (ip)
strlcpy(pctx->remote_ip, ip, sizeof(pctx->remote_ip));
status_type = PW_STATUS_ALIVE;
syslog(LOG_DEBUG, "radius-auth: sending session interim update");
if (rc_avpair_add(rh, &send, PW_ACCT_STATUS_TYPE, &status_type, -1, 0) == NULL) {
ret = -1;
goto cleanup;
}
append_acct_standard(pctx, rh, &send);
append_stats(rh, &send, stats);
ret = rc_aaa(rh, 0, send, &recvd, NULL, 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, "radius-auth: incorrect sid size");
return -1;
}
base64_encode((char *)sid, sid_size, (char *)pctx->sid, sizeof(pctx->sid));
syslog(LOG_DEBUG, "radius-auth: opening session %s", pctx->sid);
if (rc_avpair_add(rh, &send, PW_ACCT_STATUS_TYPE, &status_type, -1, 0) == NULL) {
ret = -1;
goto cleanup;
}
append_acct_standard(pctx, rh, &send);
ret = rc_aaa(rh, 0, send, &recvd, NULL, 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, stats_st *stats)
{
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, "radius-auth: closing session");
if (rc_avpair_add(rh, &send, PW_ACCT_STATUS_TYPE, &status_type, -1, 0) == NULL)
return;
ret = PW_USER_REQUEST;
if (rc_avpair_add(rh, &send, PW_ACCT_TERMINATE_CAUSE, &ret, -1, 0) == NULL) {
goto cleanup;
}
append_acct_standard(pctx, rh, &send);
append_stats(rh, &send, stats);
ret = rc_aaa(rh, 0, send, &recvd, NULL, 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,
.allows_retries = 1,
@@ -546,9 +334,6 @@ const struct auth_mod_st radius_auth_funcs = {
.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
};

View File

@@ -27,7 +27,6 @@
struct radius_ctx_st {
char username[MAX_USERNAME_SIZE*2];
char groupname[MAX_GROUPNAME_SIZE];
char sid[BASE64_LENGTH(SID_SIZE) + 1];
char remote_ip[MAX_IP_STR];

View File

@@ -33,10 +33,13 @@
#include <c-ctype.h>
#include <auth/pam.h>
#include <auth/radius.h>
#include <acct/pam.h>
#include <acct/radius.h>
#include <auth/plain.h>
#include <auth/gssapi.h>
#include <auth/common.h>
#include <sec-mod-sup-config.h>
#include <sec-mod-acct.h>
#include <sys/types.h>
#include <sys/socket.h>
@@ -69,6 +72,7 @@ static struct cfg_options available_options[] = {
{ .name = "select-group", .type = OPTION_MULTI_LINE, .mandatory = 0 },
{ .name = "custom-header", .type = OPTION_MULTI_LINE, .mandatory = 0 },
{ .name = "split-dns", .type = OPTION_MULTI_LINE, .mandatory = 0 },
{ .name = "acct", .type = OPTION_STRING, .mandatory = 0 },
{ .name = "server-name", .type = OPTION_STRING, .mandatory = 0 },
{ .name = "listen-host", .type = OPTION_STRING, .mandatory = 0 },
{ .name = "listen-host-is-dyndns", .type = OPTION_BOOLEAN, .mandatory = 0 },
@@ -533,6 +537,51 @@ static void figure_auth_funcs(struct cfg_st *config, char **auth, unsigned auth_
talloc_free(auth);
}
typedef struct acct_types_st {
const char *name;
unsigned name_size;
const struct acct_mod_st *mod;
char *(*get_brackets_string)(struct cfg_st *config, const char *);
} acct_types_st;
static acct_types_st avail_acct_types[] =
{
{NAME("pam"), &pam_acct_funcs, NULL},
#ifdef HAVE_RADIUS
{NAME("radius"), &radius_acct_funcs, get_brackets_string1},
#endif
};
static void figure_acct_funcs(struct cfg_st *config, const char *acct)
{
unsigned i;
unsigned found = 0;
/* Set the accounting method */
for (i=0;i<sizeof(avail_acct_types)/sizeof(avail_acct_types[0]);i++) {
if (c_strncasecmp(acct, avail_acct_types[i].name, avail_acct_types[i].name_size) == 0) {
if (avail_acct_types[i].get_brackets_string)
config->acct.additional = avail_acct_types[i].get_brackets_string(config, acct+avail_acct_types[i].name_size);
if ((avail_acct_types[i].mod->auth_types & config->auth[0].type) == 0) {
fprintf(stderr, "You cannot mix the '%s' accounting method with the '%s' authentication method\n", acct, config->auth[0].name);
exit(1);
}
config->acct.amod = avail_acct_types[i].mod;
config->acct.name = avail_acct_types[i].name;
found = 1;
break;
}
}
if (found == 0) {
fprintf(stderr, "Unknown or unsupported accounting method: %s\n", acct);
exit(1);
}
fprintf(stderr, "Setting '%s' as accounting method\n", config->acct.name);
}
#ifdef HAVE_GSSAPI
static void parse_kkdcp(struct cfg_st *config, char **urlfw, unsigned urlfw_size)
{
@@ -692,6 +741,13 @@ unsigned urlfw_size = 0;
exit(1);
}
tmp = NULL;
READ_STRING("acct", tmp);
if (tmp != NULL) {
figure_acct_funcs(config, tmp);
talloc_free(tmp);
}
/* When adding allocated data, remember to modify
* reload_cfg_file();
*/

View File

@@ -115,7 +115,9 @@ message cli_stats_msg
required uint64 bytes_out = 2;
optional bytes sid = 3; /* only required by sec-mod */
required uint32 uptime = 4; /* sec-mod */
optional string ip = 5; /* only required by sec-mod */
optional string remote_ip = 5; /* only required by sec-mod */
optional string ipv4 = 6; /* only required by sec-mod */
optional string ipv6 = 7; /* only required by sec-mod */
}
/* UDP_FD */

View File

@@ -115,6 +115,17 @@ An example configuration file follows.
#enable-auth = gssapi
#enable-auth = "gssapi[keytab:/etc/key.tab]"
# Accounting methods available:
# pam: can only be combined with PAM authentication method, it provides
# a session opened using PAM.
#
# radius: can be combined with any authentication method, it provides
# radius accounting to available users (see also stats-report-time).
#
# Only one accounting method can be specified.
#acct = "pam"
#acct = "radius[/etc/radiusclient/radiusclient.conf]"
# Whether to enable seccomp/Linux namespaces 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.

41
src/sec-mod-acct.h Normal file
View File

@@ -0,0 +1,41 @@
/*
* Copyright (C) 2015 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 ACCT_H
# define ACCT_H
#include <main.h>
#include <sec-mod-auth.h>
typedef struct acct_mod_st {
unsigned int type; /* ACCT_TYPE_ */
unsigned int auth_types; /* or of the AUTH_TYPEs which are compatible with this */
void (*global_init)(void *pool, const char *server_name, void* additional);
void (*global_deinit)(void);
/* The context provided below is of the authentication method */
int (*open_session)(unsigned auth_method, void *ctx, const common_auth_info_st *ai, const void *sid, unsigned sid_size); /* optional, may be null */
void (*session_stats)(unsigned auth_method, void *ctx, const common_auth_info_st *ai, struct stats_st *stats); /* optional, may be null */
void (*close_session)(unsigned auth_method, void *ctx, const common_auth_info_st *ai, struct stats_st *stats); /* optional may be null */
} acct_mod_st;
/* The accounting messages exchanged with the worker thread are shown in ipc.proto.
*/
#endif

View File

@@ -50,6 +50,7 @@
#include <sec-mod.h>
#include <vpn.h>
#include <sec-mod-sup-config.h>
#include <sec-mod-acct.h>
#ifdef HAVE_GSSAPI
# include <gssapi/gssapi.h>
@@ -64,6 +65,9 @@ void sec_auth_init(sec_mod_st * sec, struct cfg_st *config)
if (config->auth[i].enabled && config->auth[i].amod && config->auth[i].amod->global_init)
config->auth[i].amod->global_init(sec, config->server_name, config->auth[i].additional);
}
if (config->acct.amod && config->acct.amod->global_init)
config->acct.amod->global_init(sec, config->server_name, config->acct.additional);
}
static int generate_cookie(sec_mod_st * sec, client_entry_st * entry)
@@ -71,15 +75,15 @@ static int generate_cookie(sec_mod_st * sec, client_entry_st * entry)
int ret;
Cookie msg = COOKIE__INIT;
msg.username = entry->username;
msg.groupname = entry->groupname;
msg.username = entry->auth_info.username;
msg.groupname = entry->auth_info.groupname;
msg.hostname = entry->hostname;
msg.ip = entry->ip;
msg.ip = entry->auth_info.remote_ip;
msg.tls_auth_ok = entry->tls_auth_ok;
/* Fixme: possibly we should allow for completely random seeds */
if (sec->config->predictable_ips != 0) {
msg.ipv4_seed = hash_any(entry->username, strlen(entry->username), 0);
msg.ipv4_seed = hash_any(entry->auth_info.username, strlen(entry->auth_info.username), 0);
} else {
ret = gnutls_rnd(GNUTLS_RND_NONCE, &msg.ipv4_seed, sizeof(msg.ipv4_seed));
if (ret < 0)
@@ -121,7 +125,7 @@ int send_sec_auth_reply(int cfd, sec_mod_st * sec, client_entry_st * entry, AUTH
msg.cookie.data = entry->cookie;
msg.cookie.len = entry->cookie_size;
msg.user_name = entry->username;
msg.user_name = entry->auth_info.username;
if (entry->msg_str != NULL) {
msg.msg = entry->msg_str;
@@ -199,33 +203,33 @@ static int check_user_group_status(sec_mod_st * sec, client_entry_st * e,
if (e->auth_type & AUTH_TYPE_CERTIFICATE) {
if (tls_auth_ok == 0) {
seclog(sec, LOG_INFO, "user %s (session: %s) presented no certificate",
e->username, e->printable_sid);
e->auth_info.username, e->auth_info.psid);
return -1;
}
e->tls_auth_ok = tls_auth_ok;
if (tls_auth_ok != 0) {
if (e->username[0] == 0 && sec->config->cert_user_oid != NULL) {
if (e->auth_info.username[0] == 0 && sec->config->cert_user_oid != NULL) {
if (cert_user == NULL) {
seclog(sec, LOG_INFO, "no username in the certificate!");
return -1;
}
strlcpy(e->username, cert_user, sizeof(e->username));
if (cert_groups_size > 0 && sec->config->cert_group_oid != NULL && e->groupname[0] == 0)
strlcpy(e->groupname, cert_groups[0], sizeof(e->groupname));
strlcpy(e->auth_info.username, cert_user, sizeof(e->auth_info.username));
if (cert_groups_size > 0 && sec->config->cert_group_oid != NULL && e->auth_info.groupname[0] == 0)
strlcpy(e->auth_info.groupname, cert_groups[0], sizeof(e->auth_info.groupname));
} else {
if (sec->config->cert_user_oid != NULL && cert_user && strcmp(e->username, cert_user) != 0) {
if (sec->config->cert_user_oid != NULL && cert_user && strcmp(e->auth_info.username, cert_user) != 0) {
seclog(sec, LOG_INFO,
"user '%s' (session: %s) presented a certificate from user '%s'",
e->username, e->printable_sid, cert_user);
e->auth_info.username, e->auth_info.psid, cert_user);
return -1;
}
if (sec->config->cert_group_oid != NULL) {
found = 0;
for (i=0;i<cert_groups_size;i++) {
if (strcmp(e->groupname, cert_groups[i]) == 0) {
if (strcmp(e->auth_info.groupname, cert_groups[i]) == 0) {
found++;
break;
}
@@ -233,7 +237,7 @@ static int check_user_group_status(sec_mod_st * sec, client_entry_st * e,
if (found == 0) {
seclog(sec, LOG_INFO,
"user '%s' (session: %s) presented a certificate from group '%s' but he isn't a member of it",
e->username, e->printable_sid, e->groupname);
e->auth_info.username, e->auth_info.psid, e->auth_info.groupname);
return -1;
}
}
@@ -267,7 +271,7 @@ int handle_sec_auth_res(int cfd, sec_mod_st * sec, client_entry_st * e, int resu
if (result == ERR_AUTH_CONTINUE) {
/* if the module allows multiple retries for the password */
if (e->status != PS_AUTH_INIT && e->module && e->module->allows_retries) {
add_ip_to_ban_list(sec, e->ip, 1, time(0) + sec->config->min_reauth_time);
add_ip_to_ban_list(sec, e->auth_info.remote_ip, 1, time(0) + sec->config->min_reauth_time);
}
ret = send_sec_auth_reply_msg(cfd, sec, e);
@@ -281,8 +285,8 @@ int handle_sec_auth_res(int cfd, sec_mod_st * sec, client_entry_st * e, int resu
e->status = PS_AUTH_COMPLETED;
if (e->module) {
e->module->auth_user(e->auth_ctx, e->username,
sizeof(e->username));
e->module->auth_user(e->auth_ctx, e->auth_info.username,
sizeof(e->auth_info.username));
}
ret = send_sec_auth_reply(cfd, sec, e, AUTH__REP__OK);
@@ -291,13 +295,13 @@ int handle_sec_auth_res(int cfd, sec_mod_st * sec, client_entry_st * e, int resu
seclog(sec, LOG_ERR, "could not send reply auth cmd.");
return ret;
}
remove_ip_from_ban_list(sec, e->ip);
remove_ip_from_ban_list(sec, e->auth_info.remote_ip);
ret = 0;
} else {
e->status = PS_AUTH_FAILED;
add_ip_to_ban_list(sec, e->ip, 1, time(0) + sec->config->min_reauth_time);
add_ip_to_ban_list(sec, e->auth_info.remote_ip, 1, time(0) + sec->config->min_reauth_time);
ret = send_sec_auth_reply(cfd, sec, e, AUTH__REP__FAILED);
if (ret < 0) {
@@ -345,7 +349,7 @@ int handle_sec_auth_session_cmd(int cfd, sec_mod_st *sec, const SecAuthSessionMs
}
if (e->status != PS_AUTH_COMPLETED) {
seclog(sec, LOG_ERR, "session cmd received in unauthenticated client %s (session: %s)!", e->username, e->printable_sid);
seclog(sec, LOG_ERR, "session cmd received in unauthenticated client %s (session: %s)!", e->auth_info.username, e->auth_info.psid);
return -1;
}
@@ -363,8 +367,8 @@ int handle_sec_auth_session_cmd(int cfd, sec_mod_st *sec, const SecAuthSessionMs
return -1;
}
if (e->module != NULL && e->module->open_session != NULL && e->session_is_open == 0) {
ret = e->module->open_session(e->auth_ctx, req->sid.data, req->sid.len);
if (sec->config->acct.amod != NULL && sec->config->acct.amod->open_session != NULL && e->session_is_open == 0) {
ret = sec->config->acct.amod->open_session(e->module->type, e->auth_ctx, &e->auth_info, req->sid.data, req->sid.len);
if (ret < 0) {
e->status = PS_AUTH_FAILED;
seclog(sec, LOG_ERR, "could not open session.");
@@ -385,7 +389,7 @@ int handle_sec_auth_session_cmd(int cfd, sec_mod_st *sec, const SecAuthSessionMs
if (rep.reply == AUTH__REP__OK && 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' (session: %s)", e->username, e->printable_sid);
seclog(sec, LOG_ERR, "error reading additional configuration for '%s' (session: %s)", e->auth_info.username, e->auth_info.psid);
talloc_free(lpool);
return ERR_READ_CONFIG;
}
@@ -400,16 +404,16 @@ int handle_sec_auth_session_cmd(int cfd, sec_mod_st *sec, const SecAuthSessionMs
talloc_free(lpool);
if (rep.reply != AUTH__REP__OK) {
seclog(sec, LOG_INFO, "denied open session for user '%s' (session: %s)", e->username, e->printable_sid);
seclog(sec, LOG_INFO, "denied open session for user '%s' (session: %s)", e->auth_info.username, e->auth_info.psid);
del_client_entry(sec, e);
} else { /* set expiration time to unlimited (until someone closes the session) */
seclog(sec, LOG_INFO, "initiating session for user '%s' (session: %s)", e->username, e->printable_sid);
seclog(sec, LOG_INFO, "initiating session for user '%s' (session: %s)", e->auth_info.username, e->auth_info.psid);
e->time = -1;
e->in_use++;
}
} else { /* CLOSE */
seclog(sec, LOG_INFO, "temporarily closing session for %s (session: %s)", e->username, e->printable_sid);
seclog(sec, LOG_INFO, "temporarily closing session for %s (session: %s)", e->auth_info.username, e->auth_info.psid);
if (req->has_uptime && req->uptime > e->stats.uptime) {
e->stats.uptime = req->uptime;
@@ -447,7 +451,7 @@ int handle_sec_auth_stats_cmd(sec_mod_st * sec, const CliStatsMsg * req)
}
if (e->status != PS_AUTH_COMPLETED) {
seclog(sec, LOG_ERR, "session stats received in unauthenticated client %s (session: %s)!", e->username, e->printable_sid);
seclog(sec, LOG_ERR, "session stats received in unauthenticated client %s (session: %s)!", e->auth_info.username, e->auth_info.psid);
return -1;
}
@@ -459,11 +463,18 @@ int handle_sec_auth_stats_cmd(sec_mod_st * sec, const CliStatsMsg * req)
if (req->uptime > e->stats.uptime)
e->stats.uptime = req->uptime;
if (e->module == NULL || e->module->session_stats == NULL)
if (sec->config->acct.amod == NULL || sec->config->acct.amod->session_stats == NULL)
return 0;
stats_add_to(&totals, &e->stats, &e->saved_stats);
e->module->session_stats(e->auth_ctx, &totals, req->ip);
if (req->remote_ip)
strlcpy(e->auth_info.remote_ip, req->remote_ip, sizeof(e->auth_info.remote_ip));
if (req->ipv4)
strlcpy(e->auth_info.ipv4, req->ipv4, sizeof(e->auth_info.ipv4));
if (req->ipv6)
strlcpy(e->auth_info.ipv6, req->ipv6, sizeof(e->auth_info.ipv6));
sec->config->acct.amod->session_stats(e->module->type, e->auth_ctx, &e->auth_info, &totals);
return 0;
}
@@ -492,16 +503,16 @@ int handle_sec_auth_cont(int cfd, sec_mod_st * sec, const SecAuthContMsg * req)
if (e->status != PS_AUTH_INIT && e->status != PS_AUTH_CONT) {
seclog(sec, LOG_ERR, "auth cont received for %s (session: %s) but we are on state %u!",
e->username, e->printable_sid, e->status);
e->auth_info.username, e->auth_info.psid, e->status);
ret = -1;
goto cleanup;
}
seclog(sec, LOG_DEBUG, "auth cont for user '%s' (session: %s)", e->username, e->printable_sid);
seclog(sec, LOG_DEBUG, "auth cont for user '%s' (session: %s)", e->auth_info.username, e->auth_info.psid);
if (req->password == NULL) {
seclog(sec, LOG_ERR, "no password given in auth cont for user '%s' (session: %s)",
e->username, e->printable_sid);
e->auth_info.username, e->auth_info.psid);
ret = -1;
goto cleanup;
}
@@ -520,7 +531,7 @@ int handle_sec_auth_cont(int cfd, sec_mod_st * sec, const SecAuthContMsg * req)
if (ret < 0) {
seclog(sec, LOG_DEBUG,
"error in password given in auth cont for user '%s' (session: %s)",
e->username, e->printable_sid);
e->auth_info.username, e->auth_info.psid);
goto cleanup;
}
@@ -543,7 +554,7 @@ int set_module(sec_mod_st * sec, client_entry_st *e, unsigned auth_type)
e->module = sec->config->auth[i].amod;
e->auth_type = sec->config->auth[i].type;
seclog(sec, LOG_INFO, "using '%s' authentication to authenticate user (session: %s)", sec->config->auth[i].name, e->printable_sid);
seclog(sec, LOG_INFO, "using '%s' authentication to authenticate user (session: %s)", sec->config->auth[i].name, e->auth_info.psid);
return 0;
}
}
@@ -589,26 +600,26 @@ int handle_sec_auth_init(int cfd, sec_mod_st * sec, const SecAuthInitMsg * req)
}
ret =
e->module->auth_group(e->auth_ctx, req->group_name, e->groupname,
sizeof(e->groupname));
e->module->auth_group(e->auth_ctx, req->group_name, e->auth_info.groupname,
sizeof(e->auth_info.groupname));
if (ret != 0) {
ret = -1;
goto cleanup;
}
e->groupname[sizeof(e->groupname) - 1] = 0;
e->auth_info.groupname[sizeof(e->auth_info.groupname) - 1] = 0;
if (req->user_name != NULL) {
strlcpy(e->username, req->user_name, sizeof(e->username));
strlcpy(e->auth_info.username, req->user_name, sizeof(e->auth_info.username));
}
}
if (e->auth_type & AUTH_TYPE_CERTIFICATE) {
if (e->groupname[0] == 0 && req->group_name != NULL && sec->config->cert_group_oid != NULL) {
if (e->auth_info.groupname[0] == 0 && req->group_name != NULL && sec->config->cert_group_oid != NULL) {
unsigned i, found = 0;
for (i=0;i<req->n_cert_group_names;i++) {
if (strcmp(req->group_name, req->cert_group_names[i]) == 0) {
strlcpy(e->groupname, req->cert_group_names[i], sizeof(e->groupname));
strlcpy(e->auth_info.groupname, req->cert_group_names[i], sizeof(e->auth_info.groupname));
found = 1;
break;
}
@@ -634,7 +645,7 @@ int handle_sec_auth_init(int cfd, sec_mod_st * sec, const SecAuthInitMsg * req)
e->status = PS_AUTH_INIT;
seclog(sec, LOG_DEBUG, "auth init %sfor user '%s' (session: %s) of group: '%s' from '%s'",
req->tls_auth_ok?"(with cert) ":"",
e->username, e->printable_sid, e->groupname, req->ip);
e->auth_info.username, e->auth_info.psid, e->auth_info.groupname, req->ip);
if (need_continue != 0) {
ret = ERR_AUTH_CONTINUE;
@@ -651,10 +662,10 @@ void sec_auth_user_deinit(sec_mod_st * sec, client_entry_st * e)
if (e->module == NULL)
return;
seclog(sec, LOG_DEBUG, "permamently closing session of user '%s' (session: %s)", e->username, e->printable_sid);
seclog(sec, LOG_DEBUG, "permamently closing session of user '%s' (session: %s)", e->auth_info.username, e->auth_info.psid);
if (e->auth_ctx != NULL) {
if (e->module->close_session) {
e->module->close_session(e->auth_ctx, &e->saved_stats);
if (sec->config->acct.amod != NULL && sec->config->acct.amod->close_session != NULL && e->session_is_open != 0) {
sec->config->acct.amod->close_session(e->module->type, e->auth_ctx, &e->auth_info, &e->saved_stats);
}
e->module->auth_deinit(e->auth_ctx);
e->auth_ctx = NULL;

View File

@@ -27,7 +27,7 @@
#define MAX_AUTH_REQS 8
#define MAX_GROUPS 32
struct auth_mod_st {
typedef struct auth_mod_st {
unsigned int type;
unsigned int allows_retries; /* whether the module allows retries of the same password */
void (*global_init)(void *pool, const char *server_name, void* additional);
@@ -38,13 +38,9 @@ struct auth_mod_st {
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, const void *sid, unsigned sid_size); /* optional, may be null */
void (*session_stats)(void *ctx, struct stats_st *stats, const char *ip); /* optional, may be null */
void (*close_session)(void *ctx, struct stats_st *stats); /* optional may be null */
void (*auth_deinit)(void* ctx);
void (*group_list)(void *pool, void *additional, char ***groupname, unsigned *groupname_size);
};
} auth_mod_st;
void main_auth_init(main_server_st *s);
void proc_auth_deinit(main_server_st* s, struct proc_st* proc);

View File

@@ -95,7 +95,7 @@ client_entry_st *new_client_entry(sec_mod_st *sec, const char *ip)
return NULL;
}
strlcpy(e->ip, ip, sizeof(e->ip));
strlcpy(e->auth_info.remote_ip, ip, sizeof(e->auth_info.remote_ip));
do {
ret = gnutls_rnd(GNUTLS_RND_RANDOM, e->sid, sizeof(e->sid));
@@ -114,8 +114,7 @@ client_entry_st *new_client_entry(sec_mod_st *sec, const char *ip)
goto fail;
}
snprintf(e->printable_sid, sizeof(e->printable_sid), "%.2x%.2x%.2x",
(unsigned) e->sid[0], (unsigned) e->sid[1], (unsigned) e->sid[2]);
base64_encode((char *)e->sid, SID_SIZE, (char *)e->auth_info.psid, sizeof(e->auth_info.psid));
e->time = time(0);
if (htable_add(db, rehash(e, NULL), e) == 0) {

View File

@@ -24,6 +24,7 @@
#include <cookies.h>
#include <gnutls/abstract.h>
#include <ccan/htable/htable.h>
#include <base64.h>
typedef struct sec_mod_st {
gnutls_datum_t dcookie_key; /* the key to generate cookies */
@@ -44,6 +45,15 @@ typedef struct stats_st {
time_t uptime;
} stats_st;
typedef struct common_auth_info_st {
char username[MAX_USERNAME_SIZE*2];
char groupname[MAX_GROUPNAME_SIZE]; /* the owner's group */
char psid[BASE64_LENGTH(SID_SIZE) + 1]; /* printable */
char remote_ip[MAX_IP_STR];
char ipv4[MAX_IP_STR];
char ipv6[MAX_IP_STR];
} common_auth_info_st;
typedef struct client_entry_st {
/* A unique session identifier used to distinguish sessions
* prior to authentication. It is sent as cookie to the client
@@ -52,9 +62,6 @@ typedef struct client_entry_st {
*/
uint8_t sid[SID_SIZE];
/* a part of sid used in the logs to differentiate the session */
char printable_sid[7];
void * auth_ctx; /* the context of authentication */
unsigned session_is_open; /* whether open_session was done */
unsigned in_use; /* counter of users of this structure */
@@ -67,10 +74,7 @@ typedef struct client_entry_st {
unsigned status; /* PS_AUTH_ */
char ip[MAX_IP_STR]; /* the user's IP */
char hostname[MAX_HOSTNAME_SIZE]; /* the requested hostname */
char username[MAX_USERNAME_SIZE]; /* the owner */
char groupname[MAX_GROUPNAME_SIZE]; /* the owner's group */
uint8_t *cookie; /* the cookie associated with the session */
unsigned cookie_size;
@@ -81,6 +85,9 @@ typedef struct client_entry_st {
/* the auth type associated with the user */
unsigned auth_type;
struct common_auth_info_st auth_info;
/* the module this entry is using */
const struct auth_mod_st *module;
} client_entry_st;

View File

@@ -269,9 +269,9 @@ static int get_sup_config(struct cfg_st *cfg, client_entry_st *entry,
char file[_POSIX_PATH_MAX];
int ret;
if (cfg->per_group_dir != NULL && entry->groupname[0] != 0) {
if (cfg->per_group_dir != NULL && entry->auth_info.groupname[0] != 0) {
snprintf(file, sizeof(file), "%s/%s", cfg->per_group_dir,
entry->groupname);
entry->auth_info.groupname);
ret = read_sup_config_file(cfg, msg, pool, file, cfg->default_group_conf, "group");
if (ret < 0)
@@ -280,7 +280,7 @@ static int get_sup_config(struct cfg_st *cfg, client_entry_st *entry,
if (cfg->per_user_dir != NULL) {
snprintf(file, sizeof(file), "%s/%s", cfg->per_user_dir,
entry->username);
entry->auth_info.username);
ret = read_sup_config_file(cfg, msg, pool, file, cfg->default_user_conf, "user");
if (ret < 0)
return ret;

View File

@@ -87,6 +87,12 @@ extern int syslog_open;
#define AUTH_TYPE_RADIUS (1<<5 | AUTH_TYPE_USERNAME_PASS)
#define AUTH_TYPE_GSSAPI (1<<6)
#define ALL_AUTH_TYPES ((AUTH_TYPE_PAM|AUTH_TYPE_PLAIN|AUTH_TYPE_CERTIFICATE|AUTH_TYPE_RADIUS|AUTH_TYPE_GSSAPI) & (~AUTH_TYPE_USERNAME_PASS))
#define VIRTUAL_AUTH_TYPES (AUTH_TYPE_USERNAME_PASS)
#define ACCT_TYPE_PAM (1<<1)
#define ACCT_TYPE_RADIUS (1<<2)
#define ERR_SUCCESS 0
#define ERR_BAD_COMMAND -2
#define ERR_AUTH_FAIL -3
@@ -218,6 +224,12 @@ typedef struct auth_struct_st {
bool enabled;
} auth_struct_st;
typedef struct acct_struct_st {
const char *name;
char *additional;
const struct acct_mod_st *amod;
} acct_struct_st;
typedef struct kkdcp_realm_st {
char *realm;
struct sockaddr_storage addr;
@@ -262,6 +274,7 @@ struct cfg_st {
auth_struct_st auth[MAX_AUTH_METHODS];
unsigned auth_methods;
acct_struct_st acct;
gnutls_certificate_request_t cert_req;
char *priorities;

View File

@@ -618,9 +618,12 @@ int periodic_check(worker_st * ws, unsigned mtu_overhead, time_t now,
msg.sid.data = ws->sid;
msg.has_sid = 1;
msg.ip = human_addr2((void *)&ws->remote_addr, ws->remote_addr_len,
msg.remote_ip = human_addr2((void *)&ws->remote_addr, ws->remote_addr_len,
buf, sizeof(buf), 0);
msg.ipv4 = ws->vinfo.ipv4;
msg.ipv4 = ws->vinfo.ipv6;
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);

View File

@@ -20,6 +20,8 @@ use-occtl = true
# to generate password entries.
#auth = "plain[/etc/ocserv/ocpasswd]"
acct = pam
# A banner to be displayed on clients
#banner = "Welcome"

View File

@@ -21,6 +21,8 @@ use-occtl = true
# to generate password entries.
#auth = "plain[/etc/ocserv/ocpasswd]"
acct = "radius[/etc/radiusclient/radiusclient.conf]"
# A banner to be displayed on clients
#banner = "Welcome"