22
22
# Create SSHA password
23
23
function make_ssha_password ($ password ) {
24
24
$ salt = random_bytes (4 );
25
+ $ hash = make_ssha_password_with_salt ($ password , $ salt );
26
+ return $ hash ;
27
+ }
28
+
29
+ # Creates SSHA password using custom salt
30
+ # Notes: use ONLY for verification purpose, security issue when using this function to encode a password into a LDAP with a fixed salt.
31
+ function make_ssha_password_with_salt ($ password , $ salt ) {
25
32
$ hash = "{SSHA} " . base64_encode (pack ("H* " , sha1 ($ password . $ salt )) . $ salt );
26
33
return $ hash ;
27
34
}
@@ -41,6 +48,13 @@ function make_sha512_password($password) {
41
48
# Create SMD5 password
42
49
function make_smd5_password ($ password ) {
43
50
$ salt = random_bytes (4 );
51
+ $ hash = make_smd5_password_with_salt ($ password , $ hash );
52
+ return $ hash ;
53
+ }
54
+
55
+ # Creates SMD5 password using custom salt
56
+ # Notes: use ONLY for verification purpose, security issue when using this function to encode a password into a LDAP with a fixed salt.
57
+ function make_smd5_password_with_salt ($ password , $ salt ) {
44
58
$ hash = "{SMD5} " . base64_encode (pack ("H* " , md5 ($ password . $ salt )) . $ salt );
45
59
return $ hash ;
46
60
}
@@ -61,9 +75,9 @@ function make_crypt_password($password, $hash_options) {
61
75
62
76
// Generate salt
63
77
$ possible = '0123456789 ' .
64
- 'abcdefghijklmnopqrstuvwxyz ' .
65
- 'ABCDEFGHIJKLMNOPQRSTUVWXYZ ' .
66
- './ ' ;
78
+ 'abcdefghijklmnopqrstuvwxyz ' .
79
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZ ' .
80
+ './ ' ;
67
81
$ salt = "" ;
68
82
69
83
while ( strlen ( $ salt ) < $ salt_length ) {
@@ -74,6 +88,13 @@ function make_crypt_password($password, $hash_options) {
74
88
$ salt = $ hash_options ['crypt_salt_prefix ' ] . $ salt ;
75
89
}
76
90
91
+ $ hash = make_crypt_password_with_salt ( $ password , $ salt );
92
+ return $ hash ;
93
+ }
94
+
95
+ # Creates CRYPT password using custom salt
96
+ # Notes: use ONLY for verification purpose, security issue when using this function to encode a password into a LDAP with a fixed salt.
97
+ function make_crypt_password_with_salt ($ password , $ salt ) {
77
98
$ hash = '{CRYPT} ' . crypt ( $ password , $ salt );
78
99
return $ hash ;
79
100
}
@@ -238,6 +259,84 @@ function check_password_strength( $password, $oldpassword, $pwd_policy_config, $
238
259
239
260
return $ result ;
240
261
}
262
+ # Hash old password using same method and salt as ldap password
263
+ # @return the old password, hashed
264
+ function hash_old_password ($ ldap_password , $ old_password ) {
265
+ if ( preg_match ( '/^\{(\w+)\}/ ' , $ ldap_password , $ matches ) ) {
266
+ $ current_hash_method = strtoupper ($ matches [1 ]);
267
+
268
+ # Check old password using current hash
269
+ if ( $ current_hash_method == "SSHA " ) {
270
+ #Get salt of ldap_password
271
+ $ sha1_len = 20 ;
272
+ $ ldap_bytes = base64_decode (str_replace ("{SSHA} " , "" , str_replace ("{ssha} " , "" , $ ldap_password )));
273
+ $ ldap_salt = substr ($ ldap_bytes , $ sha1_len );
274
+ $ old_password_hash = make_ssha_password_with_salt ($ old_password , $ ldap_salt );
275
+ }
276
+ if ( $ current_hash_method == "SHA " ) {
277
+ $ old_password_hash = make_sha_password ($ old_password );
278
+ }
279
+ if ( $ current_hash_method == "SHA512 " ) {
280
+ $ old_password_hash = make_sha512_password ($ old_password );
281
+ }
282
+ if ( $ current_hash_method == "SMD5 " ) {
283
+ $ md5_len = 16 ;
284
+ $ ldap_bytes = base64_decode (str_replace ("{SMD5} " , "" , str_replace ("{smd5} " , "" , $ ldap_password )));
285
+ $ ldap_salt = substr ($ ldap_bytes , $ md5_len );
286
+ $ old_password_hash = make_smd5_password_with_salt ($ old_password , $ ldap_salt );
287
+ }
288
+ if ( $ current_hash_method == "MD5 " ) {
289
+ $ old_password_hash = make_md5_password ($ old_password );
290
+ }
291
+ if ( $ current_hash_method == "CRYPT " ) {
292
+ # salt value and length may vary. Checking values for a recognizable form. They are all described in php crypt method online description
293
+ $ ldap_bytes = str_replace ("{CRYPT} " , "" , str_replace ("{crypt} " , "" , $ ldap_password ));
294
+ if ( substr ($ ldap_bytes , 0 , 1 ) == '_ ' ) {
295
+ # [NOT TESTED]if $ldap_password starts with '_': Extended DES hash, salt starts with '_' and is 9 bytes long
296
+ $ ldap_salt = substr ($ ldap_bytes , 0 , 9 );
297
+ }
298
+ elseif ( substr ($ ldap_bytes , 0 , 3 ) == '$1$ ' ) {
299
+ # if $ldap_password starts with '$1$': MD5 hashing, salt starts with $1$ and ends with '$'
300
+ $ exploded = explode ('$ ' , $ ldap_bytes , 4 );
301
+ $ ldap_salt = '$1$ ' . $ exploded [2 ] . '$ ' ;
302
+ }
303
+ elseif ( substr ($ ldap_bytes , 0 , 2 ) == '$2 ' ) {
304
+ # [NOT TESTABLE]if $ldap_password starts with '$2': Blowfish hash
305
+ $ exploded = explode ('$ ' , $ ldap_bytes , 4 );
306
+ $ ldap_salt = '$ ' . $ exploded [1 ] . '$ ' . $ exploded [2 ] . '$ ' . substr ($ exploded [3 ], 0 , 22 );
307
+ }
308
+ elseif ( substr ($ ldap_bytes , 0 , 3 ) == '$5$ ' ) {
309
+ # if $ldap_password starts with '$5$': sha256 sum
310
+ $ exploded = explode ('$ ' , $ ldap_bytes , 5 );
311
+ if ( substr ($ exploded [2 ], 0 , 7 ) == 'rounds= ' ) {
312
+ $ ldap_salt = '$5$ ' . $ exploded [2 ] . '$ ' . $ exploded [3 ] . '$ ' ;
313
+ } else {
314
+ $ ldap_salt = '$5$ ' . $ exploded [2 ] . '$ ' ;
315
+ }
316
+ }
317
+ # if $ldap_password starts with '$6$': sha512 sum, salt is 16 char long
318
+ elseif ( substr ($ ldap_bytes , 0 , 3 ) == '$6$ ' ) {
319
+ # if $ldap_password starts with '$6$': sha512 sum
320
+ $ exploded = explode ('$ ' , $ ldap_bytes , 5 );
321
+ if ( substr ($ exploded [2 ], 0 , 7 ) == 'rounds= ' ) {
322
+ $ ldap_salt = '$6$ ' . $ exploded [2 ] . '$ ' . $ exploded [3 ] . '$ ' ;
323
+ } else {
324
+ $ ldap_salt = '$6$ ' . $ exploded [2 ] . '$ ' ;
325
+ }
326
+ }
327
+ else {
328
+ # if $ldap password doesn't start with '$': DES hash, salt = two first letters
329
+ $ ldap_salt = substr ($ ldap_bytes , 0 , 2 );
330
+ }
331
+ $ old_password_hash = make_crypt_password_with_salt ($ old_password , $ ldap_salt );
332
+ }
333
+ }
334
+ else {
335
+ # Could not get the hash type, empty value for old_password_hash so that it fails
336
+ $ old_password_hash = "" ;
337
+ }
338
+ return $ old_password_hash ;
339
+ }
241
340
242
341
# Change password
243
342
# @return result code
@@ -267,7 +366,7 @@ function change_password( $ldap, $dn, $password, $ad_mode, $ad_options, $samba_m
267
366
if ( isset ($ userpassword ) ) {
268
367
if ( preg_match ( '/^\{(\w+)\}/ ' , $ userpassword [0 ], $ matches ) ) {
269
368
$ hash = strtoupper ($ matches [1 ]);
270
- }
369
+ }
271
370
}
272
371
}
273
372
}
0 commit comments