mirror of
https://gitlab.com/openconnect/ocserv.git
synced 2026-02-10 08:46:58 +08:00
Added support for reading user configuration from radius.
This commit is contained in:
@@ -76,6 +76,7 @@ ocserv_SOURCES = main.c main-auth.c worker-vpn.c worker-auth.c tlslib.c \
|
||||
icmp-ping.c icmp-ping.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 \
|
||||
|
||||
@@ -33,26 +33,20 @@
|
||||
|
||||
#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;
|
||||
|
||||
struct radius_ctx_st {
|
||||
char username[MAX_USERNAME_SIZE*2];
|
||||
char groupname[MAX_GROUPNAME_SIZE];
|
||||
char msg[4096];
|
||||
|
||||
char ipv4[MAX_IP_STR];
|
||||
char ipv6[MAX_IP_STR];
|
||||
|
||||
const char *config; /* radius config file */
|
||||
const char *pass_msg;
|
||||
unsigned retries;
|
||||
};
|
||||
|
||||
static void radius_global_init(void *pool, void *additional)
|
||||
{
|
||||
rh = rc_read_config(additional);
|
||||
@@ -170,6 +164,7 @@ static int radius_auth_pass(void *ctx, const char *pass, unsigned pass_len)
|
||||
|
||||
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,
|
||||
@@ -177,9 +172,35 @@ static int radius_auth_pass(void *ctx, const char *pass, unsigned pass_len)
|
||||
(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) {
|
||||
inet_ntop(AF_INET, &vp->lvalue, pctx->ipv4, sizeof(pctx->ipv4));
|
||||
/* 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);
|
||||
}
|
||||
|
||||
@@ -23,6 +23,27 @@
|
||||
|
||||
#include <sec-mod-auth.h>
|
||||
|
||||
struct radius_ctx_st {
|
||||
char username[MAX_USERNAME_SIZE*2];
|
||||
char groupname[MAX_GROUPNAME_SIZE];
|
||||
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
|
||||
|
||||
64
src/config.c
64
src/config.c
@@ -34,6 +34,7 @@
|
||||
#include <auth/pam.h>
|
||||
#include <auth/radius.h>
|
||||
#include <auth/plain.h>
|
||||
#include <sec-mod-sup-config.h>
|
||||
|
||||
#include <vpn.h>
|
||||
#include <cookies.h>
|
||||
@@ -145,7 +146,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)
|
||||
{
|
||||
@@ -302,7 +305,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;
|
||||
@@ -315,10 +318,47 @@ 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;
|
||||
|
||||
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;
|
||||
@@ -366,6 +406,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) {
|
||||
@@ -395,17 +437,27 @@ unsigned force_cert_auth;
|
||||
amod = &plain_auth_funcs;
|
||||
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_string(config, auth[j]+6);
|
||||
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
|
||||
|
||||
@@ -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, radius[config].
|
||||
# plain, pam, radius[configfile,groupconfig].
|
||||
#auth = "certificate"
|
||||
#auth = "pam"
|
||||
|
||||
@@ -97,8 +97,9 @@ An example configuration file follows.
|
||||
#auth = "plain[/etc/ocserv/ocpasswd]"
|
||||
|
||||
# The radius option requires specifying freeradius-client configuration
|
||||
# file.
|
||||
#auth = "radius[/etc/radiusclient/radiusclient.conf]"
|
||||
# file. If the groupconfig option is set, then config-per-user will be overriden,
|
||||
# and all configuration will be read from radius.
|
||||
#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
|
||||
|
||||
@@ -29,9 +29,14 @@
|
||||
#include <vpn.h>
|
||||
#include <sec-mod-sup-config.h>
|
||||
#include <sup-config/file.h>
|
||||
#include <sup-config/radius.h>
|
||||
|
||||
void sup_config_init(sec_mod_st *sec)
|
||||
{
|
||||
sec->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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,9 @@
|
||||
|
||||
#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.
|
||||
*/
|
||||
|
||||
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
|
||||
Reference in New Issue
Block a user