2 ** Copyright 2012-2015 Double Precision, Inc. See COPYING for
3 ** distribution information.
7 #include "courier_auth_config.h"
10 #include "courierauthdebug.h"
15 #include <sys/types.h>
18 static const char *configfilename
=0;
19 static char *configauth
=0;
20 static size_t configauth_size
=0;
22 #define err courier_auth_err
24 const char *authgetconfig(const char *filename
, const char *env
)
30 if (configfilename
&& strcmp(filename
, configfilename
))
38 configfilename
=filename
;
42 FILE *f
=fopen(filename
, "r");
46 if (fstat(fileno(f
), &buf
) ||
47 (configauth
=malloc(buf
.st_size
+2)) == 0)
52 if (fread(configauth
, buf
.st_size
, 1, f
) != 1)
59 configauth
[configauth_size
=buf
.st_size
]=0;
61 for (i
=0; i
<configauth_size
; i
++)
62 if (configauth
[i
] == '\n')
63 { /* siefca@pld.org.pl */
64 if (!i
|| configauth
[i
-1] != '\\')
70 configauth
[i
]=configauth
[i
-1]= ' ';
76 for (i
=0; i
<configauth_size
; )
79 if (strncmp(p
, env
, l
) == 0 &&
80 isspace((int)(unsigned char)p
[l
]))
83 while (*p
&& *p
!= '\n' &&
84 isspace((int)(unsigned char)*p
))
89 while (i
< configauth_size
)
90 if (configauth
[i
++] == 0) break;
93 if (i
< configauth_size
)
98 /* siefca@pld.org.pl */
99 #define MAX_SUBSTITUTION_LEN 32
100 #define SV_BEGIN_MARK "$("
101 #define SV_END_MARK ")"
102 #define SV_BEGIN_LEN ((sizeof(SV_BEGIN_MARK))-1)
103 #define SV_END_LEN ((sizeof(SV_END_MARK))-1)
105 /* siefca@pld.org.pl */
113 /* siefca@pld.org.pl */
114 typedef int (*parsefunc
)(const char *, size_t, void *);
116 /* siefca@pld.org.pl */
117 static struct var_data
*get_variable (const char *begin
, size_t len
,
118 struct var_data
*vdt
)
120 struct var_data
*vdp
;
122 if (!begin
|| !vdt
) /* should never happend */
124 err("get_variable: critical error while "
125 "parsing substitution variable");
130 err("get_variable: unknown empty substitution "
131 "variable - aborting");
134 if (len
> MAX_SUBSTITUTION_LEN
)
136 err("get_variable: variable name too long "
137 "while parsing substitution. "
140 "%.*s...", MAX_SUBSTITUTION_LEN
, begin
);
144 for (vdp
=vdt
; vdp
->name
; vdp
++)
145 if (vdp
->size
== len
+1 &&
146 !strncmp(begin
, vdp
->name
, len
))
150 if (!vdp
->value_length
) /* length cache */
151 vdp
->value_length
= strlen (vdp
->value
);
155 err("get_variable: unknown substitution variable "
164 /* siefca@pld.org.pl */
165 static int ParsePlugin_counter (const char *p
, size_t length
, void *vp
)
167 if (!p
|| !vp
|| length
< 0)
169 err("get_variable: bad arguments while counting "
174 *((size_t *)vp
) += length
;
179 /* siefca@pld.org.pl */
180 static int ParsePlugin_builder (const char *p
, size_t length
, void *vp
)
182 char **strptr
= (char **) vp
;
184 if (!p
|| !vp
|| length
< 0)
186 err("get_variable: bad arguments while building "
191 if (!length
) return 0;
192 memcpy ((void *) *strptr
, (void *) p
, length
);
198 /* siefca@pld.org.pl */
199 static int parse_core (const char *source
, struct var_data
*vdt
,
200 parsefunc outfn
, void *result
)
204 const char *p
, *q
, *e
,
207 struct var_data
*v_ptr
;
213 err("auth_parse: no memory allocated for result "
214 "while parser core was invoked");
219 err("auth_parse: no substitution table found "
220 "while parser core was invoked");
225 while ( (p
=strstr(q
, SV_BEGIN_MARK
)) )
227 e
= strstr (p
, SV_END_MARK
);
230 err("auth_parse: syntax error in "
232 "- no closing symbol found! "
233 "bad variable begins with:"
234 "%.*s...", MAX_SUBSTITUTION_LEN
, p
);
240 ** __________sometext$(variable_name)_________
242 ** t_begin' t_end' `v_begin `v_end
246 v_begin
= p
+SV_BEGIN_LEN
; /* variable field ptr */
247 v_end
= e
-SV_END_LEN
; /* variable field last character */
248 v_size
= v_end
-v_begin
+1;/* variable field length */
250 t_begin
= q
; /* text field ptr */
251 t_end
= p
-1; /* text field last character */
252 t_size
= t_end
-t_begin
+1;/* text field length */
255 if ( (outfn (t_begin
, t_size
, result
)) == -1 )
258 /* work on variable */
259 v_ptr
= get_variable (v_begin
, v_size
, vdt
);
260 if (!v_ptr
) return -1;
262 if ( (outfn (v_ptr
->value
, v_ptr
->value_length
, result
)) == -1 )
268 /* work on last part of text if any */
270 if ( (outfn (q
, strlen(q
), result
)) == -1 )
276 /* siefca@pld.org.pl */
277 static char *parse_string (const char *source
, struct var_data
*vdt
)
279 struct var_data
*vdp
= NULL
;
280 char *output_buf
= NULL
,
284 if (source
== NULL
|| *source
== '\0' ||
285 vdt
== NULL
|| vdt
[0].name
== NULL
)
287 err("auth_parse: source clause is empty "
288 "- this is critical error");
292 /* zero var_data length cache - important! */
293 for (vdp
=vdt
; vdp
->name
; vdp
++)
294 vdp
->value_length
= 0;
297 /* phase 1 - count and validate string */
298 if ( (parse_core (source
, vdt
, &ParsePlugin_counter
, &buf_size
)) != 0)
301 /* phase 2 - allocate memory */
302 output_buf
= malloc (buf_size
);
308 pass_buf
= output_buf
;
310 /* phase 3 - build the output string */
311 if ( (parse_core (source
, vdt
, &ParsePlugin_builder
, &pass_buf
)) != 0)
321 static char *local_part_escaped(const char *username
,
322 char *(*escape_func
)(const char *, size_t))
324 const char *p
=strchr(username
, '@');
325 size_t n
=p
? p
-username
:strlen(username
);
327 return escape_func(username
, n
);
330 static char *domain_part_escaped(const char *username
,
331 const char *defdomain
,
332 char *(*escape_func
)(const char *, size_t))
334 const char *p
=strchr(username
, '@');
344 return escape_func(p
, n
);
347 static int local_and_domain_part_escaped(char *(*escape_func
)(const char *, size_t),
348 const char *username
,
349 const char *defdomain
,
353 if ((*local_ret
=local_part_escaped(username
, escape_func
)) == NULL
)
356 if ((*domain_ret
=domain_part_escaped(username
, defdomain
,
357 escape_func
)) == NULL
)
366 /* siefca@pld.org.pl */
367 char *auth_parse_select_clause (char *(*escape_func
)(const char *, size_t),
368 const char *clause
, const char *username
,
369 const char *defdomain
,
374 static struct var_data vd
[]={
375 {"local_part", NULL
, sizeof("local_part"), 0},
376 {"domain", NULL
, sizeof("domain"), 0},
377 {"service", NULL
, sizeof("service"), 0},
383 if (clause
== NULL
|| *clause
== '\0' ||
384 !username
|| *username
== '\0')
387 if (!local_and_domain_part_escaped(escape_func
,
394 vd
[2].value
= service
;
396 str
=parse_string (clause
, vd
);
402 /* siefca@pld.org.pl */
403 char *auth_parse_chpass_clause (char *(*escape_func
)(const char *, size_t),
404 const char *clause
, const char *username
,
405 const char *defdomain
, const char *newpass
,
406 const char *newpass_crypt
)
410 static struct var_data vd
[]={
411 {"local_part", NULL
, sizeof("local_part"), 0},
412 {"domain", NULL
, sizeof("domain"), 0},
413 {"newpass", NULL
, sizeof("newpass"), 0},
414 {"newpass_crypt", NULL
, sizeof("newpass_crypt"), 0},
419 if (clause
== NULL
|| *clause
== '\0' ||
420 !username
|| *username
== '\0' ||
421 !newpass
|| *newpass
== '\0' ||
422 !newpass_crypt
|| *newpass_crypt
== '\0') return NULL
;
424 if (!local_and_domain_part_escaped(escape_func
,
431 vd
[2].value
= newpass
;
432 vd
[3].value
= newpass_crypt
;
434 if (!vd
[0].value
|| !vd
[1].value
||
435 !vd
[2].value
|| !vd
[3].value
)
442 str
=parse_string (clause
, vd
);