]>
Commit | Line | Data |
---|---|---|
258494a2 | 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 | |
9e0529f5 | 3 | +++ courier-imap-1.3.12/authlib/README.myownquery Sun Dec 30 01:41:38 2001 |
4 | @@ -0,0 +1,543 @@ | |
258494a2 | 5 | + |
6 | + | |
7 | + | |
8 | + | |
9 | + Developer Notes for courier-imap-myownquery.patch | |
10 | + | |
11 | + | |
12 | + | |
13 | + | |
9e0529f5 | 14 | + document version: 1.03 |
258494a2 | 15 | + author: Pawel Wilk |
16 | + | |
17 | + | |
18 | + | |
19 | + | |
20 | + | |
21 | + | |
22 | + | |
23 | + | |
24 | + | |
25 | + | |
26 | + | |
27 | + | |
28 | + | |
29 | + | |
30 | + | |
31 | + | |
32 | +0 What's that? | |
33 | + | |
34 | +1 Modifications overview | |
35 | + | |
36 | +2 Definitions | |
37 | + | |
38 | +3 New data types | |
39 | + 3.1 struct var_data | |
40 | + 3.2 typedef size_t (*parsefunc) | |
41 | + | |
42 | +4 New functions | |
9e0529f5 | 43 | + 4.1 get_variable |
44 | + 4.2 parse_core | |
45 | + 4.3 ParsePlugin_counter | |
46 | + 4.4 ParsePlugin_builder | |
47 | + 4.5 parse_string | |
48 | + 4.6 validate_password | |
49 | + 4.7 get_localpart | |
50 | + 4.8 get_domain | |
51 | + 4.9 parse_select_clause | |
52 | + 4.10 parse_chpass_clause | |
258494a2 | 53 | + |
54 | +5 Ideas and TODO | |
55 | + | |
9e0529f5 | 56 | +6 Thanks |
258494a2 | 57 | + |
58 | + | |
59 | + | |
60 | + | |
61 | + *----------------------- | |
62 | + 0 What's that? | |
63 | + *----------------------- | |
64 | + | |
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. | |
72 | + | |
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. | |
76 | + | |
77 | +This patch was created using `diff -Nur` on courier-imap-1.3.12 source. | |
78 | + | |
79 | + | |
80 | + | |
81 | + | |
82 | + | |
83 | + *----------------------- | |
84 | + 1 Modifications overview | |
85 | + *----------------------- | |
86 | + | |
87 | +Modified files: authmysqllib.c authmysqlrc | |
88 | + | |
89 | +Each modified set of instructions is marked by my e-mail address: | |
90 | +siefca@pld.org.pl | |
91 | + | |
92 | +Changes in the current source code are related to: | |
93 | + | |
94 | +- sections where the queries are constructed | |
95 | + (including memory allocation for the buffers) | |
96 | + | |
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 | |
100 | + subroutines | |
101 | + | |
102 | +- section where the configuration file is read | |
103 | + | |
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 | |
108 | + | |
109 | +- sections where the query is constructed | |
110 | + | |
111 | + selection is made, depending on configuration variables which | |
112 | + are set or not - if own query is used | |
113 | + | |
114 | + | |
115 | + | |
116 | + | |
117 | + | |
118 | + *----------------------- | |
119 | + 2 Definitions | |
120 | + *----------------------- | |
121 | + | |
9e0529f5 | 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) | |
258494a2 | 127 | + |
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 ")". | |
9e0529f5 | 134 | +MAX_SUBSTITUTION_LEN defines maximal length of a substitution variable's |
135 | +identifier (name). | |
258494a2 | 136 | + |
137 | +The last two definitions are just for code simplification. | |
138 | + | |
139 | + | |
140 | + | |
141 | + | |
142 | + | |
143 | + | |
144 | + *----------------------- | |
145 | + 3 New data types | |
146 | + *----------------------- | |
147 | + | |
148 | +This section describes new data type definitions and variables. | |
149 | + | |
150 | +3.1 struct var_data | |
151 | + | |
152 | +struct var_data { | |
153 | + const char *name; | |
154 | + const char *value; | |
155 | + const size_t size; | |
156 | + size_t value_length; | |
157 | + } ; | |
158 | + | |
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). | |
163 | + | |
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 | |
168 | + | |
169 | + | |
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 | |
174 | + | |
175 | +Example: | |
176 | + | |
9e0529f5 | 177 | +struct var_data vdt[] = { |
258494a2 | 178 | + {"some", "replacement", sizeof("some"), 0}, |
179 | + {"anotha", NULL, sizeof("anotha"), 0}, | |
180 | + {NULL, NULL, 0, 0} | |
181 | +}; | |
182 | + | |
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. | |
187 | + | |
188 | + | |
189 | +3.2 typedef size_t (*parsefunc) | |
190 | + | |
9e0529f5 | 191 | +typedef int (*parsefunc)(const char *, size_t, void *); |
258494a2 | 192 | + |
193 | +This type definition refers to the function pointer, which is used | |
194 | +to pass plugin functions into the core parsing subroutine. This definition | |
9e0529f5 | 195 | +is included to simplify the declaration of the parse_core() function. |
258494a2 | 196 | + |
197 | + | |
198 | + | |
199 | + | |
200 | + | |
201 | + *----------------------- | |
202 | + 4 New functions | |
203 | + *----------------------- | |
204 | + | |
205 | +This section describes added functions. | |
206 | + | |
9e0529f5 | 207 | +4.1 get_variable |
258494a2 | 208 | + |
209 | +NAME | |
210 | + | |
9e0529f5 | 211 | + get_variable |
258494a2 | 212 | + |
213 | +SYNOPSIS | |
9e0529f5 | 214 | + |
215 | + static const struct var_data *get_variable (const char *begin, | |
216 | + size_t len, | |
217 | + struct var_data *vdt); | |
258494a2 | 218 | + |
219 | +DESCRIPTION | |
220 | + | |
9e0529f5 | 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. | |
258494a2 | 224 | + |
9e0529f5 | 225 | + This function is also responsible for updating length cache field |
226 | + of vdt elements and validating requested variables. | |
258494a2 | 227 | + |
9e0529f5 | 228 | + This function repports errors by sending human readable |
229 | + messages to the standard error stream. | |
258494a2 | 230 | + |
258494a2 | 231 | +RETURN VALUE |
232 | + | |
9e0529f5 | 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. | |
258494a2 | 236 | + |
258494a2 | 237 | + |
9e0529f5 | 238 | +4.2 parse_core |
258494a2 | 239 | + |
240 | +NAME | |
241 | + | |
9e0529f5 | 242 | + parse_core |
258494a2 | 243 | + |
244 | +SYNOPSIS | |
9e0529f5 | 245 | + static int parse_core (const char *source, struct var_data *vdt, |
246 | + parsefunc outfn, void *result); | |
258494a2 | 247 | + |
248 | +DESCRIPTION | |
249 | + | |
9e0529f5 | 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 | |
264 | + it calls it. | |
265 | + | |
266 | + outfn() function should be passed by its pointer which | |
267 | + refers to declaration: | |
258494a2 | 268 | + |
9e0529f5 | 269 | + int (*outfn) (const char *begin, |
270 | + size_t string_length, | |
271 | + void *void_pointer); | |
272 | + | |
273 | + Each time outfn() is called the result argument of parse_core() | |
274 | + is passed to the outfn() as a last argument (void_pointer). | |
275 | + | |
276 | + Example: | |
277 | + | |
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. | |
258494a2 | 284 | + |
9e0529f5 | 285 | + This function repports errors by sending human readable |
286 | + messages to the standard error stream. | |
258494a2 | 287 | + |
288 | +RETURN VALUE | |
289 | + | |
9e0529f5 | 290 | + This function returns -1 if an error has occured and 0 if |
291 | + everything went good. | |
292 | + | |
293 | +4.3 ParsePlugin_counter | |
258494a2 | 294 | + |
295 | +NAME | |
296 | + | |
9e0529f5 | 297 | + ParsePlugin_counter |
258494a2 | 298 | + |
299 | +SYNOPSIS | |
300 | + | |
9e0529f5 | 301 | + int ParsePlugin_counter (const char *begin, size_t len, |
302 | + void *vp); | |
258494a2 | 303 | + |
304 | +DESCRIPTION | |
305 | + | |
9e0529f5 | 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 | |
311 | + is not used. | |
258494a2 | 312 | + |
9e0529f5 | 313 | + This function repports errors by sending human readable |
314 | + messages to the standard error stream. | |
258494a2 | 315 | + |
316 | +RETURN VALUE | |
317 | + | |
9e0529f5 | 318 | + This function returns the variable size or -1 if an error |
319 | + has occured, 0 if everything went good. | |
258494a2 | 320 | + |
9e0529f5 | 321 | +4.4 ParsePlugin_builder |
258494a2 | 322 | + |
323 | +NAME | |
324 | + | |
9e0529f5 | 325 | + ParsePlugin_builder |
258494a2 | 326 | + |
327 | +SYNOPSIS | |
328 | + | |
9e0529f5 | 329 | + int ParsePlugin_builder (const char *begin, size_t len, |
330 | + void *vp); | |
258494a2 | 331 | + |
332 | +DESCRIPTION | |
333 | + | |
9e0529f5 | 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 | |
342 | + argument. | |
258494a2 | 343 | + |
344 | +RETURN VALUE | |
345 | + | |
9e0529f5 | 346 | + This function returns the variable size or -1 if an error |
347 | + has occured, 0 if everything went good. | |
258494a2 | 348 | + |
9e0529f5 | 349 | +4.5 parse_string |
258494a2 | 350 | + |
351 | +NAME | |
352 | + parse_string | |
353 | + | |
354 | +SYNOPSIS | |
355 | + | |
9e0529f5 | 356 | + static char *parse_string (const char *source, struct var_data *vdt); |
258494a2 | 357 | + |
358 | +DESCRIPTION | |
359 | + | |
360 | + This function parses the string pointed with source according to the | |
361 | + replacement instructions set in var_data array, which is passed with | |
9e0529f5 | 362 | + its pointer vdt. It produces changed string located in newly allocated |
258494a2 | 363 | + memory area. |
364 | + | |
9e0529f5 | 365 | + This function calls parse_core() function with various parsing |
366 | + subroutines passed as function pointers. | |
258494a2 | 367 | + |
9e0529f5 | 368 | + 1. It uses parse_core() with ParsePlugin_counter to obtain the |
369 | + total amount of memory needed for the output string. | |
258494a2 | 370 | + |
9e0529f5 | 371 | + 2. It allocates the memory. |
258494a2 | 372 | + |
9e0529f5 | 373 | + 3. It uses parse_core() with ParsePlugin_builder to build the |
374 | + output string. | |
375 | + | |
376 | + This function repports errors by sending human readable | |
377 | + messages to the standard error stream. | |
258494a2 | 378 | + |
379 | +RETURN VALUE | |
380 | + | |
381 | + Function returns pointer to the result buffer or NULL | |
382 | + if an error has occured. | |
383 | + | |
384 | +WARNINGS | |
385 | + | |
386 | + This function allocates some amount of memory using standard | |
387 | + ANSI C routines. Memory allocated by this function should be | |
388 | + freed with free(). | |
389 | + | |
390 | + | |
9e0529f5 | 391 | +4.6 validate_password |
258494a2 | 392 | + |
393 | +NAME | |
394 | + validate_password | |
395 | + | |
396 | +SYNOPSIS | |
397 | + | |
398 | + static const char *validate_password (const char *password); | |
399 | + | |
400 | +DESCRIPTION | |
401 | + | |
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. | |
406 | + | |
407 | +RETURN VALUE | |
408 | + | |
409 | + It returns a pointer to the static buffer which contains | |
410 | + validated password string or NULL if an error has occured. | |
411 | + | |
412 | + | |
9e0529f5 | 413 | +4.7 get_localpart |
258494a2 | 414 | + |
415 | +NAME | |
416 | + | |
417 | + get_localpart | |
418 | + | |
419 | +SYNOPSIS | |
420 | + | |
421 | + static const char *get_localpart (const char *username); | |
422 | + | |
423 | +DESCRIPTION | |
424 | + | |
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. | |
429 | + | |
430 | +RETURN VALUE | |
431 | + | |
432 | + Pointer to the static buffer containing local part or | |
433 | + NULL if there was some error. | |
434 | + | |
435 | + | |
9e0529f5 | 436 | +4.8 get_domain |
258494a2 | 437 | + |
438 | +NAME | |
439 | + | |
440 | + get_domain | |
441 | + | |
442 | +SYNOPSIS | |
443 | + | |
444 | + static const char *get_domain (const char *username, | |
445 | + const char *defdomain); | |
446 | + | |
447 | +DESCRIPTION | |
448 | + | |
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 | |
454 | + used instead. | |
455 | + | |
456 | +RETURN VALUE | |
457 | + | |
458 | + Pointer to the static buffer containing domain name or | |
459 | + NULL if there was some error. | |
460 | + | |
461 | + | |
9e0529f5 | 462 | +4.9 parse_select_clause |
258494a2 | 463 | + |
464 | +NAME | |
465 | + | |
466 | + parse_select_clause | |
467 | + | |
468 | +SYNOPSIS | |
469 | + | |
470 | + static char *parse_select_clause (const char *clause, | |
471 | + const char *username, | |
472 | + const char *defdomain); | |
473 | + | |
474 | +DESCRIPTION | |
475 | + | |
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) | |
480 | + and $(domain). | |
481 | + | |
482 | + | |
483 | +RETURN VALUE | |
484 | + | |
485 | + Same as parse_string(). | |
486 | + | |
487 | + | |
9e0529f5 | 488 | +4.10 parse_chpass_clause |
258494a2 | 489 | + |
490 | +NAME | |
491 | + | |
492 | + parse_chpass_clause | |
493 | + | |
494 | +SYNOPSIS | |
495 | + | |
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); | |
501 | + | |
502 | +DESCRIPTION | |
503 | + | |
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), | |
509 | + $(newpass_crypt). | |
510 | + | |
511 | +RETURN VALUE | |
512 | + | |
513 | + Same as parse_string(). | |
514 | + | |
515 | + | |
516 | + | |
517 | + | |
518 | + | |
519 | + *------------------------ | |
520 | + 5 Ideas and TODO | |
9e0529f5 | 521 | + *------------------------ |
258494a2 | 522 | + |
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 | |
527 | + | |
528 | +- add clauses: | |
529 | + | |
530 | + - MYSQL_PRESELECT_CLAUSE (query which comes before MYSQL_SELECT_CLAUSE) | |
531 | + - MYSQL_POSTSELECT_CLAUSE (query which comes after MYSQL_SELECT_CLAUSE) | |
9e0529f5 | 532 | + |
533 | + | |
534 | + | |
535 | + | |
536 | + | |
537 | + *------------------------ | |
538 | + 6 Thanks | |
539 | + *------------------------ | |
540 | + | |
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. | |
258494a2 | 545 | + |
546 | +--------------------------------------------------------------------------- | |
547 | + | |
548 | diff -Nur courier-imap-1.3.12.orig/authlib/authmysqllib.c courier-imap-1.3.12/authlib/authmysqllib.c | |
0fe2d1c5 | 549 | --- courier-imap-1.3.12.orig/authlib/authmysqllib.c Mon Aug 6 05:12:39 2001 |
9e0529f5 | 550 | +++ courier-imap-1.3.12/authlib/authmysqllib.c Sun Dec 30 01:41:00 2001 |
0b0a7302 | 551 | @@ -3,7 +3,6 @@ |
552 | ** distribution information. | |
553 | */ | |
554 | ||
555 | - | |
556 | #include <stdio.h> | |
557 | #include <stdlib.h> | |
558 | #include <string.h> | |
9e0529f5 | 559 | @@ -18,8 +17,26 @@ |
258494a2 | 560 | #include "authmysqlrc.h" |
561 | #include "auth.h" | |
0fe2d1c5 | 562 | |
258494a2 | 563 | +/* siefca@pld.org.pl */ |
9e0529f5 | 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) | |
258494a2 | 569 | + |
0fe2d1c5 | 570 | static const char rcsid[]="$Id$"; |
571 | ||
9e0529f5 | 572 | +/* siefca@pld.org.pl */ |
0b0a7302 | 573 | +struct var_data { |
0fe2d1c5 | 574 | + const char *name; |
575 | + const char *value; | |
576 | + const size_t size; | |
0b0a7302 | 577 | + size_t value_length; |
9e0529f5 | 578 | + } ; |
0b0a7302 | 579 | + |
9e0529f5 | 580 | +/* siefca@pld.org.pl */ |
581 | +typedef int (*parsefunc)(const char *, size_t, void *); | |
0fe2d1c5 | 582 | + |
583 | static const char *read_env(const char *env) | |
584 | { | |
585 | static char *mysqlauth=0; | |
9e0529f5 | 586 | @@ -51,7 +68,13 @@ |
0fe2d1c5 | 587 | |
588 | for (i=0; i<mysqlauth_size; i++) | |
589 | if (mysqlauth[i] == '\n') | |
590 | - mysqlauth[i]=0; | |
591 | + { /* siefca@pld.org.pl */ | |
0b0a7302 | 592 | + if (!i || mysqlauth[i-1] != '\\') |
593 | + mysqlauth[i] ='\0'; | |
0fe2d1c5 | 594 | + else |
0b0a7302 | 595 | + mysqlauth[i] = |
596 | + mysqlauth[i-1] = ' '; | |
0fe2d1c5 | 597 | + } |
598 | fclose(f); | |
599 | } | |
600 | ||
9e0529f5 | 601 | @@ -199,17 +222,370 @@ |
0fe2d1c5 | 602 | strcat(strcpy(p, "@"), defdomain); |
603 | } | |
604 | ||
605 | +/* siefca@pld.org.pl */ | |
9e0529f5 | 606 | +static struct var_data *get_variable (const char *begin, size_t len, |
607 | + struct var_data *vdt) | |
0fe2d1c5 | 608 | +{ |
0b0a7302 | 609 | +struct var_data *vdp; |
0fe2d1c5 | 610 | + |
9e0529f5 | 611 | + if (!begin || !vdt) /* should never happend */ |
612 | + { | |
613 | + fprintf (stderr, "authmysql: critical error while " | |
614 | + "parsing substitution variable\n"); | |
615 | + return NULL; | |
616 | + } | |
617 | + if (len < 1) | |
618 | + { | |
619 | + fprintf (stderr, "authmysql: unknown empty substitution " | |
620 | + "variable - aborting\n"); | |
621 | + return NULL; | |
622 | + } | |
623 | + if (len > MAX_SUBSTITUTION_LEN) | |
624 | + { | |
625 | + fprintf (stderr, "authmysql: variable name too long " | |
626 | + "while parsing substitution\n" | |
627 | + "authmysql: name begins with " | |
628 | + SV_BEGIN_MARK | |
629 | + "%.*s...\n", MAX_SUBSTITUTION_LEN, begin); | |
630 | + return NULL; | |
631 | + } | |
632 | + | |
633 | + for (vdp=vdt; vdp->name; vdp++) | |
0b0a7302 | 634 | + if (vdp->size == len+1 && |
635 | + !strncmp(begin, vdp->name, len)) | |
9e0529f5 | 636 | + { |
637 | + if (!vdp->value) | |
638 | + vdp->value = ""; | |
639 | + if (!vdp->value_length) /* length cache */ | |
640 | + vdp->value_length = strlen (vdp->value); | |
641 | + return vdp; | |
642 | + } | |
0b0a7302 | 643 | + |
644 | + fprintf (stderr, "authmysql: unknown substitution variable " | |
258494a2 | 645 | + SV_BEGIN_MARK |
646 | + "%.*s" | |
647 | + SV_END_MARK | |
648 | + "\n", len, begin); | |
0b0a7302 | 649 | + |
650 | + return NULL; | |
651 | +} | |
0fe2d1c5 | 652 | + |
0b0a7302 | 653 | +/* siefca@pld.org.pl */ |
9e0529f5 | 654 | +static int ParsePlugin_counter (const char *p, size_t length, void *vp) |
655 | +{ | |
656 | + if (!p || !vp || length < 0) | |
657 | + { | |
658 | + fprintf (stderr, "authmysql: bad arguments while counting " | |
659 | + "query string\n"); | |
660 | + return -1; | |
661 | + } | |
662 | + | |
663 | + *((size_t *)vp) += length; | |
664 | + | |
665 | + return 0; | |
666 | +} | |
667 | + | |
668 | +/* siefca@pld.org.pl */ | |
669 | +static int ParsePlugin_builder (const char *p, size_t length, void *vp) | |
0b0a7302 | 670 | +{ |
9e0529f5 | 671 | +char **strptr = (char **) vp; |
672 | + | |
673 | + if (!p || !vp || length < 0) | |
674 | + { | |
675 | + fprintf (stderr, "authmysql: bad arguments while building " | |
676 | + "query string\n"); | |
677 | + return -1; | |
678 | + } | |
679 | + | |
680 | + if (!length) return 0; | |
681 | + memcpy ((void *) *strptr, (void *) p, length); | |
682 | + *strptr += length; | |
683 | + | |
684 | + return 0; | |
685 | +} | |
686 | + | |
687 | +/* siefca@pld.org.pl */ | |
688 | +static int parse_core (const char *source, struct var_data *vdt, | |
689 | + parsefunc outfn, void *result) | |
690 | +{ | |
691 | +int ret; | |
692 | +size_t v_size = 0, | |
258494a2 | 693 | + t_size = 0; |
0b0a7302 | 694 | +const char *p, *q, *e, |
695 | + *v_begin, *v_end, | |
9e0529f5 | 696 | + *t_begin, *t_end; |
697 | +struct var_data *v_ptr; | |
0b0a7302 | 698 | + |
699 | + if (!source) | |
700 | + source = ""; | |
9e0529f5 | 701 | + if (!result) |
702 | + { | |
703 | + fprintf (stderr, "authmysql: no memory allocated for result" | |
704 | + "while parser core was invoked\n"); | |
705 | + return -1; | |
706 | + } | |
707 | + if (!vdt) | |
708 | + { | |
709 | + fprintf (stderr, "authmysql: no substitution table found " | |
710 | + "while parser core was invoked\n"); | |
711 | + return -1; | |
712 | + } | |
713 | + | |
0b0a7302 | 714 | + q = source; |
258494a2 | 715 | + while ( (p=strstr(q, SV_BEGIN_MARK)) ) |
0fe2d1c5 | 716 | + { |
258494a2 | 717 | + e = strstr (p, SV_END_MARK); |
0b0a7302 | 718 | + if (!e) |
0fe2d1c5 | 719 | + { |
0b0a7302 | 720 | + fprintf (stderr, "authmysql: syntax error in " |
9e0529f5 | 721 | + "substitution " |
722 | + "- no closing symbol fould!\n" | |
723 | + "authmysql: bad variable begins with:" | |
724 | + "%.*s...\n", MAX_SUBSTITUTION_LEN, p); | |
0b0a7302 | 725 | + return -1; |
0fe2d1c5 | 726 | + } |
0b0a7302 | 727 | + |
728 | + /* | |
729 | + ** | |
730 | + ** __________sometext$(variable_name)_________ | |
9e0529f5 | 731 | + ** | | | | |
0b0a7302 | 732 | + ** t_begin' t_end' `v_begin `v_end |
733 | + ** | |
734 | + */ | |
735 | + | |
9e0529f5 | 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 */ | |
0b0a7302 | 739 | + |
9e0529f5 | 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 */ | |
0b0a7302 | 743 | + |
9e0529f5 | 744 | + /* work on text */ |
745 | + if ( (outfn (t_begin, t_size, result)) == -1 ) | |
746 | + return -1; | |
0b0a7302 | 747 | + |
9e0529f5 | 748 | + /* work on variable */ |
749 | + v_ptr = get_variable (v_begin, v_size, vdt); | |
750 | + if (!v_ptr) return -1; | |
751 | + | |
752 | + if ( (outfn (v_ptr->value, v_ptr->value_length, result)) == -1 ) | |
753 | + return -1; | |
754 | + | |
755 | + q = e + 1; | |
0b0a7302 | 756 | + } |
757 | + | |
9e0529f5 | 758 | + /* work on last part of text if any */ |
759 | + if (*q != '\0') | |
760 | + if ( (outfn (q, strlen(q), result)) == -1 ) | |
761 | + return -1; | |
0fe2d1c5 | 762 | + |
9e0529f5 | 763 | + return 0; |
0fe2d1c5 | 764 | +} |
765 | + | |
766 | +/* siefca@pld.org.pl */ | |
9e0529f5 | 767 | +static char *parse_string (const char *source, struct var_data *vdt) |
0b0a7302 | 768 | +{ |
9e0529f5 | 769 | +char *output_buf = NULL, |
770 | + *pass_buf = NULL; | |
771 | +size_t buf_size = 2; | |
0b0a7302 | 772 | + |
773 | + if (source == NULL || *source == '\0' || | |
9e0529f5 | 774 | + vdt == NULL || vdt[0].name == NULL) |
0b0a7302 | 775 | + { |
776 | + fprintf (stderr, "authmysql: source clause is empty " | |
777 | + "- this is critical error\n"); | |
778 | + return NULL; | |
779 | + } | |
780 | + | |
9e0529f5 | 781 | + /* phase 1 - count and validate string */ |
782 | + if ( (parse_core (source, vdt, &ParsePlugin_counter, &buf_size)) != 0) | |
0b0a7302 | 783 | + return NULL; |
784 | + | |
9e0529f5 | 785 | + /* phase 2 - allocate memory */ |
0b0a7302 | 786 | + output_buf = malloc (buf_size); |
787 | + if (!output_buf) | |
788 | + { | |
789 | + perror ("malloc"); | |
790 | + return NULL; | |
791 | + } | |
9e0529f5 | 792 | + pass_buf = output_buf; |
0b0a7302 | 793 | + |
9e0529f5 | 794 | + /* phase 3 - build the output string */ |
795 | + if ( (parse_core (source, vdt, &ParsePlugin_builder, &pass_buf)) != 0) | |
0b0a7302 | 796 | + { |
797 | + free (output_buf); | |
798 | + return NULL; | |
9e0529f5 | 799 | + } |
800 | + *pass_buf = '\0'; | |
0b0a7302 | 801 | + |
802 | + return output_buf; | |
9e0529f5 | 803 | +} |
0b0a7302 | 804 | + |
805 | +/* siefca@pld.org.pl */ | |
0fe2d1c5 | 806 | +static const char *get_localpart (const char *username) |
807 | +{ | |
258494a2 | 808 | +size_t lbuf = 0; |
809 | +const char *l_end, *p; | |
810 | +char *q; | |
811 | +static char localpart_buf[130]; | |
812 | + | |
813 | + if (!username || *username == '\0') return NULL; | |
0fe2d1c5 | 814 | + |
0fe2d1c5 | 815 | + p = strchr(username,'@'); |
816 | + if (p) | |
817 | + { | |
258494a2 | 818 | + if ((p-username) > 128) |
819 | + return NULL; | |
820 | + l_end = p; | |
0fe2d1c5 | 821 | + } |
822 | + else | |
823 | + { | |
258494a2 | 824 | + if ((lbuf = strlen(username)) > 128) |
825 | + return NULL; | |
826 | + l_end = username + lbuf; | |
0fe2d1c5 | 827 | + } |
828 | + | |
258494a2 | 829 | + p=username; |
830 | + q=localpart_buf; | |
831 | + | |
832 | + while (*p && p != l_end) | |
0b0a7302 | 833 | + if (*p == '\"' || *p == '\\' || |
834 | + *p == '\'' || (int)(unsigned char)*p < ' ') | |
258494a2 | 835 | + p++; |
836 | + else | |
837 | + *q++ = *p++; | |
0b0a7302 | 838 | + |
258494a2 | 839 | + *q = '\0'; |
0fe2d1c5 | 840 | + return localpart_buf; |
841 | +} | |
842 | + | |
843 | +/* siefca@pld.org.pl */ | |
844 | +static const char *get_domain (const char *username, const char *defdomain) | |
845 | +{ | |
0b0a7302 | 846 | +static char domain_buf[260]; |
258494a2 | 847 | +const char *p; |
848 | +char *q; | |
0fe2d1c5 | 849 | + |
258494a2 | 850 | + if (!username || *username == '\0') return NULL; |
0fe2d1c5 | 851 | + p = strchr(username,'@'); |
852 | + | |
258494a2 | 853 | + if (!p || *(p+1) == '\0') |
854 | + { | |
855 | + if (defdomain && *defdomain) | |
856 | + return defdomain; | |
857 | + else | |
858 | + return NULL; | |
859 | + } | |
860 | + | |
861 | + p++; | |
862 | + if ((strlen(p)) > 256) | |
863 | + return NULL; | |
864 | + | |
865 | + q = domain_buf; | |
866 | + while (*p) | |
867 | + if (*p == '\"' || *p == '\\' || | |
868 | + *p == '\'' || (int)(unsigned char)*p < ' ') | |
869 | + p++; | |
870 | + else | |
871 | + *q++ = *p++; | |
872 | + | |
873 | + *q = '\0'; | |
874 | + return domain_buf; | |
0fe2d1c5 | 875 | +} |
876 | + | |
877 | +/* siefca@pld.org.pl */ | |
0b0a7302 | 878 | +static const char *validate_password (const char *password) |
879 | +{ | |
880 | +static char pass_buf[260]; | |
881 | +const char *p; | |
882 | +char *q; | |
883 | + | |
258494a2 | 884 | + if (!password || *password == '\0' || (strlen(password)) > 256) |
885 | + return NULL; | |
0b0a7302 | 886 | + |
258494a2 | 887 | + p = password; |
888 | + q = pass_buf; | |
889 | + | |
890 | + while (*p) | |
0b0a7302 | 891 | + if (*p == '\"' || *p == '\\' || *p == '\'') |
892 | + *q++ = '\\'; | |
258494a2 | 893 | + else |
894 | + *q++ = *p++; | |
0b0a7302 | 895 | + |
896 | + *q = '\0'; | |
0b0a7302 | 897 | + return pass_buf; |
898 | +} | |
899 | + | |
900 | + | |
901 | +/* siefca@pld.org.pl */ | |
0fe2d1c5 | 902 | +static char *parse_select_clause (const char *clause, const char *username, |
903 | + const char *defdomain) | |
904 | +{ | |
905 | +static struct var_data vd[]={ | |
0b0a7302 | 906 | + {"local_part", NULL, sizeof("local_part"), 0}, |
907 | + {"domain", NULL, sizeof("domain"), 0}, | |
908 | + {NULL, NULL, 0, 0}}; | |
0fe2d1c5 | 909 | + |
910 | + if (clause == NULL || *clause == '\0' || | |
258494a2 | 911 | + !username || *username == '\0') |
912 | + return NULL; | |
0fe2d1c5 | 913 | + |
0b0a7302 | 914 | + vd[0].value = get_localpart (username); |
915 | + vd[1].value = get_domain (username, defdomain); | |
258494a2 | 916 | + if (!vd[0].value || !vd[1].value) |
917 | + return NULL; | |
0fe2d1c5 | 918 | + |
0b0a7302 | 919 | + return (parse_string (clause, vd)); |
0fe2d1c5 | 920 | +} |
921 | + | |
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) | |
926 | +{ | |
927 | +static struct var_data vd[]={ | |
0b0a7302 | 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}}; | |
0fe2d1c5 | 933 | + |
934 | + if (clause == NULL || *clause == '\0' || | |
935 | + !username || *username == '\0' || | |
936 | + !newpass || *newpass == '\0' || | |
258494a2 | 937 | + !newpass_crypt || *newpass_crypt == '\0') return NULL; |
0fe2d1c5 | 938 | + |
0b0a7302 | 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); | |
943 | + | |
944 | + if (!vd[0].value || !vd[1].value || | |
945 | + !vd[2].value || !vd[3].value) return NULL; | |
0fe2d1c5 | 946 | + |
0b0a7302 | 947 | + return (parse_string (clause, vd)); |
0fe2d1c5 | 948 | +} |
0fe2d1c5 | 949 | + |
950 | struct authmysqluserinfo *auth_mysql_getuserinfo(const char *username) | |
951 | { | |
952 | -const char *user_table; | |
953 | -const char *defdomain; | |
954 | +const char *user_table =NULL; | |
955 | +const char *defdomain =NULL; | |
956 | char *querybuf, *p; | |
957 | MYSQL_ROW row; | |
958 | MYSQL_RES *result; | |
959 | ||
960 | -const char *crypt_field, *clear_field, *maildir_field, *home_field, | |
961 | - *name_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, | |
966 | + *home_field =NULL, | |
967 | + *name_field =NULL, | |
968 | + *login_field =NULL, | |
969 | + *uid_field =NULL, | |
970 | + *gid_field =NULL, | |
971 | + *quota_field =NULL, | |
972 | + *where_clause =NULL, | |
973 | + *select_clause =NULL; /* siefca@pld.org.pl */ | |
974 | ||
975 | static const char query[]= | |
976 | "SELECT %s, %s, %s, %s, %s, %s, %s, %s, %s FROM %s WHERE %s = \""; | |
9e0529f5 | 977 | @@ -232,79 +608,95 @@ |
0fe2d1c5 | 978 | free(ui.fullname); |
979 | memset(&ui, 0, sizeof(ui)); | |
980 | ||
981 | - user_table=read_env("MYSQL_USER_TABLE"); | |
982 | - defdomain=read_env("DEFAULT_DOMAIN"); | |
983 | - | |
984 | - if (!user_table) | |
985 | + select_clause=read_env("MYSQL_SELECT_CLAUSE"); | |
986 | + defdomain=read_env("DEFAULT_DOMAIN"); | |
987 | + | |
988 | + if (!select_clause) /* siefca@pld.org.pl */ | |
989 | { | |
990 | - fprintf(stderr, "authmysql: MYSQL_USER_TABLE not set in " | |
991 | - AUTHMYSQLRC ".\n"); | |
992 | - return (0); | |
993 | - } | |
994 | + user_table=read_env("MYSQL_USER_TABLE"); | |
995 | ||
996 | - crypt_field=read_env("MYSQL_CRYPT_PWFIELD"); | |
997 | - clear_field=read_env("MYSQL_CLEAR_PWFIELD"); | |
998 | - name_field=read_env("MYSQL_NAME_FIELD"); | |
999 | + if (!user_table) | |
1000 | + { | |
1001 | + fprintf(stderr, "authmysql: MYSQL_USER_TABLE not set in " | |
1002 | + AUTHMYSQLRC ".\n"); | |
1003 | + return (0); | |
1004 | + } | |
1005 | ||
1006 | - if (!crypt_field && !clear_field) | |
1007 | - { | |
1008 | - fprintf(stderr, | |
1009 | - "authmysql: MYSQL_CRYPT_PWFIELD and " | |
1010 | - "MYSQL_CLEAR_PWFIELD not set in " AUTHMYSQLRC ".\n"); | |
1011 | - return (0); | |
1012 | - } | |
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"); | |
258494a2 | 1019 | + |
0fe2d1c5 | 1020 | + if (!crypt_field && !clear_field) |
1021 | + { | |
1022 | + fprintf(stderr, | |
1023 | + "authmysql: MYSQL_CRYPT_PWFIELD and " | |
1024 | + "MYSQL_CLEAR_PWFIELD not set in " AUTHMYSQLRC ".\n"); | |
1025 | + return (0); | |
1026 | + } | |
1027 | + if (!crypt_field) crypt_field="\"\""; | |
1028 | + if (!clear_field) clear_field="\"\""; | |
1029 | + if (!name_field) name_field="\"\""; | |
0fe2d1c5 | 1030 | |
258494a2 | 1031 | - uid_field = read_env("MYSQL_UID_FIELD"); |
1032 | - if (!uid_field) uid_field = "uid"; | |
0b0a7302 | 1033 | + uid_field = read_env("MYSQL_UID_FIELD"); |
1034 | + if (!uid_field) uid_field = "uid"; | |
0fe2d1c5 | 1035 | |
258494a2 | 1036 | - gid_field = read_env("MYSQL_GID_FIELD"); |
1037 | - if (!gid_field) gid_field = "gid"; | |
0b0a7302 | 1038 | + gid_field = read_env("MYSQL_GID_FIELD"); |
1039 | + if (!gid_field) gid_field = "gid"; | |
0fe2d1c5 | 1040 | |
258494a2 | 1041 | - login_field = read_env("MYSQL_LOGIN_FIELD"); |
1042 | - if (!login_field) login_field = "id"; | |
0b0a7302 | 1043 | + login_field = read_env("MYSQL_LOGIN_FIELD"); |
1044 | + if (!login_field) login_field = "id"; | |
0fe2d1c5 | 1045 | |
258494a2 | 1046 | - home_field = read_env("MYSQL_HOME_FIELD"); |
1047 | - if (!home_field) home_field = "home"; | |
0b0a7302 | 1048 | + home_field = read_env("MYSQL_HOME_FIELD"); |
1049 | + if (!home_field) home_field = "home"; | |
0fe2d1c5 | 1050 | |
258494a2 | 1051 | - maildir_field=read_env("MYSQL_MAILDIR_FIELD"); |
1052 | - if (!maildir_field) maildir_field="\"\""; | |
0b0a7302 | 1053 | + maildir_field=read_env("MYSQL_MAILDIR_FIELD"); |
1054 | + if (!maildir_field) maildir_field="\"\""; | |
0fe2d1c5 | 1055 | |
258494a2 | 1056 | - quota_field=read_env("MYSQL_QUOTA_FIELD"); |
1057 | - if (!quota_field) quota_field="\"\""; | |
0b0a7302 | 1058 | + quota_field=read_env("MYSQL_QUOTA_FIELD"); |
1059 | + if (!quota_field) quota_field="\"\""; | |
258494a2 | 1060 | |
1061 | - where_clause=read_env("MYSQL_WHERE_CLAUSE"); | |
1062 | - if (!where_clause) where_clause = ""; | |
0fe2d1c5 | 1063 | + where_clause=read_env("MYSQL_WHERE_CLAUSE"); |
1064 | + if (!where_clause) where_clause = ""; | |
1065 | + } | |
1066 | ||
1067 | if (!defdomain) defdomain=""; | |
1068 | ||
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) | |
0b0a7302 | 1073 | - + strlen(name_field)); |
1074 | - if (!querybuf) | |
0fe2d1c5 | 1075 | + if (!select_clause) /* siefca@pld.org.pl */ |
0b0a7302 | 1076 | { |
1077 | - perror("malloc"); | |
1078 | - return (0); | |
1079 | - } | |
0fe2d1c5 | 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) | |
0b0a7302 | 1084 | + + strlen(name_field)); |
258494a2 | 1085 | + |
0fe2d1c5 | 1086 | + if (!querybuf) |
1087 | + { | |
1088 | + perror("malloc"); | |
1089 | + return (0); | |
1090 | + } | |
9e0529f5 | 1091 | + |
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); | |
258494a2 | 1095 | |
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); | |
9e0529f5 | 1100 | + p=querybuf+strlen(querybuf); |
0b0a7302 | 1101 | |
1102 | - append_username(p, username, defdomain); | |
1103 | - strcat(p, "\""); | |
0fe2d1c5 | 1104 | + append_username(p, username, defdomain); |
1105 | + strcat(p, "\""); | |
0b0a7302 | 1106 | |
1107 | - if (strcmp(where_clause, "")) { | |
1108 | - strcat(p, " AND ("); | |
1109 | - strcat(p, where_clause); | |
1110 | - strcat(p, ")"); | |
0fe2d1c5 | 1111 | + if (strcmp(where_clause, "")) { |
1112 | + strcat(p, " AND ("); | |
1113 | + strcat(p, where_clause); | |
1114 | + strcat(p, ")"); | |
1115 | + } | |
0b0a7302 | 1116 | } |
1117 | - | |
0fe2d1c5 | 1118 | + else |
0b0a7302 | 1119 | + { |
0fe2d1c5 | 1120 | + /* siefca@pld.org.pl */ |
1121 | + querybuf=parse_select_clause (select_clause, username, defdomain); | |
1122 | + if (!querybuf) return 0; | |
0b0a7302 | 1123 | + } |
1124 | + | |
0fe2d1c5 | 1125 | if (mysql_query (mysql, querybuf)) |
1126 | { | |
1127 | /* <o.blasnik@nextra.de> */ | |
9e0529f5 | 1128 | @@ -379,12 +771,13 @@ |
0fe2d1c5 | 1129 | const char *comma; |
1130 | int rc=0; | |
1131 | ||
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, | |
1140 | + *defdomain =NULL, | |
1141 | + *where_clause =NULL, | |
1142 | + *user_table =NULL, | |
1143 | + *login_field =NULL, | |
1144 | + *chpass_clause =NULL; /* siefca@pld.org.pl */ | |
1145 | ||
1146 | if (!mysql) | |
1147 | return (-1); | |
9e0529f5 | 1148 | @@ -412,21 +805,34 @@ |
0fe2d1c5 | 1149 | ++l; |
1150 | } | |
1151 | ||
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"); | |
1161 | - | |
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:"") | |
1168 | - + 200); | |
1169 | + if (!chpass_clause) | |
1170 | + { | |
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:"") | |
1182 | + + 200); | |
1183 | + } | |
1184 | + else | |
1185 | + { | |
1186 | + sql_buf=parse_chpass_clause(chpass_clause, | |
1187 | + user, | |
1188 | + defdomain, | |
1189 | + pass, | |
1190 | + newpass_crypt); | |
1191 | + } | |
1192 | + | |
1193 | ||
1194 | if (!sql_buf) | |
1195 | { | |
9e0529f5 | 1196 | @@ -434,53 +840,57 @@ |
0fe2d1c5 | 1197 | return (-1); |
1198 | } | |
1199 | ||
1200 | - sprintf(sql_buf, "UPDATE %s SET", user_table); | |
1201 | - | |
1202 | - comma=""; | |
1203 | - | |
1204 | - if (clear_field && *clear_field) | |
1205 | + if (!chpass_clause) /*siefca@pld.org.pl */ | |
1206 | { | |
1207 | - char *q; | |
1208 | + sprintf(sql_buf, "UPDATE %s SET", user_table); | |
1209 | ||
1210 | - strcat(strcat(strcat(sql_buf, " "), clear_field), | |
1211 | - "=\""); | |
1212 | + comma=""; | |
1213 | ||
1214 | - q=sql_buf+strlen(sql_buf); | |
1215 | - while (*pass) | |
1216 | + if (clear_field && *clear_field) | |
1217 | { | |
1218 | - if (*pass == '"' || *pass == '\\') | |
1219 | - *q++= '\\'; | |
1220 | - *q++ = *pass++; | |
1221 | + char *q; | |
1222 | + | |
1223 | + strcat(strcat(strcat(sql_buf, " "), clear_field), | |
1224 | + "=\""); | |
1225 | + | |
1226 | + q=sql_buf+strlen(sql_buf); | |
1227 | + while (*pass) | |
1228 | + { | |
1229 | + if (*pass == '"' || *pass == '\\') | |
1230 | + *q++= '\\'; | |
1231 | + *q++ = *pass++; | |
1232 | + } | |
1233 | + strcpy(q, "\""); | |
1234 | + comma=", "; | |
1235 | } | |
1236 | - strcpy(q, "\""); | |
1237 | - comma=", "; | |
1238 | - } | |
1239 | ||
1240 | - if (crypt_field && *crypt_field) | |
1241 | - { | |
1242 | - strcat(strcat(strcat(strcat(strcat(strcat(sql_buf, comma), | |
1243 | - " "), | |
1244 | - crypt_field), | |
1245 | - "=\""), | |
1246 | - newpass_crypt_ptr), | |
1247 | - "\""); | |
1248 | - } | |
1249 | - free(newpass_crypt); | |
1250 | + if (crypt_field && *crypt_field) | |
1251 | + { | |
1252 | + strcat(strcat(strcat(strcat(strcat(strcat(sql_buf, comma), | |
1253 | + " "), | |
1254 | + crypt_field), | |
1255 | + "=\""), | |
1256 | + newpass_crypt_ptr), | |
1257 | + "\""); | |
1258 | + } | |
1259 | + free(newpass_crypt); | |
1260 | ||
1261 | - strcat(strcat(strcat(sql_buf, " WHERE "), | |
1262 | - login_field), | |
1263 | - "=\""); | |
1264 | + strcat(strcat(strcat(sql_buf, " WHERE "), | |
1265 | + login_field), | |
1266 | + "=\""); | |
1267 | ||
1268 | - append_username(sql_buf+strlen(sql_buf), user, defdomain); | |
1269 | + append_username(sql_buf+strlen(sql_buf), user, defdomain); | |
1270 | ||
1271 | - strcat(sql_buf, "\""); | |
1272 | + strcat(sql_buf, "\""); | |
1273 | ||
1274 | - if (where_clause && *where_clause) | |
1275 | - { | |
1276 | - strcat(sql_buf, " AND ("); | |
1277 | - strcat(sql_buf, where_clause); | |
1278 | - strcat(sql_buf, ")"); | |
1279 | - } | |
1280 | + if (where_clause && *where_clause) | |
1281 | + { | |
1282 | + strcat(sql_buf, " AND ("); | |
1283 | + strcat(sql_buf, where_clause); | |
1284 | + strcat(sql_buf, ")"); | |
1285 | + } | |
1286 | + | |
1287 | + } /* end of: if (!chpass_clause) */ | |
1288 | ||
1289 | if (mysql_query (mysql, sql_buf)) | |
1290 | { | |
258494a2 | 1291 | diff -Nur courier-imap-1.3.12.orig/authlib/authmysqlrc courier-imap-1.3.12/authlib/authmysqlrc |
0fe2d1c5 | 1292 | --- courier-imap-1.3.12.orig/authlib/authmysqlrc Sun Oct 7 18:32:56 2001 |
9e0529f5 | 1293 | +++ courier-imap-1.3.12/authlib/authmysqlrc Fri Dec 28 02:08:01 2001 |
0b0a7302 | 1294 | @@ -141,4 +141,65 @@ |
0fe2d1c5 | 1295 | # |
1296 | # MYSQL_WHERE_CLAUSE server='mailhost.example.com' | |
1297 | ||
1298 | - | |
1299 | +##NAME: MYSQL_SELECT_CLAUSE:0 | |
1300 | +# | |
1301 | +# (EXPERIMENTAL) | |
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 | |
0b0a7302 | 1305 | +# in order specified bellow: |
0fe2d1c5 | 1306 | +# |
1307 | +# username, cryptpw, uid, gid, clearpw, home, maildir, quota, fullname | |
1308 | +# | |
1309 | +# Enabling this option causes ignorance of any other field-related | |
1310 | +# options, excluding default domain. | |
1311 | +# | |
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 | |
0b0a7302 | 1314 | +# in the right place of your query. These variables are: |
1315 | +# $(local_part) and $(domain) | |
0fe2d1c5 | 1316 | +# |
1317 | +# If a $(domain) is empty (not given by the remote user) the default domain | |
1318 | +# name is used in its place. | |
1319 | +# | |
1320 | +# This example is a little bit modified adaptation of vmail-sql | |
1321 | +# database scheme: | |
0b0a7302 | 1322 | +# |
1323 | +# MYSQL_SELECT_CLAUSE SELECT popbox.local_part, \ | |
0fe2d1c5 | 1324 | +# CONCAT('{MD5}', popbox.password_hash), \ |
1325 | +# domain.uid, \ | |
1326 | +# domain.gid, \ | |
1327 | +# popbox.clearpw, \ | |
1328 | +# CONCAT(domain.path, '/', popbox.mbox_name), \ | |
1329 | +# '', \ | |
1330 | +# domain.quota, \ | |
1331 | +# '', \ | |
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 | |
1336 | +# | |
1337 | +##NAME: MYSQL_CHPASS_CLAUSE:0 | |
1338 | +# | |
1339 | +# (EXPERIMENTAL) | |
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. | |
1344 | +# | |
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) | |
1349 | +# | |
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 | |
1354 | +# | |
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)' | |
1360 | +# |