From f600fa3b1a3a4c81f6573d05dbcf286e2834a389 Mon Sep 17 00:00:00 2001 From: Craig Andrews Date: Wed, 11 Nov 2009 12:16:58 -0500 Subject: Rename the plugins, as I'm separating out Authn, Authz, and user information into separate plugins --- plugins/Auth/AuthPlugin.php | 172 ------------------ plugins/Authentication/AuthenticationPlugin.php | 172 ++++++++++++++++++ plugins/Ldap/LdapPlugin.php | 195 --------------------- plugins/Ldap/README | 50 ------ .../LdapAuthenticationPlugin.php | 195 +++++++++++++++++++++ plugins/LdapAuthentication/README | 50 ++++++ 6 files changed, 417 insertions(+), 417 deletions(-) delete mode 100644 plugins/Auth/AuthPlugin.php create mode 100644 plugins/Authentication/AuthenticationPlugin.php delete mode 100644 plugins/Ldap/LdapPlugin.php delete mode 100644 plugins/Ldap/README create mode 100644 plugins/LdapAuthentication/LdapAuthenticationPlugin.php create mode 100644 plugins/LdapAuthentication/README (limited to 'plugins') diff --git a/plugins/Auth/AuthPlugin.php b/plugins/Auth/AuthPlugin.php deleted file mode 100644 index cb52730f6..000000000 --- a/plugins/Auth/AuthPlugin.php +++ /dev/null @@ -1,172 +0,0 @@ -. - * - * @category Plugin - * @package StatusNet - * @author Craig Andrews - * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 - * @link http://status.net/ - */ - -if (!defined('STATUSNET') && !defined('LACONICA')) { - exit(1); -} - -/** - * Superclass for plugins that do authentication - * - * @category Plugin - * @package StatusNet - * @author Craig Andrews - * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 - * @link http://status.net/ - */ - -abstract class AuthPlugin extends Plugin -{ - //is this plugin authoritative for authentication? - public $authn_authoritative = false; - - //should accounts be automatically created after a successful login attempt? - public $autoregistration = false; - - //can the user change their email address - public $email_changeable=true; - - //can the user change their email address - public $password_changeable=true; - - //------------Auth plugin should implement some (or all) of these methods------------\\ - /** - * Check if a nickname/password combination is valid - * @param nickname - * @param password - * @return boolean true if the credentials are valid, false if they are invalid. - */ - function checkPassword($nickname, $password) - { - return false; - } - - /** - * Automatically register a user when they attempt to login with valid credentials. - * User::register($data) is a very useful method for this implementation - * @param nickname - * @return boolean true if the user was created, false if autoregistration is not allowed, null if this plugin is not responsible for this nickname - */ - function autoRegister($nickname) - { - return null; - } - - /** - * Change a user's password - * The old password has been verified to be valid by this plugin before this call is made - * @param nickname - * @param oldpassword - * @param newpassword - * @return boolean true if the password was changed, false if password changing failed for some reason, null if this plugin is not responsible for this nickname - */ - function changePassword($nickname,$oldpassword,$newpassword) - { - return null; - } - - /** - * Can a user change this field in his own profile? - * @param nickname - * @param field - * @return boolean true if the field can be changed, false if not allowed to change it, null if this plugin is not responsible for this nickname - */ - function canUserChangeField($nickname, $field) - { - return null; - } - - //------------Below are the methods that connect StatusNet to the implementing Auth plugin------------\\ - function __construct() - { - parent::__construct(); - } - - function StartCheckPassword($nickname, $password, &$authenticatedUser){ - if($this->password_changeable){ - $authenticated = $this->checkPassword($nickname, $password); - if($authenticated){ - $authenticatedUser = User::staticGet('nickname', $nickname); - if(!$authenticatedUser && $this->autoregistration){ - if($this->autoregister($nickname)){ - $authenticatedUser = User::staticGet('nickname', $nickname); - } - } - return false; - }else{ - if($this->authn_authoritative){ - return false; - } - } - //we're not authoritative, so let other handlers try - }else{ - if($this->authn_authoritative){ - //since we're authoritative, no other plugin could do this - throw new Exception(_('Password changing is not allowed')); - } - } - } - - function onStartChangePassword($nickname,$oldpassword,$newpassword) - { - if($this->password_changeable){ - $authenticated = $this->checkPassword($nickname, $oldpassword); - if($authenticated){ - $result = $this->changePassword($nickname,$oldpassword,$newpassword); - if($result){ - //stop handling of other handlers, because what was requested was done - return false; - }else{ - throw new Exception(_('Password changing failed')); - } - }else{ - if($this->authn_authoritative){ - //since we're authoritative, no other plugin could do this - throw new Exception(_('Password changing failed')); - }else{ - //let another handler try - return null; - } - } - }else{ - if($this->authn_authoritative){ - //since we're authoritative, no other plugin could do this - throw new Exception(_('Password changing is not allowed')); - } - } - } - - function onStartAccountSettingsPasswordMenuItem($widget) - { - if($this->authn_authoritative && !$this->password_changeable){ - //since we're authoritative, no other plugin could change passwords, so do render the menu item - return false; - } - } -} - diff --git a/plugins/Authentication/AuthenticationPlugin.php b/plugins/Authentication/AuthenticationPlugin.php new file mode 100644 index 000000000..ef78c7ce4 --- /dev/null +++ b/plugins/Authentication/AuthenticationPlugin.php @@ -0,0 +1,172 @@ +. + * + * @category Plugin + * @package StatusNet + * @author Craig Andrews + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +if (!defined('STATUSNET') && !defined('LACONICA')) { + exit(1); +} + +/** + * Superclass for plugins that do authentication + * + * @category Plugin + * @package StatusNet + * @author Craig Andrews + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +abstract class AuthenticationPlugin extends Plugin +{ + //is this plugin authoritative for authentication? + public $authoritative = false; + + //should accounts be automatically created after a successful login attempt? + public $autoregistration = false; + + //can the user change their email address + public $email_changeable=true; + + //can the user change their email address + public $password_changeable=true; + + //------------Auth plugin should implement some (or all) of these methods------------\\ + /** + * Check if a nickname/password combination is valid + * @param nickname + * @param password + * @return boolean true if the credentials are valid, false if they are invalid. + */ + function checkPassword($nickname, $password) + { + return false; + } + + /** + * Automatically register a user when they attempt to login with valid credentials. + * User::register($data) is a very useful method for this implementation + * @param nickname + * @return boolean true if the user was created, false if autoregistration is not allowed, null if this plugin is not responsible for this nickname + */ + function autoRegister($nickname) + { + return null; + } + + /** + * Change a user's password + * The old password has been verified to be valid by this plugin before this call is made + * @param nickname + * @param oldpassword + * @param newpassword + * @return boolean true if the password was changed, false if password changing failed for some reason, null if this plugin is not responsible for this nickname + */ + function changePassword($nickname,$oldpassword,$newpassword) + { + return null; + } + + /** + * Can a user change this field in his own profile? + * @param nickname + * @param field + * @return boolean true if the field can be changed, false if not allowed to change it, null if this plugin is not responsible for this nickname + */ + function canUserChangeField($nickname, $field) + { + return null; + } + + //------------Below are the methods that connect StatusNet to the implementing Auth plugin------------\\ + function __construct() + { + parent::__construct(); + } + + function StartCheckPassword($nickname, $password, &$authenticatedUser){ + if($this->password_changeable){ + $authenticated = $this->checkPassword($nickname, $password); + if($authenticated){ + $authenticatedUser = User::staticGet('nickname', $nickname); + if(!$authenticatedUser && $this->autoregistration){ + if($this->autoregister($nickname)){ + $authenticatedUser = User::staticGet('nickname', $nickname); + } + } + return false; + }else{ + if($this->authoritative){ + return false; + } + } + //we're not authoritative, so let other handlers try + }else{ + if($this->authoritative){ + //since we're authoritative, no other plugin could do this + throw new Exception(_('Password changing is not allowed')); + } + } + } + + function onStartChangePassword($nickname,$oldpassword,$newpassword) + { + if($this->password_changeable){ + $authenticated = $this->checkPassword($nickname, $oldpassword); + if($authenticated){ + $result = $this->changePassword($nickname,$oldpassword,$newpassword); + if($result){ + //stop handling of other handlers, because what was requested was done + return false; + }else{ + throw new Exception(_('Password changing failed')); + } + }else{ + if($this->authoritative){ + //since we're authoritative, no other plugin could do this + throw new Exception(_('Password changing failed')); + }else{ + //let another handler try + return null; + } + } + }else{ + if($this->authoritative){ + //since we're authoritative, no other plugin could do this + throw new Exception(_('Password changing is not allowed')); + } + } + } + + function onStartAccountSettingsPasswordMenuItem($widget) + { + if($this->authoritative && !$this->password_changeable){ + //since we're authoritative, no other plugin could change passwords, so do render the menu item + return false; + } + } +} + diff --git a/plugins/Ldap/LdapPlugin.php b/plugins/Ldap/LdapPlugin.php deleted file mode 100644 index 88ca92b37..000000000 --- a/plugins/Ldap/LdapPlugin.php +++ /dev/null @@ -1,195 +0,0 @@ -. - * - * @category Plugin - * @package StatusNet - * @author Craig Andrews - * @copyright 2009 Craig Andrews http://candrews.integralblue.com - * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 - * @link http://status.net/ - */ - -if (!defined('STATUSNET') && !defined('LACONICA')) { - exit(1); -} - -require_once INSTALLDIR.'/plugins/Auth/AuthPlugin.php'; -require_once 'Net/LDAP2.php'; - -class LdapPlugin extends AuthPlugin -{ - public $host=null; - public $port=null; - public $version=null; - public $starttls=null; - public $binddn=null; - public $bindpw=null; - public $basedn=null; - public $options=null; - public $filter=null; - public $scope=null; - public $attributes=array(); - - function __construct() - { - parent::__construct(); - } - - //---interface implementation---// - - function checkPassword($nickname, $password) - { - $ldap = $this->ldap_get_connection(); - if(!$ldap){ - return false; - } - $entry = $this->ldap_get_user($nickname); - if(!$entry){ - return false; - }else{ - $config = $this->ldap_get_config(); - $config['binddn']=$entry->dn(); - $config['bindpw']=$password; - if($this->ldap_get_connection($config)){ - return true; - }else{ - return false; - } - } - } - - function autoRegister($nickname) - { - $attributes=array(); - $config_attributes = array('nickname','email','fullname','homepage','location'); - foreach($config_attributes as $config_attribute){ - $value = common_config('ldap', $config_attribute.'_attribute'); - if($value!==false){ - array_push($attributes,$value); - } - } - $entry = $this->ldap_get_user($nickname,$attributes); - if($entry){ - $registration_data = array(); - foreach($config_attributes as $config_attribute){ - $value = common_config('ldap', $config_attribute.'_attribute'); - if($value!==false){ - if($config_attribute=='email'){ - $registration_data[$config_attribute]=common_canonical_email($entry->getValue($value,'single')); - }else if($config_attribute=='nickname'){ - $registration_data[$config_attribute]=common_canonical_nickname($entry->getValue($value,'single')); - }else{ - $registration_data[$config_attribute]=$entry->getValue($value,'single'); - } - } - } - //set the database saved password to a random string. - $registration_data['password']=common_good_rand(16); - $user = User::register($registration_data); - return true; - }else{ - //user isn't in ldap, so we cannot register him - return null; - } - } - - function changePassword($nickname,$oldpassword,$newpassword) - { - //TODO implement this - throw new Exception(_('Sorry, changing LDAP passwords is not supported at this time')); - - return false; - } - - function canUserChangeField($nickname, $field) - { - switch($field) - { - case 'password': - case 'nickname': - case 'email': - return false; - } - } - - //---utility functions---// - function ldap_get_config(){ - $config = array(); - $keys = array('host','port','version','starttls','binddn','bindpw','basedn','options','filter','scope'); - foreach($keys as $key){ - $value = $this->$key; - if($value!==null){ - $config[$key]=$value; - } - } - return $config; - } - - function ldap_get_connection($config = null){ - if($config == null){ - $config = $this->ldap_get_config(); - } - - //cannot use Net_LDAP2::connect() as StatusNet uses - //PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, 'handleError'); - //PEAR handling can be overridden on instance objects, so we do that. - $ldap = new Net_LDAP2($config); - $ldap->setErrorHandling(PEAR_ERROR_RETURN); - $err=$ldap->bind(); - if (Net_LDAP2::isError($err)) { - common_log(LOG_WARNING, 'Could not connect to LDAP server: '.$err->getMessage()); - return false; - } - return $ldap; - } - - /** - * get an LDAP entry for a user with a given username - * - * @param string $username - * $param array $attributes LDAP attributes to retrieve - * @return string DN - */ - function ldap_get_user($username,$attributes=array()){ - $ldap = $this->ldap_get_connection(); - $filter = Net_LDAP2_Filter::create(common_config('ldap','nickname_attribute'), 'equals', $username); - $options = array( - 'scope' => 'sub', - 'attributes' => $attributes - ); - $search = $ldap->search(null,$filter,$options); - - if (PEAR::isError($search)) { - common_log(LOG_WARNING, 'Error while getting DN for user: '.$search->getMessage()); - return false; - } - - if($search->count()==0){ - return false; - }else if($search->count()==1){ - $entry = $search->shiftEntry(); - return $entry; - }else{ - common_log(LOG_WARNING, 'Found ' . $search->count() . ' ldap user with the username: ' . $username); - return false; - } - } -} diff --git a/plugins/Ldap/README b/plugins/Ldap/README deleted file mode 100644 index 063286cef..000000000 --- a/plugins/Ldap/README +++ /dev/null @@ -1,50 +0,0 @@ -The LDAP plugin allows for StatusNet to handle authentication, authorization, and user information through LDAP. - -Installation -============ -add "addPlugin('ldap', array('setting'=>'value', 'setting2'=>'value2', ...);" to the bottom of your config.php - -Settings -======== -authn_authoritative (false): Set to true if LDAP's responses are authoritative (meaning if LDAP fails, do check the any other plugins or the internal password database). -autoregistration (false): Set to true if users should be automatically created when they attempt to login. -email_changeable (true): Are users allowed to change their email address? (true or false) -password_changeable (true): Are users allowed to change their passwords? (true or false) - -host*: LDAP server name to connect to. You can provide several hosts in an array in which case the hosts are tried from left to right.. See http://pear.php.net/manual/en/package.networking.net-ldap2.connecting.php -port: Port on the server. See http://pear.php.net/manual/en/package.networking.net-ldap2.connecting.php -version: LDAP version. See http://pear.php.net/manual/en/package.networking.net-ldap2.connecting.php -starttls: TLS is started after connecting. See http://pear.php.net/manual/en/package.networking.net-ldap2.connecting.php -binddn: The distinguished name to bind as (username). See http://pear.php.net/manual/en/package.networking.net-ldap2.connecting.php -bindpw: Password for the binddn. See http://pear.php.net/manual/en/package.networking.net-ldap2.connecting.php -basedn*: LDAP base name (root directory). See http://pear.php.net/manual/en/package.networking.net-ldap2.connecting.php -options: See http://pear.php.net/manual/en/package.networking.net-ldap2.connecting.php -filter: Default search filter. See http://pear.php.net/manual/en/package.networking.net-ldap2.connecting.php -scope: Default search scope. See http://pear.php.net/manual/en/package.networking.net-ldap2.connecting.php - -attributes: an array with the key being the StatusNet user attribute name, and the value the LDAP attribute name - nickname* - email - fullname - homepage - location - -* required -default values are in (parenthesis) - -Example -======= -Here's an example of an LDAP plugin configuration that connects to Microsoft Active Directory. - -addPlugin('ldap', array( - 'authn_authoritative'=>true, - 'autoregistration'=>true, - 'binddn'=>'username', - 'bindpw'=>'password', - 'basedn'=>'OU=Users,OU=StatusNet,OU=US,DC=americas,DC=global,DC=loc', - 'host'=>array('server1', 'server2'), - 'attributes'=>array( - 'nickname'=>'sAMAccountName', - 'email'=>'mail', - 'fullname'=>'displayName') -)); diff --git a/plugins/LdapAuthentication/LdapAuthenticationPlugin.php b/plugins/LdapAuthentication/LdapAuthenticationPlugin.php new file mode 100644 index 000000000..f14080b2d --- /dev/null +++ b/plugins/LdapAuthentication/LdapAuthenticationPlugin.php @@ -0,0 +1,195 @@ +. + * + * @category Plugin + * @package StatusNet + * @author Craig Andrews + * @copyright 2009 Craig Andrews http://candrews.integralblue.com + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +if (!defined('STATUSNET') && !defined('LACONICA')) { + exit(1); +} + +require_once INSTALLDIR.'/plugins/Authentication/AuthenticationPlugin.php'; +require_once 'Net/LDAP2.php'; + +class LdapAuthenticatonPlugin extends AuthenticationPlugin +{ + public $host=null; + public $port=null; + public $version=null; + public $starttls=null; + public $binddn=null; + public $bindpw=null; + public $basedn=null; + public $options=null; + public $filter=null; + public $scope=null; + public $attributes=array(); + + function __construct() + { + parent::__construct(); + } + + //---interface implementation---// + + function checkPassword($nickname, $password) + { + $ldap = $this->ldap_get_connection(); + if(!$ldap){ + return false; + } + $entry = $this->ldap_get_user($nickname); + if(!$entry){ + return false; + }else{ + $config = $this->ldap_get_config(); + $config['binddn']=$entry->dn(); + $config['bindpw']=$password; + if($this->ldap_get_connection($config)){ + return true; + }else{ + return false; + } + } + } + + function autoRegister($nickname) + { + $attributes=array(); + $config_attributes = array('nickname','email','fullname','homepage','location'); + foreach($config_attributes as $config_attribute){ + $value = common_config('ldap', $config_attribute.'_attribute'); + if($value!==false){ + array_push($attributes,$value); + } + } + $entry = $this->ldap_get_user($nickname,$attributes); + if($entry){ + $registration_data = array(); + foreach($config_attributes as $config_attribute){ + $value = common_config('ldap', $config_attribute.'_attribute'); + if($value!==false){ + if($config_attribute=='email'){ + $registration_data[$config_attribute]=common_canonical_email($entry->getValue($value,'single')); + }else if($config_attribute=='nickname'){ + $registration_data[$config_attribute]=common_canonical_nickname($entry->getValue($value,'single')); + }else{ + $registration_data[$config_attribute]=$entry->getValue($value,'single'); + } + } + } + //set the database saved password to a random string. + $registration_data['password']=common_good_rand(16); + $user = User::register($registration_data); + return true; + }else{ + //user isn't in ldap, so we cannot register him + return null; + } + } + + function changePassword($nickname,$oldpassword,$newpassword) + { + //TODO implement this + throw new Exception(_('Sorry, changing LDAP passwords is not supported at this time')); + + return false; + } + + function canUserChangeField($nickname, $field) + { + switch($field) + { + case 'password': + case 'nickname': + case 'email': + return false; + } + } + + //---utility functions---// + function ldap_get_config(){ + $config = array(); + $keys = array('host','port','version','starttls','binddn','bindpw','basedn','options','filter','scope'); + foreach($keys as $key){ + $value = $this->$key; + if($value!==null){ + $config[$key]=$value; + } + } + return $config; + } + + function ldap_get_connection($config = null){ + if($config == null){ + $config = $this->ldap_get_config(); + } + + //cannot use Net_LDAP2::connect() as StatusNet uses + //PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, 'handleError'); + //PEAR handling can be overridden on instance objects, so we do that. + $ldap = new Net_LDAP2($config); + $ldap->setErrorHandling(PEAR_ERROR_RETURN); + $err=$ldap->bind(); + if (Net_LDAP2::isError($err)) { + common_log(LOG_WARNING, 'Could not connect to LDAP server: '.$err->getMessage()); + return false; + } + return $ldap; + } + + /** + * get an LDAP entry for a user with a given username + * + * @param string $username + * $param array $attributes LDAP attributes to retrieve + * @return string DN + */ + function ldap_get_user($username,$attributes=array()){ + $ldap = $this->ldap_get_connection(); + $filter = Net_LDAP2_Filter::create(common_config('ldap','nickname_attribute'), 'equals', $username); + $options = array( + 'scope' => 'sub', + 'attributes' => $attributes + ); + $search = $ldap->search(null,$filter,$options); + + if (PEAR::isError($search)) { + common_log(LOG_WARNING, 'Error while getting DN for user: '.$search->getMessage()); + return false; + } + + if($search->count()==0){ + return false; + }else if($search->count()==1){ + $entry = $search->shiftEntry(); + return $entry; + }else{ + common_log(LOG_WARNING, 'Found ' . $search->count() . ' ldap user with the username: ' . $username); + return false; + } + } +} diff --git a/plugins/LdapAuthentication/README b/plugins/LdapAuthentication/README new file mode 100644 index 000000000..03647e7c7 --- /dev/null +++ b/plugins/LdapAuthentication/README @@ -0,0 +1,50 @@ +The LDAP Authentication plugin allows for StatusNet to handle authentication through LDAP. + +Installation +============ +add "addPlugin('ldapAuthentication', array('setting'=>'value', 'setting2'=>'value2', ...);" to the bottom of your config.php + +Settings +======== +authoritative (false): Set to true if LDAP's responses are authoritative (meaning if LDAP fails, do check the any other plugins or the internal password database). +autoregistration (false): Set to true if users should be automatically created when they attempt to login. +email_changeable (true): Are users allowed to change their email address? (true or false) +password_changeable (true): Are users allowed to change their passwords? (true or false) + +host*: LDAP server name to connect to. You can provide several hosts in an array in which case the hosts are tried from left to right.. See http://pear.php.net/manual/en/package.networking.net-ldap2.connecting.php +port: Port on the server. See http://pear.php.net/manual/en/package.networking.net-ldap2.connecting.php +version: LDAP version. See http://pear.php.net/manual/en/package.networking.net-ldap2.connecting.php +starttls: TLS is started after connecting. See http://pear.php.net/manual/en/package.networking.net-ldap2.connecting.php +binddn: The distinguished name to bind as (username). See http://pear.php.net/manual/en/package.networking.net-ldap2.connecting.php +bindpw: Password for the binddn. See http://pear.php.net/manual/en/package.networking.net-ldap2.connecting.php +basedn*: LDAP base name (root directory). See http://pear.php.net/manual/en/package.networking.net-ldap2.connecting.php +options: See http://pear.php.net/manual/en/package.networking.net-ldap2.connecting.php +filter: Default search filter. See http://pear.php.net/manual/en/package.networking.net-ldap2.connecting.php +scope: Default search scope. See http://pear.php.net/manual/en/package.networking.net-ldap2.connecting.php + +attributes: an array with the key being the StatusNet user attribute name, and the value the LDAP attribute name + nickname* + email + fullname + homepage + location + +* required +default values are in (parenthesis) + +Example +======= +Here's an example of an LDAP plugin configuration that connects to Microsoft Active Directory. + +addPlugin('ldapAuthentication', array( + 'authoritative'=>true, + 'autoregistration'=>true, + 'binddn'=>'username', + 'bindpw'=>'password', + 'basedn'=>'OU=Users,OU=StatusNet,OU=US,DC=americas,DC=global,DC=loc', + 'host'=>array('server1', 'server2'), + 'attributes'=>array( + 'nickname'=>'sAMAccountName', + 'email'=>'mail', + 'fullname'=>'displayName') +)); -- cgit v1.2.3-54-g00ecf