--- cyrus-sasl2-2.1.22.dfsg1.orig/debian/patches/0021_crypted_passwords.dpatch +++ cyrus-sasl2-2.1.22.dfsg1/debian/patches/0021_crypted_passwords.dpatch @@ -0,0 +1,162 @@ +#! /bin/sh /usr/share/dpatch/dpatch-run +## 0021_crypted_passwords.dpatch by Karsten Behrens +## +## All lines beginning with `## DP:' are a description of the patch. +## DP: Enable encrypted stored passwords + +@DPATCH@ +diff -urNad trunk~/lib/checkpw.c trunk/lib/checkpw.c +--- trunk~/lib/checkpw.c ++++ trunk/lib/checkpw.c +@@ -94,6 +94,23 @@ + # endif + #endif + ++/****************************** ++ * crypt(3) patch start * ++ ******************************/ ++char *crypt(const char *key, const char *salt); ++ ++/* cleartext password formats */ ++#define PASSWORD_FORMAT_CLEARTEXT 1 ++#define PASSWORD_FORMAT_CRYPT 2 ++#define PASSWORD_FORMAT_CRYPTTRAD 3 ++#define PASSWORD_SALT_BUF_LEN 22 ++ ++/* weeds out crypt(3) password's salt */ ++int _sasl_get_salt (char *dest, char *src, int format); ++ ++/****************************** ++ * crypt(3) patch stop * ++ ******************************/ + + /* we store the following secret to check plaintext passwords: + * +@@ -143,6 +160,50 @@ + "*cmusaslsecretPLAIN", + NULL }; + struct propval auxprop_values[3]; ++ ++ /****************************** ++ * crypt(3) patch start * ++ * for password format check * ++ ******************************/ ++ sasl_getopt_t *getopt; ++ void *context; ++ const char *p = NULL; ++ /** ++ * MD5: 12 char salt ++ * BLOWFISH: 16 char salt ++ */ ++ char salt[PASSWORD_SALT_BUF_LEN]; ++ 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) { ++ /* ++ memset(pass_format_str, '\0', PASSWORD_FORMAT_STR_LEN); ++ strncpy(pass_format_str, p, (PASSWORD_FORMAT_STR_LEN - 1)); ++ */ ++ /* modern, modular crypt(3) */ ++ if (strncmp(p, "crypt", 11) == 0) ++ password_format = PASSWORD_FORMAT_CRYPT; ++ /* traditional crypt(3) */ ++ else if (strncmp(p, "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; ++ } ++ ++ /****************************** ++ * crypt(3) patch stop * ++ * for password format check * ++ ******************************/ + + if (!conn || !userstr) + return SASL_BADPARAM; +@@ -179,15 +240,30 @@ + ret = SASL_BADPARAM; + goto done; + } ++ /****************************** ++ * crypt(3) patch start * ++ ******************************/ + +- /* 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; ++ /* get salt */ ++ _sasl_get_salt(salt, (char *) auxprop_values[0].values[0], password_format); ++ ++ /* crypt(3)-ed password? */ ++ if (password_format != PASSWORD_FORMAT_CLEARTEXT) { ++ /* compare password */ ++ 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; ++ /****************************** ++ * crypt(3) patch stop * ++ ******************************/ + } else if(auxprop_values[1].name + && auxprop_values[1].values + && auxprop_values[1].values[0]) { +@@ -975,3 +1051,37 @@ + #endif + { NULL, NULL } + }; ++ ++/* weeds out crypt(3) password's salt */ ++int _sasl_get_salt (char *dest, char *src, int format) { ++ int num; /* how many characters is salt long? */ ++ switch (format) { ++ case PASSWORD_FORMAT_CRYPT: ++ /* md5 crypt */ ++ if (src[1] == '1') ++ num = 12; ++ /* blowfish crypt */ ++ else if (src[1] == '2') ++ num = (src[1] == '2' && src[2] == 'a') ? 17 : 16; ++ /* traditional crypt */ ++ else ++ num = 2; ++ break; ++ ++ case PASSWORD_FORMAT_CRYPTTRAD: ++ num = 2; ++ break; ++ ++ default: ++ return 1; ++ } ++ ++ /* destroy destination */ ++ memset(dest, '\0', (num + 1)); ++ ++ /* copy salt to destination */ ++ strncpy(dest, src, num); ++ ++ return 1; ++} ++