1 diff -urNp -x '*.orig' cyrus-sasl-2.1.27.org/Makefile.in cyrus-sasl-2.1.27/Makefile.in
2 --- cyrus-sasl-2.1.27.org/Makefile.in 2018-10-09 16:58:13.000000000 +0200
3 +++ cyrus-sasl-2.1.27/Makefile.in 2021-09-28 23:58:30.012662863 +0200
4 @@ -308,7 +308,7 @@ LDAP_LIBS = @LDAP_LIBS@
6 LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@
11 LIB_CRYPT = @LIB_CRYPT@
13 diff -urNp -x '*.orig' cyrus-sasl-2.1.27.org/doc/legacy/options.html cyrus-sasl-2.1.27/doc/legacy/options.html
14 --- cyrus-sasl-2.1.27.org/doc/legacy/options.html 2017-07-24 14:53:03.000000000 +0200
15 +++ cyrus-sasl-2.1.27/doc/legacy/options.html 2021-09-28 23:58:30.012662863 +0200
16 @@ -163,6 +163,14 @@ database.</TD>
20 +<TD>password_format</TD><TD></TD>
21 +<TD>Method of password storage (possible values: 'plain', 'crypt', 'crypt_trad').
22 +Default 'plain' is down-compatible with earlier versions. 'crypt_trad'
23 +uses old crypt format of 2 chars salt, 'crypt' automagically recognizes crypt
24 +formats from md5 crypt, blowfish crypt and old crypt (2 chars salt).</TD>
28 <TD>sql_engine</TD><TD>SQL plugin</TD>
29 <TD>Name of SQL engine to use (possible values: 'mysql', 'pgsql', 'sqlite', 'sqlite3').</TD>
30 <TD><tt>mysql</tt></TD>
31 diff -urNp -x '*.orig' cyrus-sasl-2.1.27.org/lib/checkpw.c cyrus-sasl-2.1.27/lib/checkpw.c
32 --- cyrus-sasl-2.1.27.org/lib/checkpw.c 2018-11-08 18:29:57.000000000 +0100
33 +++ cyrus-sasl-2.1.27/lib/checkpw.c 2021-09-28 23:58:30.012662863 +0200
38 +/******************************
39 + * crypt(3) patch start *
40 + ******************************/
41 +char *crypt(const char *key, const char *salt);
43 +/* cleartext password formats */
44 +#define PASSWORD_FORMAT_CLEARTEXT 1
45 +#define PASSWORD_FORMAT_CRYPT 2
46 +#define PASSWORD_FORMAT_CRYPTTRAD 3
47 +#define PASSWORD_SALT_BUF_LEN 22
49 +/* weeds out crypt(3) password's salt */
50 +int _sasl_get_salt (char *dest, char *src, int format);
52 +/******************************
53 + * crypt(3) patch stop *
54 + ******************************/
56 /* we store the following secret to check plaintext passwords:
58 @@ -142,7 +159,51 @@ static int auxprop_verify_password(sasl_
59 "*cmusaslsecretPLAIN",
61 struct propval auxprop_values[3];
64 + /******************************
65 + * crypt(3) patch start *
66 + * for password format check *
67 + ******************************/
68 + sasl_getopt_t *getopt;
70 + const char *p = NULL;
73 + * BLOWFISH: 16 char salt
75 + char salt[PASSWORD_SALT_BUF_LEN];
76 + int password_format;
78 + /* get password format from auxprop configuration */
79 + if (_sasl_getcallback(conn, SASL_CB_GETOPT, &getopt, &context) == SASL_OK) {
80 + getopt(context, NULL, "password_format", &p, NULL);
83 + /* set password format */
86 + memset(pass_format_str, '\0', PASSWORD_FORMAT_STR_LEN);
87 + strncpy(pass_format_str, p, (PASSWORD_FORMAT_STR_LEN - 1));
89 + /* modern, modular crypt(3) */
90 + if (strncmp(p, "crypt", 11) == 0)
91 + password_format = PASSWORD_FORMAT_CRYPT;
92 + /* traditional crypt(3) */
93 + else if (strncmp(p, "crypt_trad", 11) == 0)
94 + password_format = PASSWORD_FORMAT_CRYPTTRAD;
95 + /* cleartext password */
97 + password_format = PASSWORD_FORMAT_CLEARTEXT;
99 + /* cleartext password */
100 + password_format = PASSWORD_FORMAT_CLEARTEXT;
103 + /******************************
104 + * crypt(3) patch stop *
105 + * for password format check *
106 + ******************************/
108 if (!conn || !userstr)
109 return SASL_BADPARAM;
111 @@ -188,14 +249,31 @@ static int auxprop_verify_password(sasl_
115 - /* At the point this has been called, the username has been canonified
116 - * and we've done the auxprop lookup. This should be easy. */
117 - if(auxprop_values[0].name
118 - && auxprop_values[0].values
119 - && auxprop_values[0].values[0]
120 - && !strcmp(auxprop_values[0].values[0], passwd)) {
121 - /* We have a plaintext version and it matched! */
124 + /******************************
125 + * crypt(3) patch start *
126 + ******************************/
129 + _sasl_get_salt(salt, (char *) auxprop_values[0].values[0], password_format);
131 + /* crypt(3)-ed password? */
132 + if (password_format != PASSWORD_FORMAT_CLEARTEXT) {
133 + /* compare password */
134 + if (auxprop_values[0].name && auxprop_values[0].values && auxprop_values[0].values[0] && strcmp(crypt(passwd, salt), auxprop_values[0].values[0]) == 0)
137 + ret = SASL_BADAUTH;
139 + else if (password_format == PASSWORD_FORMAT_CLEARTEXT) {
140 + /* compare passwords */
141 + if (auxprop_values[0].name && auxprop_values[0].values && auxprop_values[0].values[0] && strcmp(auxprop_values[0].values[0], passwd) == 0)
144 + ret = SASL_BADAUTH;
145 + /******************************
146 + * crypt(3) patch stop *
147 + ******************************/
148 } else if(auxprop_values[1].name
149 && auxprop_values[1].values
150 && auxprop_values[1].values[0]) {
151 @@ -1105,3 +1183,37 @@ struct sasl_verify_password_s _sasl_veri
156 +/* weeds out crypt(3) password's salt */
157 +int _sasl_get_salt (char *dest, char *src, int format) {
158 + int num; /* how many characters is salt long? */
160 + case PASSWORD_FORMAT_CRYPT:
164 + /* blowfish crypt */
165 + else if (src[1] == '2')
166 + num = (src[1] == '2' && src[2] == 'a') ? 17 : 16;
167 + /* traditional crypt */
172 + case PASSWORD_FORMAT_CRYPTTRAD:
180 + /* destroy destination */
181 + memset(dest, '\0', (num + 1));
183 + /* copy salt to destination */
184 + strncpy(dest, src, num);