1 <?php
2 /*
3 This code is part of GOsa (https://gosa.gonicus.de)
4 Copyright (C) 2004 Cajus Pollmeier
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
22 class passwordMethod
23 {
24 var $config = false;
25 var $attrs= array();
27 // Konstructor
28 function passwordMethod($config)
29 {
30 }
32 // Loads Methods in annother way as get_available_methods do, (For setup ..)
33 // and loads them,.
34 function get_available_methods_if_not_loaded($path_to_load="../include")
35 {
36 $oh = opendir($path_to_load);
37 $i = 0;
38 $ret = false;
39 while ($file = readdir($oh)) {
40 $one = strtolower($file);
41 if((strstr($one,"class_password-methods-" ))&&($one[0]!=".")){
42 require_once($file);
43 }
44 }
45 return(passwordMethod::get_available_methods());
46 }
51 // Crypts a single string, with given Method
52 function crypt_single_str($string,$method)
53 {
54 $available = passwordMethod::get_available_methods();
55 if(!is_array($available))
56 {
57 $available = passwordMethod::get_available_methods_if_not_loaded();
58 }
60 $test = new $available[$method](false);
61 $newpass = $test->generate_hash($string);
62 return( $newpass);
63 }
66 // this function returns all loaded classes for password encryption
67 function get_available_methods()
68 {
69 $ret =false;
70 $all = get_declared_classes();
71 $i = 0;
72 foreach($all as $one) {
73 if(preg_match('/passwordMethod/i', $one) && !preg_match("/^passwordMethod$/i", $one)){
74 $name = preg_replace ("/passwordMethod/i", "", $one);
75 $test = new $one(false);
76 if($test->is_available()) {
77 $plugname= strtolower(preg_replace ("/passwordMethod/i","",$one));
78 $ret['name'][$i]= $plugname;
79 $ret['class'][$i]=$one;
80 $ret[$i]['name']= $plugname;
81 $ret[$i]['class']= $one;
82 $ret[$plugname]=$one;
83 $i++;
84 }
85 }
86 }
87 return($ret);
88 }
90 }
92 // change_password, changes the Password, of the given dn
93 function change_password ($dn, $password, $mode=0, $hash= "")
94 {
95 global $config;
96 $newpass= "";
98 /* Convert to lower. Methods are lowercase */
99 $hash= strtolower($hash);
101 // Get all available encryption Methods
103 // NON STATIC CALL :)
104 $tmp = new passwordMethod($_SESSION['config']);
105 $available = $tmp->get_available_methods();
107 // read current password entry for $dn, to detect the encryption Method
108 $ldap = $config->get_ldap_link();
109 $ldap->cat ($dn, array("shadowLastChange", "userPassword", "uid"));
110 $attrs = $ldap->fetch ();
112 // Check if user account was deactivated, indicated by ! after } ... {crypt}!###
113 if(isset($attrs['userPassword'][0]) && preg_match("/^[^\}]*+\}!/",$attrs['userPassword'][0])){
114 $deactivated = TRUE;
115 }else{
116 $deactivated = FALSE;
117 }
119 # // Get current password hash method if available
120 # if($hash == "" && isset($attrs['userPassword'][0]) && preg_match("/[\{\}]/",$attrs['userPassword'][0])){
121 # $hash = preg_replace("/^[^\{]*+\{([^\}]*).*$/","\\1",$attrs['userPassword'][0]);
122 # $hash = strtolower($hash);
123 # }
125 # // Set encryption type to clear if required
126 # if (!isset($attrs['userPassword'][0]) || $hash == ""){
127 # $hash= "clear";
128 # }
130 // Detect the encryption Method
131 if ( (isset($attrs['userPassword'][0]) && preg_match ("/^{([^}]+)}(.+)/", $attrs['userPassword'][0], $matches)) || $hash != ""){
133 /* Check for supported algorithm */
134 mt_srand((double) microtime()*1000000);
136 /* Extract used hash */
137 if ($hash == ""){
138 $hash= strtolower($matches[1]);
139 }
142 // Crypt with the detected Method
143 $test = new $available[$hash]($config);
144 $test->attrs= $attrs;
145 $newpass = $test->generate_hash($password);
147 } else {
148 // Crypt it by default
149 $test = new $available['md5']($config);
150 $newpass = $test->generate_hash($password);
151 }
153 // Update shadow timestamp?
154 if (isset($attrs["shadowLastChange"][0])){
155 $shadow= (int)(date("U") / 86400);
156 } else {
157 $shadow= 0;
158 }
160 // Write back modified entry
161 $ldap->cd($dn);
162 $attrs= array();
164 // Not for groups
165 if ($mode == 0){
167 if ($shadow != 0){
168 $attrs['shadowLastChange']= $shadow;
169 }
171 // Create SMB Password
172 $attrs= generate_smb_nt_hash($password);
173 }
175 /* Readd ! if user was deactivated */
176 if($deactivated){
177 $newpass = preg_replace("/(^[^\}]+\})(.*$)/","\\1!\\2",$newpass);
178 }
180 $attrs['userPassword']= array();
181 $attrs['userPassword']= $newpass;
183 $ldap->modify($attrs);
185 new log("modify","users/passwordMethod",$dn,array_keys($attrs),$ldap->get_error());
187 if ($ldap->error != 'Success') {
188 print_red(sprintf(_("Setting the password failed. LDAP server says '%s'."),
189 $ldap->get_error()));
190 } else {
192 /* Find postmodify entries for this class */
193 $command= search_config($config->data['MENU'], "password", "POSTMODIFY");
195 if ($command != ""){
196 /* Walk through attribute list */
197 $command= preg_replace("/%userPassword/", $password, $command);
198 $command= preg_replace("/%dn/", $dn, $command);
200 if (check_command($command)){
201 @DEBUG (DEBUG_SHELL, __LINE__, __FUNCTION__, __FILE__, $command, "Execute");
202 exec($command);
203 } else {
204 $message= sprintf(_("Command '%s', specified as POSTMODIFY for plugin '%s' doesn't seem to exist."), $command, "password");
205 print_red ($message);
206 }
207 }
208 }
209 }
212 // Return something like array['sambaLMPassword']= "lalla..."
213 function generate_smb_nt_hash($password)
214 {
215 global $config;
216 $tmp= $config->data['MAIN']['SMBHASH']." ".escapeshellarg($password);
217 @DEBUG (DEBUG_LDAP, __LINE__, __FUNCTION__, __FILE__, $tmp, "Execute");
219 exec($tmp, $ar);
220 flush();
221 reset($ar);
222 $hash= current($ar);
223 if ($hash == "")
224 {
225 print_red (_("Setting for SMBHASH in gosa.conf is incorrect! Can't change Samba password."));
226 }
227 else
228 {
229 list($lm,$nt)= split (":", trim($hash));
231 if ($config->current['SAMBAVERSION'] == 3)
232 {
233 $attrs['sambaLMPassword']= $lm;
234 $attrs['sambaNTPassword']= $nt;
235 $attrs['sambaPwdLastSet']= date('U');
236 $attrs['sambaBadPasswordCount']= "0";
237 $attrs['sambaBadPasswordTime']= "0";
238 } else {
239 $attrs['lmPassword']= $lm;
240 $attrs['ntPassword']= $nt;
241 $attrs['pwdLastSet']= date('U');
242 }
243 return($attrs);
244 }
245 }
247 function crypt_single($string,$enc_type )
248 {
249 if(!class_exists("passwordMethod")){
250 require_once("class_password-methods.inc");
251 }
252 return( passwordMethod::crypt_single_str($string,$enc_type));
253 }
255 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
256 ?>