2 ** Copyright 2000-2005 Double Precision, Inc. See COPYING for
3 ** distribution information.
11 #include <sys/types.h>
16 #include "authmysql.h"
17 #include "authmysqlrc.h"
19 #include "courierauthdebug.h"
21 #define err courier_auth_err
23 /* siefca@pld.org.pl */
24 #define MAX_SUBSTITUTION_LEN 32
25 #define SV_BEGIN_MARK "$("
26 #define SV_END_MARK ")"
27 #define SV_BEGIN_LEN ((sizeof(SV_BEGIN_MARK))-1)
28 #define SV_END_LEN ((sizeof(SV_END_MARK))-1)
30 static const char rcsid
[]="$Id: authmysqllib.c,v 1.45 2007/10/07 02:50:45 mrsam Exp $";
32 /* siefca@pld.org.pl */
40 /* siefca@pld.org.pl */
41 typedef int (*parsefunc
)(const char *, size_t, void *);
43 static const char *read_env(const char *env
)
45 static char *mysqlauth
=0;
46 static size_t mysqlauth_size
=0;
53 FILE *f
=fopen(AUTHMYSQLRC
, "r");
57 if (fstat(fileno(f
), &buf
) ||
58 (mysqlauth
=malloc(buf
.st_size
+2)) == 0)
63 if (fread(mysqlauth
, buf
.st_size
, 1, f
) != 1)
70 mysqlauth
[mysqlauth_size
=buf
.st_size
]=0;
72 for (i
=0; i
<mysqlauth_size
; i
++)
73 if (mysqlauth
[i
] == '\n')
74 { /* siefca@pld.org.pl */
75 if (!i
|| mysqlauth
[i
-1] != '\\')
81 mysqlauth
[i
]=mysqlauth
[i
-1]= ' ';
87 for (i
=0; i
<mysqlauth_size
; )
90 if (memcmp(p
, env
, l
) == 0 &&
91 isspace((int)(unsigned char)p
[l
]))
94 while (*p
&& *p
!= '\n' &&
95 isspace((int)(unsigned char)*p
))
100 while (i
< mysqlauth_size
)
101 if (mysqlauth
[i
++] == 0) break;
104 if (i
< mysqlauth_size
)
109 static MYSQL mysql_buf
;
111 static MYSQL
*mysql
=0;
113 static int do_connect()
117 const char *password
;
118 const char *database
;
119 const char *server_socket
=0;
120 unsigned int server_port
=0;
121 unsigned int server_opt
=0;
126 const char *sslcacert
;
127 const char *sslcapath
;
128 const char *sslcipher
;
129 unsigned int use_ssl
=0;
132 ** Periodically detect dead connections.
136 static time_t last_time
=0;
141 if (t_check
< last_time
)
142 last_time
=t_check
; /* System clock changed */
144 if (t_check
< last_time
+ 60)
149 if (mysql_ping(mysql
) == 0) return (0);
151 DPRINTF("authmysqllib: mysql_ping failed, connection lost");
156 server
=read_env("MYSQL_SERVER");
157 userid
=read_env("MYSQL_USERNAME");
158 password
=read_env("MYSQL_PASSWORD");
159 database
=read_env("MYSQL_DATABASE");
161 #if MYSQL_VERSION_ID >= 32200
162 sslkey
=read_env("MYSQL_SSL_KEY");
163 sslcert
=read_env("MYSQL_SSL_CERT");
164 sslcacert
=read_env("MYSQL_SSL_CACERT");
165 sslcapath
=read_env("MYSQL_SSL_CAPATH");
166 sslcipher
=read_env("MYSQL_SSL_CIPHER");
168 if ((sslcert
!= NULL
) && ((sslcacert
!= NULL
) || (sslcapath
!= NULL
)))
174 server_socket
=(char *) read_env("MYSQL_SOCKET");
176 if ((p
=read_env("MYSQL_PORT")) != 0)
178 server_port
=(unsigned int) atoi(p
);
181 if ((p
=read_env("MYSQL_OPT")) != 0)
183 server_opt
=(unsigned int) atol(p
);
186 if (!server
&& !server_socket
)
188 err("authmysql: MYSQL_SERVER nor MYSQL_SOCKET set in"
195 err("authmysql: MYSQL_USERNAME not set in "
202 err("authmysql: MYSQL_DATABASE not set in "
207 #if MYSQL_VERSION_ID >= 32200
208 mysql_init(&mysql_buf
);
211 mysql_ssl_set(&mysql_buf
, sslkey
, sslcert
, sslcacert
,
212 sslcapath
, sslcipher
);
214 mysql
=mysql_real_connect(&mysql_buf
, server
, userid
, password
,
220 mysql
=mysql_connect(&mysql_buf
, server
, userid
, password
);
224 err("failed to connect to mysql server (server=%s, userid=%s): %s",
225 server
? server
: "<null>",
226 userid
? userid
: "<null>",
227 mysql_error(&mysql_buf
));
231 if (mysql_select_db(mysql
, database
))
233 err("authmysql: mysql_select_db(%s) error: %s",
234 database
, mysql_error(mysql
));
242 void auth_mysql_cleanup()
251 static struct authmysqluserinfo ui
={0, 0, 0, 0, 0, 0, 0, 0};
272 memset(&ui
, 0, sizeof(ui
));
275 static void append_username(char *p
, const char *username
,
276 const char *defdomain
)
278 for (strcpy(p
, username
); *p
; p
++)
279 if (*p
== '\'' || *p
== '"' || *p
== '\\' ||
280 (int)(unsigned char)*p
< ' ')
281 *p
=' '; /* No funny business */
282 if (strchr(username
, '@') == 0 && defdomain
&& *defdomain
)
283 strcat(strcpy(p
, "@"), defdomain
);
286 /* siefca@pld.org.pl */
287 static struct var_data
*get_variable (const char *begin
, size_t len
,
288 struct var_data
*vdt
)
290 struct var_data
*vdp
;
292 if (!begin
|| !vdt
) /* should never happend */
294 err("authmysql: critical error while "
295 "parsing substitution variable");
300 err("authmysql: unknown empty substitution "
301 "variable - aborting");
304 if (len
> MAX_SUBSTITUTION_LEN
)
306 err("authmysql: variable name too long "
307 "while parsing substitution. "
310 "%.*s...", MAX_SUBSTITUTION_LEN
, begin
);
314 for (vdp
=vdt
; vdp
->name
; vdp
++)
315 if (vdp
->size
== len
+1 &&
316 !strncmp(begin
, vdp
->name
, len
))
320 if (!vdp
->value_length
) /* length cache */
321 vdp
->value_length
= strlen (vdp
->value
);
325 err("authmysql: unknown substitution variable "
334 /* siefca@pld.org.pl */
335 static int ParsePlugin_counter (const char *p
, size_t length
, void *vp
)
337 if (!p
|| !vp
|| length
< 0)
339 err("authmysql: bad arguments while counting "
344 *((size_t *)vp
) += length
;
349 /* siefca@pld.org.pl */
350 static int ParsePlugin_builder (const char *p
, size_t length
, void *vp
)
352 char **strptr
= (char **) vp
;
354 if (!p
|| !vp
|| length
< 0)
356 err("authmysql: bad arguments while building "
361 if (!length
) return 0;
362 memcpy ((void *) *strptr
, (void *) p
, length
);
368 /* siefca@pld.org.pl */
369 static int parse_core (const char *source
, struct var_data
*vdt
,
370 parsefunc outfn
, void *result
)
374 const char *p
, *q
, *e
,
377 struct var_data
*v_ptr
;
383 err("authmysql: no memory allocated for result "
384 "while parser core was invoked");
389 err("authmysql: no substitution table found "
390 "while parser core was invoked");
395 while ( (p
=strstr(q
, SV_BEGIN_MARK
)) )
397 e
= strstr (p
, SV_END_MARK
);
400 err("authmysql: syntax error in "
402 "- no closing symbol found! "
403 "bad variable begins with:"
404 "%.*s...", MAX_SUBSTITUTION_LEN
, p
);
410 ** __________sometext$(variable_name)_________
412 ** t_begin' t_end' `v_begin `v_end
416 v_begin
= p
+SV_BEGIN_LEN
; /* variable field ptr */
417 v_end
= e
-SV_END_LEN
; /* variable field last character */
418 v_size
= v_end
-v_begin
+1;/* variable field length */
420 t_begin
= q
; /* text field ptr */
421 t_end
= p
-1; /* text field last character */
422 t_size
= t_end
-t_begin
+1;/* text field length */
425 if ( (outfn (t_begin
, t_size
, result
)) == -1 )
428 /* work on variable */
429 v_ptr
= get_variable (v_begin
, v_size
, vdt
);
430 if (!v_ptr
) return -1;
432 if ( (outfn (v_ptr
->value
, v_ptr
->value_length
, result
)) == -1 )
438 /* work on last part of text if any */
440 if ( (outfn (q
, strlen(q
), result
)) == -1 )
446 /* siefca@pld.org.pl */
447 static char *parse_string (const char *source
, struct var_data
*vdt
)
449 struct var_data
*vdp
= NULL
;
450 char *output_buf
= NULL
,
454 if (source
== NULL
|| *source
== '\0' ||
455 vdt
== NULL
|| vdt
[0].name
== NULL
)
457 err("authmysql: source clause is empty "
458 "- this is critical error");
462 /* zero var_data length cache - important! */
463 for (vdp
=vdt
; vdp
->name
; vdp
++)
464 vdp
->value_length
= 0;
467 /* phase 1 - count and validate string */
468 if ( (parse_core (source
, vdt
, &ParsePlugin_counter
, &buf_size
)) != 0)
471 /* phase 2 - allocate memory */
472 output_buf
= malloc (buf_size
);
478 pass_buf
= output_buf
;
480 /* phase 3 - build the output string */
481 if ( (parse_core (source
, vdt
, &ParsePlugin_builder
, &pass_buf
)) != 0)
491 /* siefca@pld.org.pl */
492 static const char *get_localpart (const char *username
)
495 const char *l_end
, *p
;
497 static char localpart_buf
[130];
499 if (!username
|| *username
== '\0') return NULL
;
501 p
= strchr(username
,'@');
504 if ((p
-username
) > 128)
510 if ((lbuf
= strlen(username
)) > 128)
512 l_end
= username
+ lbuf
;
518 while (*p
&& p
!= l_end
)
519 if (*p
== '\"' || *p
== '\\' ||
520 *p
== '\'' || (int)(unsigned char)*p
< ' ')
526 return localpart_buf
;
529 /* siefca@pld.org.pl */
530 static const char *get_domain (const char *username
, const char *defdomain
)
532 static char domain_buf
[260];
536 if (!username
|| *username
== '\0') return NULL
;
537 p
= strchr(username
,'@');
539 if (!p
|| *(p
+1) == '\0')
541 if (defdomain
&& *defdomain
)
548 if ((strlen(p
)) > 256)
553 if (*p
== '\"' || *p
== '\\' ||
554 *p
== '\'' || (int)(unsigned char)*p
< ' ')
563 /* siefca@pld.org.pl */
565 static const char *validateMyPassword (const char *password
)
567 static char pass_buf
[2][540]; /* Use two buffers, see parse_chpass_clause */
568 static int next_pass
=0;
572 if (!password
|| *password
== '\0' || (strlen(password
)) > 256)
575 next_pass
= 1-next_pass
;
578 q
= pass_buf
[next_pass
];
579 endq
= q
+ sizeof pass_buf
[next_pass
];
581 while (*p
&& q
< endq
)
583 if (*p
== '\"' || *p
== '\\' || *p
== '\'')
592 return pass_buf
[next_pass
];
595 /* siefca@pld.org.pl */
596 static char *parse_select_clause (const char *clause
, const char *username
,
597 const char *defdomain
,
600 static struct var_data vd
[]={
601 {"local_part", NULL
, sizeof("local_part"), 0},
602 {"domain", NULL
, sizeof("domain"), 0},
603 {"service", NULL
, sizeof("service"), 0},
606 if (clause
== NULL
|| *clause
== '\0' ||
607 !username
|| *username
== '\0')
610 vd
[0].value
= get_localpart (username
);
611 vd
[1].value
= get_domain (username
, defdomain
);
612 if (!vd
[0].value
|| !vd
[1].value
)
614 vd
[2].value
= service
;
616 return (parse_string (clause
, vd
));
619 /* siefca@pld.org.pl */
620 static char *parse_chpass_clause (const char *clause
, const char *username
,
621 const char *defdomain
, const char *newpass
,
622 const char *newpass_crypt
)
624 static struct var_data vd
[]={
625 {"local_part", NULL
, sizeof("local_part"), 0},
626 {"domain", NULL
, sizeof("domain"), 0},
627 {"newpass", NULL
, sizeof("newpass"), 0},
628 {"newpass_crypt", NULL
, sizeof("newpass_crypt"), 0},
631 if (clause
== NULL
|| *clause
== '\0' ||
632 !username
|| *username
== '\0' ||
633 !newpass
|| *newpass
== '\0' ||
634 !newpass_crypt
|| *newpass_crypt
== '\0') return NULL
;
636 vd
[0].value
= get_localpart (username
);
637 vd
[1].value
= get_domain (username
, defdomain
);
638 vd
[2].value
= validateMyPassword (newpass
);
639 vd
[3].value
= validateMyPassword (newpass_crypt
);
641 if (!vd
[0].value
|| !vd
[1].value
||
642 !vd
[2].value
|| !vd
[3].value
) return NULL
;
644 return (parse_string (clause
, vd
));
647 struct authmysqluserinfo
*auth_mysql_getuserinfo(const char *username
,
650 const char *defdomain
=NULL
;
657 const char *select_clause
; /* siefca@pld.org.pl */
659 static const char query
[]=
660 "SELECT %s, %s, %s, %s, %s, %s, %s, %s, %s, %s FROM %s WHERE %s = \"";
662 if (do_connect()) return (0);
666 select_clause
=read_env("MYSQL_SELECT_CLAUSE");
667 defdomain
=read_env("DEFAULT_DOMAIN");
668 if (!defdomain
) defdomain
="";
670 if (!select_clause
) /* siefca@pld.org.pl */
672 const char *user_table
,
685 user_table
=read_env("MYSQL_USER_TABLE");
689 err("authmysql: MYSQL_USER_TABLE not set in "
694 crypt_field
=read_env("MYSQL_CRYPT_PWFIELD");
695 clear_field
=read_env("MYSQL_CLEAR_PWFIELD");
696 name_field
=read_env("MYSQL_NAME_FIELD");
698 if (!crypt_field
&& !clear_field
)
700 err("authmysql: MYSQL_CRYPT_PWFIELD and "
701 "MYSQL_CLEAR_PWFIELD not set in " AUTHMYSQLRC
".");
704 if (!crypt_field
) crypt_field
="\"\"";
705 if (!clear_field
) clear_field
="\"\"";
706 if (!name_field
) name_field
="\"\"";
708 uid_field
= read_env("MYSQL_UID_FIELD");
709 if (!uid_field
) uid_field
= "uid";
711 gid_field
= read_env("MYSQL_GID_FIELD");
712 if (!gid_field
) gid_field
= "gid";
714 login_field
= read_env("MYSQL_LOGIN_FIELD");
715 if (!login_field
) login_field
= "id";
717 home_field
= read_env("MYSQL_HOME_FIELD");
718 if (!home_field
) home_field
= "home";
720 maildir_field
=read_env(service
&& strcmp(service
, "courier")==0
721 ? "MYSQL_DEFAULTDELIVERY"
722 : "MYSQL_MAILDIR_FIELD");
723 if (!maildir_field
) maildir_field
="\"\"";
725 quota_field
=read_env("MYSQL_QUOTA_FIELD");
726 if (!quota_field
) quota_field
="\"\"";
728 options_field
=read_env("MYSQL_AUXOPTIONS_FIELD");
729 if (!options_field
) options_field
="\"\"";
731 where_clause
=read_env("MYSQL_WHERE_CLAUSE");
732 if (!where_clause
) where_clause
= "";
734 querybuf
=malloc(sizeof(query
) + 100
735 + 2 * strlen(login_field
)
736 + strlen(crypt_field
)
737 + strlen(clear_field
)
738 + strlen(uid_field
) + strlen(gid_field
)
740 + strlen(maildir_field
)
741 + strlen(quota_field
)
743 + strlen(options_field
)
747 + strlen(where_clause
));
755 sprintf(querybuf
, query
, login_field
, crypt_field
, clear_field
,
756 uid_field
, gid_field
, home_field
, maildir_field
, quota_field
,
757 name_field
, options_field
, user_table
, login_field
);
759 p
=querybuf
+strlen(querybuf
);
761 append_username(p
, username
, defdomain
);
764 if (strcmp(where_clause
, "")) {
766 strcat(p
, where_clause
);
772 /* siefca@pld.org.pl */
773 querybuf
=parse_select_clause (select_clause
, username
,
777 DPRINTF("parse_select_clause failed (DEFAULT_DOMAIN not set?)");
782 /* Anton Dobkin <anton@viansib.ru>, VIAN, Ltd. */
783 #if MYSQL_VERSION_ID >= 41000
784 const char *character_set
=read_env("MYSQL_CHARACTER_SET");
788 char *character_set_buf
;
790 character_set_buf
=malloc(strlen(character_set
)+11);
792 if (!character_set_buf
)
798 strcpy(character_set_buf
, "SET NAMES ");
799 strcat(character_set_buf
, character_set
);
801 DPRINTF("Install of a character set for MySQL. SQL query: SET NAMES %s", character_set
);
803 if(mysql_query (mysql
, character_set_buf
))
805 err("Install of a character set for MySQL is failed: %s MYSQL_CHARACTER_SET: may be invalid character set", mysql_error(mysql
));
806 auth_mysql_cleanup();
810 free(character_set_buf
);
815 free(character_set_buf
);
819 DPRINTF("SQL query: %s", querybuf
);
820 if (mysql_query (mysql
, querybuf
))
822 /* <o.blasnik@nextra.de> */
824 DPRINTF("mysql_query failed, reconnecting: %s", mysql_error(mysql
));
825 auth_mysql_cleanup();
833 if (mysql_query (mysql
, querybuf
))
835 DPRINTF("mysql_query failed second time, giving up: %s", mysql_error(mysql
));
837 auth_mysql_cleanup();
838 /* Server went down, that's OK,
839 ** try again next time.
846 result
= mysql_store_result (mysql
);
849 if (mysql_num_rows(result
))
851 row
= mysql_fetch_row (result
);
852 num_fields
= mysql_num_fields (result
);
856 DPRINTF("incomplete row, only %d fields returned",
858 mysql_free_result(result
);
862 if (row
[0] && row
[0][0])
863 ui
.username
=strdup(row
[0]);
864 if (row
[1] && row
[1][0])
865 ui
.cryptpw
=strdup(row
[1]);
866 if (row
[2] && row
[2][0])
867 ui
.clearpw
=strdup(row
[2]);
868 /* perhaps authmysql needs a glob_uid/glob_gid feature
870 if (!row
[3] || !row
[3][0] ||
871 (ui
.uid
=strtol(row
[3], &endp
, 10), endp
[0] != '\0'))
873 DPRINTF("invalid value for uid: '%s'",
874 row
[3] ? row
[3] : "<null>");
875 mysql_free_result(result
);
878 if (!row
[4] || !row
[4][0] ||
879 (ui
.gid
=strtol(row
[4], &endp
, 10), endp
[0] != '\0'))
881 DPRINTF("invalid value for gid: '%s'",
882 row
[4] ? row
[4] : "<null>");
883 mysql_free_result(result
);
886 if (row
[5] && row
[5][0])
887 ui
.home
=strdup(row
[5]);
890 DPRINTF("required value for 'home' (column 6) is missing");
891 mysql_free_result(result
);
894 if (num_fields
> 6 && row
[6] && row
[6][0])
895 ui
.maildir
=strdup(row
[6]);
896 if (num_fields
> 7 && row
[7] && row
[7][0])
897 ui
.quota
=strdup(row
[7]);
898 if (num_fields
> 8 && row
[8] && row
[8][0])
899 ui
.fullname
=strdup(row
[8]);
900 if (num_fields
> 9 && row
[9] && row
[9][0])
901 ui
.options
=strdup(row
[9]);
905 DPRINTF("zero rows returned");
906 mysql_free_result(result
);
907 return (&ui
); /* User not found */
912 DPRINTF("mysql_store_result failed");
915 mysql_free_result(result
);
919 int auth_mysql_setpass(const char *user
, const char *pass
,
929 const char *clear_field
=NULL
,
935 *chpass_clause
=NULL
; /* siefca@pld.org.pl */
941 if (!(newpass_crypt
=authcryptpasswd(pass
, oldpass
)))
944 for (l
=0, p
=pass
; *p
; p
++)
946 if ((int)(unsigned char)*p
< ' ')
951 if (*p
== '"' || *p
== '\\')
956 /* siefca@pld.org.pl */
957 chpass_clause
=read_env("MYSQL_CHPASS_CLAUSE");
958 defdomain
=read_env("DEFAULT_DOMAIN");
959 user_table
=read_env("MYSQL_USER_TABLE");
962 login_field
= read_env("MYSQL_LOGIN_FIELD");
963 if (!login_field
) login_field
= "id";
964 crypt_field
=read_env("MYSQL_CRYPT_PWFIELD");
965 clear_field
=read_env("MYSQL_CLEAR_PWFIELD");
966 where_clause
=read_env("MYSQL_WHERE_CLAUSE");
967 sql_buf
=malloc(strlen(crypt_field
? crypt_field
:"")
968 + strlen(clear_field
? clear_field
:"")
969 + strlen(defdomain
? defdomain
:"")
970 + strlen(login_field
) + l
+ strlen(newpass_crypt
)
972 + strlen(where_clause
? where_clause
:"")
977 sql_buf
=parse_chpass_clause(chpass_clause
,
991 if (!chpass_clause
) /*siefca@pld.org.pl */
993 sprintf(sql_buf
, "UPDATE %s SET", user_table
);
997 if (clear_field
&& *clear_field
)
1001 strcat(strcat(strcat(sql_buf
, " "), clear_field
),
1004 q
=sql_buf
+strlen(sql_buf
);
1007 if (*pass
== '"' || *pass
== '\\')
1015 if (crypt_field
&& *crypt_field
)
1017 strcat(strcat(strcat(strcat(strcat(strcat(sql_buf
, comma
),
1024 free(newpass_crypt
);
1026 strcat(strcat(strcat(sql_buf
, " WHERE "),
1030 append_username(sql_buf
+strlen(sql_buf
), user
, defdomain
);
1032 strcat(sql_buf
, "\"");
1034 if (where_clause
&& *where_clause
)
1036 strcat(sql_buf
, " AND (");
1037 strcat(sql_buf
, where_clause
);
1038 strcat(sql_buf
, ")");
1044 free(newpass_crypt
);
1048 if (courier_authdebug_login_level
>= 2)
1050 DPRINTF("setpass SQL: %s", sql_buf
);
1052 if (mysql_query (mysql
, sql_buf
))
1054 DPRINTF("setpass SQL failed");
1056 auth_mysql_cleanup();
1062 void auth_mysql_enumerate( void(*cb_func
)(const char *name
,
1065 const char *homedir
,
1066 const char *maildir
,
1067 const char *options
,
1071 const char *defdomain
, *select_clause
;
1076 static const char query
[]=
1077 "SELECT %s, %s, %s, %s, %s, %s FROM %s WHERE 1=1";
1079 if (do_connect()) return;
1083 select_clause
=read_env("MYSQL_ENUMERATE_CLAUSE");
1084 defdomain
=read_env("DEFAULT_DOMAIN");
1085 if (!defdomain
|| !defdomain
[0])
1086 defdomain
="*"; /* otherwise parse_select_clause fails */
1090 const char *user_table
,
1099 user_table
=read_env("MYSQL_USER_TABLE");
1103 err("authmysql: MYSQL_USER_TABLE not set in "
1108 uid_field
= read_env("MYSQL_UID_FIELD");
1109 if (!uid_field
) uid_field
= "uid";
1111 gid_field
= read_env("MYSQL_GID_FIELD");
1112 if (!gid_field
) gid_field
= "gid";
1114 login_field
= read_env("MYSQL_LOGIN_FIELD");
1115 if (!login_field
) login_field
= "id";
1117 home_field
= read_env("MYSQL_HOME_FIELD");
1118 if (!home_field
) home_field
= "home";
1120 maildir_field
=read_env("MYSQL_MAILDIR_FIELD");
1121 if (!maildir_field
) maildir_field
="\"\"";
1123 options_field
=read_env("MYSQL_AUXOPTIONS_FIELD");
1124 if (!options_field
) options_field
="\"\"";
1126 where_clause
=read_env("MYSQL_WHERE_CLAUSE");
1127 if (!where_clause
) where_clause
= "";
1129 querybuf
=malloc(sizeof(query
) + 100
1130 + strlen(login_field
)
1131 + strlen(uid_field
) + strlen(gid_field
)
1132 + strlen(home_field
)
1133 + strlen(maildir_field
)
1134 + strlen(options_field
)
1135 + strlen(user_table
)
1136 + strlen(where_clause
));
1144 sprintf(querybuf
, query
, login_field
,
1145 uid_field
, gid_field
, home_field
, maildir_field
,
1146 options_field
, user_table
);
1148 p
=querybuf
+strlen(querybuf
);
1150 if (strcmp(where_clause
, "")) {
1151 strcat(p
, " AND (");
1152 strcat(p
, where_clause
);
1158 /* siefca@pld.org.pl */
1159 querybuf
=parse_select_clause (select_clause
, "*",
1160 defdomain
, "enumerate");
1163 DPRINTF("authmysql: parse_select_clause failed");
1167 DPRINTF("authmysql: enumerate query: %s", querybuf
);
1169 if (mysql_query (mysql
, querybuf
))
1171 DPRINTF("mysql_query failed, reconnecting: %s", mysql_error(mysql
));
1172 /* <o.blasnik@nextra.de> */
1174 auth_mysql_cleanup();
1182 if (mysql_query (mysql
, querybuf
))
1184 DPRINTF("mysql_query failed second time, giving up: %s", mysql_error(mysql
));
1186 auth_mysql_cleanup();
1192 result
= mysql_use_result (mysql
);
1195 const char *username
;
1198 const char *homedir
;
1199 const char *maildir
;
1200 const char *options
;
1202 while ((row
= mysql_fetch_row (result
)) != NULL
)
1204 if(!row
[0] || !row
[0][0]
1205 || !row
[1] || !row
[1][0]
1206 || !row
[2] || !row
[2][0]
1207 || !row
[3] || !row
[3][0])
1213 uid
=atol(row
[1]); /* FIXME use strtol to validate */
1219 if (maildir
&& !*maildir
)
1222 (*cb_func
)(username
, uid
, gid
, homedir
,
1223 maildir
, options
, void_arg
);
1226 /* NULL row could indicate end of result or an error */
1227 if (mysql_errno(mysql
))
1229 DPRINTF("mysql error during enumeration: %s", mysql_error(mysql
));
1232 (*cb_func
)(NULL
, 0, 0, NULL
, NULL
, NULL
, void_arg
);
1234 if (result
) mysql_free_result(result
);