5 |
#include <errno.h> |
#include <errno.h> |
6 |
#include <limits.h> |
#include <limits.h> |
7 |
#include <sys/stat.h> |
#include <sys/stat.h> |
8 |
#include <sys/types.h> /* IEEE Std 1003.1-2001 non-conformance. */ |
#include <sys/types.h> /* For POSIX.1-2001 non-conformant systems. */ |
9 |
#include <regex.h> |
#include <regex.h> |
10 |
|
|
11 |
#include "config.h" |
#include "config.h" |
13 |
#include "pathnames.h" |
#include "pathnames.h" |
14 |
|
|
15 |
|
|
16 |
extern char logfile[PATH_MAX]; |
extern options_t opts; |
|
extern unsigned int options; |
|
|
extern char charset[CHARSET_LEN]; |
|
17 |
extern unsigned int flags; |
extern unsigned int flags; |
|
extern unsigned int interval; |
|
|
extern long timeout; |
|
18 |
extern char *home; |
extern char *home; |
19 |
|
|
20 |
#ifdef ENCRYPTED_PASSWORDS |
#ifdef ENCRYPTED_PASSWORDS |
24 |
|
|
25 |
|
|
26 |
int parse_config(FILE * fd); |
int parse_config(FILE * fd); |
27 |
void set_options(char *line, regmatch_t * match); |
void set_options(char *line, regmatch_t * m); |
28 |
|
|
29 |
int parse_passwords(FILE * fd); |
int parse_passwords(FILE * fd); |
30 |
|
|
43 |
|
|
44 |
if (cfg == NULL) { |
if (cfg == NULL) { |
45 |
cfg = c = (char *)xmalloc(PATH_MAX * sizeof(char)); |
cfg = c = (char *)xmalloc(PATH_MAX * sizeof(char)); |
46 |
snprintf(cfg, PATH_MAX, "%s/%s", home, PATHNAME_CONFIG_FILE); |
snprintf(cfg, PATH_MAX, "%s/%s", home, PATHNAME_CONFIG); |
47 |
} |
} |
48 |
#ifdef DEBUG |
debug("configuration file: '%s'\n", cfg); |
49 |
fprintf(stderr, "debug: configuration file: '%s'\n", cfg); |
|
|
#endif |
|
|
#ifdef CHECK_PERMISSIONS |
|
50 |
check_file_perms(cfg, S_IRUSR | S_IWUSR); |
check_file_perms(cfg, S_IRUSR | S_IWUSR); |
51 |
#endif |
|
52 |
fd = fopen(cfg, "r"); |
fd = fopen(cfg, "r"); |
53 |
if (fd == NULL) |
if (fd == NULL) |
54 |
fatal(ERROR_FILE_OPEN, "opening config file %s; %s\n", cfg, |
fatal(ERROR_FILEOPEN, "opening config file %s; %s\n", cfg, |
55 |
strerror(errno)); |
strerror(errno)); |
56 |
|
|
57 |
if (c != NULL) |
if (c != NULL) |
58 |
xfree(c); |
xfree(c); |
59 |
|
|
60 |
if ((r = parse_config(fd))) |
if ((r = parse_config(fd))) |
61 |
fatal(ERROR_CONFIG_PARSE, |
fatal(ERROR_PARSER, |
62 |
"parse error in config file at row %d\n", r); |
"parse error in config file at row %d\n", r); |
63 |
|
|
64 |
fclose(fd); |
fclose(fd); |
65 |
|
|
|
#ifdef DEBUG |
|
|
fprintf(stderr, "debug: options: %0#10x '%s'\n", options, charset); |
|
|
#endif |
|
|
|
|
66 |
return 0; |
return 0; |
67 |
} |
} |
68 |
|
|
127 |
"^[[:blank:]]*JOB[[:blank:]]+([[:alnum:],_-]+)[[:blank:]]+" |
"^[[:blank:]]*JOB[[:blank:]]+([[:alnum:],_-]+)[[:blank:]]+" |
128 |
"([[:alnum:],_-]+)[[:blank:]]*\n$", |
"([[:alnum:],_-]+)[[:blank:]]*\n$", |
129 |
|
|
130 |
"^[[:blank:]]*(SET[[:blank:]])?[[:blank:]]*(LOGFILE|CHARSET)" |
"^[[:blank:]]*(SET[[:blank:]])?[[:blank:]]*(LOGFILE|CHARSET|" |
131 |
"[[:blank:]]*=[[:blank:]]*(\"[[:print:]]*\"|[[:graph:]]+)" |
"_PROTOCOL)[[:blank:]]*=[[:blank:]]*(\"[[:print:]]*\"|" |
132 |
"[[:blank:]]*\n$", |
"[[:graph:]]+)[[:blank:]]*\n$", |
133 |
|
|
134 |
"^[[:blank:]]*(SET[[:blank:]])?[[:blank:]]*(ERRORS|EXPUNGE|" |
"^[[:blank:]]*(SET[[:blank:]])?[[:blank:]]*(ERRORS|EXPUNGE|" |
135 |
"HEADERS|NAMESPACE|PEEK|SUBSCRIBE)[[:blank:]]*=[[:blank:]]*" |
"HEADERS|NAMESPACE|PEEK|SUBSCRIBE)[[:blank:]]*=[[:blank:]]*" |
180 |
/* Skip variable processing. */ |
/* Skip variable processing. */ |
181 |
else if (!regexec(&creg[10], line, 4, match, 0) || |
else if (!regexec(&creg[10], line, 4, match, 0) || |
182 |
!regexec(&creg[11], line, 4, match, 0) || |
!regexec(&creg[11], line, 4, match, 0) || |
183 |
!regexec(&creg[12], line, 4, match, 0)); |
!regexec(&creg[12], line, 4, match, 0)) |
184 |
|
continue; |
185 |
else |
else |
186 |
return row; |
return row; |
187 |
|
|
188 |
if (r == ERROR_CONFIG_PARSE) |
if (r == ERROR_PARSER) |
189 |
return row; |
return row; |
190 |
} |
} |
191 |
|
|
205 |
void |
void |
206 |
reread_config(char *cfg) |
reread_config(char *cfg) |
207 |
{ |
{ |
208 |
|
|
209 |
destroy_all(); |
destroy_all(); |
210 |
read_config(cfg); |
read_config(cfg); |
211 |
#ifdef ENCRYPTED_PASSWORDS |
#ifdef ENCRYPTED_PASSWORDS |
212 |
read_passwords(); |
read_passwords(); |
213 |
#endif |
#endif |
214 |
flags &= ~(FLAG_SIGUSR1_RECEIVED); |
flags &= ~(FLAG_SIGUSR1); |
215 |
} |
} |
216 |
|
|
217 |
|
|
221 |
void |
void |
222 |
set_options(char *line, regmatch_t * m) |
set_options(char *line, regmatch_t * m) |
223 |
{ |
{ |
224 |
|
|
225 |
if (!strncasecmp(line + m[2].rm_so, "logfile", 7)) { |
if (!strncasecmp(line + m[2].rm_so, "logfile", 7)) { |
226 |
if (*logfile == '\0') { |
if (*opts.logfile == '\0') { |
227 |
if (*(line + m[3].rm_so) == '"' && |
if (*(line + m[3].rm_so) == '"' && |
228 |
*(line + m[3].rm_eo - 1) == '"') |
*(line + m[3].rm_eo - 1) == '"') |
229 |
strncat(logfile, line + m[3].rm_so + 1, |
strncat(opts.logfile, line + m[3].rm_so + 1, |
230 |
min((m[3].rm_eo - m[3].rm_so - 2), |
min((m[3].rm_eo - m[3].rm_so - 2), |
231 |
PATH_MAX - 1)); |
PATH_MAX - 1)); |
232 |
else |
else |
233 |
strncat(logfile, line + m[3].rm_so, |
strncat(opts.logfile, line + m[3].rm_so, |
234 |
min((m[3].rm_eo - m[3].rm_so), |
min((m[3].rm_eo - m[3].rm_so), |
235 |
PATH_MAX - 1)); |
PATH_MAX - 1)); |
236 |
} |
} |
237 |
|
debug("options: logfile = '%s'\n", opts.logfile); |
238 |
} else if (!strncasecmp(line + m[2].rm_so, "charset", 7)) { |
} else if (!strncasecmp(line + m[2].rm_so, "charset", 7)) { |
239 |
if (*(line + m[3].rm_so) == '"' && |
if (*(line + m[3].rm_so) == '"' && |
240 |
*(line + m[3].rm_eo - 1) == '"') |
*(line + m[3].rm_eo - 1) == '"') |
241 |
strncat(charset, line + m[3].rm_so + 1, |
strncat(opts.charset, line + m[3].rm_so + 1, |
242 |
min((m[3].rm_eo - m[3].rm_so - 2), |
min((m[3].rm_eo - m[3].rm_so - 2), |
243 |
CHARSET_LEN - 1)); |
CHARSET_LEN - 1)); |
244 |
else |
else |
245 |
strncat(charset, line + m[3].rm_so, |
strncat(opts.charset, line + m[3].rm_so, |
246 |
min((m[3].rm_eo - m[3].rm_so), CHARSET_LEN - 1)); |
min((m[3].rm_eo - m[3].rm_so), CHARSET_LEN - 1)); |
247 |
|
debug("options: charset = '%s'\n", opts.charset); |
248 |
|
} else if (!strncasecmp(line + m[2].rm_so, "_protocol", 8)) { |
249 |
|
if (strcasestr(line + m[3].rm_so, "IMAP4rev1")) |
250 |
|
opts.force_protocol = PROTOCOL_IMAP4REV1; |
251 |
|
else if (strcasestr(line + m[3].rm_so, "IMAP4")) |
252 |
|
opts.force_protocol = PROTOCOL_IMAP4; |
253 |
|
else |
254 |
|
opts.force_protocol = PROTOCOL_NONE; |
255 |
|
debug("options: force_protocol = %d\n", opts.force_protocol); |
256 |
} else if (!strncasecmp(line + m[2].rm_so, "errors", 6)) { |
} else if (!strncasecmp(line + m[2].rm_so, "errors", 6)) { |
257 |
if (!strncasecmp(line + m[3].rm_so, "yes", 3)) |
if (!strncasecmp(line + m[3].rm_so, "yes", 3)) |
258 |
options |= OPTION_ERRORS; |
opts.errors = 1; |
259 |
else |
else |
260 |
options &= ~(OPTION_ERRORS); |
opts.errors = 0; |
261 |
|
debug("options: errors = %d\n", opts.errors); |
262 |
} else if (!strncasecmp(line + m[2].rm_so, "expunge", 7)) { |
} else if (!strncasecmp(line + m[2].rm_so, "expunge", 7)) { |
263 |
if (!strncasecmp(line + m[3].rm_so, "yes", 3)) |
if (!strncasecmp(line + m[3].rm_so, "yes", 3)) |
264 |
options |= OPTION_EXPUNGE; |
opts.expunge = 1; |
265 |
else |
else |
266 |
options &= ~(OPTION_EXPUNGE); |
opts.expunge = 0; |
267 |
|
debug("options: expunge = %d\n", opts.expunge); |
268 |
} else if (!strncasecmp(line + m[2].rm_so, "header", 6)) { |
} else if (!strncasecmp(line + m[2].rm_so, "header", 6)) { |
269 |
if (!strncasecmp(line + m[3].rm_so, "yes", 3)) |
if (!strncasecmp(line + m[3].rm_so, "yes", 3)) |
270 |
options |= OPTION_HEADERS; |
opts.headers = 1; |
271 |
else |
else |
272 |
options &= ~(OPTION_HEADERS); |
opts.headers = 0; |
273 |
|
debug("options: headers = %d\n", opts.headers); |
274 |
} else if (!strncasecmp(line + m[2].rm_so, "namespace", 9)) { |
} else if (!strncasecmp(line + m[2].rm_so, "namespace", 9)) { |
275 |
if (!strncasecmp(line + m[3].rm_so, "yes", 3)) |
if (!strncasecmp(line + m[3].rm_so, "yes", 3)) |
276 |
options |= OPTION_NAMESPACE; |
opts.namespace = 1; |
277 |
else |
else |
278 |
options &= ~(OPTION_NAMESPACE); |
opts.namespace = 0; |
279 |
|
debug("options: namespace = %d\n", opts.namespace); |
280 |
} else if (!strncasecmp(line + m[2].rm_so, "peek", 4)) { |
} else if (!strncasecmp(line + m[2].rm_so, "peek", 4)) { |
281 |
if (!strncasecmp(line + m[3].rm_so, "yes", 3)) |
if (!strncasecmp(line + m[3].rm_so, "yes", 3)) |
282 |
options |= OPTION_PEEK; |
opts.peek = 1; |
283 |
else |
else |
284 |
options &= ~(OPTION_PEEK); |
opts.peek = 0; |
285 |
|
debug("options: peek = %d\n", opts.peek); |
286 |
} else if (!strncasecmp(line + m[2].rm_so, "subscribe", 9)) { |
} else if (!strncasecmp(line + m[2].rm_so, "subscribe", 9)) { |
287 |
if (!strncasecmp(line + m[3].rm_so, "yes", 3)) |
if (!strncasecmp(line + m[3].rm_so, "yes", 3)) |
288 |
options |= OPTION_SUBSCRIBE; |
opts.subscribe = 1; |
289 |
else |
else |
290 |
options &= ~(OPTION_SUBSCRIBE); |
opts.subscribe = 0; |
291 |
|
debug("options: subscribe = %d\n", opts.subscribe); |
292 |
} else if (!strncasecmp(line + m[2].rm_so, "timeout", 7)) { |
} else if (!strncasecmp(line + m[2].rm_so, "timeout", 7)) { |
293 |
errno = 0; |
errno = 0; |
294 |
timeout = strtol(line + m[3].rm_so, NULL, 10); |
opts.timeout = strtol(line + m[3].rm_so, NULL, 10); |
295 |
if (errno) |
if (errno) |
296 |
timeout = 0; |
opts.timeout = 0; |
297 |
|
debug("options: timeout = %d\n", opts.timeout); |
298 |
} else if (!strncasecmp(line + m[2].rm_so, "daemon", 6) && |
} else if (!strncasecmp(line + m[2].rm_so, "daemon", 6) && |
299 |
!(options & OPTION_DAEMON_MODE)) { |
!opts.daemon) { |
|
options |= OPTION_DAEMON_MODE; |
|
300 |
errno = 0; |
errno = 0; |
301 |
interval = strtoul(line + m[3].rm_so, NULL, 10); |
opts.daemon = strtoul(line + m[3].rm_so, NULL, 10); |
302 |
if (errno) |
if (errno) |
303 |
interval = 0; |
opts.daemon = 0; |
304 |
|
debug("options: daemon = %d\n", opts.daemon); |
305 |
} |
} |
306 |
} |
} |
307 |
|
|
316 |
FILE *fd; |
FILE *fd; |
317 |
char pwfile[PATH_MAX]; |
char pwfile[PATH_MAX]; |
318 |
|
|
319 |
if (!(flags & FLAG_BLANK_PASSWORD)) |
if (!(flags & FLAG_BLANKPASS)) |
320 |
return ERROR_CONFIG_PARSE; |
return ERROR_PARSER; |
321 |
|
|
322 |
if (!passphr) { |
if (!passphr) { |
323 |
passphr = (char *)smalloc(PASSPHRASE_LEN); |
passphr = (char *)smalloc(PASSPHRASE_LEN); |
324 |
*passphr = '\0'; |
*passphr = '\0'; |
325 |
} |
} |
326 |
snprintf(pwfile, PATH_MAX, "%s/%s", home, PATHNAME_PASSWORD_FILE); |
snprintf(pwfile, PATH_MAX, "%s/%s", home, PATHNAME_PASSWORDS); |
327 |
#ifdef DEBUG |
debug("passwords file: '%s'\n", pwfile); |
|
fprintf(stderr, "debug: passwords file: '%s'\n", pwfile); |
|
|
#endif |
|
328 |
|
|
329 |
if (!exists_file(pwfile)) |
if (!exists_file(pwfile)) |
330 |
return ERROR_FILE_OPEN; |
return ERROR_FILEOPEN; |
331 |
|
|
|
#ifdef CHECK_PERMISSIONS |
|
332 |
check_file_perms(pwfile, S_IRUSR | S_IWUSR); |
check_file_perms(pwfile, S_IRUSR | S_IWUSR); |
|
#endif |
|
333 |
|
|
334 |
fd = fopen(pwfile, "r"); |
fd = fopen(pwfile, "r"); |
335 |
if (fd == NULL) |
if (fd == NULL) |
336 |
fatal(ERROR_FILE_OPEN, "opening passwords file %s; %s\n", |
fatal(ERROR_FILEOPEN, "opening passwords file %s; %s\n", |
337 |
pwfile, strerror(errno)); |
pwfile, strerror(errno)); |
338 |
|
|
339 |
parse_passwords(fd); |
parse_passwords(fd); |
345 |
|
|
346 |
|
|
347 |
/* |
/* |
348 |
* Parse unencrypted password file. |
* Parse unencrypted password file. |
349 |
*/ |
*/ |
350 |
int |
int |
351 |
parse_passwords(FILE * fd) |
parse_passwords(FILE * fd) |
352 |
{ |
{ |
353 |
int t; |
int t; |
354 |
char *pe; |
char *pe; |
355 |
char user[USERNAME_LEN], serv[SERVER_LEN]; |
char user[USER_LEN], serv[SERVER_LEN]; |
356 |
unsigned char *buf; |
unsigned char *buf; |
357 |
char *c, *cp, *line; |
char *c, *cp, *line; |
358 |
regex_t creg; |
regex_t creg; |
363 |
pe = NULL; |
pe = NULL; |
364 |
reg = "([[:alnum:].-]+) ([[:graph:]]+) ([[:graph:]]+)"; |
reg = "([[:alnum:].-]+) ([[:graph:]]+) ([[:graph:]]+)"; |
365 |
|
|
366 |
if (!(flags & FLAG_DAEMON_MODE)) { |
if (!(flags & FLAG_DAEMON)) { |
367 |
do { |
do { |
368 |
fseek(fd, 0L, SEEK_SET); |
fseek(fd, 0L, SEEK_SET); |
369 |
printf("Enter master passphrase: "); |
printf("Enter master passphrase: "); |
387 |
strncat(serv, line + match[1].rm_so, |
strncat(serv, line + match[1].rm_so, |
388 |
min(match[1].rm_eo - match[1].rm_so, SERVER_LEN - 1)); |
min(match[1].rm_eo - match[1].rm_so, SERVER_LEN - 1)); |
389 |
strncat(user, line + match[2].rm_so, |
strncat(user, line + match[2].rm_so, |
390 |
min(match[2].rm_eo - match[2].rm_so, USERNAME_LEN - 1)); |
min(match[2].rm_eo - match[2].rm_so, USER_LEN - 1)); |
391 |
|
|
392 |
if ((pe = (char *)find_password(user, serv))) |
if ((pe = (char *)find_password(user, serv))) |
393 |
strncat(pe, line + match[3].rm_so, |
strncat(pe, line + match[3].rm_so, |
394 |
min(match[3].rm_eo - match[3].rm_so, |
min(match[3].rm_eo - match[3].rm_so, |
395 |
PASSWORD_LEN - 1)); |
PASS_LEN - 1)); |
396 |
|
|
397 |
line = strtok_r(NULL, "\n", &c); |
line = strtok_r(NULL, "\n", &c); |
398 |
} |
} |