--- lib/checkpw.c.orig	2003-12-28 02:18:33.200763643 +0100
+++ lib/checkpw.c	2003-12-28 01:44:24.952792192 +0100
@@ -94,6 +94,13 @@
 # endif
 #endif
 
+/* cleartext password formats */
+#define PASSWORD_FORMAT_CLEARTEXT 1
+#define PASSWORD_FORMAT_CRYPT 2
+#define PASSWORD_FORMAT_CRYPTTRAD 3
+/* weeds out crypt(3) password's salt */
+int _sasl_get_salt (char *dest, char *src, int format);
+
 
 /* we store the following secret to check plaintext passwords:
  *
@@ -143,6 +150,44 @@
 				       "*cmusaslsecretPLAIN",
 				       NULL };
     struct propval auxprop_values[3];
+
+    /* for password format check */
+    sasl_getopt_t *getopt;
+    void *context;
+    const char *p = NULL;
+    char pass_format_str[11];
+    /*
+     * MD5: 12 char salt
+     * BLOWFISH: 16 char salt
+     */
+    char salt[17];
+    int password_format;
+
+	/* get password format from auxprop configuration */
+	if (_sasl_getcallback(conn, SASL_CB_GETOPT, &getopt, &context) == SASL_OK) {
+		getopt(context, NULL, "password_format", &p, NULL);
+	}
+
+	/* set password format */
+	if (p) {
+		strncpy(pass_format_str, p, 9);
+		
+		/* modern, modular crypt(3) */
+		if (strncmp(pass_format_str, "crypt", 11) == 0)
+			password_format = PASSWORD_FORMAT_CRYPT;
+		/* traditional crypt(3) */
+		else if (strncmp(pass_format_str, "crypt_trad", 11) == 0)
+			password_format = PASSWORD_FORMAT_CRYPTTRAD;
+		/* cleartext password */
+		else
+			password_format = PASSWORD_FORMAT_CLEARTEXT;
+
+	} else {
+		/* cleartext password */
+		password_format = PASSWORD_FORMAT_CLEARTEXT;
+	}
+
+
     
     if (!conn || !userstr)
 	return SASL_BADPARAM;
@@ -182,37 +227,76 @@
 
     /* At the point this has been called, the username has been canonified
      * 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;
-    } else if(auxprop_values[1].name
-	      && auxprop_values[1].values
-	      && auxprop_values[1].values[0]) {
-	const char *db_secret = auxprop_values[1].values[0];
-	sasl_secret_t *construct;
-	
-	ret = _sasl_make_plain_secret(db_secret, passwd,
-				      strlen(passwd),
-				      &construct);
-	if (ret != SASL_OK) {
-	    goto done;
-	}
-
-	if (!memcmp(db_secret, construct->data, construct->len)) {
-	    /* password verified! */
-	    ret = SASL_OK;
-	} else {
-	    /* passwords do not match */
-	    ret = SASL_BADAUTH;
-	}
 
-	sasl_FREE(construct);
+    /* check password, but with specified password format */
+    if (password_format == PASSWORD_FORMAT_CRYPT) {
+	    _sasl_get_salt(salt, auxprop_values[0].values[0], PASSWORD_FORMAT_CRYPT);
+
+	    /* compare passwords */
+	    if (
+	    	auxprop_values[0].name &&
+	        auxprop_values[0].values &&
+			auxprop_values[0].values[0] &&
+			strcmp(crypt(passwd, salt), auxprop_values[0].values[0]) == 0
+	       ) {
+		    return SASL_OK;
+		 } else
+		 	ret = SASL_BADAUTH;
+    }
+    else if (password_format == PASSWORD_FORMAT_CRYPTTRAD) {
+	    _sasl_get_salt(salt, auxprop_values[0].values[0], PASSWORD_FORMAT_CRYPTTRAD);
+	    
+	    /* compare passwords */
+	    if (
+	    	auxprop_values[0].name &&
+	        auxprop_values[0].values &&
+			auxprop_values[0].values[0] &&
+			strcmp(crypt(passwd, salt), auxprop_values[0].values[0]) == 0
+	       ) {
+		    return SASL_OK;
+		 } else
+		 	ret = SASL_BADAUTH;
+    }
+    else if (password_format == PASSWORD_FORMAT_CLEARTEXT) {
+	    
+	    /* compare passwords */
+	    if (
+	    	auxprop_values[0].name &&
+	        auxprop_values[0].values &&
+			auxprop_values[0].values[0] &&
+			strcmp(auxprop_values[0].values[0], passwd) == 0
+	       ) {
+		    return SASL_OK;
+		 } else
+		 	ret = SASL_BADAUTH;
+    }
+    /* original SASL checks continue here */
+    else if (auxprop_values[1].name &&
+	     auxprop_values[1].values &&
+	     auxprop_values[1].values[0]) {
+
+	    const char *db_secret = auxprop_values[1].values[0];
+	    sasl_secret_t *construct;
+
+	    ret = _sasl_make_plain_secret(db_secret, passwd,
+			    strlen(passwd), &construct);
+
+	    if (ret != SASL_OK) {
+		    goto done;
+            }
+	    
+	    if (!memcmp(db_secret, construct->data, construct->len)) {
+		    /* password verified! */
+		    ret = SASL_OK;
+	    } else {
+		    /* passwords do not match */
+		    ret = SASL_BADAUTH;
+	    }
+		    
+	    sasl_FREE(construct);
     } else {
-	/* passwords do not match */
-	ret = SASL_BADAUTH;
+		/* passwords do not match */
+		ret = SASL_BADAUTH;
     }
 
  done:
@@ -664,3 +748,39 @@
 #endif     
     { NULL, NULL }
 };
+
+/* weeds out crypt(3) password's salt */
+int _sasl_get_salt (char *dest, char *src, int format) {
+	/* how many characters is salt long? */
+	int num;
+
+	switch (format) {
+		case PASSWORD_FORMAT_CRYPT:
+			/* md5 crypt */
+			if (src[1] == '1')
+				num = 12;
+			/* blowfish crypt */
+			else if (src[1] == '2')
+				num = 16;
+			/* traditional crypt */
+			else
+				num = 2;
+	
+		break;
+		
+		case PASSWORD_FORMAT_CRYPTTRAD:
+			num = 2;
+		break;
+	
+		default:
+			num = 0;
+	}
+
+	/* copy salt to destination */
+	strncpy(dest, src, num);
+
+	/* terminate string */
+	dest[num] = '\0';
+
+	return 1;
+}

