--- checkpw.c.orig Wed Oct 2 11:50:09 2002 +++ checkpw.c Sat Dec 21 23:34:57 2002 @@ -145,6 +145,16 @@ "*cmusaslsecretPLAIN", NULL }; struct propval auxprop_values[3]; + + char *cryptpwptr; +#ifndef MD5_DIGEST_LENGTH +#define MD5_DIGEST_LENGTH 16 +#endif + MD5_CTX ctx; + unsigned char md5digest[MD5_DIGEST_LENGTH]; + char md5pw[MD5_DIGEST_LENGTH*2+1]; + int dindex; + if (!conn || !userstr) return SASL_BADPARAM; @@ -186,10 +196,48 @@ * and we've done the auxprop lookup. This should be easy. */ if(auxprop_values[0].name && auxprop_values[0].values - && auxprop_values[0].values[0] - && !strcmp(auxprop_values[0].values[0], passwd)) { - /* We have a plaintext version and it matched! */ - return SASL_OK; + && auxprop_values[0].values[0]) { + /* We have a plaintext version and have to see whether this + matches with a) another plaintext, b) crypt or c) MD5 lookup */ + /* First, check the plaintext:plaintext case. This is for speed + and cases where there are '{' and '}' part of the password + (see LDAP rip off below). */ + if(strcmp(auxprop_values[0].values[0], passwd)) { + /* OK, no match so far. Now, rip of the "{crypt}" (if + present) preceeding our string. This might be the + case with crypt and MD5 entries gotten from LDAP. */ + if(strstr(auxprop_values[0].values[0], "{crypt}") + == (char *)auxprop_values[0].values[0]) { + memmove((char *)auxprop_values[0].values[0], + strchr(auxprop_values[0].values[0],'}')+1, + strlen(strchr(auxprop_values[0].values[0],'}'))); + } + /* Canonified. OK, try crypt. Note that the crypt() that + ships with newer glibc's also provide "$1$..."-style MD5 + passwords strings. These are of a different format than + the MD5 password strings a MySQL uses (see the code below). */ + cryptpwptr = (char *)crypt(passwd,auxprop_values[0].values[0]); + if (strcmp(auxprop_values[0].values[0], cryptpwptr)) { + /* No crypt version either. Then try MD5 for MySQL. + We use cryptpwptr as a helper here only. */ + _sasl_MD5Init(&ctx); + _sasl_MD5Update(&ctx,passwd,strlen(passwd)); + _sasl_MD5Final(md5digest, &ctx); + for (dindex = 0, cryptpwptr = md5pw; + dindex < MD5_DIGEST_LENGTH; + dindex++, cryptpwptr += 2) { + sprintf(cryptpwptr, "%02x", md5digest[dindex]); + } + *cryptpwptr = '\0'; + if (strcmp(auxprop_values[0].values[0], md5pw)) { + /* Even not an MD5 one? Then we give up. */ + ret = SASL_BADAUTH; + goto done; + } + } + } + ret = SASL_OK; + } else if(auxprop_values[1].name && auxprop_values[1].values && auxprop_values[1].values[0]) {