package.xml0000664000076500000240000010730612611577414010132 0ustar passwd pear.horde.org Horde password changing application An application to change any user passwords stored in various backends like SQL, LDAP, Kolab, passwd files etc. Jan Schneider jan jan@horde.org yes Michael Slusarz slusarz slusarz@horde.org yes 2015-10-20 5.0.4 5.0.0 stable stable GPL-2.0 * [mjr] Fix changing password using Kolab driver (Mike Gabriel <mike.gabriel@das-netzwerkteam.de>). 5.3.0 6.0.0alpha1 6.0.0alpha1 1.7.0 horde pear.horde.org 5.0.0 6.0.0alpha1 6.0.0alpha1 Horde_Auth pear.horde.org 2.0.0 3.0.0alpha1 3.0.0alpha1 Horde_Core pear.horde.org 2.11.0 3.0.0alpha1 3.0.0alpha1 Horde_Exception pear.horde.org 2.0.0 3.0.0alpha1 3.0.0alpha1 Horde_Injector pear.horde.org 2.0.0 3.0.0alpha1 3.0.0alpha1 Horde_Util pear.horde.org 2.0.0 3.0.0alpha1 3.0.0alpha1 Horde_View pear.horde.org 2.0.0 3.0.0alpha1 3.0.0alpha1 gettext Horde_Db pear.horde.org 2.0.0 3.0.0alpha1 3.0.0alpha1 Horde_Http pear.horde.org 2.0.0 3.0.0alpha1 3.0.0alpha1 Horde_Ldap pear.horde.org 2.0.0 3.0.0alpha1 3.0.0alpha1 Horde_Vfs pear.horde.org 2.0.0 3.0.0alpha1 3.0.0alpha1 Crypt_CHAP pear.php.net com ldap soap horde Role pear.horde.org 4.0.0alpha1 4.0.0alpha1 alpha alpha 2011-09-28 GPL-2.0 * First alpha release for Horde 4. * [jan] Add Latvian translation (Jānis Eisaks <jancs@dv.lv>). * [rla] Added new driver 'horde' which uses the update() function of horde's authentication driver. * [jan] Provide default configuration files instead of .dist versions. * [jan] Fix creating temporary files with open_basedir restrictions. 4.0.0RC1 4.0.0RC1 beta beta 2011-10-28 GPL-2.0 * [bak] Fix lookup of user entry in LDAP driver. 4.0.0 4.0.0 stable stable 2011-11-02 GPL-2.0 * First stable release for Horde 4. 4.0.1 4.0.0 stable stable 2012-02-28 GPL-2.0 * [rla] Don't pass too many parameters from backends.php to Horde_Db (Bug #10963). * [jan] Make expect driver locale independent (Bug #9166). * [jan] Update Japanese translation (Hiromi Kimura <hiromi@tac.tsukuba.ac.jp>). 5.0.0beta1 5.0.0 beta stable 2013-05-07 GPL-2.0 * [mms] Add option to destroy Horde session after changing password (Bug #11766). * [mms] Http driver now uses Horde_Http_Client. * [jan] Update French translation (Paul De Vlieger <paul.de_vlieger@moniut.univ-bpclermont.fr>). * [jan] Update Polish translation (Krzysztof Kozera <krzysztof113@o2.pl>). * [jan] Update Italian translation (Massimo Malabotta <mmalabotta@units.it>). * [jan] Fix preparing multiple backends (Bug #11023). 5.0.0RC1 5.0.0 beta stable 2013-05-29 GPL-2.0 * [jan] Add policy for minimum number of non-alphanumeric characters (Friedrich Haubensak <hsk@fli-leibniz.de>, Request #12243). * [jan] Add parameter for sudo program name to expect script (Friedrich Haubensak <hsk@fli-leibniz.de>, Request #12243). 5.0.0 5.0.0 stable stable 2013-06-05 GPL-2.0 * Final release. 5.0.1 5.0.0 stable stable 2013-08-27 GPL-2.0 * [jan] Don't overwrite parameters for composite sub-drivers (Bug #12284). * [jan] Don't install expect scripts as executables. * [jan] Fix fatal error in Samba/LDAP driver (Bug #12319). * [jan] Fix user name parameter in LDAP driver (Bug #12331). 5.0.2 5.0.0 stable stable 2014-09-05 GPL-2.0 * [jan] Fix syntax error in HTTP driver (Bug #13464). * [mms] Re-add 'userdn' hook. * [jan] Update Danish translation (Erling Preben Hansen <erling@eph.dk>). * [mms] Fix usage of 'query_lookup' and 'query_modify' backend parameters (Michael Cramer <michael@bigmichi1.de>). 5.0.3 5.0.0 stable stable 2015-08-01 GPL-2.0 * [jan] Update Italian translation. * [jan] Update Galician translation. * [jan] Update Catalan translation. * [jan] Update German translation. * [jan] Update Czech translation. * [jan] Update Brazilian Portuguese translation (Luis Felipe Marzagao <duli@easylifeproject.org>). 5.0.4 5.0.0 stable stable 2015-10-21 GPL-2.0 * [mjr] Fix changing password using Kolab driver (Mike Gabriel <mike.gabriel@das-netzwerkteam.de>). passwd-5.0.4/config/.htaccess0000664000076500000240000000001612611577414013011 0ustar Deny from all passwd-5.0.4/config/backends.php0000664000076500000240000004510512611577414013506 0ustar true, 'name' => 'Horde Authentication', 'driver' => 'Horde', 'policy' => array( 'minLength' => 6, 'minNumeric' => 1, ), 'logout' => true, ); $backends['hordesql'] = array( 'disabled' => true, 'name' => 'Horde SQL Authentication', 'driver' => 'Sql', 'policy' => array( 'minLength' => 6, 'minNumeric' => 1, ), 'params' => array_merge( $GLOBALS['conf']['sql'], array( 'table' => 'horde_users', 'user_col' => 'user_uid', 'pass_col' => 'user_pass', 'show_encryption' => false, 'encryption' => isset($GLOBALS['conf']['auth']['params']['encryption']) ? $GLOBALS['conf']['auth']['params']['encryption'] : false ) ), 'logout' => true, ); $backends['poppassd'] = array( 'disabled' => true, 'name' => 'Poppassd Server', 'driver' => 'Poppassd', 'policy' => array( 'minLength' => 6, 'minNumeric' => 1, ), 'params' => array( 'host' => 'localhost', 'port' => 106 ), ); $backends['servuftp'] = array( 'disabled' => true, 'name' => 'Serv-U FTP Server', 'driver' => 'Servuftp', 'policy' => array( 'minLength' => 6, 'minNumeric' => 1, ), 'params' => array( 'host' => 'localhost', 'port' => 106, 'timeout' => 30 ), ); $backends['expect'] = array( 'disabled' => true, 'name' => 'Expect Script', 'driver' => 'Expect', 'policy' => array( 'minLength' => 6, 'minNumeric' => 1, ), 'params' => array( 'program' => '/usr/bin/expect', 'script' => PASSWD_BASE . '/scripts/passwd-expect', 'params' => '-telnet -host localhost -output /tmp/passwd.log' ), ); $backends['sudo_expect'] = array( 'disabled' => true, 'name' => 'Expect with Sudo Script', 'driver' => 'Procopen', 'policy' => array( 'minLength' => 6, 'minNumeric' => 1, ), 'params' => array( 'program' => '/usr/bin/expect ' . PASSWD_BASE . '/scripts/passwd-expect -sudo' ), ); $backends['smbpasswd'] = array( 'disabled' => true, 'name' => 'Samba Server', 'driver' => 'Smbpasswd', 'policy' => array( 'minLength' => 6, 'minNumeric' => 1, ), 'params' => array( 'program' => '/usr/bin/smbpasswd', 'host' => 'localhost' ), ); $backends['ldap'] = array( 'disabled' => true, 'name' => 'LDAP Server', 'driver' => 'Ldap', 'policy' => array( 'minLength' => 6, 'minNumeric' => 1, ), 'params' => array( 'host' => 'localhost', 'port' => 389, 'basedn' => 'o=example.com', // LDAP object key attribute. 'uid' => 'uid', // The attribute storing the password. 'attribute' => 'userPassword', // These attributes will enable shadow password policies. // 'shadowlastchange' => 'shadowLastChange', // 'shadowmin' => 'shadowMin', // This will be appended to the username when looking for the userdn. 'realm' => '', // Use this filter when searching for the user's DN. 'filter' => '', // Hash method to use when storing the password 'encryption' => 'crypt', // Whether to enable TLS for this LDAP connection // Note: make sure that the host matches cn in the server certificate. 'tls' => false, // Determine the user's DN. %u will be replaced by the user's ID. // Alternatively, disable this option and instead use the 'userdn' // hook (config/hooks.php) to dynamically set the userdn. //'userdn' => 'uid=%u,o=example.com' ), ); // NOTE: to set the ldap userdn, see horde/config/hooks.php $backends['ldapadmin'] = array( 'disabled' => true, 'name' => 'LDAP Server with Admin Bindings', 'driver' => 'Ldap', 'policy' => array( 'minLength' => 6, 'minNumeric' => 1, ), 'params' => array( 'host' => 'localhost', 'port' => 389, 'basedn' => 'o=example.com', 'admindn' => 'cn=admin,o=example.com', 'adminpw' => 'somepassword', // LDAP object key attribute. 'uid' => 'uid', // The attribute storing the password. 'attribute' => 'userPassword', // These attributes will enable shadow password policies. // 'shadowlastchange' => 'shadowLastChange', // 'shadowmin' => 'shadowMin', // This will be appended to the username when looking for the userdn. 'realm' => '', // Use this filter when searching for the user's DN. 'filter' => '', // Hash method to use when storing the password 'encryption' => 'crypt', // If set, should be 0 or 1. See the LDAP documentation about the // corresponding parameter REFERRALS. // Windows 2003 Server require to set this parameter to 0 // 'referrals' => 0, // Whether to enable TLS for this LDAP connection // Note: make sure that the host matches cn in the server certificate. 'tls' => false ), ); // NOTE: to set the ldap userdn, see horde/config/hooks.php // NOTE: to make work with samba 2.x schema you must change lm_attribute and // nt_attribute $backends['smbldap'] = array( 'disabled' => true, 'name' => 'Samba/LDAP Server', 'preferred' => '', 'policy' => array( 'minLength' => 6, 'minNumeric' => 1, ), 'driver' => 'Smbldap', 'params' => array( 'host' => 'localhost', 'port' => 389, 'basedn' => 'o=example.com', // LDAP object key attribute. 'uid' => 'uid', // The attribute storing the password. 'attribute' => 'userPassword', // This will be appended to the username when looking for the userdn. 'realm' => '', // Use this filter when searching for the user's DN. 'filter' => '', // Hash method to use when storing the password 'encryption' => 'crypt', // Whether to enable TLS for this LDAP connection // Note: make sure that the host matches cn in the server certificate. 'tls' => false, // Determine the user's DN. %u will be replaced by the user's ID. //'userdn' => 'uid=%u,o=example.com' // If any of the following attributes are commented out, they // won't be set on the LDAP server. 'lm_attribute' => 'sambaLMPassword', 'nt_attribute' => 'sambaNTPassword', 'pw_set_attribute' => 'sambaPwdLastSet', 'pw_expire_attribute' => 'sambaPwdMustChange', // The number of days until samba passwords expire. If this // is commented out, passwords will never expire. 'pw_expire_time' => 180, ), ); $backends['sql'] = array( 'disabled' => true, 'name' => 'SQL Server', 'driver' => 'Sql', 'policy' => array( 'minLength' => 6, 'minNumeric' => 1, ), 'params' => array( 'phptype' => 'mysql', 'hostspec' => 'localhost', 'username' => 'dbuser', 'password' => 'dbpasswd', 'encryption' => 'md5-hex', 'database' => 'db', 'table' => 'users', 'user_col' => 'user_uid', 'pass_col' => 'user_pass', 'show_encryption' => false // The following two settings allow you to specify custom queries for // lookup and modify functions if special functions need to be // performed. In places where a username or a password needs to be // used, refer to this placeholder reference: // %d -> gets substituted with the domain // %u -> gets substituted with the user // %U -> gets substituted with the user without a domain part // %p -> gets substituted with the plaintext password // %e -> gets substituted with the encrypted password // // 'query_lookup' => 'SELECT user_pass FROM horde_users WHERE user_uid = %u', // 'query_modify' => 'UPDATE horde_users SET user_pass = %e WHERE user_uid = %u', ), ); $backends['mailmgr'] = array( 'disabled' => true, 'name' => 'VMailMgr Server', 'driver' => 'Vmailmgr', 'policy' => array(), 'params' => array( 'vmailinc' => '/your/path/to/the/vmail.inc' ), ); $backends['vpopmail'] = array( 'disabled' => true, 'name' => 'Vpopmail Server', 'driver' => 'Vpopmail', 'policy' => array( 'minLength' => 6, 'minNumeric' => 1, ), 'params' => array( 'phptype' => 'mysql', 'hostspec' => 'localhost', 'username' => '', 'password' => '', 'encryption' => 'crypt', 'database' => 'vpopmail', 'table' => 'vpopmail', 'name' => 'pw_name', 'domain' => 'pw_domain', 'passwd' => 'pw_passwd', 'clear_passwd' => 'pw_clear_passwd', 'use_clear_passwd' => true, 'show_encryption' => true ), ); $backends['pine'] = array( 'disabled' => true, 'name' => 'Pine Password File', 'driver' => 'Pine', 'policy' => array( 'minLength' => 6, 'minNumeric' => 1, ), 'params' => array( // FTP server information. 'host' => 'localhost', 'port' => '21', 'path' => '', 'file' => '.pinepw', // Connect using the just-passed-in password? 'use_new_passwd' => false, // Host string to look for in the encrypted file. 'imaphost' => 'localhost' ), ); $backends['kolab'] = array( 'disabled' => true, 'name' => 'Local Kolab Server', 'driver' => 'Kolab', 'policy' => array( 'minLength' => 6, 'minNumeric' => 1, ), 'params' => array(), ); $backends['myscript'] = array( 'disabled' => true, 'name' => 'Custom Script', 'driver' => 'Procopen', 'policy' => array( 'minLength' => 6, 'minNumeric' => 1, ), 'params' => array( 'program' => '/path/to/my/script + myargs' ), ); // This is an example configuration for the http driver. This allows // connecting to an arbitrary URL that contains a password change form. // The params 'username','oldPasswd','passwd1', and 'passwd2' params should be // set to the name of the respective form input elements on the html form. If // there are additional form fields that the form requires, define them in the // 'fields' array in the form 'formFieldName' => 'formFieldValue'. The driver // attempts to determine the success or failure based on searching the // returned html page for the values listed in the 'eval_results' array. $backends['http'] = array( 'disabled' => true, 'name' => 'HTTP Server', 'driver' => 'Http', 'policy' => array( 'minLength' => 6, 'minNumeric' => 1, ), 'params' => array( 'url' => 'http://www.example.com/psoft/servlet/psoft.hsphere.CP', 'username' => 'mbox', 'oldPasswd' => 'old_password', 'passwd1' => 'password', 'passwd2' => 'password2', 'fields' => array( 'action' => 'change_mbox_password', 'ftemplate' => 'design/mail_passw.html' ), 'eval_results' => array( 'success' => 'Password successfully changed', 'badPass' => 'Bad old password', 'badUser' => 'Mailbox not found' ), ), ); $backends['soap'] = array( 'disabled' => true, 'name' => 'SOAP Server', 'driver' => 'Soap', 'policy' => array( 'minLength' => 6, 'minNumeric' => 1, ), 'params' => array( // If this service doesn't have a WSDL, the 'location' and 'uri' // parameters below must be specified instead. 'wsdl' => 'http://www.example.com/service.wsdl', 'method' => 'changePassword', // This is the order of the arguments to the method specified above. 'arguments' => array('username', 'oldpassword', 'newpassword'), // These parameters are directly passed to the SoapClient object, see // http://ww.php.net/manual/en/soapclient.soapclient.php for a // complete list of possible parameters. 'soap_params' => array( 'location' => '', 'uri' => '', ), ), ); // This is an example configuration for Postfix.admin 2.3. // Set the 'password_policy' section as you wish. // In most installations you probably only need to change the // hostspec and/or password fields. $backends['postfixadmin'] = array( 'disabled' => true, 'name' => 'Postfix Admin server', 'driver' => 'Sql', 'policy' => array( 'minLength' => 6, 'maxLength' => 20, 'minNumeric' => 1, ), 'params' => array( 'phptype' => 'mysql', 'hostspec' => 'localhost', 'username' => 'postfix', 'password' => 'PASSWORD', 'encryption' => 'crypt-md5', 'database' => 'postfix', 'table' => 'mailbox', 'user_col' => 'username', 'pass_col' => 'password', 'show_encryption' => false, // The following two settings allow you to specify custom queries for // lookup and modify functions if special functions need to be // performed. In places where a username or a password needs to be // used, refer to this placeholder reference: // %d -> gets substituted with the domain // %u -> gets substituted with the user // %U -> gets substituted with the user without a domain part // %p -> gets substituted with the plaintext password // %e -> gets substituted with the encrypted password // 'query_lookup' => 'SELECT password FROM mailbox WHERE username = %u and active = 1', 'query_modify' => 'UPDATE mailbox SET password = %e WHERE username = %u' ), ); // This is an example configuration for chaining multiple drivers to allow for // syncing of passwords across many backends using the composite driver as a // wrapper. // // Each of the subdrivers may contain an optional parameter called 'required' // that, when set to true, will cause the rest of the drivers be skipped if a // particular one fails. $backends['composite'] = array( 'disabled' => true, 'name' => 'All Services', 'driver' => 'Composite', 'policy' => array( 'minLength' => 6, 'minNumeric' => 1, ), 'params' => array('drivers' => array( 'sql' => array( 'name' => 'Horde Authentication', 'driver' => 'Sql', 'required' => true, 'params' => array( 'phptype' => 'mysql', 'hostspec' => 'localhost', 'username' => 'horde', 'password' => '', 'encryption' => 'md5-hex', 'database' => 'horde', 'table' => 'horde_users', 'user_col' => 'user_uid', 'pass_col' => 'user_pass', 'show_encryption' => false // 'query_lookup' => '', // 'query_modify' => '', ), ), 'smbpasswd' => array( 'name' => 'Samba Server', 'driver' => 'Smbpasswd', 'params' => array( 'program' => '/usr/bin/smbpasswd', 'host' => 'localhost', ), ), )), ); passwd-5.0.4/config/conf.xml0000664000076500000240000000254712611577414012675 0ustar Backend Settings hidden shown hidden true root,bin,daemon,adm,lp,shutdown,halt,uucp,ftp,anonymous,nobody,httpd,operator,guest,diginext,bind,cyrus,courier,games,kmem,mailnull,man,mysql,news,postfix,sshd,tty,www true passwd-5.0.4/config/hooks.php.dist0000664000076500000240000000420712611577414014017 0ustar backend userid mapping hook. * * @param string $userid The username as input by user. * @param Passwd_Driver $driver The driver object. * * @return string The username in the backend. */ // public function username($userid, $driver) // { // // Example: Translate what the user enters, in the username box, // // into what the backend expects. // if ($driver instanceof Passwd_Driver_Http) { // return $userid . '@example.com'; // } // // return $userid; // } /** * Userdn hook. * * @param string $authid The authenticated username. * * @return string Userdn to use. */ // public function userdn($authid) // { // // Example: Provide LDAP server with a userdn so that you do not // // have to perform anonymous binds. // return 'uid=' . $authid . ',o=example.com'; // } /** * Default username hook. * * @return string Return the username to use in the form. */ // public function default_username() // { // // Example: This is the default value if this hook is not defined. // return $GLOBALS['registry']->getAuth(); // } /** * Hook called after the password has changed. If the password change * affects the current Horde session, this has NOT yet been handled by * the calling code. * * @param string $user The user ID. * @param string $oldpass The old password. * @param string $newpass The new password. */ // public function password_changed($user, $oldpass, $newpass) // { // Horde::log(sprintf('User %s has changed his password.', $user), 'NOTICE'); // } } passwd-5.0.4/docs/CHANGES0000600000076500000240000002662312611577414011673 0ustar ------ v5.0.4 ------ [mjr] Fix changing password using Kolab driver (Mike Gabriel ). ------ v5.0.3 ------ [jan] Update Italian translation. [jan] Update Galician translation. [jan] Update Catalan translation. [jan] Update German translation. [jan] Update Czech translation. [jan] Update Brazilian Portuguese translation (Luis Felipe Marzagao ). ------ v5.0.2 ------ [jan] Fix syntax error in HTTP driver (Bug #13464). [mms] Re-add 'userdn' hook. [jan] Update Danish translation (Erling Preben Hansen ). [mms] Fix usage of 'query_lookup' and 'query_modify' backend parameters (Michael Cramer ). ------ v5.0.1 ------ [jan] Don't overwrite parameters for composite sub-drivers (Bug #12284). [jan] Don't install expect scripts as executables. [jan] Fix fatal error in Samba/LDAP driver (Bug #12319). [jan] Fix user name parameter in LDAP driver (Bug #12331). ------ v5.0.0 ------ [jan] Add policy for minimum number of non-alphanumeric characters (Friedrich Haubensak , Request #12243). [jan] Add parameter for sudo program name to expect script (Friedrich Haubensak , Request #12243). ----------- v5.0.0beta1 ----------- [mms] Add option to destroy Horde session after changing password (Bug #11766). [mms] Http driver now uses Horde_Http_Client. [jan] Update French translation (Paul De Vlieger ). [jan] Update Polish translation (Krzysztof Kozera ). [jan] Update Italian translation (Massimo Malabotta ). [jan] Fix preparing multiple backends (Bug #11023). ------ v4.0.1 ------ [rla] Don't pass too many parameters from backends.php to Horde_Db (Bug #10963). [jan] Make expect driver locale independent (Bug #9166). [jan] Update Japanese translation (Hiromi Kimura ). ---- v4.0 ---- [bak] Fix lookup of user entry in LDAP driver. ----------- v4.0-ALPHA1 ----------- [jan] Add Latvian translation (Jānis Eisaks ). [rla] Add new driver 'horde' which uses the update() function of horde's authentication driver. [jan] Provide default configuration files instead of .dist versions. [jan] Fix creating temporary files with open_basedir restrictions. ------ v3.1.3 ------ [jan] Fix examples using 'minSymbols' instead of 'minSymbol' (Bug #8854). [jan] Fix PHP error when changing passwords with LDAP driver (Bug #8686). ------ v3.1.2 ------ [jan] Enable output compression (horde@albasoft.com, Bug #8649). [jan] Add Croatian translation (Valentin Vidic ). [jan] Add option to configure referrals for LDAP driver (manilal@ejyothi.com, Request #8582). [jan] Simplify and fix smbldap driver (Bug #8192). ------ v3.1.1 ------ [cjh] SECURITY: Fix XSS when specifying an invalid backend key (security@davidwharton.us, #8398). [jan] Add hook that's called after successfully changing the password. [jan] Add SOAP driver. [jan] Add example configuration for Postfix Admin (Michael Brennen ). [jan] Fix binding to LDAP server if using the userdn hook. ---- v3.1 ---- [cjh] Fix bad mode for STDERR in the procopen driver (info@opensolutions.net, Bug #8022). -------- v3.1-RC2 -------- [cjh] Don't include the old password in LDAP driver error messages (Joffrey van Wageningen ). -------- v3.1-RC1 -------- [cjh] Add missing enforcement of minSymbol password policy (yann@pleiades.fr.eu.org, Bug #7260). [cjh] Only update smbldap attributes for Samba users, and update all attributes at once instead of one at a time (marco@csita.unige.it, Request #5977). [cjh] Don't set smbldap attributes that are commented out in the config (fabio.pedretti@ing.unibs.it, Request #5937). [jan] Move all Passwd-specific hook examples from Horde's config/ directory. [cjh] Add support for switching between encryption schemes (ulrich-horde@topfen.net, Request #2865). [jan] Add support for sudo to the example expect script (Dennis Voetelink , Request #5300). [mas] Conform to WCAG 1.0 Priority 2/Section 508 accessibility guidelines. (Request #4080) [jan] Add new expect driver that uses the expect PECL PHP extension (Duck ). [mjr] Add new http driver for changing passwords via an existing web form. [mjr] Pass reference to driver to the _passwd_hook_username call. [jan] Add Turkish translation (METU ). ------ v3.0.1 ------ [jan] Add placeholders for domain and username parts to SQL driver queries (Vilius Sumskas , Request #4985). [jan] Improve error checking in poppassd driver (Bug #4505, horde@koornneef.net). [jan] Add Slovenian translation (Duck ). [jan] Compare hashing algorithms in passwords case insensitively (andreas@altroot.de, Bug #2708). [jan] Allow password changing for special Kolab users (mzizka@hotmail.com, Request #4128). [jan] Add Japanese translation (Hiromi Kimura ). [ben] Better support for MS-SQL [cjh] Add support in the expect driver for rssh, scponly, and other programs that can execute certain commands over ssh without providing a prompt (Request #2887). ---- v3.0 ---- [jan] Add configuration option to switch between using user names with and without realms. [jan] Add Slovak translation (Ivan Noris ). -------- v3.0-RC1 -------- [jan] Extend the expect script to allow setups with passwd as the login shell (Request #2550, Lionel Elie Mamane ). [jan] Don't bind to LDAP anonymously if binding with userdn fails (Bug #2502). [cjh] Fix updating shadowlastchange attribute in ldap driver (Roel Gloudemans ). [jan] Extend the smbldap driver from the ldap driver to support all parameters of the ldap driver (Request #2499). --------- v3.0-BETA --------- [cjh] Use Crypt_CHAP to generate smbldap passwords (Bug #1223). [stb] Add Kolab driver. [cjh] Allow using admin credentials in the LDAP driver (Bug #1409). [cjh] Use bind variables in SQL drivers (selsky@columbia.edu, Bug #1718). [cjh] Allow the list of refused usernames to be empty (Bug #1544). [cjh] If $conf['user']['change'] is false, don't trust form input for the userid. [jan] Add Catalan translation (Joan Jorba Calsina ). [cjh] Add ADSI and PSPASSWD windows password drivers (LRM ). [jan] Add Persian (Western) translation (Vahid Ghafarpour ). [jan] Add shadowLastChange and shadowMin configuration items to LDAP driver (Roel Gloudemans ). [cjh] Add proc_open() driver (Samuel Nicolary ). [cjh] Add an SMB LDAP driver (Shane Boulter ). [cjh] Add SSL support to the LDAP driver (LRM ). [max] Add minSymbols and minClasses password policies. See comments in config/backends.php.dist for more information. [max] Add optional 'required' parameters to composite driver's subdriver configurations. [max] Add optional parameter 'no_reset' to the backend configs which prevents reseting the authenticated user's credentials on password changes. [max] Properly reset authenticated user's credentials. [cjh] Use password encryption that's now implemented in the Auth:: package. [max] Add pine driver which changes a pine-encoded file using FTP. [max] Fix password checking when encryption requires a random salt. [max] Add composite driver which will replace all the groups stuff. [max] Add support for backend groups to allow syncing of multiple backends. [max] Add query_lookup and query_modify parameters to the sql driver. [ejr] Add tls support for ldap driver. [ejr] Fix error reporting in poppassd driver. [ejr] Add binddn hook submitted by Amith Varghese . [ejr] make sure oldpassword == horde_login_password before changing horde cached password. [ejr] Fix md5 (md5-hex and md5-base64) encryption for ldap/sql (Amith Varghese ). [mc] Move templates to horde style directory layout, getName() -> getParam(). [ejr] Implemented new CVS HEAD themes. [ejr] Updated to new CVS HEAD notification system. ------ v2.2.2 ------ [jan] Close XSS when setting the parent frame's page title by javascript (cjh). [ejr] Configuration item for showing/changing username in the form. [jan] Allow to set the protocol version in the LDAP driver (ben@alkaloid.net). [cjh] Add crypt-blowfish and crypt-md5 encryption types. Also add crypt-des for completion which is just an alias for crypt (max). [jan] Add Estonian translation (Toomas Aas ). ------ v2.2.1 ------ [jan] Bug #40: Fix smbpasswd driver with non-bash shells (Christopher Huyler ). [jan] Add Simplified Chinese translation (Zhang Bo ). ---------- v2.2.1-RC1 ---------- [jan] Add Indonesian language (Slamin ). [jan] Add Galician translation (Rafael Varela Pet , Guillermo Mendez ). [jan] Add Danish translation (Anders Bruun Olsen ). [jan] Add Arabic (Syria) translation (Platinum Development Team ). [jan] Add Hungarian translation (Szabo Gyula ). [jan] Add Romanian translation (Eugen Hoanca , Marius Dragulescu ). [jan] Add Lithuanian translation (Vilius Sumskas ). [ejr] Fix BC breaks in vpopmail and sql drivers. ---- v2.2 ---- [ejr] Allow bc for php versions that don't have the ctype extension. -------- v2.2-RC2 -------- [ejr] Fix missing path for expect binary. [ejr] Add missing scripts/ directory and missing expect script. [ejr] Fix error reporting in expect driver (j.huinink@wanadoo.nl). [ejr] Remove old realm code that was previously missed. [ejr] Port servuftp driver to new backends.conf format. [ejr] Return actual error message text in poppassd driver (submitted by Leena Heino ). [ejr] Change is_a(*, 'PEAR_Error') calls to PEAR::isError() calls for php bc. -------- v2.2-RC1 -------- [ejr] Add vpopmail driver (Anton Nekhoroshikh ). [mac] Add vmailmgr driver (Marco Kaiser ). [ejr] Add expect script (Gaudenz Steinlin). [ejr] Change ldap code to do self-password changes, add phpdoc. [ejr] Update ldap driver (Tjeerd van der Zee). [ejr] Reset Horde/IMP cached credentials when changing password. [ejr] Add username hooks (mac). [ejr] Rewrite driver system, add backends.conf system (mc). [jan] Add Italian translation (Fichera Gianrico ). [cjh] Close several small XSS vulnerabilities (Mitja Kolsek ). ---- v2.1 ---- [ejr] Add servuftp interface. [ejr] Add exim sql backend. [ejr] Add smbpasswd support. [ejr] Move to driver driven system. [mc] Add javascript checks for form input. [jan] Add Bulgarian translation (Miroslav Pendev ). ---- v2.0 ---- [ejr] Added optional checks for password lengths and strength testing. [ejr] Remove check for prefs.php in notconfigured.inc. [ejr] Change from short-tag - Michael Slusarz Driver Developers ================= - Anton Nekhoroshikh - Gaudenz Steinlin - Ilya Krel - Lucas - Luiz R Malheiros (malheiros@gmail.com) - Marco Kaiser - Mattias Webjörn Eriksson - Max Kalika - Mike Cochrane - René Lund Jensen - Samuel Nicolary - Shane Boulter - Stuart Bingë - Tjeerd van der Zee - Ralf Lang Localization ============ ===================== ====================================================== Arabian (Syria) Platinum Development Team Brazilian Portuguese Darci Antonio Tartari Fabio de Almeida Bulgarian Miroslav Pendev Catalan Joan Jorba Calsina Chinese (Simplified) Wenzhuo Zhang Anna Chen Chinese (Traditional) David Chang Croatian Valentin Vidic Czech Pavel Chytil Dutch Tjeerd van der Zee Resan Sa-Ardnuam Danish Anders Bruun Olsen Brian Truelsen Erling Preben Hansen Estonian Toomas Aas Alar Sing Finnish Tero Matinlassi Leena Heino French Daniel Huhardeaux Benoit St-André Pierre Lachance Paul De Vlieger Galician Rafael Varela Guillermo Mendez Gloria Presedo German Jens A Tkotz Jan Schneider Hungarian Robert Szokovacs Gyula Szabo Andras Galos Indonesian Slamin Italian Gianrico Fichera Marko Djukic Fabio Pedretti Massimo Malabotta Japanese Hiromi Kimura Latvian Jānis Eisaks Lithuanian Darius Matuliauskas Vilius Šumskas Norwegian Nynorsk Per-Stian Vatne Persian MetaNET Amirkabir Polish Mariusz Zynel Piotr Adamcio Tadeusz Lesiecki Piotr Tarnowski Krzysztof Kozera Maciej Uhlig Portuguese João César Marigonda Manuel Menezes de Sequeira Romanian Marius Dragulescu Eugen Hoanca Russian Illya Belov Slovak Ivan Noris Jozef Sudolský Slovenian Duck Spanish Manuel Perez Ayala Juan C. Blanco Swedish Mattias Webjörn Eriksson Turkish Middle East Technical University ===================== ====================================================== Inactive Developers =================== - Mathieu Clabaut - Chuck Hagenbuch - Eric Rostetter Special thanks ============== - Thanks to John Wedoff, who helped debug a session/login problem. - Thanks to Oliver Schultze (OSL) for help with bug fixes, documentation suggestions, and moral support. - Thanks to Tero Tapani Matinlassi for pointing out my bad coding when I rushed the realm changes into effect, and even providing the solution! - Thanks to Tjeerd van der Zee and Mattias Webjörn Eriksson for all their help and patience coding the LDAP support. - Thanks to Amith Varghese for various contributions including the LDAP binddn hook. passwd-5.0.4/docs/INSTALL0000664000076500000240000002671112611577414011741 0ustar ====================== Installing Passwd H5 ====================== :Contact: horde@lists.horde.org .. contents:: Contents .. section-numbering:: This document contains instructions for installing the Passwd Password Changing application on your system. For information on the capabilities and features of Passwd, see the file README_. Prerequisites ============= To function properly, Passwd **requires** the following: 1. A working Horde installation. Passwd runs within the `Horde Application Framework`_, a set of common tools for web applications written in PHP. You must install Horde before installing Passwd. .. Important:: Passwd H5 requires version 5.0+ of the Horde Framework - earlier versions of Horde will **not** work. .. Important:: Be sure to have completed all of the steps in the `horde/docs/INSTALL`_ file for the Horde Framework before installing Passwd. Many of Passwd's prerequisites are also Horde prerequisites. Additionally, many of Passwd's optional features are configured via the Horde install. .. _`Horde Application Framework`: http://www.horde.org/apps/horde 2. The following PHP capabilities, depending on the drivers you want use: a. Character Type support ``--enable-ctype`` b. LDAP support ``--with-ldap`` [OPTIONAL] LDAP support is required for the kolab, ldap, and smbldap drivers. c. Hash support [OPTIONAL] Hash support is necessary for the smbldap driver. See `LDAP Implementation Information`_ for details. d. Mcrypt support ``--with-mcrypt`` [OPTIONAL] Mcrypt support is necessary for the smbldap driver. See `LDAP Implementation Information`_ for details. e. SOAP support ``--enable-soap`` [OPTIONAL] SOAP support is necessary for the soap driver. 3. The following PEAR modules: (See `horde/docs/INSTALL`_ for instructions on installing PEAR modules) .. Important:: If you are going to install Passwd the recommended way, i.e. using the PEAR installer, you can skip the remainder of this section. Installing Passwd through PEAR will automatically download and install all required PEAR modules. a. Crypt_CHAP [OPTIONAL] Passwd uses this package to encrypt passwords for the smbldap driver. The following items might be required, depending on the drivers you want to use: 1. A poppassd server installed, running, and working on a system. 2. An LDAP server installed, running, and working for authentication. 3. A working smbpasswd program on the web server. It can access a remote server, but the smbpasswd binary must be installed on the local system. 4. A working SQL authentication system. 5. Expect installed, and access to telnet or ssh to the machine where passwords are stored/set (could be localhost). 6. A SOAP service endpoint. Installing Passwd =================== The **RECOMMENDED** way to install Passwd is using the PEAR installer. Alternatively, if you want to run the latest development code or get the latest not yet released fixes, you can install Passwd from Git. Installing with PEAR ~~~~~~~~~~~~~~~~~~~~ First follow the instructions in `horde/docs/INSTALL`_ to prepare a PEAR environment for Horde and install the Horde Framework. When installing Passwd through PEAR now, the installer will automatically install any dependencies of Passwd too. If you want to install Passwd with all optional dependencies, but without the binary PECL packages that need to be compiled, specify both the ``-a`` and the ``-B`` flag:: pear install -a -B horde/passwd By default, only the required dependencies will be installed:: pear install horde/passwd If you want to install Passwd even with all binary dependencies, you need to remove the ``-B`` flag. Please note that this might also try to install PHP extensions through PECL that might need further configuration or activation in your PHP configuration:: pear install -a horde/passwd Installing from Git ~~~~~~~~~~~~~~~~~~~ See http://www.horde.org/source/git.php Configuring Passwd ==================== 1. Configuring Passwd You must login to Horde as a Horde Administrator to finish the configuration of Passwd. Use the Horde ``Administration`` menu item to get to the administration page, and then click on the ``Configuration`` icon to get the configuration page. Select ``Password`` from the selection list of applications. Fill in or change any configuration values as needed. When done click on ``Generate Password Configuration`` to generate the ``conf.php`` file. If your web server doesn't have write permissions to the Passwd configuration directory or file, it will not be able to write the file. In this case, go back to ``Configuration`` and choose one of the other methods to create the configuration file ``passwd/config/conf.php``. Documentation on the format and purpose of the other configuration files in the ``config/`` directory can be found in each file. You may create ``*.local.php`` versions of these files if you wish to customize Passwd's appearance and behavior. See the header of the configuration files for details and examples. The defaults will be correct for most sites. 2. Testing Passwd Once you have configured Passwd, bring up the included test page in your Web browser to ensure that all necessary prerequisites have been met. See the `horde/docs/INSTALL`_ document for further details on Horde test scripts. If you installed Passwd as described above, the URL to the test page would be:: http://your-server/horde/test.php?app=passwd Security considerations ======================= .. Note:: Some drivers like poppassd always use clear text password transmissions. Others may also use clear text passwords (e.g. the expect script driver using telnet rather than ssh). This can be considered somewhat safe if the server is on the same machine, there are no user interactive logins allowed on that machine, and the connection uses the loopback (localhost) interface. It is up to the administrator to evaluate the security implications of using this module, and to understand the security implications of how their server and this module is configured. .. Note:: Setting this module to allow guest access might also be considered a security risk. By default, guest access is disabled. It is up to the administrator to evaluate the security implications of using this module with guest access if they choose to do so. Poppassd Server Software ======================== The following are some links that users have submitted. No warrenty is made for the following links or any software obtained from then. These are all user submitted links, and have not been tested or verified. Use these links are your own risk! * http://www.ceti.com.pl/~kravietz/prog.html * http://www.samera.net/rpm/ * http://netwinsite.com/poppassd/ * http://echelon.pl/pubs/poppassd-1.8.1.tar.gz LDAP Implementation Information =============================== The module includes support for changing LDAP stored passwords. LDAP can store passwords in multiple ways, namely: a. Plain text passwords b. SHA encrypted passwords c. SSHA encrypted passwords d. Crypt encrypted passwords e. MD5 encrypted passwords (using base64 encoding - md5-base64) f. SMD5 encrypted passwords The smbldap extension require the php hash and mcrypt extensions. To enable these you must compile php with ``--with-mcrypt[=DIR]`` and **without** the ``--disable-hash`` parameters. ``DIR`` is the mcrypt install directory. Crypt cannot handle passwords longer than eight characters (it accepts them but truncates them at 8 characters). If you want to use longer passwords, you may use SHA. The user must be able to authenticate to the LDAP directory and change his own password now (we no longer do root access to LDAP). This assumes that the LDAP administrator has allowed everyone to write their own password, something like:: access to attribute=userPassword by self write by anonymous auth by * none SQL Implementation Information ============================== The module includes support for changing passwords stored in a SQL database. The SQL driver is similar to the LDAP driver except that it also supports MD5 encryption using hex encoding (md5-hex). If you created your passwords using the PHP md5() function then use md5-hex. Smbpasswd Implementation Information ==================================== To use this module, you must pass the address of your Samba domain controller on which to change the password. This can be "localhost" for the server that Horde runs on. The remote system name may be passed as the NETBIOS name, the DNS name, or the IP address of the SMB/CIFS server to connect to. The username is run through ``escapeshellcmd()``, so any usernames with strange characters ($, &, etc) may not work. I'm not sure if any of these are even valid for SMB/CIFS authentication, but if so, they may not work in this module. .. Note:: If changing a Windows NT Domain password the remote machine specified must be the Primary Domain Controller for the domain (Backup Domain Controllers only have a read-only copy of the user account database and will not allow the password change). Since smbpasswd works in client-server mode communicating with a local smbd for a non-root user, the smbd daemon must be running for this to work. A common problem is to add a restriction to the hosts that may access the smbd running on the local machine by specifying a allow hosts or deny hosts entry in the ``smb.conf`` file and neglecting to allow "localhost" access to the smbd. In addition, the smbpasswd command is only useful if Samba has been set up to use encrypted passwords. Expect Script Information ========================= This code allows users to change their passwords via an expect script. The module requires the expect program and a telnet or ssh program. You may need to change some of the expect patterns in ``passwd-expect`` such as the ``badpassword_string`` or ``success_string`` (as only two examples). For security reasons, it is generally suggested to use ssh rather than telnet for the transport, if possible. Expect PECL Information ======================= This code allows users to change their passwords via the PHP PECL expect extension. It requires the PECL expect extension and a ssh program. You can find the extension on http://pecl.php.net/package/expect Obtaining Support ================= If you encounter problems with Passwd, help is available! The Horde Frequently Asked Questions List (FAQ), available on the Web at http://wiki.horde.org/FAQ The Horde Project runs a number of mailing lists, for individual applications and for issues relating to the project as a whole. Information, archives, and subscription information can be found at http://www.horde.org/community/mail Lastly, Horde developers, contributors and users may also be found on IRC, on the channel #horde on the Freenode Network (irc.freenode.net). Please keep in mind that Passwd is free software written by volunteers. For information on reasonable support expectations, please read http://www.horde.org/community/support Thanks for using Passwd! The Passwd team .. _README: README .. _`horde/docs/INSTALL`: ../../horde/docs/INSTALL .. _`horde/docs/TRANSLATIONS`: ../../horde/docs/TRANSLATIONS passwd-5.0.4/docs/RELEASE_NOTES0000664000076500000240000000140212611577414012651 0ustar Configuration and update anything that's highlighted as outdated. Upgrading to Passwd 5.0.2 ========================= Hooks Configuration (hooks.php) ------------------------------- The 'userdn' hook has been re-added. Upgrading to Passwd 5.0 ======================= NOTE: If changing a password that is currently being used to authenticate to Horde, you CANNOT continue to use Horde after changing the authentication password. Instead, you MUST configure backends.local.php to logout of Horde after a successful password change (see the logout parameter in ``config/backends.php``). The old authentication credentials may be cached in various Horde applications, and there is no way to clear this cache unless the session is destroyed. Backend Configuration (backends.php) ------------------------------------ The following options have been added:: logout The following options have been removed:: no_reset Hooks Configuration (hooks.php) ------------------------------- The 'default_username' hook no longer receives a $user parameter. The 'userdn' hook has been removed. It can now be configured using the 'userdn' parameter in the LDAP driver configuration. Upgrading to Passwd 4.0 ======================= Backend Configuration (backends.php) ------------------------------------ The 'password policy' setting in backends.php has been renamed to 'policy'. Upgrading to Passwd 3.1 ======================= Application Hooks ----------------- All hooks that are specific to Passwd have been moved from the ``horde/config/hooks.php`` file. Move your existing Passwd Hooks from there to ``passwd/config/hooks.php``. New Hook Parameters ------------------- The _passwd_hook_username hook is now passed an additional parameter, the Passwd_Driver_* object for the backend that you are changing the password on. This allows Passwd to support users being able to change passwords on multiple backends even when the different backends may have different requirements for the username (such as one requiring'user@example.com' while another only requiring 'user'). Additionally, the Passwd_Driver_composite driver also supports this functionality by checking for the existence of a parameter called 'be_username' in each of it's sub-drivers. If this parameter is present, its value overrides any other value of $userid it is passed. If you wish to use this functionality of the composite driver, look at the example _passwd_hook_username function in horde/config/hooks.php.dist. .. _INSTALL: INSTALL passwd-5.0.4/js/passwd.js0000664000076500000240000000210612611577414012223 0ustar /** * Provides javascript support for the main passwd page. * * See the enclosed file COPYING for license information (GPL). If you * did not receive this file, see http://www.horde.org/licenses/gpl. */ document.observe('dom:loaded', function() { $('passwd-submit').observe('click', function(e) { if (!$F('passwd-oldpassword')) { alert(Passwd.current_pass); $('passwd-oldpassword').focus(); e.stop(); return; } if (!$F('passwd-newpassword0')) { alert(Passwd.new_pass); $('passwd-newpassword0').focus(); e.stop(); return; } if (!$F('passwd-newpassword1')) { alert(Passwd.verify_pass); $('passwd-newpassword1').focus(); e.stop(); return; } if ($F('passwd-newpassword0') != $F('passwd-newpassword1')) { alert(Passwd.no_match); $('passwd-newpassword0').focus(); e.stop(); return; } }); $('passwd').focusFirstElement(); }); passwd-5.0.4/lib/Driver/Adsi.php0000664000076500000240000000414412611577414013346 0ustar * $backends['adsi'] = array( * 'name' => 'Sample ADSI backend', * 'preferred' => 'localhost', * 'policy' => array( * 'minLength' => 8, * 'maxLength' => 14 * ), * 'driver' => 'adsi', * 'params' => array( * 'target' => 'YOUR_MACHINE/DOMAIN_NAME_HERE' * ) * ) * * * Backend parameters: * target = Target Windows machine/domain name (Required) * * @author Luiz R Malheiros * @category Horde * @copyright 2004-2015 Horde LLC * @license http://www.horde.org/licenses/gpl GPL * @package Passwd */ class Passwd_Driver_Adsi extends Passwd_Driver { /** */ protected function _changePassword($user, $oldpass, $newpass) { if (empty($this->_params['target'])) { throw new Passwd_Exception(_("Password module is missing target parameter.")); } $root = new COM('WinNT:'); $adsi = $root->OpenDSObject( 'WinNT://' . $this->_params['target'] . '/' . $user . ',user', $this->_params['target'] . '\\' . $user, $oldpass, 1 ); if (!$adsi) { throw new Passwd_Exception(_("Access Denied.")); } if ($result = $adsi->ChangePassword($oldpass, $newpass)) { throw new Passwd_Exception(sprintf(_("ADSI error %s."), $result)); } } } passwd-5.0.4/lib/Driver/Composite.php0000664000076500000240000000500312611577414014423 0ustar * @category Horde * @copyright 2003-2015 Horde LLC * @license http://www.horde.org/licenses/gpl GPL * @package Passwd */ class Passwd_Driver_Composite extends Passwd_Driver { /** * Hash of instantiated drivers. * * @var array */ protected $_drivers = null; /** * @param array $params Driver parameters: * - drivers: (array) Array of Passwd_Driver objects. * * @throws Passwd_Exception */ public function __construct(array $params = array()) { if (!isset($params['drivers']) || !is_array($params['drivers'])) { throw new Passwd_Exception(_("Required 'drivers' is misconfigured in Composite configuration.")); } parent::__construct($params); } /** * Instantiate configured drivers. */ protected function _loadDrivers() { if (!is_null($this->_drivers)) { return; } $driver = $GLOBALS['injector']->getInstance('Passwd_Factory_Driver'); foreach ($this->_params['drivers'] as $key => $val) { if (!isset($this->_drivers[$key])) { try { $res = $driver->create($key, array_merge($val, array( 'is_subdriver' => true ))); } catch (Passwd_Exception $e) { throw new Passwd_Exception(sprintf(_("%s: unable to load sub driver: %s"), $key, $e->getMessage())); } $this->_drivers[$key] = $res; } } } /** */ protected function _changePassword($user, $oldpass, $newpass) { $this->_loadDrivers(); foreach ($this->_drivers as $key => $driver) { try { $driver->changePassword($user, $oldpass, $newpass); } catch (Passwd_Exception $e) { throw new Passwd_Exception(sprintf(_("Failure in changing password for %s: %s"), $this->_params['drivers'][$key]['name'], $e->getMessage())); } } } } passwd-5.0.4/lib/Driver/Expect.php0000664000076500000240000000320612611577414013714 0ustar * @category Horde * @copyright 2000-2015 Horde LLC * @license http://www.horde.org/licenses/gpl GPL * @package Passwd */ class Passwd_Driver_Expect extends Passwd_Driver { /** */ protected function _changePassword($user, $oldpass, $newpass) { // Sanity checks. if (!@is_executable($this->_params['program'])) { throw new Passwd_Exception(sprintf(_("%s does not exist or is not executable."), $this->_params['program'])); } // Temporary logfile for error messages. $log = Horde::getTempFile('passwd'); // Open expect script for writing. $prog = 'LANG=C LC_ALL=C ' . $this->_params['program'] . ' -f ' . escapeshellarg($this->_params['script']) . ' -- ' . $this->_params['params'] . ' -log ' . escapeshellarg($log); $exp = @popen($prog, 'w'); @fwrite($exp, $user . "\n"); @fwrite($exp, $oldpass . "\n"); @fwrite($exp, $newpass . "\n"); if (@pclose($exp)) { $errormsg = implode(' ', @file($log)); @unlink($log); if ($errormsg) { throw new Passwd_Exception($errormsg); } } } } passwd-5.0.4/lib/Driver/Expectpecl.php0000664000076500000240000000740512611577414014565 0ustar * @category Horde * @copyright 2006-2015 Horde LLC * @license http://www.horde.org/licenses/gpl GPL * @package Passwd */ class Passwd_Driver_Expectpecl extends Passwd_Driver { /** * Expect connection handle. * * @var resource */ protected $_stream; /** * Handles expect communication. * * @param string $expect String to expect. * @param string $error Error message. * * @throws Passwd_Exception */ protected function _ctl($expect, $error) { $result = expect_expectl($this->_stream, array( array( 0 => $expect, 1 => 'ok', 2 => EXP_REGEXP ) )); switch ($result) { case EXP_EOF: throw new Passwd_Exception(_("End of file.")); case EXP_TIMEOUT: throw new Passwd_Exception(_("Time out.")); case EXP_FULLBUFFER: throw new Passwd_Exception(_("Full buffer.")); case 'ok': return; default: throw new Passwd_Exception($error); } } /** */ protected function _changePassword($user, $oldpass, $newpass) { if (!Horde_Util::loadExtension('expect')) { throw new Passwd_Exception(_("expect extension cannot be loaded")); } // Set up parameters foreach (array('logfile', 'loguser', 'timeout') as $val) { if (isset($this->_params[$val])) { ini_set('expect.' . $val, $this->_params[$val]); } } // Open connection $call = sprintf( 'ssh %s@%s %s', $user, $this->_params['host'], $this->_params['program'] ); if (!($this->_stream = expect_popen($call))) { throw new Passwd_Exception(_("Unable to open expect stream")); } // Log in $this->_ctl( '(P|p)assword.*', _("Could not login to system (no password prompt)") ); // Send login password fwrite($this->_stream, $oldpass . "\n"); // Expect old password prompt $this->_ctl( '((O|o)ld|login|current).* (P|p)assword.*', _("Could not start passwd program (no old password prompt)") ); // Send old password fwrite($this->_stream, $oldpass . "\n"); // Expect new password prompt $this->_ctl( '(N|n)ew.* (P|p)assword.*', _("Could not change password (bad old password?)") ); // Send new password fwrite($this->_stream, $newpass . "\n"); // Expect reenter password prompt $this->_ctl( "((R|r)e-*enter.*(P|p)assword|Retype new( UNIX)? password|(V|v)erification|(V|v)erify|(A|a)gain).*", _("New password not valid (too short, bad password, too similar, ...)") ); // Send new password fwrite($this->_stream, $newpass . "\n"); // Expect successfully message $this->_ctl( '((P|p)assword.* changed|successfully)', _("Could not change password.") ); } } passwd-5.0.4/lib/Driver/Horde.php0000664000076500000240000000311412611577414013523 0ustar * @category Horde * @copyright 2011-2015 Horde LLC * @license http://www.horde.org/licenses/gpl GPL * @package Passwd */ class Passwd_Driver_Horde extends Passwd_Driver { /** */ protected function _changePassword($user, $oldpass, $newpass) { $auth = $this->_params['auth']; if (!$auth->hasCapability('update')) { throw new Passwd_Exception(_("The current horde configuration does not allow changing passwords.")); } /* Check the provided old password. */ try { if ($auth->authenticate($user, array('password' => $oldpass, false))) { /* Actually modify the password. */ $auth->updateUser($user, $user, array( 'password' => $newpass )); } else { throw new Passwd_Exception(_("Incorrect old password.")); } } catch (Horde_Auth_Exception $e) { throw new Passwd_Exception($e); } } } passwd-5.0.4/lib/Driver/Http.php0000664000076500000240000000452012611577414013403 0ustar * @author Michael Slusarz * @category Horde * @copyright 2000-2015 Horde LLC * @license http://www.horde.org/licenses/gpl GPL * @package Passwd */ class Passwd_Driver_Http extends Passwd_Driver { /** */ protected function _changePassword($user, $oldpass, $newpass) { // Add the required fields that most web-based forms would use. // Then add any fields that were passed in _params['fields']. $post_data = array_merge(array( $this->_params['username'] => $user, $this->_params['oldPasswd'] => $oldpass, $this->_params['passwd1'] => $newpass, $this->_params['passwd2'] => $newpass ), $this->_params['fields']); // Send the request try { $response = $GLOBALS['injector']->getInstance('Horde_Core_Factory_HttpClient')->create()->post($this->_params['url'], $post_data); } catch (Horde_Http_Exception $e) { throw new Passwd_Exception($e); } // Make sure we have a good response code if ($response->code != 200) { throw new Passwd_Exception(_("The requested website for changing user passwords could not be reached.")); } // We got *some* response from the server, so get the content and // let's see if we can't figure out if it was a success or not. $body = $response->getBody(); if (strpos($body, $this->_params['eval_results']['badPass'])) { throw new Passwd_Exception(_("Incorrect old password.")); } if (strpos($body, $this->_params['eval_results']['badUser'])) { throw new Passwd_Exception(_("The username could not be found.")); } if (!strpos($body, $this->_params['eval_results']['success'])) { throw new Passwd_Exception(_("Your password could not be changed.")); } } } passwd-5.0.4/lib/Driver/Kolab.php0000664000076500000240000000524212611577414013516 0ustar * @category Horde * @copyright 2005-2015 Horde LLC * @license http://www.horde.org/licenses/gpl GPL * @package Passwd */ class Passwd_Driver_Kolab extends Passwd_Driver { /** */ protected function _changePassword($user, $oldpass, $newpass) { global $conf; // Connect to the LDAP server. $ds = ldap_connect( $conf['kolab']['ldap']['server'], $conf['kolab']['ldap']['port'] ); if (!$ds) { throw new Passwd_Exception(_("Could not connect to LDAP server")); } ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3); // Bind anonymously, or use the phpdn user if available. if (!empty($conf['kolab']['ldap']['phpdn'])) { $phpdn = $conf['kolab']['ldap']['phpdn']; $phppw = $conf['kolab']['ldap']['phppw']; $result = @ldap_bind($ds, $phpdn, $phppw); } else { $result = @ldap_bind($ds); } if (!$result) { throw new Passwd_Exception(_("Could not bind to LDAP server")); } // Make sure we're using the full user@domain format. if (strstr($user, '@') === false) { $user .= '@' . $conf['kolab']['imap']['maildomain']; } // Find the user's DN. $result = ldap_search( $ds, $conf['kolab']['ldap']['basedn'], 'mail=' . $user ); $entry = ldap_first_entry($ds, $result); if ($entry === false) { throw new Passwd_Exception(_("User not found.")); } $userdn = ldap_get_dn($ds, $entry); // Connect as the user. $result = @ldap_bind($ds, $userdn, $oldpass); if (!$result) { throw new Passwd_Exception(_("Incorrect old password.")); } // And finally change the password. $new_details['userPassword'] = '{sha}' . base64_encode(pack('H*', sha1($newpass))); if (!ldap_mod_replace($ds, $userdn, $new_details)) { throw new Passwd_Exception(ldap_error($ds)); } ldap_unbind($ds); } } passwd-5.0.4/lib/Driver/Ldap.php0000664000076500000240000001340112611577414013342 0ustar * @author Mattias Webjörn Eriksson * @author Ralf Lang * @author Eric Jon Rostetter * @author Jan Schneider * @author Tjeerd van der Zee * @category Horde * @copyright 2000-2015 Horde LLC * @license http://www.horde.org/licenses/gpl GPL * @package Passwd */ class Passwd_Driver_Ldap extends Passwd_Driver { /** * LDAP object. * * @var resource */ protected $_ldap = false; /** * The user's DN. * * @var string */ protected $_userdn; /** */ public function __construct(array $params = array()) { foreach (array('basedn', 'ldap', 'uid') as $val) { if (!isset($params[$val])) { throw new InvalidArgumentException(__CLASS__ . ': Missing ' . $val . ' parameter.'); } } $this->_ldap = $params['ldap']; unset($params['ldap']); parent::__construct(array_merge(array( 'host' => 'localhost', 'port' => 389, 'encryption' => 'crypt', 'show_encryption' => 'true', 'uid' => 'uid', 'basedn' => '', 'admindn' => '', 'adminpw' => '', 'realm' => '', 'filter' => null, 'tls' => false, 'attribute' => 'userPassword', 'shadowlastchange' => '', 'shadowmin' => '' ), $params)); if (!empty($this->_params['tls']) && empty($this->_params['sslhost'])) { $this->_params['sslhost'] = $this->_params['host']; } } /** * Compares a plaintext password with an encrypted password. * * @param string $encrypted An encrypted password. * @param string $plaintext An unencrypted password. * * @throws Passwd_Exception if passwords don't match. */ protected function _comparePasswords($encrypted, $plaintext) { $encrypted = preg_replace('/^{MD5}(.*)/i', '{MD5-BASE64}$1', $encrypted); return parent::_comparePasswords($encrypted, $plaintext); } /** */ protected function _changePassword($user, $oldpass, $newpass) { global $injector; // Append realm as username@realm if 'realm' parameter is set. if (!empty($this->_params['realm'])) { $user .= '@' . $this->_params['realm']; } // Try to get the user's dn from config. if (isset($this->_params['userdn'])) { $this->_userdn = str_replace('%u', $user, $this->_params['userdn']); } else { try { $this->_userdn = $injector->getInstance('Horde_Core_Hooks')->callHook( 'userdn', 'passwd', array($user) ); } catch (Horde_Exception_HookNotSet $e) { // @todo Fix finding the user DN. // $this->_userdn = $this->_ldap->findUserDN($user); $this->_userdn = $this->_params['uid'] . '=' . $user . ',' . $this->_params['basedn']; } } try { // Check the old password by binding as the userdn. $this->_ldap->bind($this->_userdn, $oldpass); } catch (Horde_Ldap_Exception $e) { throw new Passwd_Exception($e); } // Rebind with admin credentials. if (!empty($this->_params['admindn'])) { try { $this->_ldap->bind(); } catch (Horde_Ldap_Exception $e) { throw new Passwd_Exception($e); } } // Get existing user information. try { if (!($entry = $this->_ldap->getEntry($this->_userdn))) { throw new Passwd_Exception(_("User not found.")); } } catch (Horde_Ldap_Exception $e) { throw new Passwd_Exception($e); } // Init the shadow policy array. $lookupshadow = array( 'shadowlastchange' => false, 'shadowmin' => false ); foreach (array_keys($lookupshadow) as $val) { if (!empty($this->_params[$val]) && $entry->exists($this->_params[$val])) { $lookupshadow[$val] = $entry->getValue($this->_params[$val]); } } // Check if we may change the password. if ($lookupshadow['shadowlastchange'] && $lookupshadow['shadowmin'] && (($lookupshadow['shadowlastchange'] + $lookupshadow['shadowmin']) > (time() / 86400))) { throw new Passwd_Exception(_("Minimum password age has not yet expired")); } // Change the user's password and update lastchange. try { $entry->replace(array( $this->_params['attribute'] => $this->_encryptPassword($newpass) ), true); if (!empty($this->_params['shadowlastchange']) && $lookupshadow['shadowlastchange']) { $entry->replace(array( $this->_params['shadowlastchange'] => floor(time() / 86400) )); } $entry->update(); } catch (Horde_Ldap_Exception $e) { throw new Passwd_Exception($e); } } } passwd-5.0.4/lib/Driver/Null.php0000664000076500000240000000126712611577414013403 0ustar * @category Horde * @copyright 2013-2015 Horde LLC * @license http://www.horde.org/licenses/gpl GPL * @package Passwd */ class Passwd_Driver_Null extends Passwd_Driver { /** */ protected function _changePassword($user, $oldpass, $newpass) { } } passwd-5.0.4/lib/Driver/Pine.php0000664000076500000240000002025512611577414013362 0ustar * @category Horde * @copyright 2003-2015 Horde LLC * @license http://www.horde.org/licenses/gpl GPL * @package Passwd */ class Passwd_Driver_Pine extends Passwd_Driver { /** Lower boundary character. */ const FIRSTCH = 0x20; /** Upper boundary character. */ const LASTCH = 0x7e; /** Median character. */ const TABSZ = 0x5f; /** * Boolean which contains state of the ftp connection. * * @var boolean */ protected $_connected = false; /** * Contents array of the pine password file. * * @var array */ protected $_contents = array(); /** * Horde_Vfs instance. * * @var VFS */ protected $_ftp; /** */ public function __construct(array $params = array()) { self::__construct(array_merge(array( /* We self-encrypt here, so plaintext is needed. */ 'encryption' => 'plain', 'show_encryption' => false, /* Sensible FTP server parameters. */ 'host' => 'localhost', 'port' => 21, 'path' => '', 'file' => '.pinepw', /* Connect to FTP server using just-passed-in credentials? * Only useful if using the composite driver and changing * system (FTP) password prior to this one. */ 'use_new_passwd' => false, /* What host to look for on each line? */ 'imaphost' => 'localhost' ), $params)); } /** * Connects to the FTP server. * * @throws Passwd_Exception */ protected function _connect($user, $password) { if ($this->_connected) { return; } $params = array( 'username' => $user, 'password' => $password, 'hostspec' => $this->_params['host'], 'port' => $this->_params['port'], ); try { $this->_ftp = Horde_Vfs::factory('ftp', $params); $this->_ftp->checkCredentials(); } catch (Horde_Vfs_Exception $e) { throw new Passwd_Exception($e); } $this->_connected = true; } /** * Disconnect from the FTP server. * * @throws Passwd_Exception */ protected function _disconnect() { if ($this->_connected) { try { $this->_ftp->disconnect(); } catch (Horde_Vfs_Exception $e) { throw new Passwd_Exception($e); } $this->_connected = false; } } /** * Decodes a Pine-encoded password string. * * The algorithm is borrowed from read_passfile() and xlate_out() * functions in pine/imap.c file distributed in the Pine source archive. * * @param string $string The contents of a pine-encoded password file. * * @return array List of lines of decoded elements. */ protected function _decode($string) { $list = array(); $lines = explode("\n", $string); for ($n = 0; $n < sizeof($lines); $n++) { $key = $n; $tmp = $lines[$n]; for ($i = 0; $i < strlen($tmp); $i++) { if ((ord($tmp[$i]) >= self::FIRSTCH) && (ord($tmp[$i]) <= self::LASTCH)) { $xch = ord($tmp[$i]) - ($dti = $key); $xch += ($xch < self::FIRSTCH - self::TABSZ) ? 2 * self::TABSZ : ($xch < self::FIRSTCH) ? self::TABSZ : 0; $dti = ($xch - self::FIRSTCH) + $dti; $dti -= ($dti >= 2 * self::TABSZ) ? 2 * self::TABSZ : ($dti >= self::TABSZ) ? self::TABSZ : 0; $key = $dti; $tmp[$i] = chr($xch); } } if ($i && $tmp[$i - 1] == "\n") { $tmp = substr($tmp, 0, -1); } $parts = explode("\t", $tmp); if (count($parts) >= 4) { $list[] = $parts; } } return $list; } /** * Encodes an array of elements into a Pine-readable password string. * * The algorithm is borrowed from write_passfile() and xlate_in() * functions in pine/imap.c file distributed in the Pine source archive. * * @param array $lines List of lines of decoded elements. * * @return array Contents of a pine-readable password file. */ protected function _encode($lines) { $string = ''; for ($n = 0; $n < sizeof($lines); $n++) { if (isset($lines[$n][4])) { $lines[$n][4] = "\t" . $lines[$n][4]; } else { $lines[$n][4] = ''; } $key = $n; $tmp = vsprintf("%.100s\t%.100s\t%.100s\t%d%s\n", $lines[$n]); for ($i = 0; $i < strlen($tmp); $i++) { $eti = $key; if ((ord($tmp[$i]) >= self::FIRSTCH) && (ord($tmp[$i]) <= self::LASTCH)) { $eti += ord($tmp[$i]) - self::FIRSTCH; $eti -= ($eti >= 2 * self::TABSZ) ? 2 * self::TABSZ : ($eti >= self::TABSZ) ? self::TABSZ : 0; $key = $eti; $tmp[$i] = chr($eti + self::FIRSTCH); } } $string .= $tmp; } return $string; } /** * Finds out if a username and password is valid. * * @param string $user The userID to check. * @param string $oldPassword An old password to check. * * @throws Passwd_Exception */ protected function _lookup($user, $oldPassword) { try { $contents = $this->_ftp->read($this->_params['path'], $this->_params['file']); } catch (Horde_Vfs_Exception $e) { throw new Passwd_Exception($e); } $this->_contents = $this->_decode($contents); foreach ($this->_contents as $line) { if ($line[1] == $user && (($line[2] == $this->_params['imaphost']) || (!empty($line[4]) && $line[4] == $this->_params['imaphost']))) { $this->_comparePasswords($line[0], $oldPassword); return; } } throw new Passwd_Exception(_("User not found.")); } /** * Modifies a pine password record for a user. * * @param string $user The user whose record we will udpate. * @param string $newPassword The new password value to set. * * @throws Passwd_Exception */ protected function _modify($user, $newPassword) { for ($i = 0; $i < sizeof($this->_contents); $i++) { if ($this->_contents[$i][1] == $user && (($this->_contents[$i][2] == $this->_params['imaphost']) || (!empty($this->_contents[$i][4]) && $this->_contents[$i][4] == $this->_params['imaphost']))) { $this->_contents[$i][0] = $newPassword; } } $string = $this->_encode($this->_contents); try { $this->_ftp->writeData($this->_params['path'], $this->_params['file'], $string); } catch (Horde_Vfs_Exception $e) { throw new Passwd_Exception($e); } } /** */ protected function _changePassword($user, $oldpass, $newpass) { /* Connect to the ftp server. */ $this->_connect($user, $this->_params['use_new_passwd'] ? $newpass : $oldpass); $this->_lookup($user, $oldpass); $this->_modify($user, $newpass); $this->_disconnect(); } } passwd-5.0.4/lib/Driver/Poppassd.php0000664000076500000240000000635412611577414014264 0ustar * @category Horde * @copyright 2000-2015 Horde LLC * @license http://www.horde.org/licenses/gpl GPL * @package Passwd */ class Passwd_Driver_Poppassd extends Passwd_Driver { /** */ public function __construct(array $params = array()) { parent::__construct(array_merge(array( 'host' => 'localhost', 'port' => 106 ), $params)); } /** * Connects to the server. * * @throws Passwd_Exception */ protected function _connect() { $this->_fp = fsockopen( $this->_params['host'], $this->_params['port'], $errno, $errstr, 30 ); if (!$this->_fp) { throw new Passwd_Exception($errstr); } $this->_getPrompt(); } /** * Disconnects from the server. */ protected function _disconnect() { if (isset($this->_fp)) { fputs($this->_fp, "quit\n"); fclose($this->_fp); } } /** * Parses a response from the server to see what it was. * * @throws Passwd_Exception */ protected function _getPrompt() { if (!($prompt = fgets($this->_fp, 4096))) { throw new Passwd_Exception(_("No prompt returned from server.")); } if (!preg_match('/^[1-5][0-9][0-9]/', $prompt)) { throw new Passwd_Exception($prompt); } /* This should probably be a regex match for 2?0 or 3?0, no? */ $rc = substr($prompt, 0, 3); if (!in_array($rc, array('200', '220', '250', '300'))) { throw new Passwd_Exception($prompt); } } /** * Sends a command to the server. * * @throws Passwd_Exception */ protected function _sendCommand($cmd, $arg) { $line = $cmd . ' ' . $arg . "\n"; if (!($res_fputs = fputs($this->_fp, $line))) { throw new Passwd_Exception(_("Cannot send command to server.")); } $this->_getPrompt(); } /** */ protected function _changePassword($user, $oldpass, $newpass) { $this->_connect(); try { $this->_sendCommand('user', $user); } catch (Passwd_Exception $e) { $this->_disconnect(); throw new Passwd_Exception(_("User not found") . ': ' . $e->getMessage()); } try { $this->_sendCommand('pass', $oldpass); } catch (Passwd_Exception $e) { $this->_disconnect(); throw new Passwd_Exception(_("Incorrect old password.") . ': ' . $e->getMessage()); } try { $this->_sendCommand('newpass', $newpass); } catch (Passwd_Exception $e) { $this->_disconnect(); throw $e; } } } passwd-5.0.4/lib/Driver/Procopen.php0000664000076500000240000000400212611577414014244 0ustar * @category Horde * @copyright 2004-2015 Horde LLC * @license http://www.horde.org/licenses/gpl GPL * @package Passwd */ class Passwd_Driver_Procopen extends Passwd_Driver { /** */ protected function _changePassword($user, $oldpass, $newpass) { $descr = array( 0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w') ); $output = ''; $process = @proc_open($this->_params['program'], $descr, $pipes); if (is_resource($process)) { fwrite($pipes[0], "$user\n"); fwrite($pipes[0], "$oldpass\n"); fwrite($pipes[0], "$newpass\n"); fclose($pipes[0]); while (!feof($pipes[1])) { $output .= fgets($pipes[1], 1024); } fclose($pipes[1]); while (!feof($pipes[2])) { $output .= fgets($pipes[2], 1024); } fclose($pipes[2]); $return_value = proc_close($process); } else { $return_value = -1; } $output .= " (Exit Status: $return_value)"; if ($return_value != 0) { throw new Passwd_Exception($output); } } } passwd-5.0.4/lib/Driver/Pspasswd.php0000664000076500000240000001024212611577414014266 0ustar * $backends['pspasswd'] = array( * 'name' => 'Sample pspasswd backend', * 'preferred' => 'localhost', * 'policy' => array( * 'minLength' => 8, * 'maxLength' => 14 * ), * 'driver' => 'pspasswd', * 'params' => array( * 'server' => 'YOUR_SERVER_NAME', * 'bin' => 'DRIVE:\\DIR\\pspasswd.exe', // Notice: "\\" * 'admusr' => 'Administrator', * 'admpwd' => 'Password', * 'domain' => 'YOUR_DOMAIN_NAME' * ) * ); * * * Backend parameters:
 * server	= Machine where you want to change the password (Required)
 * bin		= Full pathname of the pspasswd.exe program (Required)
 * admusr	= User with administrative privileges (Required)
 * admpwd	= Password of the administrative user (Required)
 * domain	= Windows domain name (Optional)
 * 
* * For example: Passing a NT4 PDC server name to the server parameter * means you can change the user's password on that NT4 Domain. * * Special thanks to Mark Russinovich (mark@sysinternals.com) for the * tool and helping me solve some questions about it. * * @author Luiz R Malheiros (malheiros@gmail.com) * @category Horde * @copyright 2000-2015 Horde LLC * @license http://www.horde.org/licenses/gpl GPL * @package Passwd */ class Passwd_Driver_Pspasswd extends Passwd_Driver { /** */ public function __construct(array $params = array()) { if (empty($params['server']) || empty($params['bin']) || empty($params['admusr']) || empty($params['admpwd'])) { throw new Passwd_Exception(_("Password module is missing required parameters.")); } if (!file_exists($params['bin'])) { throw new Passwd_Exception(_("Password module can't find the supplied bin.")); } parent::__construct($params); } /** */ protected function _changePassword($user, $oldpass, $newpass) { $server = $this->_params['server']; $chpwd_adm = $this->_params['admusr']; $chpwd_usr = $user; if (!empty($this->_params['domain'])) { $chpwd_adm = $this->_params['domain'] . "\\" . $chpwd_adm; $chpwd_usr = $this->_params['domain'] . "\\" . $chpwd_usr_name; } exec('NET USE \\\\' . $server . '\\IPC$ /D >NUL 2>NUL'); $cmdline = 'NET USE \\\\' . $server . '\\IPC$ "' . $oldpass . '" /USER:' . $chpwd_usr; exec($cmdline, $cmdreply, $retval); if (strpos(implode(' ', $cmdreply), 'The command completed successfully.') === false) { throw new Passwd_Exception(_("Failed to verify old password.")); } exec('NET USE \\\\' . $server . '\\IPC$ /D >NUL 2>NUL'); $cmdline = $this->_params['bin'] . ' \\\\' . $server . ' -u ' . $chpwd_adm . ' -p ' . $this->_params['admpwd'] . ' ' . $user. ' ' . $newpass; exec($cmdline, $cmdreply, $retval); exec('NET USE \\\\' . $server . '\\IPC$ /D >NUL 2>NUL'); if (strpos(implode(' ', $cmdreply), 'Password for ' . $server . '\\' . $user. ' successfully changed.') === false) { throw new Passwd_Exception(_("Access Denied.")); } } } passwd-5.0.4/lib/Driver/Servuftp.php0000664000076500000240000000607212611577414014306 0ustar 30 ), $params)); } /** */ protected function _changePassword($user, $oldpass, $newpass) { if ($this->_connect() != self::CONNECTED) { throw new Passwd_Exception(_("Connection failed")); } if ($this->_sendCommand('user', $user) != self::USERNAMEOK) { $this->_disconnect(); throw new Passwd_Exception(_("Unknown user")); } if ($this->_sendCommand('pass', $oldpass) != self::PASSWORDOK) { $this->_disconnect(); throw new Passwd_Exception(_("Incorrect password")); } if ($this->_sendCommand('site pswd', '"' . $oldpass. '" "' . $newpass. '"') != self::PASSWORDOK) { $this->_disconnect(); throw new Passwd_Exception(_("Cannot change password")); } $this->_disconnect(); } /** * @throws Passwd_Exception */ protected function _connect() { $this->_fp = fsockopen( $this->_params['host'], $this->_params['port'], $errno, $errstr, $this->_params['timeout'] ); if (!$this->_fp) { throw new Passwd_Exception($errstr); } return $this->_getPrompt(); } /** * @throws Passwd_Exception */ protected function _disconnect() { if ($this->_fp) { fputs($this->_fp, "quit\n"); fclose($this->_fp); } } /** * @throws Passwd_Exception */ protected function _getPrompt() { $prompt = fgets($this->_fp, 4096); if (preg_match('/^[1-5][0-9][0-9]/', $prompt, $res)) { return $res[1]; } } /** * @throws Passwd_Exception */ protected function _sendCommand($cmd, $arg) { $line = $cmd . ' ' . $arg . "\r\n"; fputs($this->_fp, $line); return $this->_getPrompt(); } } passwd-5.0.4/lib/Driver/Smbldap.php0000664000076500000240000000657312611577414014060 0ustar * @author Mike Cochrane * @author Mattias Webjörn Eriksson * @author Eric Jon Rostetter * @author Tjeerd van der Zee * @category Horde * @copyright 2004-2015 Horde LLC * @license http://www.horde.org/licenses/gpl GPL * @package Passwd */ class Passwd_Driver_Smbldap extends Passwd_Driver_Ldap { /** */ public function __construct(array $params = array()) { parent::__construct(array_merge(array( 'lm_attribute' => null, 'nt_attribute' => null, 'pw_set_attribute' => null, 'pw_expire_attribute' => null, 'pw_expire_time' => null, 'smb_objectclass' => 'sambaSamAccount' ), $params)); } /** */ protected function _changePassword($user, $oldpass, $newpass) { parent::_changePassword($user, $oldpass, $newpass); // Get existing user information. $entry = $this->_ldap->getEntry($this->_userdn); // Return if the user is not a Samba user. if (!in_array($this->_params['smb_objectclass'], $entry->getValue('objectClass', 'all'))) { return; } // Crypt_CHAP is not PSR-0 compatible. require_once 'Crypt/CHAP.php'; $hash = new Crypt_CHAP_MSv2(); $hash->password = $newpass; $lmpasswd = Horde_String::upper(bin2hex($hash->lmPasswordHash())); $ntpasswd = Horde_String::upper(bin2hex($hash->ntPasswordHash())); $settime = time(); if (!is_null($this->_params['pw_expire_time'])) { // 24 hours/day * 60 min/hour * 60 secs/min = 86400 seconds/day $expiretime = $settime + ($this->_params['pw_expire_time'] * 86400); } else { // This is NT's version of infinity time: // http://lists.samba.org/archive/samba/2004-January/078175.html $expiretime = 2147483647; } // All changes must succeed or fail together. Attributes with // null name are not updated. $changes = array(); if (!is_null($this->_params['lm_attribute'])) { $changes[$this->_params['lm_attribute']] = $lmpasswd; } if (!is_null($this->_params['nt_attribute'])) { $changes[$this->_params['nt_attribute']] = $ntpasswd; } if (!is_null($this->_params['pw_set_attribute'])) { $changes[$this->_params['pw_set_attribute']] = $settime; } if (!is_null($this->_params['pw_expire_attribute'])) { $changes[$this->_params['pw_expire_attribute']] = $expiretime; } if (count($changes) > 0) { try { $entry->replace($changes, true); $entry->update(); } catch (Horde_Ldap_Exception $e) { throw new Passwd_Exception($e); } } } } passwd-5.0.4/lib/Driver/Smbpasswd.php0000664000076500000240000000570512611577414014435 0ustar * @category Horde * @copyright 2000-2015 Horde LLC * @license http://www.horde.org/licenses/gpl GPL * @package Passwd */ class Passwd_Driver_Smbpasswd extends Passwd_Driver { /** * Socket connection resource. * * @var resource */ protected $_fp; /** */ public function __construct(array $params = array()) { parent::__construct(array_merge(array( 'host' => 'localhost', 'program' => '/usr/bin/smbpasswd' ), $params)); } /** * Connects a pipe to the sambaserver using the smbpasswd program. * * @param string $user The user to change the password for * @param string $tmpfile The name of a temporary file in which to write * output. * * @throws Passwd_Exception */ protected function _connect($user, $tmpfile) { if (!is_executable($this->_params['program'])) { throw new Passwd_Exception(_("Passwd is not properly configured.")); } $cmd = sprintf( '%s -r %s -s -U "%s" > %s 2>&1', $this->_params['program'], $this->_params['host'], $user, $tmpfile ); if (!($this->_fp = @popen($cmd, 'w'))) { throw new Passwd_Exception(_("Could not open pipe to smbpasswd.")); } } /** * Disconnects the pipe to the sambaserver. */ protected function _disconnect() { @pclose($this->_fp); } /** * Sends a string to the waiting sambaserver. * * @param string $cmd The string to send to the server. * * @throws Passwd_Exception */ protected function _sendCommand($cmd) { if (fputs($this->_fp, $cmd . "\n") == -1) { throw new Passwd_Exception(_("Error sending data to smbpasswd.")); } sleep(1); } /** */ protected function _changePassword($user, $oldpass, $newpass) { // Clean up user name in case evil characters are in it. $user = escapeshellcmd($user); $tmpfile = Horde::getTempFile('smbpasswd'); $this->_connect($user, $tmpfile); $this->_sendCommand($oldpass); $this->_sendCommand($newpass); $this->_sendCommand($newpass); $this->_disconnect(); $res = file($tmpfile); if (strstr($res[count($res) - 1], 'Password changed for user') === false) { throw new Passwd_Exception(strrchr(trim($res[count($res) - 2]), ':')); } } } passwd-5.0.4/lib/Driver/Soap.php0000664000076500000240000000426412611577414013373 0ustar * @category Horde * @copyright 2009-2015 Horde LLC * @license http://www.horde.org/licenses/gpl GPL * @package Passwd */ class Passwd_Driver_Soap extends Passwd_Driver { /** */ public function __construct(array $params = array()) { if (!class_exists('SoapClient')) { throw new Passwd_Exception('You need the soap PHP extension to use this driver.'); } if (empty($params['wsdl']) && (empty($params['soap_params']['location']) || empty($params['soap_params']['uri']))) { throw new Passwd_Exception('Either the "wsdl" or the "location" and "uri" parameter must be provided.'); } if (isset($params['wsdl'])) { unset($params['soap_params']['location']); unset($params['soap_params']['uri']); } $params['soap_params']['exceptions'] = false; parent::__construct($params); } /** */ protected function changePassword($user, $oldpass, $newpass) { $args = array(); if (($pos = array_search('username', $this->_params['arguments'])) !== false) { $args[$pos] = $user; } if (($pos = array_search('oldpassword', $this->_params['arguments'])) !== false) { $args[$pos] = $oldpass; } if (($pos = array_search('newpassword', $this->_params['arguments'])) !== false) { $args[$pos] = $newpass; } $client = new SoapClient( $this->_params['wsdl'], $this->_params['soap_params'] ); $res = $client->__soapCall($this->_params['method'], $args); if ($res instanceof SoapFault) { throw new Passwd_Exception($res->getMessage(), $res->getCode()); } } } passwd-5.0.4/lib/Driver/Sql.php0000664000076500000240000001460612611577414013231 0ustar * @author Mattias Webjörn Eriksson * @author Ilya Krel * @author Ralf Lang (H4 conversion) * @author Eric Jon Rostetter * @author Tjeerd van der Zee * @category Horde * @copyright 2000-2015 Horde LLC * @license http://www.horde.org/licenses/gpl GPL * @package Passwd */ class Passwd_Driver_Sql extends Passwd_Driver { /** * Handle for the current database connection. * * @var Horde_Db_Adapter */ protected $_db; /** * @param array $params Driver parameters: * - db: (Horde_Db_Adapter; REQUIRED) A DB Adapter object. * - encryption: (string) The encryption type. * - pass_col: (string) The table column for password. * - query_lookup: (string) Should we use a custom query for lookup? * - query_modify: (string) Should we use a custom query for changing? * - show_encryption: (boolean) Prepend the encryption type to the * password? * - table: (string) The name of the user database table. * - user_col: (string) The table column for user name. */ public function __construct(array $params = array()) { if (isset($params['db'])) { $this->_db = $params['db']; unset($params['db']); } else { throw new InvalidArgumentException('Missing required Horde_Db_Adapter object'); } /* These default to matching the Auth_Sql defaults. */ parent::__construct(array_merge(array( 'encryption' => 'ssha', 'pass_col' => 'user_pass', 'query_lookup' => false, 'query_modify' => false, 'show_encryption' => false, 'table' => 'horde_users', 'user_col' => 'user_uid' ), $params)); } /** * Finds out if a username and password is valid. * * @param string $userID The userID to check. * @param string $oldpass An old password to check. * * @throws Passwd_Exception */ protected function _lookup($user, $oldpass) { if (!empty($this->_params['query_lookup'])) { list($sql, $values) = $this->_parseQuery($this->_params['query_lookup'], $user, $oldpass); } else { /* Build the SQL query. */ $sql = 'SELECT ' . $this->_params['pass_col'] . ' FROM ' . $this->_params['table'] . ' WHERE ' . $this->_params['user_col'] . ' = ?'; $values = array($user); } /* Run query. */ try { $result = $this->_db->selectOne($sql, $values); } catch (Horde_Db_Exception $e) { throw new Passwd_Exception($e); } if (!is_array($result)) { throw new Passwd_Exception(_("User not found")); } /* Check the passwords match. */ $this->_comparePasswords($result[$this->_params['pass_col']], $oldpass); } /** * Modifies a SQL password record for a user. * * @param string $user The user whose record we will udpate. * @param string $newpass The new password value to set. * * @throws Passwd_Exception */ protected function _modify($user, $newpass) { if (!empty($this->_params['query_modify'])) { list($sql, $values) = $this->_parseQuery($this->_params['query_modify'], $user, $newpass); } else { /* Encrypt the password. */ $newpass= $this->_encryptPassword($newpass); /* Build the SQL query. */ $sql = 'UPDATE ' . $this->_params['table'] . ' SET ' . $this->_params['pass_col'] . ' = ?' . ' WHERE ' . $this->_params['user_col'] . ' = ?'; $values = array($newpass, $user); } /* Execute the query. */ try { $this->_db->update($sql, $values); } catch (Horde_Db_Exception $e) { throw new Passwd_Exception($e); } } /** * Parses the string as an SQL query substituting placeholders for * their values. * * @param string $string The string to process as a query. * @param string $user The user to use for the %u placeholder. * @param string $password The password to use for the %p and %e * placeholders. * * @return string The processed SQL query. */ protected function _parseQuery($string, $user, $password) { $query = ''; $values = array(); $length = strlen($string); @list($username, $domain) = explode('@', $user); for ($i = 0; $i < $length; $i++) { if ($string[$i] == '%' && !empty($string[$i + 1])) { switch ($string[++$i]) { case 'd': $query .= '?'; $values[] = $domain; break; case 'u': $query .= '?'; $values[] = $user; break; case 'U': $query .= '?'; $values[] = $username; break; case 'p': $query .= '?'; $values[] = $password; break; case 'e': $query .= '?'; $values[] = $this->_encryptPassword($password); break; case '%': $query .= '%'; break; default: $query .= '%' . $string[$i]; break; } } else { $query .= $string[$i]; } } return array($query, $values); } /** */ protected function _changePassword($user, $oldpass, $newpass) { $this->_lookup($user, $oldpass); $this->_modify($user, $newpass); } } passwd-5.0.4/lib/Driver/Vmailmgr.php0000664000076500000240000000230512611577414014241 0ustar * @category Horde * @copyright 2002-2015 Horde LLC * @license http://www.horde.org/licenses/gpl GPL * @package Passwd */ class Passwd_Driver_Vmailmgr extends Passwd_Driver { /** */ protected function _changePassword($user, $oldpass, $newpass) { if (isset($this->_params['vmailinc']) && is_readable($this->_params['vmailinc'])) { include $this->_params['vmailinc']; } else { throw new Passwd_Exception('vmail.inc not found! (' . $this->_params['vmailinc'] . ')'); } list($user, $domain) = explode('@', $user); $res = vchpass($domain, $oldpass, $user, $newpass); if ($res[0]) { throw new Passwd_Exception(_("Incorrect old password.")); } } } passwd-5.0.4/lib/Driver/Vpopmail.php0000664000076500000240000001174612611577414014263 0ustar * @author Mattias Webjörn Eriksson * @author Ilya Krel * @author Ralf Lang * @author Anton Nekhoroshikh * @author Eric Jon Rostetter * @author Tjeerd van der Zee * @category Horde * @copyright 2002-2015 Horde LLC * @license http://www.horde.org/licenses/gpl GPL * @package Passwd */ class Passwd_Driver_Vpopmail extends Passwd_Driver { /** * The Horde_Db object. * * @var Horde_Db_Adapter */ protected $_db; /** * State of SQL connection. * * @var boolean */ protected $_connected = false; /** */ public function __construct($params = array()) { if (!isset($params['db'])) { throw new Passwd_Exception('Missing required Horde_Db_Adapter object'); } $this->_db = $params['db']; unset($params['db']); /* Use defaults from Horde. */ parent::__construct(array_merge( Horde::getDriverConfig('', 'sql'), array( 'clear_passwd' => 'pw_clear_passwd', 'domain' => 'pw_domain', 'encryption' => 'crypt', 'name' => 'pw_name', 'passwd' => 'pw_passwd', 'show_encryption' => false, 'table' => 'horde_users', 'use_clear_passwd' => false ), $params )); } /** * Finds out if a username and password is valid. * * @param string $user The username to check. * @param string $oldpass An old password to check. * * @throws Passwd_Exception */ protected function _lookup($user, $oldpass) { /* Only split up username if domain is set in backend configuration. */ if (!empty($this->_params['domain'])) { list($name, $domain) = explode('@', $user); } else { $name = $user; } /* Build the SQL query. */ $sql = 'SELECT ' . $this->_params['passwd'] . ' FROM ' . $this->_params['table'] . ' WHERE ' . $this->_params['name'] . ' = ?'; $values = array($name); if ($this->_params['domain']) { $sql .= ' AND ' . $this->_params['domain'] . ' = ?'; $values[] = $domain; } /* Execute the query. */ try { $result = $this->_db->selectOne($sql, $values); } catch (Horde_Db_Exception $e) { throw new Passwd_Exception($e); } if (!is_array($result)) { throw new Passwd_Exception(_("User not found")); } /* Check the passwords match. */ $this->_comparePasswords($result[$this->_params['passwd']], $oldpass); } /** * Modifies a SQL password record for a user. * * @param string $user The user whose record we will udpate. * @param string $newpass The new password value to set. * * @throws Passwd_Exception */ protected function _modify($user, $newpass) { /* Only split up username if domain is set in backend. */ if ($this->_params['domain']) { list($name, $domain) = explode('@', $user); } else { $name = $user; } /* Encrypt the password. */ $clear_password = $newpass; $newpass = $this->_encryptPassword($newpass); /* Build the SQL query. */ $sql = 'UPDATE ' . $this->_params['table'] . ' SET ' . $this->_params['passwd'] . ' = ?'; $values = array($newpass); if ($this->_params['use_clear_passwd']) { $sql .= ', ' . $this->_params['clear_passwd'] . ' = ?'; $values[] = $clear_password; } $sql .= ' WHERE ' . $this->_params['name'] . ' = ?'; $values[] = $name; if ($this->_params['domain']) { $sql .= ' AND ' . $this->_params['domain'] . ' = ?'; $values[] = $domain; } /* Execute the query. */ try { $this->_db->update($sql, $values); } catch (Horde_Db_Exception $e) { throw new Passwd_Exception($e); } } /** */ protected function _changePassword($user, $oldpass, $newpass) { $this->_lookup($user, $oldpass); $this->_modify($user, $newpass); } } passwd-5.0.4/lib/Factory/Driver.php0000664000076500000240000001565612611577414014107 0ustar * @category Horde * @copyright 2011-2015 Horde LLC * @license http://www.horde.org/licenses/gpl.php * @package Passwd * * @property-read array $backends Backend list. */ class Passwd_Factory_Driver extends Horde_Core_Factory_Base { /** * Backend configurations. * * @var array */ private $_backends = null; /** * Created Passwd_Driver instances. * * @var array */ private $_instances = array(); /** */ public function __get($name) { switch ($name) { case 'backends': $this->_loadBackends(); return $this->_backends; } } /** * Returns the Passwd_Driver instance. * * @param string $name A string containing the internal name of this * backend. * @param array $params Any backend parameters if not the defaults. * * @return Passwd_Driver The singleton instance. * @throws Passwd_Exception */ public function create($name, $params = array()) { $this->_loadBackends(); $backends = empty($params['is_subdriver']) ? $this->_backends : array($name => $params); if (empty($backends[$name])) { throw new Passwd_Exception(sprintf(_("The password backend \"%s\" does not exist."), $name)); } $backend = $backends[$name]; if (!isset($this->_instances[$name])) { $class = 'Passwd_Driver_' . Horde_String::ucfirst(basename($backend['driver'])); if (!class_exists($class)) { throw new Passwd_Exception(sprintf(_("Unable to load the definition of %s."), $class)); } if (empty($backend['params'])) { $backend['params'] = array(); } if (empty($backend['policy'])) { $backend['policy'] = array(); } if (empty($params['is_subdriver']) && !empty($params)) { $backend['params'] = array_merge($backend['params'], $params); } switch ($class) { case 'Passwd_Driver_Ldap': case 'Passwd_Driver_Smbldap': if (isset($backend['params']['admindn'])) { $backend['params']['binddn'] = $backend['params']['admindn']; } if (isset($backend['params']['adminpw'])) { $backend['params']['bindpw'] = $backend['params']['adminpw']; } if (isset($backend['params']['host'])) { $backend['params']['hostspec'] = $backend['params']['host']; } try { $backend['params']['ldap'] = new Horde_Ldap($backend['params']); } catch (Horde_Ldap_Exception $e) { throw new Passwd_Exception($e); } break; case 'Passwd_Driver_Sql': case 'Passwd_Driver_Vpopmail': if (!($backend['params']['db'] instanceof Horde_Db_Adapter)) { try { if (empty($backend['params'])) { $backend['params']['db'] = $this->_injector ->getInstance('Horde_Db_Adapter'); } else { $params = $backend['params']; unset($params['table'], $params['user_col'], $params['pass_col'], $params['encryption'], $params['show_encryption'], $params['query_lookup'], $params['query_modify']); $backend['params']['db'] = $this->_injector ->getInstance('Horde_Core_Factory_Db') ->create('passwd', $params); } } catch (Horde_Db_Exception $e) { throw new Passwd_Exception($e); } } break; case 'Passwd_Driver_Horde': $backend['params']['auth'] = $this->_injector ->getInstance('Horde_Core_Factory_Auth') ->create(); break; case 'Passwd_Driver_Soap': if (!empty($GLOBALS['conf']['http']['proxy']['proxy_host'])) { $backend['params']['soap_params']['proxy_host'] = $GLOBALS['conf']['http']['proxy']['proxy_host']; $backend['params']['soap_params']['proxy_port'] = $GLOBALS['conf']['http']['proxy']['proxy_port']; $backend['params']['soap_params']['proxy_login'] = $GLOBALS['conf']['http']['proxy']['proxy_user']; $backend['params']['soap_params']['proxy_password'] = $GLOBALS['conf']['http']['proxy']['proxy_pass']; } $backend['params']['soap_params']['encoding'] = 'UTF-8'; break; } try { $driver = new $class($backend['params']); } catch (Passwd_Exception $e) { throw $e; } catch (Exception $e) { throw new Passwd_Exception($e); } /* Shouldn't we fetch policy from backend and inject some handler * class here? */ if (!empty($backend['params']['is_subdriver'])) { return $driver; } $this->_instances[$name] = $driver; } return $this->_instances[$name]; } /** * @throws Passwd_Exception */ protected function _loadBackends() { if (!is_null($this->_backends)) { return; } $allbackends = Horde::loadConfiguration('backends.php', 'backends', 'passwd'); if (!isset($allbackends) || !is_array($allbackends)) { throw new Passwd_Exception(_("No backends configured in backends.php")); } $backends = array(); foreach ($allbackends as $name => $backend) { if (empty($backend['disabled'])) { /* Make sure the 'params' entry exists. */ if (!isset($backend['params'])) { $backend['params'] = array(); } $backends[$name] = $backend; } } /* Check for valid backend configuration. */ if (empty($backends)) { throw new Passwd_Exception(_("No backend configured for this host")); } $this->_backends = $backends; } } passwd-5.0.4/lib/.htaccess0000664000076500000240000000001612611577414012312 0ustar Deny from all passwd-5.0.4/lib/Application.php0000664000076500000240000000272112611577414013475 0ustar * @author Ben Klang * @category Horde * @copyright 2002-2015 Horde LLC * @license http://www.horde.org/licenses/gpl GPL * @package Passwd */ class Passwd_Application extends Horde_Registry_Application { /** * The version of passwd as shown in the admin view */ public $version = 'H5 (5.0.4)'; } passwd-5.0.4/lib/Basic.php0000664000076500000240000002162212611577414012254 0ustar * @author Eric Rostetter * @author Jan Schneider * @author Michael Slusarz * @category Horde * @copyright 2000-2015 Horde LLC * @license http://www.horde.org/licenses/gpl GPL * @package Passwd */ class Passwd_Basic { /** * @var array */ private $_backends; /** * @var string */ private $_output; /** * User ID. * * @var string */ private $_userid; /** * @var Horde_Variables */ private $_vars; /** */ public function __construct(Horde_Variables $vars) { global $conf, $injector, $registry; $this->_userid = $registry->getAuth(); if ($conf['user']['change'] === true) { $this->_userid = $vars->get('userid', $this->_userid); } else { try { $this->_userid = Horde::callHook('default_username', array(), 'passwd'); } catch (Horde_Exception_HookNotSet $e) {} } $this->_backends = $injector->getInstance('Passwd_Factory_Driver')->backends; $this->_vars = $vars; $this->_init(); } /** */ public function render() { echo $this->_output; } /** */ public function status() { Horde::startBuffer(); $GLOBALS['notification']->notify(array('listeners' => array('status'))); return Horde::endBuffer(); } /** */ private function _init() { global $conf, $page_output; // Get the backend details. $backend_key = $this->_vars->backend; if (!isset($this->_backends[$backend_key])) { $backend_key = null; } if ($backend_key && $this->_vars->submit) { $this->_changePassword($backend_key); } // Choose the prefered backend from config/backends.php. foreach ($this->_backends as $k => $v) { if (!isset($backend_key) && (substr($k, 0, 1) != '_')) { $backend_key = $k; } if ($this->_isPreferredBackend($v)) { $backend_key = $k; break; } } $view = new Horde_View(array( 'templatePath' => PASSWD_TEMPLATES )); $view->addHelper('FormTag'); $view->addHelper('Horde_Core_View_Helper_Help'); $view->addHelper('Horde_Core_View_Helper_Label'); $view->addHelper('Tag'); $view->formInput = Horde_Util::formInput(); $view->url = $this->_vars->return_to; $view->userid = $this->_userid; $view->userChange = $conf['user']['change']; $view->showlist = ($conf['backend']['backend_list'] == 'shown'); $view->backend = $backend_key; // Build the userChange): ?>

header ?>

userChange): ?> showlist): ?>
hordeLabel('userid', _("Username:")) ?> hordeHelp('passwd', 'username') ?>
hordeLabel('oldpassword', _("Old password:")) ?> hordeHelp('passwd', 'old-password') ?>
hordeLabel('newpassword0', _("New password:")) ?> hordeHelp('passwd', 'new-password') ?>
hordeLabel('newpassword1', _("Confirm new password:")) ?> hordeHelp('passwd', 'confirm-password') ?>
hordeLabel('backend', _("Change password for:")) ?> hordeHelp('passwd', 'server') ?>

" /> " />

passwd-5.0.4/test/Passwd/Unit/Driver/SqlTest.php0000664000076500000240000000264512611577414016462 0ustar * @category Horde * @copyright 2013 Horde LLC * @internal * @package Passwd * @subpackage UnitTests */ class Passwd_Unit_Driver_SqlTest extends Passwd_TestCase { private $driver; public static function setUpBeforeClass() { self::createBasicPasswdSetup(new Horde_Test_Setup()); parent::setUpBeforeClass(); } public function setUp() { $GLOBALS['injector'] = $this->getInjector(); $factory = new Passwd_Factory_Driver($this->getInjector()); $factory->backends = array(); // Get a Horde_Db_Adapter to prevent usage of Horde_Core_Factory_Db. $db = new Horde_Db_Adapter_Pdo_Sqlite(array('dbname' => ':memory:')); $db->execute("CREATE TABLE horde_users ( user_uid VARCHAR(255) PRIMARY KEY NOT NULL, user_pass VARCHAR(255) NOT NULL, user_soft_expiration_date INTEGER, user_hard_expiration_date INTEGER );"); $this->driver = new Passwd_Driver_Sql(array('db' => $db)); } public function testSetup() { $this->assertInstanceOf('Passwd_Driver', $this->driver); } /** * @expectedException Passwd_Exception */ public function testChangePasswordFailsForNonexistingUser() { $res = $this->driver->changePassword('Patricia', 'alt', 'neu'); } } passwd-5.0.4/test/Passwd/Unit/Factory/DriverTest.php0000664000076500000240000000361312611577414017326 0ustar * @category Horde * @copyright 2013 Horde LLC * @internal * @license http://www.horde.org/licenses/gpl GPL * @package Passwd * @subpackage UnitTests */ class Passwd_Unit_Factory_DriverTest extends Passwd_TestCase { protected $_backends = array(); public function setUp() { $this->markTestIncomplete('Factories with configuration files don\'t work out of the box.'); $this->_backends = array( 'null' => array( 'disabled' => false, 'name' => 'Null', 'driver' => 'Null', 'policy' => array( 'minLength' => 6, 'minNumeric' => 1 ) ) ); } public function testGettingSubdriversWorks() { $factory = new Passwd_Factory_Driver($this->getInjector()); $factory->backends = array(); $driver = $factory->create('Null', array( 'is_subdriver' => true, 'driver' => 'Null' )); $this->assertInstanceOf('Passwd_Driver', $driver); } public function testGetBackendsReturnsResultOfSetBackends() { $GLOBALS['injector'] = $this->getInjector(); $factory = new Passwd_Factory_Driver($this->getInjector()); $factory->backends = $this->_backends; $this->assertArrayHasKey('null', $factory->backends); } // This test is currently blocked by a static call public function testGettingTheSameDriverTwiceWorks() { $GLOBALS['injector'] = $this->getInjector(); $factory = new Passwd_Factory_Driver($this->getInjector()); $factory->backends = $this->_backends; $driver1 = $factory->create('null'); $driver2 = $factory->create('null'); $this->assertEquals($driver1, $driver2); } } passwd-5.0.4/test/Passwd/AllTests.php0000664000076500000240000000013212611577414014431 0ustar run(); passwd-5.0.4/test/Passwd/Autoload.php0000664000076500000240000000051212611577414014450 0ustar passwd-5.0.4/test/Passwd/TestCase.php0000664000076500000240000000154512611577414014422 0ustar * @category Horde * @copyright 2013 Horde LLC * @internal * @license http://www.horde.org/licenses/gpl GPL * @package Passwd * @subpackage UnitTests */ class Passwd_TestCase extends PHPUnit_Framework_TestCase { protected function getInjector() { return new Horde_Injector(new Horde_Injector_TopLevel()); } static protected function createBasicPasswdSetup(Horde_Test_Setup $setup) { $setup->setup( array( '_PARAMS' => array( 'user' => 'test@example.com', 'app' => 'passwd' ), 'Horde_Registry' => 'Registry', ) ); $setup->makeGlobal( array( 'registry' => 'Horde_Registry', ) ); } } passwd-5.0.4/themes/default/graphics/favicon.ico0000664000076500000240000000331612611577414016606 0ustar  (( @  >>>PPPRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRPPP>>>===RRRRRRRRRRRRGGGGGGGGGGGGRRRRRRRRRRRR======RRRRRRRRRRRRDDD======DDDRRRRRRRRRRRR======RRRRRRRRRRRRAAAWWWWWWAAARRRRRRRRRRRR======RRRRRRRRRMMM===SSSlSSSl===MMMRRRRRRRRR======RRRRRRRRRMMM888'''0'''0888MMMRRRRRRRRR======RRRRRRRRRMMMHHHhhHHHMMMRRRRRRRRR======RRRRRRRRRQQQEEEEEEQQQRRRRRRRRR======CCCMMMEEEEEEEEEEEEEEEEEEEEEEEEMMMCCC===...888JJJ===000000000000000000===JJJ888...###I===JJJ===(((`````(((`===JJJ===###IJJJJJJ======JJJJJJJJJHHH======HHHJJJDDDBBB===44===BBBDDD@@@===AAAAAA===@@@)))=444===EEEVVVWWWWWWVVVEEE===444)))=(((111999============999111(((%%%i((((((((((((((((((%%%ipppppppppppppasswd-5.0.4/themes/default/graphics/passwd.png0000664000076500000240000000065512611577414016477 0ustar PNG  IHDRW?PLTEJJJ(((((((((EEE%%%@@@DDDWWW===VVV((()))EEEHHH888'''SSSWWW>>>###===RRRJJJMMMQQQBBBAAAHHHDDD999444...111EEECCCPPP(((888000GGGkttRNS`i̷`=h0l4IEaQIDATx^ur0DQz/㶒&3eΑZx!-R=:[4@ * @category Horde * @copyright 2002-2015 Horde LLC * @license http://www.horde.org/licenses/gpl GPL * @package Passwd */ require_once __DIR__ . '/lib/Application.php'; Horde_Registry::appInit('passwd'); $ob = new Passwd_Basic($injector->getInstance('Horde_Variables')); $status = $ob->status(); $page_output->header(array( 'title' => _("Change Password"), 'view' => $registry::VIEW_BASIC )); echo $status; $ob->render(); $page_output->footer(); passwd-5.0.4/README0000664000076500000240000000416712611577414010641 0ustar ================= What is Passwd? ================= :Contact: dev@lists.horde.org .. contents:: Contents .. section-numbering:: Passwd is the Horde password changing application. Right now, Passwd provides fairly complete support for changing passwords via Poppassd, LDAP, Unix expect scripts, the Unix smbpasswd command for SMB/CIFS passwords, Kolab, ADSI, Pine, Serv-U FTP, VMailMgr, vpopmail, and SQL passwords. This software is OSI Certified Open Source Software. OSI Certified is a certification mark of the `Open Source Initiative`_. .. _`Open Source Initiative`: http://www.opensource.org/ Obtaining Passwd ================ Further information on Passwd and the latest version can be obtained at http://www.horde.org/apps/passwd Documentation ============= The following documentation is available in the Passwd distribution: :README_: This file :COPYING_: Copyright and license information :`docs/CHANGES`_: Changes by release :`docs/CREDITS`_: Project developers :`docs/INSTALL`_: Installation instructions and notes :`docs/TODO`_: Development TODO list Installation ============ Instructions for installing Passwd can be found in the file INSTALL_ in the ``docs/`` directory of the Passwd distribution. Assistance ========== If you encounter problems with Passwd, help is available! The Horde Frequently Asked Questions List (FAQ), available on the Web at http://wiki.horde.org/FAQ Horde LLC runs a number of mailing lists, for individual applications and for issues relating to the project as a whole. Information, archives, and subscription information can be found at http://www.horde.org/community/mail Lastly, Horde developers, contributors and users also make occasional appearances on IRC, on the channel #horde on the Freenode Network (irc.freenode.net). Licensing ========= For licensing and copyright information, please see the file COPYING_ in the Passwd distribution. Thanks, The Passwd team .. _README: README .. _COPYING: http://www.horde.org/licenses/gpl .. _docs/CHANGES: CHANGES .. _docs/CREDITS: CREDITS .. _INSTALL: .. _docs/INSTALL: INSTALL .. _docs/TODO: TODO