From c4a9f99a8d79e201b2af5053a095c83bb1a26467 Mon Sep 17 00:00:00 2001 From: jim-p Date: Wed, 12 Aug 2015 12:20:10 -0400 Subject: Fix GUI auth from RADIUS to grab group names from the Class attribute. Implements #935 The RADIUS server must populate the Class attribute with a string, semicolon-separated, of user groups. Similar to LDAP, local groups must exist with matching names, and privileges are determined by the local matching groups. --- etc/inc/auth.inc | 25 +++++++++++++++++++++++-- etc/inc/authgui.inc | 2 +- etc/inc/priv.inc | 4 +++- etc/inc/radius.inc | 2 +- usr/local/www/diag_authentication.php | 5 +++-- 5 files changed, 31 insertions(+), 7 deletions(-) diff --git a/etc/inc/auth.inc b/etc/inc/auth.inc index 594b57b..5543e82 100644 --- a/etc/inc/auth.inc +++ b/etc/inc/auth.inc @@ -1349,6 +1349,24 @@ function radius_backed($username, $passwd, $authcfg, &$attributes = array()) { return $ret; } +/* + $attributes must contain a "class" key containing the groups and local + groups must exist to match. +*/ +function radius_get_groups($attributes) { + $groups = array(); + if (!empty($attributes) && is_array($attributes) && !empty($attributes['class'])) { + $groups = explode(";", $attributes['class']); + foreach ($groups as & $grp) { + $grp = strtolower(trim($grp)); + if (substr($grp, 0, 3) == "ou=") { + $grp = substr($grp, 3); + } + } + } + return $groups; +} + function get_user_expiration_date($username) { $user = getUserEntry($username); if ($user['expires']) { @@ -1407,7 +1425,7 @@ function auth_get_authserver_list() { return $list; } -function getUserGroups($username, $authcfg) { +function getUserGroups($username, $authcfg, &$attributes = array()) { global $config; $allowed_groups = array(); @@ -1417,6 +1435,7 @@ function getUserGroups($username, $authcfg) { $allowed_groups = @ldap_get_groups($username, $authcfg); break; case 'radius': + $allowed_groups = @radius_get_groups($attributes); break; default: $user = getUserEntry($username); @@ -1488,14 +1507,16 @@ function session_auth() { } /* Validate incoming login request */ + $attributes = array(); if (isset($_POST['login']) && !empty($_POST['usernamefld']) && !empty($_POST['passwordfld'])) { $authcfg = auth_get_authserver($config['system']['webgui']['authmode']); - if (authenticate_user($_POST['usernamefld'], $_POST['passwordfld'], $authcfg) || + if (authenticate_user($_POST['usernamefld'], $_POST['passwordfld'], $authcfg, $attributes) || authenticate_user($_POST['usernamefld'], $_POST['passwordfld'])) { // Generate a new id to avoid session fixation session_regenerate_id(); $_SESSION['Logged_In'] = "True"; $_SESSION['Username'] = $_POST['usernamefld']; + $_SESSION['user_radius_attributes'] = $attributes; $_SESSION['last_access'] = time(); $_SESSION['protocol'] = $config['system']['webgui']['protocol']; if (!isset($config['system']['webgui']['quietlogin'])) { diff --git a/etc/inc/authgui.inc b/etc/inc/authgui.inc index 2c4aea0..07cf9a9 100644 --- a/etc/inc/authgui.inc +++ b/etc/inc/authgui.inc @@ -54,7 +54,7 @@ if (!session_auth()) { * We give them access only to the appropriate pages based on * the user or group privileges. */ -$allowedpages = getAllowedPages($_SESSION['Username']); +$allowedpages = getAllowedPages($_SESSION['Username'], $_SESSION['user_radius_attributes']); /* * redirect to first allowed page if requesting a wrong url diff --git a/etc/inc/priv.inc b/etc/inc/priv.inc index 7549844..851643b 100644 --- a/etc/inc/priv.inc +++ b/etc/inc/priv.inc @@ -278,7 +278,7 @@ function getPrivPages(& $entry, & $allowed_pages) { } } -function getAllowedPages($username) { +function getAllowedPages($username, &$attributes = array()) { global $config, $_SESSION; if (!function_exists("ldap_connect")) { @@ -292,6 +292,8 @@ function getAllowedPages($username) { // obtain ldap groups if we are in ldap mode if ($authcfg['type'] == "ldap") { $allowed_groups = @ldap_get_groups($username, $authcfg); + } elseif ($authcfg['type'] == "radius") { + $allowed_groups = @radius_get_groups($attributes); } if (!$allowed_groups) { // search for a local user by name diff --git a/etc/inc/radius.inc b/etc/inc/radius.inc index 709607f..ac610bd 100644 --- a/etc/inc/radius.inc +++ b/etc/inc/radius.inc @@ -484,7 +484,7 @@ class Auth_RADIUS extends PEAR { break; case RADIUS_CLASS: - $this->attributes['class'] = radius_cvt_int($data); + $this->attributes['class'] = radius_cvt_string($data); break; case RADIUS_FRAMED_PROTOCOL: diff --git a/usr/local/www/diag_authentication.php b/usr/local/www/diag_authentication.php index de8a43b..d0b81d5 100644 --- a/usr/local/www/diag_authentication.php +++ b/usr/local/www/diag_authentication.php @@ -57,9 +57,10 @@ if ($_POST) { } if (!$input_errors) { - if (authenticate_user($_POST['username'], $_POST['passwordfld'], $authcfg)) { + $attributes = array(); + if (authenticate_user($_POST['username'], $_POST['passwordfld'], $authcfg, $attributes)) { $savemsg = gettext("User") . ": " . $_POST['username'] . " " . gettext("authenticated successfully."); - $groups = getUserGroups($_POST['username'], $authcfg); + $groups = getUserGroups($_POST['username'], $authcfg, $attributes); $savemsg .= "
" . gettext("This user is a member of these groups") . ":
"; foreach ($groups as $group) { $savemsg .= "{$group} "; -- cgit v1.1