RADIUS authentication patch
Demus
Joined: 2007-06-13
Posts: 1 |
Posted: Wed, 2007-06-13 22:48 |
I've done a quick hack to allow authentication to be passed seamlessly to a RADIUS server. It requires the radius PHP module. http://pecl.php.net/package/radius The goal was to deploy Gallery 2 as a means of sharing photos amongst employees of my company. Many of these employees find it very difficult to remember/keep track of multiple passwords, and as a result would never use the service. With this patch they can simply use their Active Directory usernames and passwords. The brief overview: SECURITY WARNING!!!!!!!!!! The second security warning is that the MD5 hashes for these passwords are stored in the local SQL database. This is done to speed up requests, and to prevent many RADIUS requests. If the security of your SQL database is questionable, or you connect to it with an unencrypted socket then you should comment out the changePassword lines. Future developments: A configurable module would elevate this patch from "hack" status. Currently RADIUS server configs are loaded from a php file. Also configuration options to decide the level of RADIUS authentication (full-time or when the local MD5s don't match) would be nice. UserLevel.inc.path --- UserLogin.inc.orig 2007-03-09 02:36:19.000000000 -0700 +++ UserLogin.inc 2007-06-13 12:29:57.000000000 -0600 @@ -88,6 +88,137 @@ GalleryUtilities::unsanitizeInputValues($form['password'], false); $isCorrect = (isset($user) && $user->isCorrectPassword($form['password'])); + /* RADIUS authentication v0.0.1 - By Demus * + * Requires php_radius * + * Authenticates a username & password against a * + * radius server. If successful either updates the * + * hashed password, or creates a new user account. */ + + if (!$isCorrect) { + + // Load radius configs + define ("IN_RADIUS_INIT", 1); + require(dirname(__FILE__) . '/../../radius_config.php'); + + // Create radius handle and add radius server + if (!($radh = radius_auth_open()) || !radius_add_server ($radh, $radius_hostname, $radius_port, $radius_secret, 15, 1)) + { + // Destroy sensitive information + unset ($radius_hostname, $radius_port, $radius_secret); + + // Create error information + $results['delegate']['view'] = 'core.UserAdmin'; + $results['delegate']['subView'] = 'core.UserLogin'; + $results['status'] = array(); + $error[] = 'form[error][radius][unknown]'; + $results['error'] = $error; + + return array(null, $results); + } + + // Destroy sensitive information + unset ($radius_hostname, $radius_port, $radius_secret); + + // Create authentication request + if (!radius_create_request($radh,RADIUS_ACCESS_REQUEST)) + { + $results['delegate']['view'] = 'core.UserAdmin'; + $results['delegate']['subView'] = 'core.UserLogin'; + $results['status'] = array(); + $error[] = 'form[error][radius][unknown]'; + $results['error'] = $error; + + return array(null, $results); + } + + // Attach username and password + radius_put_attr($radh,RADIUS_USER_NAME,$form['username']); + radius_put_attr($radh,RADIUS_USER_PASSWORD,$form['password']); + + // Send request to the server + switch (radius_send_request($radh)) + { + case RADIUS_ACCESS_ACCEPT: + $isCorrect = true; + break; + default: + $isCorrect = false; + } + + // If successfull and user does not exist, create it + if ($isCorrect && !isset($user)) + { + list ($ret, $user) = GalleryCoreApi::newFactoryInstance('GalleryEntity', 'GalleryUser'); + + if ($ret || !isset($user) || $user->create($form['username'])) + { + // Set our error status and fall back to the view + $results['delegate']['view'] = 'core.UserAdmin'; + $results['delegate']['subView'] = 'core.UserLogin'; + $results['status'] = array(); + $error[] = 'form[error][radius][unknown]'; + $results['error'] = $error; + + return array(null, $results); + } + + // Assume username@domain - user can update later if need be + $user->setEmail($form['username'] . '@' . $radius_domain); + + // Check for first.last naming convention, otherwise just use username + if (strpos($form['username'], '.') === FALSE) + $user->setFullName (ucfirst($form['username'])); + else + $user->setFullName( ucfirst(substr($form['username'], 0, strpos($form['username'], '.'))) + . ' ' . + ucfirst(substr($form['username'], strpos($form['username'], '.')+1))); + + // Set language to english + // Fix me: Should set to default language setting + $user->setLanguage('en_US'); + + // WARNING: Possible security risk. Compromise of Gallery database + // could lead to compromise of RADIUS security. + $user->changePassword($form['password']); + + if ($user->save()) { + $results['delegate']['view'] = 'core.UserAdmin'; + $results['delegate']['subView'] = 'core.UserLogin'; + $results['status'] = array(); + $error[] = 'form[error][radius][unknown]'; + $results['error'] = $error; + + return array(null, $results); + } + } else if ($isCorrect) // Update hashed password + { + // WARNING: Possible security risk. Compromise of Gallery database + // could lead to compromise of RADIUS security. + list ($ret, $lockId) = GalleryCoreApi::acquireWriteLock($user->getId()); + + if (!$ret) + { + $user->changePassword($form['password']); + $ret = $user->save(); + GalleryCoreApi::releaseLocks($lockId); + } + + if ($ret) + { + $results['delegate']['view'] = 'core.UserAdmin'; + $results['delegate']['subView'] = 'core.UserLogin'; + $results['status'] = array(); + $error[] = 'form[error][radius][unknown]'; + $results['error'] = $error; + + return array(null, $results); + } + + } + // Continue with login + } + /* End RADIUS authentication */ + /* Prepare for validation */ $options = array('pass' => $isCorrect); list ($ret, $options['level']) = radius_config.php (place in gallery root folder) <?php if (!defined("IN_RADIUS_INIT")) die ("Hacking attempt!"); $radius_hostname="radiusserver.yourhost.com"; $radius_port=1812; $radius_secret="somesecret"; $radius_domain="yourhost.com"; ?> UserLogin.tpl.patch (if you want the RADIUS error message to be displayed) --- UserLogin.tpl.orig 2006-12-01 14:14:46.000000000 -0700 +++ UserLogin.tpl 2007-06-13 16:46:37.000000000 -0600 @@ -54,6 +54,11 @@ {g->text text="Your login information is incorrect. Please try again."} </div> {/if} + {if isset($form.error.radius.unknown)} + <div class="giError"> + {g->text text="An error occurred with the RADIUS server. Please try again."} + </div> + {/if} </div> {* Include our ValidationPlugins *} |
|