1 diff -Nur courier-imap-1.3.12.orig/authlib/README.myownquery courier-imap-1.3.12/authlib/README.myownquery
2 --- courier-imap-1.3.12.orig/authlib/README.myownquery Thu Jan 1 01:00:00 1970
3 +++ courier-imap-1.3.12/authlib/README.myownquery Sun Dec 30 01:41:38 2001
9 + Developer Notes for courier-imap-myownquery.patch
14 + document version: 1.03
34 +1 Modifications overview
40 + 3.2 typedef size_t (*parsefunc)
45 + 4.3 ParsePlugin_counter
46 + 4.4 ParsePlugin_builder
48 + 4.6 validate_password
51 + 4.9 parse_select_clause
52 + 4.10 parse_chpass_clause
61 + *-----------------------
63 + *-----------------------
65 +Courier-imap-myownquery.patch allows administrator to set own MySQL queries
66 +used by authdaemon to authenticate user (including fetchig credentials) and to
67 +change user's password. It allows to construct SELECT or UPDATE clause in the
68 +configuration file (authmysqlrc) by adding two new configuration variables:
69 +MYSQL_SELECT_CLAUSE and MYSQL_CHPASS_CLAUSE. It may be useful in the mail
70 +environments where there is such a need to have different database structure
71 +and/or tables scheme than expected by authmysql module.
73 +It also implements a small parsing engine for substitution variables which
74 +may appear in the clauses and are used to put informations like username
75 +or domain into the right place of a query.
77 +This patch was created using `diff -Nur` on courier-imap-1.3.12 source.
83 + *-----------------------
84 + 1 Modifications overview
85 + *-----------------------
87 +Modified files: authmysqllib.c authmysqlrc
89 +Each modified set of instructions is marked by my e-mail address:
92 +Changes in the current source code are related to:
94 +- sections where the queries are constructed
95 + (including memory allocation for the buffers)
97 + when MYSQL_SELECT_CLAUSE or MYSQL_CHPASS_CLAUSE is
98 + used then the query goes through the parsing functions
99 + passing over current memory allocation and query construction
102 +- section where the configuration file is read
104 + i've had to modify read_env() function to allow line breaks
105 + - now each sequence of the backslash as a first character and
106 + newline as the second is replaced by two whitespaces while
107 + putting into the buffer
109 +- sections where the query is constructed
111 + selection is made, depending on configuration variables which
112 + are set or not - if own query is used
118 + *-----------------------
120 + *-----------------------
122 +#define MAX_SUBSTITUTION_LEN 32
123 +#define SV_BEGIN_MARK "$("
124 +#define SV_END_MARK ")"
125 +#define SV_BEGIN_LEN ((sizeof(SV_BEGIN_MARK))-1)
126 +#define SV_END_LEN ((sizeof(SV_END_MARK))-1)
128 +These definitions allows to change substitution marks in an easy way.
129 +SV_BEGIN_MARK refers to sequence of characters treated as a prefix of
130 +each substitution variable and SV_END_MARK refers to string which is
131 +a closing suffix. If the expected substitution variable is called
132 +'local_part' (without apostrophes) then '$(local_part)' is a valid
133 +string representation for SV_BEGIN_MARK set to "$(" and SV_END_MARK to ")".
134 +MAX_SUBSTITUTION_LEN defines maximal length of a substitution variable's
137 +The last two definitions are just for code simplification.
144 + *-----------------------
146 + *-----------------------
148 +This section describes new data type definitions and variables.
156 + size_t value_length;
159 +This structure holds information needed by parsing routines.
160 +Using var_data array you may specify a set of string substitutions
161 +which should be done while parsing a query. Last element in array
162 +should have all fields set to zero (null).
164 +name field - should contain substituted variable name
165 +value - should contain string which replaces it
166 +size - should contain string size including the last zero byte ('\0')
167 +value_length - should be set to zero - it is used as a value size cache
170 +explanation: size is used to increase speed of calculation proccess
171 + value_length is used to cache length of a value during the
172 + parsing subroutines - it helps when substitution variable
173 + occures more than once within the query
177 +struct var_data vdt[] = {
178 + {"some", "replacement", sizeof("some"), 0},
179 + {"anotha", NULL, sizeof("anotha"), 0},
183 +In this example we've declared that $(some) in the query should be
184 +replaced by 'replacement' text, and replacement for $(anotha) will
185 +be defined in the code before passing on the array pointer to
186 +the paring function.
189 +3.2 typedef size_t (*parsefunc)
191 +typedef int (*parsefunc)(const char *, size_t, void *);
193 +This type definition refers to the function pointer, which is used
194 +to pass plugin functions into the core parsing subroutine. This definition
195 +is included to simplify the declaration of the parse_core() function.
201 + *-----------------------
203 + *-----------------------
205 +This section describes added functions.
215 + static const struct var_data *get_variable (const char *begin,
217 + struct var_data *vdt);
221 + This function searches an array pointed by vdt and tries to find
222 + the substitution variable, which name is identified with begin
223 + pointer and length of len bytes long.
225 + This function is also responsible for updating length cache field
226 + of vdt elements and validating requested variables.
228 + This function repports errors by sending human readable
229 + messages to the standard error stream.
233 + This function returns a pointer to the array element which is
234 + structure of var_data type, which contains variable definition
235 + of a given name. It returns NULL on error or failure.
245 + static int parse_core (const char *source, struct var_data *vdt,
246 + parsefunc outfn, void *result);
250 + This is the parsing routine for query strings containing the
251 + substitution variables. It reads the string pointed with source
252 + and tries to catch a valid substitution variables or parts which
253 + are plain text blocks. The main purpose of using this function
254 + it to split source string into parts and for each part call
255 + outfn() function. Those parts are substrings identified by
256 + pointer to some element of the source string and size.
257 + Those elements are the result of splitting source string into
258 + logical parts: plain text substrings and substitution variables'
259 + values. To get the values of any found substitution variables
260 + parse_core() uses get_variable() function. To find places
261 + where substitution variables occurs it uses strstr() function
262 + in conjunction with SV_BEGIN_MARK and SV_END_MARK definitions.
263 + It passes vdt structure pointer to get_variable() function is
266 + outfn() function should be passed by its pointer which
267 + refers to declaration:
269 + int (*outfn) (const char *begin,
270 + size_t string_length,
271 + void *void_pointer);
273 + Each time outfn() is called the result argument of parse_core()
274 + is passed to the outfn() as a last argument (void_pointer).
278 + Example string "$(local_part) AND $(domain)" will cause the
279 + outfn() to be called 3 times. First time for a value of
280 + $(local_part) substitution variable, second time
281 + for " AND " string, and the last time for $(domain) variable's
282 + value. Variables are passed to outfn() by their (found) values,
283 + plain text blocks are passed as they appear.
285 + This function repports errors by sending human readable
286 + messages to the standard error stream.
290 + This function returns -1 if an error has occured and 0 if
291 + everything went good.
293 +4.3 ParsePlugin_counter
297 + ParsePlugin_counter
301 + int ParsePlugin_counter (const char *begin, size_t len,
306 + This is parsing plugin function. It simply increments the value
307 + found in the memory area pointed by vp. It assumes that
308 + the memory area is allocated for the variable of size_t
309 + type and that area was passed by (size_t *) pointer.
310 + The value is incremented by len argument. Begin argument
313 + This function repports errors by sending human readable
314 + messages to the standard error stream.
318 + This function returns the variable size or -1 if an error
319 + has occured, 0 if everything went good.
321 +4.4 ParsePlugin_builder
325 + ParsePlugin_builder
329 + int ParsePlugin_builder (const char *begin, size_t len,
334 + This is parsing plugin function. It simply copies len bytes
335 + of a string pointed by begin to the end of memory area pointed by
336 + vp. It assumes that the area pointed by vp is passed by (char **)
337 + type pointer and refers to the (char *) pointer variable.
338 + After each call it shifts the value of pointer variable (char *)
339 + incrementing it by len bytes. Be careful when using this function
340 + - its changes the given pointer value. Always operate on an
341 + additional pointer type variable when passing it as the third
346 + This function returns the variable size or -1 if an error
347 + has occured, 0 if everything went good.
356 + static char *parse_string (const char *source, struct var_data *vdt);
360 + This function parses the string pointed with source according to the
361 + replacement instructions set in var_data array, which is passed with
362 + its pointer vdt. It produces changed string located in newly allocated
365 + This function calls parse_core() function with various parsing
366 + subroutines passed as function pointers.
368 + 1. It uses parse_core() with ParsePlugin_counter to obtain the
369 + total amount of memory needed for the output string.
371 + 2. It allocates the memory.
373 + 3. It uses parse_core() with ParsePlugin_builder to build the
376 + This function repports errors by sending human readable
377 + messages to the standard error stream.
381 + Function returns pointer to the result buffer or NULL
382 + if an error has occured.
386 + This function allocates some amount of memory using standard
387 + ANSI C routines. Memory allocated by this function should be
391 +4.6 validate_password
398 + static const char *validate_password (const char *password);
402 + This function checks whether password string does contain
403 + any dangerous characters, which may be used to pass command
404 + strings to the database connection stream. If it founds one
405 + it replaces it by the backslash character.
409 + It returns a pointer to the static buffer which contains
410 + validated password string or NULL if an error has occured.
421 + static const char *get_localpart (const char *username);
425 + This function detaches local part of an e-mail address
426 + from string pointed with username and puts it to the
427 + buffer of the fixed length. All necessary cleaning is
428 + made on the result string.
432 + Pointer to the static buffer containing local part or
433 + NULL if there was some error.
444 + static const char *get_domain (const char *username,
445 + const char *defdomain);
449 + This function detaches domain part of an e-mail address
450 + from string pointed with username and puts it to the
451 + buffer of the fixed length. All necessary cleaning is
452 + made on the result string. If function cannot find domain
453 + part in the string the string pointed by defdomain is
458 + Pointer to the static buffer containing domain name or
459 + NULL if there was some error.
462 +4.9 parse_select_clause
466 + parse_select_clause
470 + static char *parse_select_clause (const char *clause,
471 + const char *username,
472 + const char *defdomain);
476 + This function is a simple wrapper to the parse_string()
477 + function. It parses a query pointed by caluse. username
478 + and defdomain strings are used to replace corresponding
479 + substitution strings if present in the query: $(local_part)
485 + Same as parse_string().
488 +4.10 parse_chpass_clause
492 + parse_chpass_clause
496 + static char *parse_chpass_clause (const char *clause,
497 + const char *username,
498 + const char *defdomain,
499 + const char *newpass,
500 + const char *newpass_crypt);
504 + This function is a simple wrapper to the parse_string()
505 + function. It parses a query pointed by caluse. username,
506 + defdomain, newpass and newpass_crypt strings are used to
507 + replace corresponding substitution strings if present in
508 + the query: $(local_part), $(domain), $(newpass),
513 + Same as parse_string().
519 + *------------------------
521 + *------------------------
523 +- solve problem with fixed buffer length of local part and the domain part
524 + strings after split (problem?)
525 +- allow admin to set a group name instead of numerical group id
526 +- allow admin to set a username instead of numerical user id
530 + - MYSQL_PRESELECT_CLAUSE (query which comes before MYSQL_SELECT_CLAUSE)
531 + - MYSQL_POSTSELECT_CLAUSE (query which comes after MYSQL_SELECT_CLAUSE)
537 + *------------------------
539 + *------------------------
541 +At the beginning this patch was messy indeed. :> I would like to thank
542 +Sam Varshavchik for pointing me a lot how to make it more fast and solid.
543 +I would also thank Philip Hazel, Chris Lightfoot and Mike Bremford which
544 +by their software capabilities inspired me to write it.
546 +---------------------------------------------------------------------------
548 diff -Nur courier-imap-1.3.12.orig/authlib/authmysqllib.c courier-imap-1.3.12/authlib/authmysqllib.c
549 --- courier-imap-1.3.12.orig/authlib/authmysqllib.c Mon Aug 6 05:12:39 2001
550 +++ courier-imap-1.3.12/authlib/authmysqllib.c Sun Dec 30 01:41:00 2001
552 ** distribution information.
560 #include "authmysqlrc.h"
563 +/* siefca@pld.org.pl */
564 +#define MAX_SUBSTITUTION_LEN 32
565 +#define SV_BEGIN_MARK "$("
566 +#define SV_END_MARK ")"
567 +#define SV_BEGIN_LEN ((sizeof(SV_BEGIN_MARK))-1)
568 +#define SV_END_LEN ((sizeof(SV_END_MARK))-1)
570 static const char rcsid[]="$Id$";
572 +/* siefca@pld.org.pl */
577 + size_t value_length;
580 +/* siefca@pld.org.pl */
581 +typedef int (*parsefunc)(const char *, size_t, void *);
583 static const char *read_env(const char *env)
585 static char *mysqlauth=0;
588 for (i=0; i<mysqlauth_size; i++)
589 if (mysqlauth[i] == '\n')
591 + { /* siefca@pld.org.pl */
592 + if (!i || mysqlauth[i-1] != '\\')
593 + mysqlauth[i] ='\0';
596 + mysqlauth[i-1] = ' ';
601 @@ -199,17 +222,370 @@
602 strcat(strcpy(p, "@"), defdomain);
605 +/* siefca@pld.org.pl */
606 +static struct var_data *get_variable (const char *begin, size_t len,
607 + struct var_data *vdt)
609 +struct var_data *vdp;
611 + if (!begin || !vdt) /* should never happend */
613 + fprintf (stderr, "authmysql: critical error while "
614 + "parsing substitution variable\n");
619 + fprintf (stderr, "authmysql: unknown empty substitution "
620 + "variable - aborting\n");
623 + if (len > MAX_SUBSTITUTION_LEN)
625 + fprintf (stderr, "authmysql: variable name too long "
626 + "while parsing substitution\n"
627 + "authmysql: name begins with "
629 + "%.*s...\n", MAX_SUBSTITUTION_LEN, begin);
633 + for (vdp=vdt; vdp->name; vdp++)
634 + if (vdp->size == len+1 &&
635 + !strncmp(begin, vdp->name, len))
639 + if (!vdp->value_length) /* length cache */
640 + vdp->value_length = strlen (vdp->value);
644 + fprintf (stderr, "authmysql: unknown substitution variable "
653 +/* siefca@pld.org.pl */
654 +static int ParsePlugin_counter (const char *p, size_t length, void *vp)
656 + if (!p || !vp || length < 0)
658 + fprintf (stderr, "authmysql: bad arguments while counting "
663 + *((size_t *)vp) += length;
668 +/* siefca@pld.org.pl */
669 +static int ParsePlugin_builder (const char *p, size_t length, void *vp)
671 +char **strptr = (char **) vp;
673 + if (!p || !vp || length < 0)
675 + fprintf (stderr, "authmysql: bad arguments while building "
680 + if (!length) return 0;
681 + memcpy ((void *) *strptr, (void *) p, length);
687 +/* siefca@pld.org.pl */
688 +static int parse_core (const char *source, struct var_data *vdt,
689 + parsefunc outfn, void *result)
694 +const char *p, *q, *e,
697 +struct var_data *v_ptr;
703 + fprintf (stderr, "authmysql: no memory allocated for result"
704 + "while parser core was invoked\n");
709 + fprintf (stderr, "authmysql: no substitution table found "
710 + "while parser core was invoked\n");
715 + while ( (p=strstr(q, SV_BEGIN_MARK)) )
717 + e = strstr (p, SV_END_MARK);
720 + fprintf (stderr, "authmysql: syntax error in "
722 + "- no closing symbol fould!\n"
723 + "authmysql: bad variable begins with:"
724 + "%.*s...\n", MAX_SUBSTITUTION_LEN, p);
730 + ** __________sometext$(variable_name)_________
732 + ** t_begin' t_end' `v_begin `v_end
736 + v_begin = p+SV_BEGIN_LEN; /* variable field ptr */
737 + v_end = e-SV_END_LEN; /* variable field last character */
738 + v_size = v_end-v_begin+1;/* variable field length */
740 + t_begin = q; /* text field ptr */
741 + t_end = p-1; /* text field last character */
742 + t_size = t_end-t_begin+1;/* text field length */
745 + if ( (outfn (t_begin, t_size, result)) == -1 )
748 + /* work on variable */
749 + v_ptr = get_variable (v_begin, v_size, vdt);
750 + if (!v_ptr) return -1;
752 + if ( (outfn (v_ptr->value, v_ptr->value_length, result)) == -1 )
758 + /* work on last part of text if any */
760 + if ( (outfn (q, strlen(q), result)) == -1 )
766 +/* siefca@pld.org.pl */
767 +static char *parse_string (const char *source, struct var_data *vdt)
769 +char *output_buf = NULL,
771 +size_t buf_size = 2;
773 + if (source == NULL || *source == '\0' ||
774 + vdt == NULL || vdt[0].name == NULL)
776 + fprintf (stderr, "authmysql: source clause is empty "
777 + "- this is critical error\n");
781 + /* phase 1 - count and validate string */
782 + if ( (parse_core (source, vdt, &ParsePlugin_counter, &buf_size)) != 0)
785 + /* phase 2 - allocate memory */
786 + output_buf = malloc (buf_size);
792 + pass_buf = output_buf;
794 + /* phase 3 - build the output string */
795 + if ( (parse_core (source, vdt, &ParsePlugin_builder, &pass_buf)) != 0)
805 +/* siefca@pld.org.pl */
806 +static const char *get_localpart (const char *username)
809 +const char *l_end, *p;
811 +static char localpart_buf[130];
813 + if (!username || *username == '\0') return NULL;
815 + p = strchr(username,'@');
818 + if ((p-username) > 128)
824 + if ((lbuf = strlen(username)) > 128)
826 + l_end = username + lbuf;
832 + while (*p && p != l_end)
833 + if (*p == '\"' || *p == '\\' ||
834 + *p == '\'' || (int)(unsigned char)*p < ' ')
840 + return localpart_buf;
843 +/* siefca@pld.org.pl */
844 +static const char *get_domain (const char *username, const char *defdomain)
846 +static char domain_buf[260];
850 + if (!username || *username == '\0') return NULL;
851 + p = strchr(username,'@');
853 + if (!p || *(p+1) == '\0')
855 + if (defdomain && *defdomain)
862 + if ((strlen(p)) > 256)
867 + if (*p == '\"' || *p == '\\' ||
868 + *p == '\'' || (int)(unsigned char)*p < ' ')
877 +/* siefca@pld.org.pl */
878 +static const char *validate_password (const char *password)
880 +static char pass_buf[260];
884 + if (!password || *password == '\0' || (strlen(password)) > 256)
891 + if (*p == '\"' || *p == '\\' || *p == '\'')
901 +/* siefca@pld.org.pl */
902 +static char *parse_select_clause (const char *clause, const char *username,
903 + const char *defdomain)
905 +static struct var_data vd[]={
906 + {"local_part", NULL, sizeof("local_part"), 0},
907 + {"domain", NULL, sizeof("domain"), 0},
908 + {NULL, NULL, 0, 0}};
910 + if (clause == NULL || *clause == '\0' ||
911 + !username || *username == '\0')
914 + vd[0].value = get_localpart (username);
915 + vd[1].value = get_domain (username, defdomain);
916 + if (!vd[0].value || !vd[1].value)
919 + return (parse_string (clause, vd));
922 +/* siefca@pld.org.pl */
923 +static char *parse_chpass_clause (const char *clause, const char *username,
924 + const char *defdomain, const char *newpass,
925 + const char *newpass_crypt)
927 +static struct var_data vd[]={
928 + {"local_part", NULL, sizeof("local_part"), 0},
929 + {"domain", NULL, sizeof("domain"), 0},
930 + {"newpass", NULL, sizeof("newpass"), 0},
931 + {"newpass_crypt", NULL, sizeof("newpass_crypt"), 0},
932 + {NULL, NULL, 0, 0}};
934 + if (clause == NULL || *clause == '\0' ||
935 + !username || *username == '\0' ||
936 + !newpass || *newpass == '\0' ||
937 + !newpass_crypt || *newpass_crypt == '\0') return NULL;
939 + vd[0].value = get_localpart (username);
940 + vd[1].value = get_domain (username, defdomain);
941 + vd[2].value = validate_password (newpass);
942 + vd[3].value = validate_password (newpass_crypt);
944 + if (!vd[0].value || !vd[1].value ||
945 + !vd[2].value || !vd[3].value) return NULL;
947 + return (parse_string (clause, vd));
950 struct authmysqluserinfo *auth_mysql_getuserinfo(const char *username)
952 -const char *user_table;
953 -const char *defdomain;
954 +const char *user_table =NULL;
955 +const char *defdomain =NULL;
960 -const char *crypt_field, *clear_field, *maildir_field, *home_field,
962 - *login_field, *uid_field, *gid_field, *quota_field, *where_clause;
963 +const char *crypt_field =NULL,
964 + *clear_field =NULL,
965 + *maildir_field =NULL,
968 + *login_field =NULL,
971 + *quota_field =NULL,
972 + *where_clause =NULL,
973 + *select_clause =NULL; /* siefca@pld.org.pl */
975 static const char query[]=
976 "SELECT %s, %s, %s, %s, %s, %s, %s, %s, %s FROM %s WHERE %s = \"";
977 @@ -232,79 +608,95 @@
979 memset(&ui, 0, sizeof(ui));
981 - user_table=read_env("MYSQL_USER_TABLE");
982 - defdomain=read_env("DEFAULT_DOMAIN");
985 + select_clause=read_env("MYSQL_SELECT_CLAUSE");
986 + defdomain=read_env("DEFAULT_DOMAIN");
988 + if (!select_clause) /* siefca@pld.org.pl */
990 - fprintf(stderr, "authmysql: MYSQL_USER_TABLE not set in "
991 - AUTHMYSQLRC ".\n");
994 + user_table=read_env("MYSQL_USER_TABLE");
996 - crypt_field=read_env("MYSQL_CRYPT_PWFIELD");
997 - clear_field=read_env("MYSQL_CLEAR_PWFIELD");
998 - name_field=read_env("MYSQL_NAME_FIELD");
1001 + fprintf(stderr, "authmysql: MYSQL_USER_TABLE not set in "
1002 + AUTHMYSQLRC ".\n");
1006 - if (!crypt_field && !clear_field)
1009 - "authmysql: MYSQL_CRYPT_PWFIELD and "
1010 - "MYSQL_CLEAR_PWFIELD not set in " AUTHMYSQLRC ".\n");
1013 - if (!crypt_field) crypt_field="\"\"";
1014 - if (!clear_field) clear_field="\"\"";
1015 - if (!name_field) name_field="\"\"";
1016 + crypt_field=read_env("MYSQL_CRYPT_PWFIELD");
1017 + clear_field=read_env("MYSQL_CLEAR_PWFIELD");
1018 + name_field=read_env("MYSQL_NAME_FIELD");
1020 + if (!crypt_field && !clear_field)
1023 + "authmysql: MYSQL_CRYPT_PWFIELD and "
1024 + "MYSQL_CLEAR_PWFIELD not set in " AUTHMYSQLRC ".\n");
1027 + if (!crypt_field) crypt_field="\"\"";
1028 + if (!clear_field) clear_field="\"\"";
1029 + if (!name_field) name_field="\"\"";
1031 - uid_field = read_env("MYSQL_UID_FIELD");
1032 - if (!uid_field) uid_field = "uid";
1033 + uid_field = read_env("MYSQL_UID_FIELD");
1034 + if (!uid_field) uid_field = "uid";
1036 - gid_field = read_env("MYSQL_GID_FIELD");
1037 - if (!gid_field) gid_field = "gid";
1038 + gid_field = read_env("MYSQL_GID_FIELD");
1039 + if (!gid_field) gid_field = "gid";
1041 - login_field = read_env("MYSQL_LOGIN_FIELD");
1042 - if (!login_field) login_field = "id";
1043 + login_field = read_env("MYSQL_LOGIN_FIELD");
1044 + if (!login_field) login_field = "id";
1046 - home_field = read_env("MYSQL_HOME_FIELD");
1047 - if (!home_field) home_field = "home";
1048 + home_field = read_env("MYSQL_HOME_FIELD");
1049 + if (!home_field) home_field = "home";
1051 - maildir_field=read_env("MYSQL_MAILDIR_FIELD");
1052 - if (!maildir_field) maildir_field="\"\"";
1053 + maildir_field=read_env("MYSQL_MAILDIR_FIELD");
1054 + if (!maildir_field) maildir_field="\"\"";
1056 - quota_field=read_env("MYSQL_QUOTA_FIELD");
1057 - if (!quota_field) quota_field="\"\"";
1058 + quota_field=read_env("MYSQL_QUOTA_FIELD");
1059 + if (!quota_field) quota_field="\"\"";
1061 - where_clause=read_env("MYSQL_WHERE_CLAUSE");
1062 - if (!where_clause) where_clause = "";
1063 + where_clause=read_env("MYSQL_WHERE_CLAUSE");
1064 + if (!where_clause) where_clause = "";
1067 if (!defdomain) defdomain="";
1069 - querybuf=malloc(sizeof(query) + 100 + strlen(user_table) + strlen(defdomain)
1070 - + strlen(crypt_field) + strlen(clear_field) + strlen(maildir_field)
1071 - + strlen(uid_field) + strlen(gid_field) + 2 * strlen(login_field)
1072 - + strlen(home_field) + strlen(quota_field) + strlen(where_clause)
1073 - + strlen(name_field));
1075 + if (!select_clause) /* siefca@pld.org.pl */
1080 + querybuf=malloc(sizeof(query) + 100 + strlen(user_table) + strlen(defdomain)
1081 + + strlen(crypt_field) + strlen(clear_field) + strlen(maildir_field)
1082 + + strlen(uid_field) + strlen(gid_field) + 2 * strlen(login_field)
1083 + + strlen(home_field) + strlen(quota_field) + strlen(where_clause)
1084 + + strlen(name_field));
1092 + sprintf(querybuf, query, login_field, crypt_field, clear_field,
1093 + uid_field, gid_field, home_field, maildir_field, quota_field,
1094 + name_field, user_table, login_field);
1096 - sprintf(querybuf, query, login_field, crypt_field, clear_field,
1097 - uid_field, gid_field, home_field, maildir_field, quota_field,
1098 - name_field, user_table, login_field);
1099 - p=querybuf+strlen(querybuf);
1100 + p=querybuf+strlen(querybuf);
1102 - append_username(p, username, defdomain);
1104 + append_username(p, username, defdomain);
1107 - if (strcmp(where_clause, "")) {
1108 - strcat(p, " AND (");
1109 - strcat(p, where_clause);
1111 + if (strcmp(where_clause, "")) {
1112 + strcat(p, " AND (");
1113 + strcat(p, where_clause);
1120 + /* siefca@pld.org.pl */
1121 + querybuf=parse_select_clause (select_clause, username, defdomain);
1122 + if (!querybuf) return 0;
1125 if (mysql_query (mysql, querybuf))
1127 /* <o.blasnik@nextra.de> */
1128 @@ -379,12 +771,13 @@
1132 - const char *clear_field;
1133 - const char *crypt_field;
1134 - const char *defdomain;
1135 - const char *where_clause;
1136 - const char *user_table;
1137 - const char *login_field;
1138 + const char *clear_field =NULL,
1139 + *crypt_field =NULL,
1141 + *where_clause =NULL,
1142 + *user_table =NULL,
1143 + *login_field =NULL,
1144 + *chpass_clause =NULL; /* siefca@pld.org.pl */
1148 @@ -412,21 +805,34 @@
1152 - login_field = read_env("MYSQL_LOGIN_FIELD");
1153 - if (!login_field) login_field = "id";
1154 - crypt_field=read_env("MYSQL_CRYPT_PWFIELD");
1155 - clear_field=read_env("MYSQL_CLEAR_PWFIELD");
1156 + /* siefca@pld.org.pl */
1157 + chpass_clause=read_env("MYSQL_CHPASS_CLAUSE");
1158 defdomain=read_env("DEFAULT_DOMAIN");
1159 - where_clause=read_env("MYSQL_WHERE_CLAUSE");
1160 user_table=read_env("MYSQL_USER_TABLE");
1162 - sql_buf=malloc(strlen(crypt_field ? crypt_field:"")
1163 - + strlen(clear_field ? clear_field:"")
1164 - + strlen(defdomain ? defdomain:"")
1165 - + strlen(login_field) + l + strlen(newpass_crypt)
1166 - + strlen(user_table)
1167 - + strlen(where_clause ? where_clause:"")
1169 + if (!chpass_clause)
1171 + login_field = read_env("MYSQL_LOGIN_FIELD");
1172 + if (!login_field) login_field = "id";
1173 + crypt_field=read_env("MYSQL_CRYPT_PWFIELD");
1174 + clear_field=read_env("MYSQL_CLEAR_PWFIELD");
1175 + where_clause=read_env("MYSQL_WHERE_CLAUSE");
1176 + sql_buf=malloc(strlen(crypt_field ? crypt_field:"")
1177 + + strlen(clear_field ? clear_field:"")
1178 + + strlen(defdomain ? defdomain:"")
1179 + + strlen(login_field) + l + strlen(newpass_crypt)
1180 + + strlen(user_table)
1181 + + strlen(where_clause ? where_clause:"")
1186 + sql_buf=parse_chpass_clause(chpass_clause,
1196 @@ -434,53 +840,57 @@
1200 - sprintf(sql_buf, "UPDATE %s SET", user_table);
1204 - if (clear_field && *clear_field)
1205 + if (!chpass_clause) /*siefca@pld.org.pl */
1208 + sprintf(sql_buf, "UPDATE %s SET", user_table);
1210 - strcat(strcat(strcat(sql_buf, " "), clear_field),
1214 - q=sql_buf+strlen(sql_buf);
1216 + if (clear_field && *clear_field)
1218 - if (*pass == '"' || *pass == '\\')
1223 + strcat(strcat(strcat(sql_buf, " "), clear_field),
1226 + q=sql_buf+strlen(sql_buf);
1229 + if (*pass == '"' || *pass == '\\')
1240 - if (crypt_field && *crypt_field)
1242 - strcat(strcat(strcat(strcat(strcat(strcat(sql_buf, comma),
1246 - newpass_crypt_ptr),
1249 - free(newpass_crypt);
1250 + if (crypt_field && *crypt_field)
1252 + strcat(strcat(strcat(strcat(strcat(strcat(sql_buf, comma),
1256 + newpass_crypt_ptr),
1259 + free(newpass_crypt);
1261 - strcat(strcat(strcat(sql_buf, " WHERE "),
1264 + strcat(strcat(strcat(sql_buf, " WHERE "),
1268 - append_username(sql_buf+strlen(sql_buf), user, defdomain);
1269 + append_username(sql_buf+strlen(sql_buf), user, defdomain);
1271 - strcat(sql_buf, "\"");
1272 + strcat(sql_buf, "\"");
1274 - if (where_clause && *where_clause)
1276 - strcat(sql_buf, " AND (");
1277 - strcat(sql_buf, where_clause);
1278 - strcat(sql_buf, ")");
1280 + if (where_clause && *where_clause)
1282 + strcat(sql_buf, " AND (");
1283 + strcat(sql_buf, where_clause);
1284 + strcat(sql_buf, ")");
1287 + } /* end of: if (!chpass_clause) */
1289 if (mysql_query (mysql, sql_buf))
1291 diff -Nur courier-imap-1.3.12.orig/authlib/authmysqlrc courier-imap-1.3.12/authlib/authmysqlrc
1292 --- courier-imap-1.3.12.orig/authlib/authmysqlrc Sun Oct 7 18:32:56 2001
1293 +++ courier-imap-1.3.12/authlib/authmysqlrc Fri Dec 28 02:08:01 2001
1294 @@ -141,4 +141,65 @@
1296 # MYSQL_WHERE_CLAUSE server='mailhost.example.com'
1299 +##NAME: MYSQL_SELECT_CLAUSE:0
1302 +# This is optional, MYSQL_SELECT_CLAUSE can be set when you have a database,
1303 +# which is structuraly different from proposed. The fixed string will
1304 +# be used to do a SELECT operation on database, which should return fields
1305 +# in order specified bellow:
1307 +# username, cryptpw, uid, gid, clearpw, home, maildir, quota, fullname
1309 +# Enabling this option causes ignorance of any other field-related
1310 +# options, excluding default domain.
1312 +# There are two variables, which you can use. Substitution will be made
1313 +# for them, so you can put entered username (local part) and domain name
1314 +# in the right place of your query. These variables are:
1315 +# $(local_part) and $(domain)
1317 +# If a $(domain) is empty (not given by the remote user) the default domain
1318 +# name is used in its place.
1320 +# This example is a little bit modified adaptation of vmail-sql
1323 +# MYSQL_SELECT_CLAUSE SELECT popbox.local_part, \
1324 +# CONCAT('{MD5}', popbox.password_hash), \
1327 +# popbox.clearpw, \
1328 +# CONCAT(domain.path, '/', popbox.mbox_name), \
1332 +# FROM popbox, domain \
1333 +# WHERE popbox.local_part = '$(local_part)' \
1334 +# AND popbox.domain_name = '$(domain)' \
1335 +# AND popbox.domain_name = domain.domain_name
1337 +##NAME: MYSQL_CHPASS_CLAUSE:0
1340 +# This is optional, MYSQL_CHPASS_CLAUSE can be set when you have a database,
1341 +# which is structuraly different from proposed. The fixed string will
1342 +# be used to do an UPDATE operation on database. In other words, it is
1343 +# used, when changing password.
1345 +# There are four variables, which you can use. Substitution will be made
1346 +# for them, so you can put entered username (local part) and domain name
1347 +# in the right place of your query. There variables are:
1348 +# $(local_part) , $(domain) , $(newpass) , $(newpass_crypt)
1350 +# If a $(domain) is empty (not given by the remote user) the default domain
1351 +# name is used in its place.
1352 +# $(newpass) contains plain password
1353 +# $(newpass_crypt) contains its crypted form
1355 +# MYSQL_CHPASS_CLAUSE UPDATE popbox \
1356 +# SET clearpw='$(newpass)', \
1357 +# password_hash='$(newpass_crypt)' \
1358 +# WHERE local_part='$(local_part)' \
1359 +# AND domain_name='$(domain)'