4646 */
4747class OSS_Auth_Password
4848{
49- const HASH_PLAINTEXT = 'plaintext ' ;
50- const HASH_PLAIN = 'plain ' ;
51- const HASH_BCRYPT = 'bcrypt ' ;
52- const HASH_MD5 = 'md5 ' ;
53- const HASH_MD5_SALTED = 'md5.salted ' ;
54- const HASH_SHA1 = 'sha1 ' ;
55- const HASH_SHA1_SALTED = 'sha1.salted ' ;
56- const HASH_DOVECOT = 'dovecot: ' ;
57- const HASH_CRYPT = 'crypt: ' ;
58- const HASH_UNKNOWN = '*unknown* ' ;
59-
60-
49+ const HASH_PLAINTEXT = 'plaintext ' ;
50+ const HASH_PLAIN = 'plain ' ;
51+ const HASH_BCRYPT = 'bcrypt ' ;
52+ const HASH_MD5 = 'md5 ' ;
53+ const HASH_MD5_SALTED = 'md5-salted ' ;
54+ const HASH_SHA1 = 'sha1 ' ;
55+ const HASH_SHA1_SALTED = 'sha1-salted ' ;
56+ const HASH_DOVECOT = 'dovecot: ' ;
57+ const HASH_CRYPT = 'crypt: ' ;
58+ const HASH_UNKNOWN = '*unknown* ' ;
59+
60+ // Bad salts - in April 2016 it was pointed out that a typo in the code below meant that
61+ // md5.salted and sha1.salted didn't actually use the requested salt string but a fixed
62+ // salt of "md5.salted" and "sha1.salted" respectivily.
63+ // These constants are for backwards compatibility for anyone that used those:
64+ const HASH_MD5_BADSALT = 'md5.salted ' ;
65+ const HASH_SHA1_BADSALT = 'sha1.salted ' ;
66+
6167 /**
6268 * A generic password hashing method using a given configuration array
6369 *
6470 * The parameters expected in `$config` are:
6571 *
6672 * * `pwhash` - a hashing method from the `HASH_` constants in this class
73+ * * `pwsalt` - a hashing salt for HASH_SHA1_SALTED and HASH_MD5_SALTED
6774 * * `hash_cost` - a *cost* parameter for certain hashing functions - e.g. bcrypt (defaults to 9)
6875 *
6976 * @param string $pw The plaintext password to hash
@@ -74,17 +81,17 @@ class OSS_Auth_Password
7481 public static function hash ( $ pw , $ config )
7582 {
7683 $ hash = self ::HASH_UNKNOWN ;
77-
84+
7885 if ( is_array ( $ config ) )
7986 {
8087 if ( !isset ( $ config ['pwhash ' ] ) )
8188 throw new OSS_Exception ( 'Cannot hash password without a hash method ' );
82-
89+
8390 $ hash = $ config ['pwhash ' ];
8491 }
8592 else
8693 $ hash = $ config ;
87-
94+
8895 if ( substr ( $ hash , 0 , 8 ) == 'dovecot: ' )
8996 {
9097 return ViMbAdmin_Dovecot::password ( substr ( $ hash , 8 ), $ pw , $ config ['username ' ] );
@@ -114,7 +121,7 @@ public static function hash( $pw, $config )
114121 default :
115122 throw new OSS_Exception ( 'Unknown crypt password hashing method ' );
116123 }
117- return crypt ( $ pw , $ salt );
124+ return crypt ( $ pw , $ salt );
118125 }
119126 else
120127 {
@@ -124,11 +131,11 @@ public static function hash( $pw, $config )
124131 case self ::HASH_PLAIN :
125132 return $ pw ;
126133 break ;
127-
134+
128135 case self ::HASH_BCRYPT :
129136 if ( !isset ( $ config ['hash_cost ' ] ) )
130137 $ config ['hash_cost ' ] = 9 ;
131-
138+
132139 $ bcrypt = new OSS_Crypt_Bcrypt ( $ config ['hash_cost ' ] );
133140 return $ bcrypt ->hash ( $ pw );
134141 break ;
@@ -138,19 +145,29 @@ public static function hash( $pw, $config )
138145 break ;
139146
140147 case self ::HASH_MD5_SALTED :
141- return md5 ( $ pw . $ config ['pwhash ' ] );
148+ return md5 ( $ pw . $ config ['pwsalt ' ] );
142149 break ;
143150
144151 case self ::HASH_SHA1 :
145152 return sha1 ( $ pw );
146153 break ;
147154
148155 case self ::HASH_SHA1_SALTED :
156+ return sha1 ( $ pw . $ config ['pwsalt ' ] );
157+ break ;
158+
159+
160+
161+ case self ::HASH_MD5_BADSALT :
162+ return md5 ( $ pw . $ config ['pwhash ' ] );
163+ break ;
164+
165+ case self ::HASH_SHA1_BADSALT :
149166 return sha1 ( $ pw . $ config ['pwhash ' ] );
150167 break ;
151168
152169 // UPDATE PHPDOC ABOVE WHEN ADDING NEW METHODS!
153-
170+
154171 default :
155172 throw new OSS_Exception ( 'Unknown password hashing method ' );
156173 }
@@ -176,18 +193,18 @@ public static function verify( $pwplain, $pwhash, $config )
176193 {
177194 if ( !isset ( $ config ['pwhash ' ] ) )
178195 throw new OSS_Exception ( 'Cannot verify password without a hash method ' );
179-
196+
180197 $ hash = $ config ['pwhash ' ];
181198 }
182199 else
183200 $ hash = $ config ;
184-
201+
185202 switch ( $ config ['pwhash ' ] )
186203 {
187204 case self ::HASH_BCRYPT :
188205 if ( !isset ( $ config ['hash_cost ' ] ) )
189206 $ config ['hash_cost ' ] = 9 ;
190-
207+
191208 $ bcrypt = new OSS_Crypt_Bcrypt ( $ config ['hash_cost ' ] );
192209 return $ bcrypt ->verify ( $ pwplain , $ pwhash );
193210 break ;
0 commit comments