1 diff -ur courier-imap-1.3.12.orig/authlib/authmysqllib.c courier-imap-1.3.12/authlib/authmysqllib.c
2 --- courier-imap-1.3.12.orig/authlib/authmysqllib.c Mon Aug 6 05:12:39 2001
3 +++ courier-imap-1.3.12/authlib/authmysqllib.c Sun Dec 9 23:58:55 2001
6 static const char rcsid[]="$Id$";
8 +struct var_data { /* siefca@pld.org.pl */
14 static const char *read_env(const char *env)
16 static char *mysqlauth=0;
19 for (i=0; i<mysqlauth_size; i++)
20 if (mysqlauth[i] == '\n')
22 + { /* siefca@pld.org.pl */
23 + if (i && mysqlauth[i-1] == '\\')
32 @@ -199,17 +211,218 @@
33 strcat(strcpy(p, "@"), defdomain);
36 +/* siefca@pld.org.pl */
37 +static char *parse_string (const char *source, size_t init_bufsize,
38 + struct var_data *vd)
40 + struct var_data *vdp;
41 + static size_t querybuf_size = 0; /* will learn after first run */
45 + char *p, *q, *r, *querybuf;
47 + if (source == NULL || *source == '\0' ||
48 + vd == NULL || vd[0].name == NULL)
51 + if (!querybuf_size) /* first time invoked */
53 + querybuf_size = 10 +
55 + strlen(source); /* initial value */
56 + /* assuming that each value of the expected variables
57 + * will appear once... if it is too small
58 + * (e.g. will appear more than once) don't worry,
59 + * we will expand amount of memory later
61 + for (vdp=vd; vdp->name; vdp++)
62 + querybuf_size += strlen (vdp->value);
64 + querybuf = malloc(querybuf_size);
76 + if (!p || *p == '\0') break;
78 + if (*p == '\0' || *p == ')') break;
80 + if (!r || (r-p+1) > (32*sizeof(char))) break;
81 + for (vdp=vd; vdp->name; vdp++)
83 + if (r-p+1 == vdp->size &&
84 + !strncmp(p, vdp->name, r-p))
90 + if (vdp->name == NULL)
92 + fprintf(stderr, "authmysql: unknown variable in "
93 + "substitution: $(%.*s)\n", r-p, p);
96 + willtake = (strlen(vdp->value))+(p-q);
97 + if (willtake+querybuf_taken >= querybuf_size-16)
99 + querybuf_size += willtake + 16;
100 + /* learned new querybuf's size */
101 + querybuf=realloc(querybuf, querybuf_size);
104 + perror ("realloc");
107 + /* warning: querybuf's address may have change! */
108 + /* but for now it's safe... */
110 + strncat(querybuf, q, p-q-2);
111 + strcat(querybuf, vdp->value);
112 + querybuf_taken += willtake;
115 + willtake = (strlen(q));
116 + if (willtake+querybuf_taken >= querybuf_size-16)
118 + querybuf_size += willtake + 16;
119 + querybuf=realloc(querybuf, querybuf_size);
122 + perror ("realloc");
126 + strcat(querybuf, q);
131 +/* siefca@pld.org.pl */
132 +static const char *get_localpart (const char *username)
135 + static char localpart_buf[130];
137 + if (!username || *username == '\0') return NULL;
138 + p = strchr(username,'@');
141 + if (p-username > 128) return NULL;
142 + strncpy (localpart_buf, username, p-username);
146 + if ((strlen(username)) > 128) return NULL;
147 + strcpy (localpart_buf, username);
150 + for (p = localpart_buf; *p; p++)
151 + if (*p == '\\' || (int)(unsigned char)*p < ' ')
154 + return localpart_buf;
157 +/* siefca@pld.org.pl */
158 +static const char *get_domain (const char *username, const char *defdomain)
160 + static char domain_buf[260];
163 + if (!username || *username == '\0') return NULL;
164 + p = strchr(username,'@');
169 + if ((strlen(p)) > 256) return NULL;
170 + for (q=domain_buf; *p; p++, q++)
171 + if (*p == '\\' || (int)(unsigned char)*p < ' ')
178 + if (defdomain && *defdomain) return defdomain;
183 +/* siefca@pld.org.pl */
184 +static char *parse_select_clause (const char *clause, const char *username,
185 + const char *defdomain)
187 +static struct var_data vd[]={
188 + {"local_part", NULL, sizeof("local_part")},
189 + {"domain", NULL, sizeof("domain")},
192 + if (clause == NULL || *clause == '\0' ||
193 + !username || *username == '\0') return NULL;
195 + vd[0].value=get_localpart (username);
196 + vd[1].value=get_domain (username, defdomain);
197 + if (!vd[0].value || !vd[1].value) return NULL;
199 + return (parse_string (clause, 16, vd));
202 +/* siefca@pld.org.pl */
203 +static char *parse_chpass_clause (const char *clause, const char *username,
204 + const char *defdomain, const char *newpass,
205 + const char *newpass_crypt)
207 +static struct var_data vd[]={
208 + {"local_part", NULL, sizeof("local_part")},
209 + {"domain", NULL, sizeof("domain")},
210 + {"newpass", NULL, sizeof("newpass")},
211 + {"newpass_crypt", NULL, sizeof("newpass_crypt")},
214 + if (clause == NULL || *clause == '\0' ||
215 + !username || *username == '\0' ||
216 + !newpass || *newpass == '\0' ||
217 + !newpass_crypt || *newpass_crypt == '\0') return NULL;
219 + vd[0].value=get_localpart (username);
220 + vd[1].value=get_domain (username, defdomain);
221 + vd[2].value=newpass;
222 + vd[3].value=newpass_crypt;
223 + if (!vd[0].value || !vd[1].value) return NULL;
225 + return (parse_string (clause, 16, vd));
229 struct authmysqluserinfo *auth_mysql_getuserinfo(const char *username)
231 -const char *user_table;
232 -const char *defdomain;
233 +const char *user_table =NULL;
234 +const char *defdomain =NULL;
239 -const char *crypt_field, *clear_field, *maildir_field, *home_field,
241 - *login_field, *uid_field, *gid_field, *quota_field, *where_clause;
242 +const char *crypt_field =NULL,
243 + *clear_field =NULL,
244 + *maildir_field =NULL,
247 + *login_field =NULL,
250 + *quota_field =NULL,
251 + *where_clause =NULL,
252 + *select_clause =NULL; /* siefca@pld.org.pl */
254 static const char query[]=
255 "SELECT %s, %s, %s, %s, %s, %s, %s, %s, %s FROM %s WHERE %s = \"";
256 @@ -232,79 +445,95 @@
258 memset(&ui, 0, sizeof(ui));
260 - user_table=read_env("MYSQL_USER_TABLE");
261 - defdomain=read_env("DEFAULT_DOMAIN");
264 + select_clause=read_env("MYSQL_SELECT_CLAUSE");
265 + defdomain=read_env("DEFAULT_DOMAIN");
267 + if (!select_clause) /* siefca@pld.org.pl */
269 - fprintf(stderr, "authmysql: MYSQL_USER_TABLE not set in "
270 - AUTHMYSQLRC ".\n");
273 + user_table=read_env("MYSQL_USER_TABLE");
275 - crypt_field=read_env("MYSQL_CRYPT_PWFIELD");
276 - clear_field=read_env("MYSQL_CLEAR_PWFIELD");
277 - name_field=read_env("MYSQL_NAME_FIELD");
280 + fprintf(stderr, "authmysql: MYSQL_USER_TABLE not set in "
281 + AUTHMYSQLRC ".\n");
285 - if (!crypt_field && !clear_field)
288 - "authmysql: MYSQL_CRYPT_PWFIELD and "
289 - "MYSQL_CLEAR_PWFIELD not set in " AUTHMYSQLRC ".\n");
292 - if (!crypt_field) crypt_field="\"\"";
293 - if (!clear_field) clear_field="\"\"";
294 - if (!name_field) name_field="\"\"";
295 + crypt_field=read_env("MYSQL_CRYPT_PWFIELD");
296 + clear_field=read_env("MYSQL_CLEAR_PWFIELD");
297 + name_field=read_env("MYSQL_NAME_FIELD");
299 - uid_field = read_env("MYSQL_UID_FIELD");
300 - if (!uid_field) uid_field = "uid";
301 + if (!crypt_field && !clear_field)
304 + "authmysql: MYSQL_CRYPT_PWFIELD and "
305 + "MYSQL_CLEAR_PWFIELD not set in " AUTHMYSQLRC ".\n");
308 + if (!crypt_field) crypt_field="\"\"";
309 + if (!clear_field) clear_field="\"\"";
310 + if (!name_field) name_field="\"\"";
312 + uid_field = read_env("MYSQL_UID_FIELD");
313 + if (!uid_field) uid_field = "uid";
315 - gid_field = read_env("MYSQL_GID_FIELD");
316 - if (!gid_field) gid_field = "gid";
317 + gid_field = read_env("MYSQL_GID_FIELD");
318 + if (!gid_field) gid_field = "gid";
320 - login_field = read_env("MYSQL_LOGIN_FIELD");
321 - if (!login_field) login_field = "id";
322 + login_field = read_env("MYSQL_LOGIN_FIELD");
323 + if (!login_field) login_field = "id";
325 - home_field = read_env("MYSQL_HOME_FIELD");
326 - if (!home_field) home_field = "home";
327 + home_field = read_env("MYSQL_HOME_FIELD");
328 + if (!home_field) home_field = "home";
330 - maildir_field=read_env("MYSQL_MAILDIR_FIELD");
331 - if (!maildir_field) maildir_field="\"\"";
332 + maildir_field=read_env("MYSQL_MAILDIR_FIELD");
333 + if (!maildir_field) maildir_field="\"\"";
335 - quota_field=read_env("MYSQL_QUOTA_FIELD");
336 - if (!quota_field) quota_field="\"\"";
337 + quota_field=read_env("MYSQL_QUOTA_FIELD");
338 + if (!quota_field) quota_field="\"\"";
340 - where_clause=read_env("MYSQL_WHERE_CLAUSE");
341 - if (!where_clause) where_clause = "";
342 + where_clause=read_env("MYSQL_WHERE_CLAUSE");
343 + if (!where_clause) where_clause = "";
346 if (!defdomain) defdomain="";
348 - querybuf=malloc(sizeof(query) + 100 + strlen(user_table) + strlen(defdomain)
349 - + strlen(crypt_field) + strlen(clear_field) + strlen(maildir_field)
350 - + strlen(uid_field) + strlen(gid_field) + 2 * strlen(login_field)
351 - + strlen(home_field) + strlen(quota_field) + strlen(where_clause)
352 + if (!select_clause) /* siefca@pld.org.pl */
354 + querybuf=malloc(sizeof(query) + 100 + strlen(user_table) + strlen(defdomain)
355 + + strlen(crypt_field) + strlen(clear_field) + strlen(maildir_field)
356 + + strlen(uid_field) + strlen(gid_field) + 2 * strlen(login_field)
357 + + strlen(home_field) + strlen(quota_field) + strlen(where_clause)
358 + strlen(name_field));
367 + sprintf(querybuf, query, login_field, crypt_field, clear_field,
368 + uid_field, gid_field, home_field, maildir_field, quota_field,
369 + name_field, user_table, login_field);
371 + p=querybuf+strlen(querybuf);
373 + append_username(p, username, defdomain);
376 + if (strcmp(where_clause, "")) {
377 + strcat(p, " AND (");
378 + strcat(p, where_clause);
386 + /* siefca@pld.org.pl */
387 + querybuf=parse_select_clause (select_clause, username, defdomain);
388 + if (!querybuf) return 0;
391 - sprintf(querybuf, query, login_field, crypt_field, clear_field,
392 - uid_field, gid_field, home_field, maildir_field, quota_field,
393 - name_field, user_table, login_field);
394 - p=querybuf+strlen(querybuf);
396 - append_username(p, username, defdomain);
399 - if (strcmp(where_clause, "")) {
400 - strcat(p, " AND (");
401 - strcat(p, where_clause);
405 if (mysql_query (mysql, querybuf))
407 /* <o.blasnik@nextra.de> */
408 @@ -379,12 +608,13 @@
412 - const char *clear_field;
413 - const char *crypt_field;
414 - const char *defdomain;
415 - const char *where_clause;
416 - const char *user_table;
417 - const char *login_field;
418 + const char *clear_field =NULL,
419 + *crypt_field =NULL,
421 + *where_clause =NULL,
423 + *login_field =NULL,
424 + *chpass_clause =NULL; /* siefca@pld.org.pl */
428 @@ -412,21 +642,34 @@
432 - login_field = read_env("MYSQL_LOGIN_FIELD");
433 - if (!login_field) login_field = "id";
434 - crypt_field=read_env("MYSQL_CRYPT_PWFIELD");
435 - clear_field=read_env("MYSQL_CLEAR_PWFIELD");
436 + /* siefca@pld.org.pl */
437 + chpass_clause=read_env("MYSQL_CHPASS_CLAUSE");
438 defdomain=read_env("DEFAULT_DOMAIN");
439 - where_clause=read_env("MYSQL_WHERE_CLAUSE");
440 user_table=read_env("MYSQL_USER_TABLE");
442 - sql_buf=malloc(strlen(crypt_field ? crypt_field:"")
443 - + strlen(clear_field ? clear_field:"")
444 - + strlen(defdomain ? defdomain:"")
445 - + strlen(login_field) + l + strlen(newpass_crypt)
446 - + strlen(user_table)
447 - + strlen(where_clause ? where_clause:"")
449 + if (!chpass_clause)
451 + login_field = read_env("MYSQL_LOGIN_FIELD");
452 + if (!login_field) login_field = "id";
453 + crypt_field=read_env("MYSQL_CRYPT_PWFIELD");
454 + clear_field=read_env("MYSQL_CLEAR_PWFIELD");
455 + where_clause=read_env("MYSQL_WHERE_CLAUSE");
456 + sql_buf=malloc(strlen(crypt_field ? crypt_field:"")
457 + + strlen(clear_field ? clear_field:"")
458 + + strlen(defdomain ? defdomain:"")
459 + + strlen(login_field) + l + strlen(newpass_crypt)
460 + + strlen(user_table)
461 + + strlen(where_clause ? where_clause:"")
466 + sql_buf=parse_chpass_clause(chpass_clause,
476 @@ -434,53 +677,57 @@
480 - sprintf(sql_buf, "UPDATE %s SET", user_table);
484 - if (clear_field && *clear_field)
485 + if (!chpass_clause) /*siefca@pld.org.pl */
488 + sprintf(sql_buf, "UPDATE %s SET", user_table);
490 - strcat(strcat(strcat(sql_buf, " "), clear_field),
494 - q=sql_buf+strlen(sql_buf);
496 + if (clear_field && *clear_field)
498 - if (*pass == '"' || *pass == '\\')
503 + strcat(strcat(strcat(sql_buf, " "), clear_field),
506 + q=sql_buf+strlen(sql_buf);
509 + if (*pass == '"' || *pass == '\\')
520 - if (crypt_field && *crypt_field)
522 - strcat(strcat(strcat(strcat(strcat(strcat(sql_buf, comma),
526 - newpass_crypt_ptr),
529 - free(newpass_crypt);
530 + if (crypt_field && *crypt_field)
532 + strcat(strcat(strcat(strcat(strcat(strcat(sql_buf, comma),
536 + newpass_crypt_ptr),
539 + free(newpass_crypt);
541 - strcat(strcat(strcat(sql_buf, " WHERE "),
544 + strcat(strcat(strcat(sql_buf, " WHERE "),
548 - append_username(sql_buf+strlen(sql_buf), user, defdomain);
549 + append_username(sql_buf+strlen(sql_buf), user, defdomain);
551 - strcat(sql_buf, "\"");
552 + strcat(sql_buf, "\"");
554 - if (where_clause && *where_clause)
556 - strcat(sql_buf, " AND (");
557 - strcat(sql_buf, where_clause);
558 - strcat(sql_buf, ")");
560 + if (where_clause && *where_clause)
562 + strcat(sql_buf, " AND (");
563 + strcat(sql_buf, where_clause);
564 + strcat(sql_buf, ")");
567 + } /* end of: if (!chpass_clause) */
569 if (mysql_query (mysql, sql_buf))
571 diff -ur courier-imap-1.3.12.orig/authlib/authmysqlrc courier-imap-1.3.12/authlib/authmysqlrc
572 --- courier-imap-1.3.12.orig/authlib/authmysqlrc Sun Oct 7 18:32:56 2001
573 +++ courier-imap-1.3.12/authlib/authmysqlrc Mon Dec 10 03:21:59 2001
576 # MYSQL_WHERE_CLAUSE server='mailhost.example.com'
579 +##NAME: MYSQL_SELECT_CLAUSE:0
582 +# This is optional, MYSQL_SELECT_CLAUSE can be set when you have a database,
583 +# which is structuraly different from proposed. The fixed string will
584 +# be used to do a SELECT operation on database, which should return fields
587 +# username, cryptpw, uid, gid, clearpw, home, maildir, quota, fullname
589 +# Enabling this option causes ignorance of any other field-related
590 +# options, excluding default domain.
592 +# There are two variables, which you can use. Substitution will be made
593 +# for them, so you can put entered username (local part) and domain name
594 +# in the right place of your query. There variables are:
595 +# $(local_part) and $(domain)
597 +# If a $(domain) is empty (not given by the remote user) the default domain
598 +# name is used in its place.
600 +# This example is a little bit modified adaptation of vmail-sql
602 +#MYSQL_SELECT_CLAUSE SELECT popbox.local_part, \
603 +# CONCAT('{MD5}', popbox.password_hash), \
607 +# CONCAT(domain.path, '/', popbox.mbox_name), \
611 +# FROM popbox, domain \
612 +# WHERE popbox.local_part = '$(local_part)' \
613 +# AND popbox.domain_name = '$(domain)' \
614 +# AND popbox.domain_name = domain.domain_name
616 +##NAME: MYSQL_CHPASS_CLAUSE:0
619 +# This is optional, MYSQL_CHPASS_CLAUSE can be set when you have a database,
620 +# which is structuraly different from proposed. The fixed string will
621 +# be used to do an UPDATE operation on database. In other words, it is
622 +# used, when changing password.
624 +# There are four variables, which you can use. Substitution will be made
625 +# for them, so you can put entered username (local part) and domain name
626 +# in the right place of your query. There variables are:
627 +# $(local_part) , $(domain) , $(newpass) , $(newpass_crypt)
629 +# If a $(domain) is empty (not given by the remote user) the default domain
630 +# name is used in its place.
631 +# $(newpass) contains plain password
632 +# $(newpass_crypt) contains its crypted form
634 +# MYSQL_CHPASS_CLAUSE UPDATE popbox \
635 +# SET clearpw='$(newpass)', \
636 +# password_hash='$(newpass_crypt)' \
637 +# WHERE local_part='$(local_part)' \
638 +# AND domain_name='$(domain)'