Overview

Packages

  • None
  • Passwd

Classes

  • Passwd
  • Passwd_Driver
  • Passwd_Driver_Adsi
  • Passwd_Driver_Composite
  • Passwd_Driver_Expect
  • Passwd_Driver_Expectpecl
  • Passwd_Driver_Horde
  • Passwd_Driver_Http
  • Passwd_Driver_Kolab
  • Passwd_Driver_Ldap
  • Passwd_Driver_Pine
  • Passwd_Driver_Poppassd
  • Passwd_Driver_Procopen
  • Passwd_Driver_Pspasswd
  • Passwd_Driver_Servuftp
  • Passwd_Driver_Smbldap
  • Passwd_Driver_Smbpasswd
  • Passwd_Driver_Soap
  • Passwd_Driver_Sql
  • Passwd_Driver_Vmailmgr
  • Passwd_Driver_Vpopmail
  • Passwd_Exception
  • Passwd_Factory_Driver
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * The SQL driver attempts to change a user's password stored in an SQL
  4:  * database and implements the Passwd_Driver API.
  5:  *
  6:  * Copyright 2000-2012 Horde LLC (http://www.horde.org/)
  7:  *
  8:  * See the enclosed file COPYING for license information (GPL). If you
  9:  * did not receive this file, see http://www.horde.org/licenses/gpl.php.
 10:  *
 11:  * @author  Mike Cochrane <mike@graftonhall.co.nz>
 12:  * @author  Ilya Krel <mail@krel.org>
 13:  * @author  Tjeerd van der Zee <admin@xar.nl>
 14:  * @author  Mattias Webjörn Eriksson <mattias@webjorn.org>
 15:  * @author  Eric Jon Rostetter <eric.rostetter@physics.utexas.edu>
 16:  * @author  Ralf Lang <lang@b1-systems.de> (H4 conversion)
 17:  * @package Passwd
 18:  */
 19: class Passwd_Driver_Sql extends Passwd_Driver
 20: {
 21:     /**
 22:      * Handle for the current database connection.
 23:      *
 24:      * @var Horde_Db_Adapter
 25:      */
 26:     protected $_db;
 27: 
 28:     /**
 29:      * Constructor.
 30:      *
 31:      * @param array $params  Additional parameters needed:
 32:      * <pre>
 33:      * 'db' - (Horde_Db_Adapter) A DB Adapter object.
 34:      * optional:
 35:      * 'table'           - (string)  The name of the user database table
 36:      * 'encryption'      - (string)  The encryption type
 37:      * 'user_col'        - (string)  The table column for user name
 38:      * 'pass_col'        - (string)  The table column for password
 39:      * 'show_encryption' - (boolean) Prepend the encryption type to the password?
 40:      * 'query_lookup'    - (string)  Should we use a custom query for lookup?
 41:      * 'query_modify'    - (string)  Should we use a custom query for changing?
 42:      * </pre>
 43:      *
 44:      * @throws InvalidArgumentException
 45:      */
 46:     public function __construct($params = array())
 47:     {
 48:         if (isset($params['db'])) {
 49:             $this->_db = $params['db'];
 50:             unset($params['db']);
 51:         } else {
 52:             throw new InvalidArgumentException('Missing required Horde_Db_Adapter object');
 53:         }
 54:         /* These default to matching the Auth_sql defaults. */
 55:         $this->_params = array_merge(
 56:             array('table'           => 'horde_users',
 57:                   'encryption'      => 'ssha',
 58:                   'user_col'        => 'user_uid',
 59:                   'pass_col'        => 'user_pass',
 60:                   'show_encryption' => false,
 61:                   'query_lookup'    => false,
 62:                   'query_modify'    => false),
 63:             $params);
 64:     }
 65: 
 66:      /**
 67:       * Finds out if a username and password is valid.
 68:       *
 69:       * @param string $userID        The userID to check.
 70:       * @param string $old_password  An old password to check.
 71:      *
 72:      * @throws Passwd_Exception
 73:       */
 74:     protected function _lookup($user, $old_password)
 75:     {
 76:         if (!empty($this->_params['query_lookup'])) {
 77:             list($sql, $values) = $this->_parseQuery($this->_params['query_lookup'], $user, $old_password);
 78:         } else {
 79:             /* Build the SQL query. */
 80:             $sql  = 'SELECT ' . $this->_params['pass_col'] . ' FROM ' . $this->_params['table'] .
 81:                     ' WHERE ' . $this->_params['user_col'] . ' = ?';
 82:             $values = array($user);
 83:         }
 84: 
 85:         /* Run query. */
 86:         try {
 87:             $result = $this->_db->selectOne($sql, $values);
 88:         } catch (Horde_Db_Exception $e) {
 89:             throw new Passwd_Exception($e);
 90:         }
 91: 
 92:         if (is_array($result)) {
 93:             $current_password = $result[$this->_params['pass_col']];
 94:         } else {
 95:             throw new Passwd_Exception(_("User not found"));
 96:         }
 97: 
 98:         /* Check the passwords match. */
 99:         $this->_comparePasswords($current_password, $old_password);
100:     }
101: 
102:     /**
103:      * Modifies a SQL password record for a user.
104:      *
105:      * @param string $user          The user whose record we will udpate.
106:      * @param string $new_password  The new password value to set.
107:      *
108:      * @throws Passwd_Exception
109:      */
110:     protected function _modify($user, $new_password)
111:     {
112:         if (!empty($this->_params['query_modify'])) {
113:             list($sql, $values) = $this->_parseQuery($this->_params['query_modify'], $user, $new_password);
114:         } else {
115:             /* Encrypt the password. */
116:             $new_password = $this->_encryptPassword($new_password);
117: 
118:             /* Build the SQL query. */
119:             $sql = 'UPDATE ' . $this->_params['table'] .
120:                    ' SET ' . $this->_params['pass_col'] . ' = ?' .
121:                    ' WHERE ' . $this->_params['user_col'] . ' = ?';
122:             $values = array($new_password, $user);
123:         }
124: 
125:         /* Execute the query. */
126:         try {
127:             $this->_db->update($sql, $values);
128:         } catch (Horde_Db_Exception $e) {
129:             throw new Passwd_Exception($e);
130:         }
131:     }
132: 
133:     /**
134:      * Parses the string as an SQL query substituting placeholders for
135:      * their values.
136:      *
137:      * @param string $string    The string to process as a query.
138:      * @param string $user      The user to use for the %u placeholder.
139:      * @param string $password  The password to use for the %p and %e placeholders.
140:      *
141:      * @return string  The processed SQL query.
142:      */
143:     protected function _parseQuery($string, $user, $password)
144:     {
145:         $query = '';
146:         $values = array();
147:         $length = strlen($string);
148:         @list($username, $domain) = explode('@', $user);
149:         for ($i = 0; $i < $length; $i++) {
150:             if ($string[$i] == '%' && !empty($string[$i + 1])) {
151:                 switch ($string[++$i]) {
152:                 case 'd':
153:                     $query .= '?';
154:                     $values[] = $domain;
155:                     break;
156: 
157:                 case 'u':
158:                     $query .= '?';
159:                     $values[] = $user;
160:                     break;
161: 
162:                 case 'U':
163:                     $query .= '?';
164:                     $values[] = $username;
165:                     break;
166: 
167:                 case 'p':
168:                     $query .= '?';
169:                     $values[] = $password;
170:                     break;
171: 
172:                 case 'e':
173:                     $query .= '?';
174:                     $values[] = $this->_encryptPassword($password);
175:                     break;
176: 
177:                 case '%':
178:                     $query .= '%';
179:                     break;
180: 
181:                 default:
182:                     $query .= '%' . $string[$i];
183:                     break;
184:                 }
185:             } else {
186:                 $query .= $string[$i];
187:             }
188:         }
189: 
190:         return array($query, $values);
191:     }
192: 
193:     /**
194:      * Changes the user's password.
195:      *
196:      * @param string $username      The user for which to change the password.
197:      * @param string $old_password  The old (current) user password.
198:      * @param string $new_password  The new user password to set.
199:      *
200:      * @throws Passwd_Exception
201:      */
202:     public function changePassword($username,  $old_password, $new_password)
203:     {
204:         /* Check the current password. */
205:         $this->_lookup($username, $old_password);
206:         $this->_modify($username, $new_password);
207:     }
208: }
209: 
API documentation generated by ApiGen