1: <?php
2: /**
3: * The PSPasswd class changes a user's password on any Windows Machine
4: * (NT+) using the pspasswd free utility available at Sysinternals
5: * website: http://www.sysinternals.com/ntw2k/freeware/pspasswd.shtml
6: *
7: * IMPORTANT!
8: *
9: * This driver should be used only as a last resort when there's no
10: * possibility of using the ADSI or LDAP drivers, which are far more
11: * secure and fast. This driver needs administrative credentials
12: * exposed on the backends.php file, which is required by the
13: * pspasswd.exe tool. It's an alternative driver that should be
14: * avoided, but could also be the only option for a few scenarios.
15: * (eg: When you don't have ADSI or LDAP support)
16: *
17: * Sample backend configuration:
18: * <code>
19: * $backends['pspasswd'] = array(
20: * 'name' => 'Sample pspasswd backend',
21: * 'preferred' => 'localhost',
22: * 'policy' => array(
23: * 'minLength' => 8,
24: * 'maxLength' => 14
25: * ),
26: * 'driver' => 'pspasswd',
27: * 'params' => array(
28: * 'server' => 'YOUR_SERVER_NAME',
29: * 'bin' => 'DRIVE:\\DIR\\pspasswd.exe', // Notice: "\\"
30: * 'admusr' => 'Administrator',
31: * 'admpwd' => 'Password',
32: * 'domain' => 'YOUR_DOMAIN_NAME'
33: * )
34: * );
35: * </code>
36: *
37: * Backend parameters:<pre>
38: * server = Machine where you want to change the password (Required)
39: * bin = Full pathname of the pspasswd.exe program (Required)
40: * admusr = User with administrative privileges (Required)
41: * admpwd = Password of the administrative user (Required)
42: * domain = Windows domain name (Optional)
43: * </pre>
44: *
45: * For example: Passing a NT4 PDC server name to the server parameter
46: * means you can change the user's password on that NT4 Domain.
47: *
48: * Special thanks to Mark Russinovich (mark@sysinternals.com) for the
49: * tool and helping me solve some questions about it.
50: *
51: * Copyright 2004-2012 Horde LLC (http://www.horde.org/)
52: *
53: * See the enclosed file COPYING for license information (GPL). If you
54: * did not receive this file, see http://www.horde.org/licenses/gpl.php.
55: *
56: * @author Luiz R Malheiros (malheiros@gmail.com)
57: * @package Passwd
58: */
59: class Passwd_Driver_Pspasswd extends Passwd_Driver
60: {
61: /**
62: * Constructor.
63: *
64: * @param array $params A hash containing connection parameters.
65: *
66: * @throws Passwd_Exception
67: */
68: public function __construct($params = array())
69: {
70: if (empty($params['server']) || empty($params['bin']) ||
71: empty($params['admusr']) || empty($params['admpwd'])) {
72: throw new Passwd_Exception(_("Password module is missing required parameters."));
73: }
74: if (!file_exists($params['bin'])) {
75: throw new Passwd_Exception(_("Password module can't find the supplied bin."));
76: }
77:
78: parent::__construct($params);
79: }
80:
81: /**
82: * Changes the user's password.
83: *
84: * @param string $user_name The user for which to change the password.
85: * @param string $old_password The old (current) user password.
86: * @param string $new_password The new user password to set.
87: *
88: * @throws Passwd_Exception
89: */
90: public function changePassword($user_name, $old_password, $new_password)
91: {
92: $server = $this->_params['server'];
93: $chpwd_adm = $this->_params['admusr'];
94: $chpwd_usr = $user_name;
95:
96: if (!empty($this->_params['domain'])) {
97: $chpwd_adm = $this->_params['domain'] . "\\" . $chpwd_adm;
98: $chpwd_usr = $this->_params['domain'] . "\\" . $chpwd_usr_name;
99: }
100:
101: exec('NET USE \\\\' . $server . '\\IPC$ /D >NUL 2>NUL');
102:
103: $cmdline = 'NET USE \\\\' . $server . '\\IPC$ "' . $old_password
104: . '" /USER:' . $chpwd_usr;
105: exec($cmdline, $cmdreply, $retval);
106:
107: if (strpos(implode(' ', $cmdreply), 'The command completed successfully.') === false) {
108: throw new Passwd_Exception(_("Failed to verify old password."));
109: }
110:
111: exec('NET USE \\\\' . $server . '\\IPC$ /D >NUL 2>NUL');
112:
113: $cmdline = $this->_params['bin'] . ' \\\\' . $server . ' -u ' . $chpwd_adm . ' -p ' . $this->_params['admpwd'] . ' ' . $user_name . ' ' . $new_password;
114: exec($cmdline, $cmdreply, $retval);
115: exec('NET USE \\\\' . $server . '\\IPC$ /D >NUL 2>NUL');
116:
117: if (strpos(implode(' ', $cmdreply), 'Password for ' . $server . '\\' . $user_name . ' successfully changed.') === false) {
118: throw new Passwd_Exception(_("Access Denied."));
119: }
120: }
121: }
122: