debian release
[hcoop/debian/courier-authlib.git] / README.authmysql.myownquery
CommitLineData
d9898ee8 1
2
3
4
5 Developer Notes for courier-imap-myownquery.patch
6
7
8
9
10 document version: 1.03
11 author: Pawel Wilk
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
280 What's that?
29
301 Modifications overview
31
322 Definitions
33
343 New data types
35 3.1 struct var_data
36 3.2 typedef size_t (*parsefunc)
37
384 New functions
39 4.1 get_variable
40 4.2 parse_core
41 4.3 ParsePlugin_counter
42 4.4 ParsePlugin_builder
43 4.5 parse_string
44 4.6 validate_password
45 4.7 get_localpart
46 4.8 get_domain
47 4.9 parse_select_clause
48 4.10 parse_chpass_clause
49
505 Ideas and TODO
51
526 Thanks
53
54
55
56
57 *-----------------------
58 0 What's that?
59 *-----------------------
60
61Courier-imap-myownquery.patch allows administrator to set own SQL queries
62used by authdaemon to authenticate user (including fetchig credentials) and to
63change user's password. It allows to construct SELECT or UPDATE clause in the
64configuration file (authmysqlrc or authpgsqlrc) by adding two new configuration
65variables: MYSQL_SELECT_CLAUSE or PGSQL_SELECT_CLAUSE and MYSQL_CHPASS_CLAUSE
66or PGSQL_CHPASS_CLAUSE. It may be useful in the mail environments where there
67is such a need to have different database structure and/or tables scheme than
68expected by authmysql or authpgsql module.
69
70It also implements a small parsing engine for substitution variables which
71may appear in the clauses and are used to put informations like username
72or domain into the right place of a query.
73
74This patch was created using `diff -Nur` on courier-imap-1.3.12 source.
75
76
77
78
79
80 *-----------------------
81 1 Modifications overview
82 *-----------------------
83
84Modified files: authmysqllib.c authmysqlrc authpgsqllib.c authpgsqlrc
85
86Each modified set of instructions is marked by my e-mail address:
87siefca@pld.org.pl (for MySQL files) or tom@minnesota.com (for PostgreSQL files)
88
89Changes in the current source code are related to:
90
91- sections where the queries are constructed
92 (including memory allocation for the buffers)
93
94 when MYSQL_SELECT_CLAUSE or MYSQL_CHPASS_CLAUSE or
95 PGSQL_SELECT_CLAUSE or PGSQL_CHPASS_CLAUSE is
96 used then the query goes through the parsing functions
97 passing over current memory allocation and query construction
98 subroutines
99
100- section where the configuration file is read
101
102 i've had to modify read_env() function to allow line breaks
103 - now each sequence of the backslash as a first character and
104 newline as the second is replaced by two whitespaces while
105 putting into the buffer
106
107- sections where the query is constructed
108
109 selection is made, depending on configuration variables which
110 are set or not - if own query is used
111
112
113
114
115
116 *-----------------------
117 2 Definitions
118 *-----------------------
119
120#define MAX_SUBSTITUTION_LEN 32
121#define SV_BEGIN_MARK "$("
122#define SV_END_MARK ")"
123#define SV_BEGIN_LEN ((sizeof(SV_BEGIN_MARK))-1)
124#define SV_END_LEN ((sizeof(SV_END_MARK))-1)
125
126These definitions allows to change substitution marks in an easy way.
127SV_BEGIN_MARK refers to sequence of characters treated as a prefix of
128each substitution variable and SV_END_MARK refers to string which is
129a closing suffix. If the expected substitution variable is called
130'local_part' (without apostrophes) then '$(local_part)' is a valid
131string representation for SV_BEGIN_MARK set to "$(" and SV_END_MARK to ")".
132MAX_SUBSTITUTION_LEN defines maximal length of a substitution variable's
133identifier (name).
134
135The last two definitions are just for code simplification.
136
137
138
139
140
141
142 *-----------------------
143 3 New data types
144 *-----------------------
145
146This section describes new data type definitions and variables.
147
1483.1 struct var_data
149
150struct var_data {
151 const char *name;
152 const char *value;
153 const size_t size;
154 size_t value_length;
155 } ;
156
157This structure holds information needed by parsing routines.
158Using var_data array you may specify a set of string substitutions
159which should be done while parsing a query. Last element in array
160should have all fields set to zero (null).
161
162name field - should contain substituted variable name
163value - should contain string which replaces it
164size - should contain string size including the last zero byte ('\0')
165value_length - should be set to zero - it is used as a value size cache
166
167
168explanation: size is used to increase speed of calculation proccess
169 value_length is used to cache length of a value during the
170 parsing subroutines - it helps when substitution variable
171 occures more than once within the query
172
173Example:
174
175struct var_data vdt[] = {
176 {"some", "replacement", sizeof("some"), 0},
177 {"anotha", NULL, sizeof("anotha"), 0},
178 {NULL, NULL, 0, 0}
179};
180
181In this example we've declared that $(some) in the query should be
182replaced by 'replacement' text, and replacement for $(anotha) will
183be defined in the code before passing on the array pointer to
184the paring function.
185
186
1873.2 typedef size_t (*parsefunc)
188
189typedef int (*parsefunc)(const char *, size_t, void *);
190
191This type definition refers to the function pointer, which is used
192to pass plugin functions into the core parsing subroutine. This definition
193is included to simplify the declaration of the parse_core() function.
194
195
196
197
198
199 *-----------------------
200 4 New functions
201 *-----------------------
202
203This section describes added functions.
204
2054.1 get_variable
206
207NAME
208
209 get_variable
210
211SYNOPSIS
212
213 static const struct var_data *get_variable (const char *begin,
214 size_t len,
215 struct var_data *vdt);
216
217DESCRIPTION
218
219 This function searches an array pointed by vdt and tries to find
220 the substitution variable, which name is identified with begin
221 pointer and length of len bytes long.
222
223 This function is also responsible for updating length cache field
224 of vdt elements and validating requested variables.
225
226 This function repports errors by sending human readable
227 messages to the standard error stream.
228
229RETURN VALUE
230
231 This function returns a pointer to the array element which is
232 structure of var_data type, which contains variable definition
233 of a given name. It returns NULL on error or failure.
234
235
2364.2 parse_core
237
238NAME
239
240 parse_core
241
242SYNOPSIS
243 static int parse_core (const char *source, struct var_data *vdt,
244 parsefunc outfn, void *result);
245
246DESCRIPTION
247
248 This is the parsing routine for query strings containing the
249 substitution variables. It reads the string pointed with source
250 and tries to catch a valid substitution variables or parts which
251 are plain text blocks. The main purpose of using this function
252 it to split source string into parts and for each part call
253 outfn() function. Those parts are substrings identified by
254 pointer to some element of the source string and size.
255 Those elements are the result of splitting source string into
256 logical parts: plain text substrings and substitution variables'
257 values. To get the values of any found substitution variables
258 parse_core() uses get_variable() function. To find places
259 where substitution variables occurs it uses strstr() function
260 in conjunction with SV_BEGIN_MARK and SV_END_MARK definitions.
261 It passes vdt structure pointer to get_variable() function is
262 it calls it.
263
264 outfn() function should be passed by its pointer which
265 refers to declaration:
266
267 int (*outfn) (const char *begin,
268 size_t string_length,
269 void *void_pointer);
270
271 Each time outfn() is called the result argument of parse_core()
272 is passed to the outfn() as a last argument (void_pointer).
273
274 Example:
275
276 Example string "$(local_part) AND $(domain)" will cause the
277 outfn() to be called 3 times. First time for a value of
278 $(local_part) substitution variable, second time
279 for " AND " string, and the last time for $(domain) variable's
280 value. Variables are passed to outfn() by their (found) values,
281 plain text blocks are passed as they appear.
282
283 This function repports errors by sending human readable
284 messages to the standard error stream.
285
286RETURN VALUE
287
288 This function returns -1 if an error has occured and 0 if
289 everything went good.
290
2914.3 ParsePlugin_counter
292
293NAME
294
295 ParsePlugin_counter
296
297SYNOPSIS
298
299 int ParsePlugin_counter (const char *begin, size_t len,
300 void *vp);
301
302DESCRIPTION
303
304 This is parsing plugin function. It simply increments the value
305 found in the memory area pointed by vp. It assumes that
306 the memory area is allocated for the variable of size_t
307 type and that area was passed by (size_t *) pointer.
308 The value is incremented by len argument. Begin argument
309 is not used.
310
311 This function repports errors by sending human readable
312 messages to the standard error stream.
313
314RETURN VALUE
315
316 This function returns the variable size or -1 if an error
317 has occured, 0 if everything went good.
318
3194.4 ParsePlugin_builder
320
321NAME
322
323 ParsePlugin_builder
324
325SYNOPSIS
326
327 int ParsePlugin_builder (const char *begin, size_t len,
328 void *vp);
329
330DESCRIPTION
331
332 This is parsing plugin function. It simply copies len bytes
333 of a string pointed by begin to the end of memory area pointed by
334 vp. It assumes that the area pointed by vp is passed by (char **)
335 type pointer and refers to the (char *) pointer variable.
336 After each call it shifts the value of pointer variable (char *)
337 incrementing it by len bytes. Be careful when using this function
338 - its changes the given pointer value. Always operate on an
339 additional pointer type variable when passing it as the third
340 argument.
341
342RETURN VALUE
343
344 This function returns the variable size or -1 if an error
345 has occured, 0 if everything went good.
346
3474.5 parse_string
348
349NAME
350 parse_string
351
352SYNOPSIS
353
354 static char *parse_string (const char *source, struct var_data *vdt);
355
356DESCRIPTION
357
358 This function parses the string pointed with source according to the
359 replacement instructions set in var_data array, which is passed with
360 its pointer vdt. It produces changed string located in newly allocated
361 memory area.
362
363 This function calls parse_core() function with various parsing
364 subroutines passed as function pointers.
365
366 1. It uses parse_core() with ParsePlugin_counter to obtain the
367 total amount of memory needed for the output string.
368
369 2. It allocates the memory.
370
371 3. It uses parse_core() with ParsePlugin_builder to build the
372 output string.
373
374 This function repports errors by sending human readable
375 messages to the standard error stream.
376
377RETURN VALUE
378
379 Function returns pointer to the result buffer or NULL
380 if an error has occured.
381
382WARNINGS
383
384 This function allocates some amount of memory using standard
385 ANSI C routines. Memory allocated by this function should be
386 freed with free().
387
388
3894.6 validate_password
390
391NAME
392 validate_password
393
394SYNOPSIS
395
396 static const char *validate_password (const char *password);
397
398DESCRIPTION
399
400 This function checks whether password string does contain
401 any dangerous characters, which may be used to pass command
402 strings to the database connection stream. If it founds one
403 it replaces it by the backslash character.
404
405RETURN VALUE
406
407 It returns a pointer to the static buffer which contains
408 validated password string or NULL if an error has occured.
409
410
4114.7 get_localpart
412
413NAME
414
415 get_localpart
416
417SYNOPSIS
418
419 static const char *get_localpart (const char *username);
420
421DESCRIPTION
422
423 This function detaches local part of an e-mail address
424 from string pointed with username and puts it to the
425 buffer of the fixed length. All necessary cleaning is
426 made on the result string.
427
428RETURN VALUE
429
430 Pointer to the static buffer containing local part or
431 NULL if there was some error.
432
433
4344.8 get_domain
435
436NAME
437
438 get_domain
439
440SYNOPSIS
441
442 static const char *get_domain (const char *username,
443 const char *defdomain);
444
445DESCRIPTION
446
447 This function detaches domain part of an e-mail address
448 from string pointed with username and puts it to the
449 buffer of the fixed length. All necessary cleaning is
450 made on the result string. If function cannot find domain
451 part in the string the string pointed by defdomain is
452 used instead.
453
454RETURN VALUE
455
456 Pointer to the static buffer containing domain name or
457 NULL if there was some error.
458
459
4604.9 parse_select_clause
461
462NAME
463
464 parse_select_clause
465
466SYNOPSIS
467
468 static char *parse_select_clause (const char *clause,
469 const char *username,
470 const char *defdomain);
471
472DESCRIPTION
473
474 This function is a simple wrapper to the parse_string()
475 function. It parses a query pointed by caluse. username
476 and defdomain strings are used to replace corresponding
477 substitution strings if present in the query: $(local_part)
478 and $(domain).
479
480
481RETURN VALUE
482
483 Same as parse_string().
484
485
4864.10 parse_chpass_clause
487
488NAME
489
490 parse_chpass_clause
491
492SYNOPSIS
493
494 static char *parse_chpass_clause (const char *clause,
495 const char *username,
496 const char *defdomain,
497 const char *newpass,
498 const char *newpass_crypt);
499
500DESCRIPTION
501
502 This function is a simple wrapper to the parse_string()
503 function. It parses a query pointed by caluse. username,
504 defdomain, newpass and newpass_crypt strings are used to
505 replace corresponding substitution strings if present in
506 the query: $(local_part), $(domain), $(newpass),
507 $(newpass_crypt).
508
509RETURN VALUE
510
511 Same as parse_string().
512
513
514
515
516
517 *------------------------
518 5 Ideas and TODO
519 *------------------------
520
521- solve problem with fixed buffer length of local part and the domain part
522 strings after split (problem?)
523- allow admin to set a group name instead of numerical group id
524- allow admin to set a username instead of numerical user id
525
526- add clauses:
527
528 - MYSQL_PRESELECT_CLAUSE (query which comes before MYSQL_SELECT_CLAUSE)
529 - MYSQL_POSTSELECT_CLAUSE (query which comes after MYSQL_SELECT_CLAUSE)
530 - PGSQL_PRESELECT_CLAUSE (query which comes before PGSQL_SELECT_CLAUSE)
531 - PGSQL_POSTSELECT_CLAUSE (query which comes after PGSQL_SELECT_CLAUSE)
532
533
534
535
536
537 *------------------------
538 6 Thanks
539 *------------------------
540
541At the beginning this patch was messy indeed. :> I would like to thank
542Sam Varshavchik for pointing me a lot how to make it more fast and solid.
543I would also thank Philip Hazel, Chris Lightfoot and Mike Bremford which
544by their software capabilities inspired me to write it.
545
546Thomas T. Thai <tom@minnesota.com> ported author's original MySQL code
547to the PostgreSQL module.
548
549---------------------------------------------------------------------------
550