radius: replace experimental Group-Name with Class attribute

The current format allows to handle multiple groups and is used
by several radius servers.

Suggested by Yick Xie.
This commit is contained in:
Nikos Mavrogiannopoulos
2016-03-28 20:25:50 +02:00
committed by Nikos Mavrogiannopoulos
parent 0b4333d7ee
commit ade786a0f1
5 changed files with 71 additions and 19 deletions

View File

@@ -82,6 +82,11 @@ ATTRIBUTE Framed-IP-Netmask 9 ipaddr
# a CIDR string)
ATTRIBUTE Framed-Route 22 string
# Sets group name using format "OU=group1;group2"
# Note that the groups sent by the server must be made known
# to ocserv, via the select-group variable.
ATTRIBUTE Class 25 string
# sets DNS servers
VENDOR Microsoft 311
@@ -112,14 +117,4 @@ ATTRIBUTE DNS-Server-IPv6-Address 169 ipv6addr
# Sets IPv6 routes
ATTRIBUTE Framed-IPv6-Prefix 97 ipv6prefix
ATTRIBUTE Route-IPv6-Information 170 ipv6prefix
############################
# Experimental attributes #
############################
# Experimental Non Protocol Attributes used by Cistron-Radiusd
#
ATTRIBUTE Group-Name 1030 string
```

View File

@@ -1,5 +1,6 @@
/*
* Copyright (C) 2014 Red Hat, Inc.
* Copyright (C) 2014-2016 Red Hat, Inc.
* Copyright (C) 2016 Nikos Mavrogiannopoulos
*
* This file is part of ocserv.
*
@@ -28,6 +29,7 @@
#include <arpa/inet.h> /* inet_ntop */
#include "radius.h"
#include "auth/common.h"
#include "str.h"
#ifdef HAVE_RADIUS
@@ -39,7 +41,7 @@
# include <radcli/radcli.h>
#endif
#define RAD_GROUP_NAME 1030
#define RAD_GROUP_NAME PW_CLASS
#define RAD_IPV4_DNS1 ((311<<16)|(28))
#define RAD_IPV4_DNS2 ((311<<16)|(29))
@@ -134,13 +136,16 @@ static int radius_auth_init(void **ctx, void *pool, const common_auth_init_st *i
static int radius_auth_group(void *ctx, const char *suggested, char *groupname, int groupname_size)
{
struct radius_ctx_st *pctx = ctx;
unsigned i;
groupname[0] = 0;
if (suggested != NULL) {
if (strcmp(suggested, pctx->groupname) == 0) {
strlcpy(groupname, pctx->groupname, groupname_size);
return 0;
for (i=0;i<pctx->groupnames_size;i++) {
if (strcmp(suggested, pctx->groupnames[i]) == 0) {
strlcpy(groupname, pctx->groupnames[i], groupname_size);
return 0;
}
}
syslog(LOG_AUTH,
@@ -149,9 +154,10 @@ static int radius_auth_group(void *ctx, const char *suggested, char *groupname,
return -1;
}
if (pctx->groupname[0] != 0 && groupname[0] == 0) {
strlcpy(groupname, pctx->groupname, groupname_size);
if (pctx->groupnames_size > 0 && groupname[0] == 0) {
strlcpy(groupname, pctx->groupnames[0], groupname_size);
}
return 0;
}
@@ -190,6 +196,39 @@ static void append_route(struct radius_ctx_st *pctx, const char *route, unsigned
}
}
/* Parses group of format "OU=group1;group2;group3" */
static void parse_groupnames(struct radius_ctx_st *pctx, const char *full)
{
char *p, *p2;
unsigned i;
pctx->groupnames_size = 0;
if (strncmp(full, "OU=", 3) == 0) {
full += 3;
p = talloc_strdup(pctx, full);
if (p == NULL)
return;
i = 0;
p2 = strsep(&p, ";");
while(p2 != NULL) {
pctx->groupnames[i++] = p2;
pctx->groupnames_size = i;
trim_trailing_whitespace(p2);
p2 = strsep(&p, ";");
}
} else {
pctx->groupnames[0] = talloc_strdup(pctx, full);
if (pctx->groupnames[0] == NULL)
return;
pctx->groupnames_size = 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)
@@ -290,7 +329,7 @@ static int radius_auth_pass(void *ctx, const char *pass, unsigned pass_len)
goto fail;
} else if (vp->attribute == RAD_GROUP_NAME && vp->type == PW_TYPE_STRING) {
/* Group-Name */
strlcpy(pctx->groupname, vp->strvalue, sizeof(pctx->groupname));
parse_groupnames(pctx, vp->strvalue);
} else if (vp->attribute == PW_FRAMED_IPV6_ADDRESS && vp->type == PW_TYPE_IPV6ADDR) {
/* Framed-IPv6-Address */
if (inet_ntop(AF_INET6, vp->strvalue, pctx->ipv6, sizeof(pctx->ipv6)) != NULL) {

View File

@@ -25,9 +25,11 @@
struct radius_ctx_st {
char username[MAX_USERNAME_SIZE*2];
char groupname[MAX_GROUPNAME_SIZE];
char user_agent[MAX_AGENT_NAME];
char *groupnames[MAX_GROUPS];
unsigned groupnames_size;
char remote_ip[MAX_IP_STR];
char our_ip[MAX_IP_STR];
unsigned interim_interval_secs;

View File

@@ -30,6 +30,20 @@
#include <main.h>
#include "vasprintf.h"
void trim_trailing_whitespace(char *str)
{
unsigned len = strlen(str);
char *p;
if (len > 0) {
p = str+len-1;
while (c_isspace(*p) && p >= str) {
*p = 0;
p--;
}
}
}
#define MEMSUB(x,y) ((ssize_t)((ptrdiff_t)x-(ptrdiff_t)y))
void str_clear(str_st * str)

View File

@@ -77,6 +77,8 @@ inline static void str_reset(str_st * buf)
buf->length = 0;
}
void trim_trailing_whitespace(char *str);
int str_append_printf(str_st *dest, const char *fmt, ...);
int str_append_str(str_st *, const char *str);
int str_replace_str(str_st *, const str_rep_tab *tab);