|
Lines 94-99
Link Here
|
| 94 |
# endif |
94 |
# endif |
| 95 |
#endif |
95 |
#endif |
| 96 |
|
96 |
|
|
|
97 |
/* cleartext password formats */ |
| 98 |
#define PASSWORD_FORMAT_CLEARTEXT 1 |
| 99 |
#define PASSWORD_FORMAT_CRYPT 2 |
| 100 |
#define PASSWORD_FORMAT_CRYPTTRAD 3 |
| 101 |
/* weeds out crypt(3) password's salt */ |
| 102 |
int _sasl_get_salt (char *dest, char *src, int format); |
| 103 |
|
| 97 |
|
104 |
|
| 98 |
/* we store the following secret to check plaintext passwords: |
105 |
/* we store the following secret to check plaintext passwords: |
| 99 |
* |
106 |
* |
|
Lines 143-148
Link Here
|
| 143 |
"*cmusaslsecretPLAIN", |
150 |
"*cmusaslsecretPLAIN", |
| 144 |
NULL }; |
151 |
NULL }; |
| 145 |
struct propval auxprop_values[3]; |
152 |
struct propval auxprop_values[3]; |
|
|
153 |
|
| 154 |
/* for password format check */ |
| 155 |
sasl_getopt_t *getopt; |
| 156 |
void *context; |
| 157 |
const char *p = NULL; |
| 158 |
char pass_format_str[11]; |
| 159 |
/* |
| 160 |
* MD5: 12 char salt |
| 161 |
* BLOWFISH: 16 char salt |
| 162 |
*/ |
| 163 |
char salt[17]; |
| 164 |
int password_format; |
| 165 |
|
| 166 |
/* get password format from auxprop configuration */ |
| 167 |
if (_sasl_getcallback(conn, SASL_CB_GETOPT, &getopt, &context) == SASL_OK) { |
| 168 |
getopt(context, NULL, "password_format", &p, NULL); |
| 169 |
} |
| 170 |
|
| 171 |
/* set password format */ |
| 172 |
if (p) { |
| 173 |
strncpy(pass_format_str, p, 9); |
| 174 |
|
| 175 |
/* modern, modular crypt(3) */ |
| 176 |
if (strncmp(pass_format_str, "crypt", 11) == 0) |
| 177 |
password_format = PASSWORD_FORMAT_CRYPT; |
| 178 |
/* traditional crypt(3) */ |
| 179 |
else if (strncmp(pass_format_str, "crypt_trad", 11) == 0) |
| 180 |
password_format = PASSWORD_FORMAT_CRYPTTRAD; |
| 181 |
/* cleartext password */ |
| 182 |
else |
| 183 |
password_format = PASSWORD_FORMAT_CLEARTEXT; |
| 184 |
|
| 185 |
} else { |
| 186 |
/* cleartext password */ |
| 187 |
password_format = PASSWORD_FORMAT_CLEARTEXT; |
| 188 |
} |
| 189 |
|
| 190 |
|
| 146 |
|
191 |
|
| 147 |
if (!conn || !userstr) |
192 |
if (!conn || !userstr) |
| 148 |
return SASL_BADPARAM; |
193 |
return SASL_BADPARAM; |
|
Lines 182-218
Link Here
|
| 182 |
|
227 |
|
| 183 |
/* At the point this has been called, the username has been canonified |
228 |
/* At the point this has been called, the username has been canonified |
| 184 |
* and we've done the auxprop lookup. This should be easy. */ |
229 |
* and we've done the auxprop lookup. This should be easy. */ |
| 185 |
if(auxprop_values[0].name |
|
|
| 186 |
&& auxprop_values[0].values |
| 187 |
&& auxprop_values[0].values[0] |
| 188 |
&& !strcmp(auxprop_values[0].values[0], passwd)) { |
| 189 |
/* We have a plaintext version and it matched! */ |
| 190 |
return SASL_OK; |
| 191 |
} else if(auxprop_values[1].name |
| 192 |
&& auxprop_values[1].values |
| 193 |
&& auxprop_values[1].values[0]) { |
| 194 |
const char *db_secret = auxprop_values[1].values[0]; |
| 195 |
sasl_secret_t *construct; |
| 196 |
|
| 197 |
ret = _sasl_make_plain_secret(db_secret, passwd, |
| 198 |
strlen(passwd), |
| 199 |
&construct); |
| 200 |
if (ret != SASL_OK) { |
| 201 |
goto done; |
| 202 |
} |
| 203 |
|
| 204 |
if (!memcmp(db_secret, construct->data, construct->len)) { |
| 205 |
/* password verified! */ |
| 206 |
ret = SASL_OK; |
| 207 |
} else { |
| 208 |
/* passwords do not match */ |
| 209 |
ret = SASL_BADAUTH; |
| 210 |
} |
| 211 |
|
230 |
|
| 212 |
sasl_FREE(construct); |
231 |
/* check password, but with specified password format */ |
|
|
232 |
if (password_format == PASSWORD_FORMAT_CRYPT) { |
| 233 |
_sasl_get_salt(salt, auxprop_values[0].values[0], PASSWORD_FORMAT_CRYPT); |
| 234 |
|
| 235 |
/* compare passwords */ |
| 236 |
if ( |
| 237 |
auxprop_values[0].name && |
| 238 |
auxprop_values[0].values && |
| 239 |
auxprop_values[0].values[0] && |
| 240 |
strcmp(crypt(passwd, salt), auxprop_values[0].values[0]) == 0 |
| 241 |
) { |
| 242 |
return SASL_OK; |
| 243 |
} else |
| 244 |
ret = SASL_BADAUTH; |
| 245 |
} |
| 246 |
else if (password_format == PASSWORD_FORMAT_CRYPTTRAD) { |
| 247 |
_sasl_get_salt(salt, auxprop_values[0].values[0], PASSWORD_FORMAT_CRYPTTRAD); |
| 248 |
|
| 249 |
/* compare passwords */ |
| 250 |
if ( |
| 251 |
auxprop_values[0].name && |
| 252 |
auxprop_values[0].values && |
| 253 |
auxprop_values[0].values[0] && |
| 254 |
strcmp(crypt(passwd, salt), auxprop_values[0].values[0]) == 0 |
| 255 |
) { |
| 256 |
return SASL_OK; |
| 257 |
} else |
| 258 |
ret = SASL_BADAUTH; |
| 259 |
} |
| 260 |
else if (password_format == PASSWORD_FORMAT_CLEARTEXT) { |
| 261 |
|
| 262 |
/* compare passwords */ |
| 263 |
if ( |
| 264 |
auxprop_values[0].name && |
| 265 |
auxprop_values[0].values && |
| 266 |
auxprop_values[0].values[0] && |
| 267 |
strcmp(auxprop_values[0].values[0], passwd) == 0 |
| 268 |
) { |
| 269 |
return SASL_OK; |
| 270 |
} else |
| 271 |
ret = SASL_BADAUTH; |
| 272 |
} |
| 273 |
/* original SASL checks continue here */ |
| 274 |
else if (auxprop_values[1].name && |
| 275 |
auxprop_values[1].values && |
| 276 |
auxprop_values[1].values[0]) { |
| 277 |
|
| 278 |
const char *db_secret = auxprop_values[1].values[0]; |
| 279 |
sasl_secret_t *construct; |
| 280 |
|
| 281 |
ret = _sasl_make_plain_secret(db_secret, passwd, |
| 282 |
strlen(passwd), &construct); |
| 283 |
|
| 284 |
if (ret != SASL_OK) { |
| 285 |
goto done; |
| 286 |
} |
| 287 |
|
| 288 |
if (!memcmp(db_secret, construct->data, construct->len)) { |
| 289 |
/* password verified! */ |
| 290 |
ret = SASL_OK; |
| 291 |
} else { |
| 292 |
/* passwords do not match */ |
| 293 |
ret = SASL_BADAUTH; |
| 294 |
} |
| 295 |
|
| 296 |
sasl_FREE(construct); |
| 213 |
} else { |
297 |
} else { |
| 214 |
/* passwords do not match */ |
298 |
/* passwords do not match */ |
| 215 |
ret = SASL_BADAUTH; |
299 |
ret = SASL_BADAUTH; |
| 216 |
} |
300 |
} |
| 217 |
|
301 |
|
| 218 |
done: |
302 |
done: |
|
Lines 664-666
Link Here
|
| 664 |
#endif |
748 |
#endif |
| 665 |
{ NULL, NULL } |
749 |
{ NULL, NULL } |
| 666 |
}; |
750 |
}; |
|
|
751 |
|
| 752 |
/* weeds out crypt(3) password's salt */ |
| 753 |
int _sasl_get_salt (char *dest, char *src, int format) { |
| 754 |
/* how many characters is salt long? */ |
| 755 |
int num; |
| 756 |
|
| 757 |
switch (format) { |
| 758 |
case PASSWORD_FORMAT_CRYPT: |
| 759 |
/* md5 crypt */ |
| 760 |
if (src[1] == '1') |
| 761 |
num = 12; |
| 762 |
/* blowfish crypt */ |
| 763 |
else if (src[1] == '2') |
| 764 |
num = 16; |
| 765 |
/* traditional crypt */ |
| 766 |
else |
| 767 |
num = 2; |
| 768 |
|
| 769 |
break; |
| 770 |
|
| 771 |
case PASSWORD_FORMAT_CRYPTTRAD: |
| 772 |
num = 2; |
| 773 |
break; |
| 774 |
|
| 775 |
default: |
| 776 |
num = 0; |
| 777 |
} |
| 778 |
|
| 779 |
/* copy salt to destination */ |
| 780 |
strncpy(dest, src, num); |
| 781 |
|
| 782 |
/* terminate string */ |
| 783 |
dest[num] = '\0'; |
| 784 |
|
| 785 |
return 1; |
| 786 |
} |