/[imapfilter]/imapfilter/file.c
ViewVC logotype

Annotation of /imapfilter/file.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.37 - (hide annotations)
Thu Jun 20 08:48:48 2002 UTC (21 years, 10 months ago) by lefcha
Branch: MAIN
Changes since 1.36: +1 -0 lines
File MIME type: text/plain
Passphrase initialization.

1 lefcha 1.1 #include <stdio.h>
2 lefcha 1.28 #include <unistd.h>
3 lefcha 1.1 #include <errno.h>
4 lefcha 1.5 #include <sys/types.h>
5 lefcha 1.1 #include <regex.h>
6     #include <string.h>
7     #include <stdlib.h>
8     #include <limits.h>
9 lefcha 1.10 #include <sys/stat.h>
10 lefcha 1.28 #include <fcntl.h>
11 lefcha 1.29 #include <time.h>
12 lefcha 1.1
13     #include "config.h"
14     #include "imapfilter.h"
15 lefcha 1.13 #include "data.h"
16 lefcha 1.1
17    
18 lefcha 1.6 extern char logfile[PATH_MAX];
19 lefcha 1.11 extern unsigned int options;
20 lefcha 1.34 extern unsigned int flags;
21     extern unsigned int interval;
22 lefcha 1.28 extern long timeout;
23 lefcha 1.29 extern char *home;
24    
25     #ifdef ENCRYPTED_PASSWORDS
26 lefcha 1.31 char *passphr; /* Master password to access the
27     passwords file. */
28 lefcha 1.28 #endif
29 lefcha 1.27
30 lefcha 1.1
31     /*
32 lefcha 1.13 * Find the path to configuration file, open it and call parse_config().
33 lefcha 1.1 */
34     int read_config(char *cfg)
35     {
36     int r;
37 lefcha 1.29 FILE *fd;
38 lefcha 1.23 char *c = NULL;
39 lefcha 1.24
40 lefcha 1.1 if (!cfg) {
41 lefcha 1.23 cfg = c = (char *) xmalloc(PATH_MAX * sizeof(char));
42 lefcha 1.1 snprintf(cfg, PATH_MAX, "%s/%s", home, ".imapfilterrc");
43     }
44 lefcha 1.36
45 lefcha 1.1 #ifdef DEBUG
46 lefcha 1.11 printf("debug: configuration file: '%s'\n", cfg);
47 lefcha 1.1 #endif
48 lefcha 1.13 #ifdef CHECK_PERMISSIONS
49 lefcha 1.28 check_file_perms(cfg, S_IRUSR | S_IWUSR);
50 lefcha 1.12 #endif
51 lefcha 1.29 fd = fopen(cfg, "r");
52 lefcha 1.1
53 lefcha 1.29 if (!fd)
54 lefcha 1.17 fatal(ERROR_FILE_OPEN, "imapfilter: opening config file %s; %s\n",
55 lefcha 1.11 cfg, strerror(errno));
56 lefcha 1.1
57 lefcha 1.23 if (c)
58 lefcha 1.29 xfree(c);
59 lefcha 1.23
60 lefcha 1.29 if ((r = parse_config(fd)))
61 lefcha 1.17 fatal(ERROR_CONFIG_PARSE,
62     "imapfilter: parse error in config file at row %d\n", r);
63 lefcha 1.1
64 lefcha 1.29 fclose(fd);
65 lefcha 1.1
66 lefcha 1.11 #ifdef DEBUG
67     printf("debug: options: %0#10x\n", options);
68     #endif
69    
70 lefcha 1.17 return 0;
71 lefcha 1.1 }
72    
73 lefcha 1.6
74 lefcha 1.10 /*
75 lefcha 1.13 * Parse configuration file.
76 lefcha 1.1 */
77 lefcha 1.29 int parse_config(FILE * fd)
78 lefcha 1.1 {
79 lefcha 1.17 int i, r = 0;
80 lefcha 1.1 unsigned int row = 0;
81     char line[LINE_MAX];
82 lefcha 1.27 regex_t creg[13];
83 lefcha 1.36 regmatch_t match[9];
84 lefcha 1.27 const char *reg[13] = {
85 lefcha 1.15 "^([[:blank:]]*\n|#.*\n)$",
86 lefcha 1.36
87     "^[[:blank:]]*ACCOUNT[[:blank:]]+([[:alnum:]_-]+)[[:blank:]]+"
88     "(([[:graph:]]+):([[:graph:]]*)|([[:graph:]]+))@([[:alnum:].-]+)"
89     "(:[[:digit:]]+)?[[:blank:]]*([[:blank:]]SSL|[[:blank:]]SSL2|"
90     "[[:blank:]]SSL3|[[:blank:]]TLS1)?[[:blank:]]*\n$",
91    
92     "^[[:blank:]]*FOLDER[[:blank:]]+([[:alnum:]_-]+)[[:blank:]]+"
93     "([[:print:]]+)[[:blank:]]*\n$",
94    
95     "^[[:blank:]]*FILTER[[:blank:]]+([[:alnum:]_-]+)[[:blank:]]*"
96     "([[:blank:]]OR|[[:blank:]]AND)?[[:blank:]]*\n$",
97    
98     "^[[:blank:]]*ACTION[[:blank:]]+(DELETE|"
99     "COPY[[:blank:]]+(\"[[:print:]]*\"|[[:graph:]]+)|"
100     "MOVE[[:blank:]]+(\"[[:print:]]*\"|[[:graph:]]+)|"
101     "RCOPY[[:blank:]]+([[:alnum:]_-]+)[[:blank:]]+"
102     "(\"[[:print:]]*\"|[[:graph:]]+)|"
103     "RMOVE[[:blank:]]+([[:alnum:]_-]+)[[:blank:]]+"
104     "(\"[[:print:]]*\"|[[:graph:]]+)|"
105     "LIST)[[:blank:]]*([[:graph:]]*)[[:blank:]]*\n$",
106    
107     "^[[:blank:]]*(MASK[[:blank:]])?[[:blank:]]*(OR[[:blank:]]|"
108     "AND[[:blank:]])?[[:blank:]]*(NOT[[:blank:]])?[[:blank:]]*"
109     "(ANSWERED|DELETED|DRAFT|FLAGGED|NEW|OLD|RECENT|SEEN|UNANSWERED|"
110     "UNDELETED|UNDRAFT|UNFLAGGED|UNSEEN)[[:blank:]]*\n$",
111    
112     "^[[:blank:]]*(MASK[[:blank:]])?[[:blank:]]*(OR[[:blank:]]|"
113     "AND[[:blank:]])?[[:blank:]]*(NOT[[:blank:]])?[[:blank:]]*"
114     "(BCC|BODY|CC|FROM|SUBJECT|TEXT|TO)[[:blank:]]+(\"[[:print:]]*\"|"
115     "[[:graph:]]+)[[:blank:]]*\n$",
116    
117     "^[[:blank:]]*(MASK[[:blank:]])?[[:blank:]]*(OR[[:blank:]]|"
118     "AND[[:blank:]])?[[:blank:]]*(NOT[[:blank:]])?[[:blank:]]*"
119     "(HEADER)[[:blank:]]+(\"[[:print:]]*\"|[[:graph:]]+)[[:blank:]]+"
120     "(\"[[:print:]]*\"|[[:graph:]]+)[[:blank:]]*\n$",
121    
122     "^[[:blank:]]*(MASK[[:blank:]])?[[:blank:]]*(OR[[:blank:]]|"
123     "AND[[:blank:]])?[[:blank:]]*(NOT[[:blank:]])?[[:blank:]]*"
124     "(LARGER|SMALLER|OLDER|NEWER)[[:blank:]]+([[:digit:]]+)"
125     "[[:blank:]]*\n$",
126    
127     "^[[:blank:]]*JOB[[:blank:]]+([[:alnum:],_-]+)[[:blank:]]+"
128     "([[:alnum:],_-]+)[[:blank:]]*\n$",
129    
130     "^[[:blank:]]*(SET[[:blank:]])?[[:blank:]]*(LOGFILE)"
131     "[[:blank:]]*=[[:blank:]]*([[:print:]]+)\n$",
132    
133     "^[[:blank:]]*(SET[[:blank:]])?[[:blank:]]*(HEADERS|NAMESPACE)"
134     "[[:blank:]]*=[[:blank:]]*(YES|NO)[[:blank:]]*\n$",
135    
136     "^[[:blank:]]*(SET[[:blank:]])?[[:blank:]]*(DAEMON|TIMEOUT)"
137     "[[:blank:]]*=[[:blank:]]*([[:digit:]]+)\n$"
138 lefcha 1.1 };
139    
140 lefcha 1.27 for (i = 0; i < 13; i++)
141 lefcha 1.14 regcomp(&creg[i], reg[i], REG_EXTENDED | REG_ICASE);
142 lefcha 1.1
143 lefcha 1.29 while (fgets(line, LINE_MAX - 1, fd)) {
144 lefcha 1.1 row++;
145 lefcha 1.15 if (!regexec(&creg[0], line, 0, match, 0))
146     continue;
147 lefcha 1.36 else if (!regexec(&creg[1], line, 9, match, 0))
148 lefcha 1.13 set_account(line, match);
149 lefcha 1.15 else if (!regexec(&creg[2], line, 3, match, 0))
150 lefcha 1.17 r = set_mboxgrp(line, match);
151 lefcha 1.15 else if (!regexec(&creg[3], line, 3, match, 0))
152 lefcha 1.17 r = set_filter(line, match);
153 lefcha 1.36 else if (!regexec(&creg[4], line, 9, match, 0))
154 lefcha 1.17 r = set_action(line, match);
155 lefcha 1.15 else if (!regexec(&creg[5], line, 7, match, 0) ||
156 lefcha 1.18 !regexec(&creg[6], line, 7, match, 0) ||
157     !regexec(&creg[7], line, 7, match, 0) ||
158     !regexec(&creg[8], line, 7, match, 0))
159 lefcha 1.17 r = set_mask(line, match);
160 lefcha 1.15 else if (!regexec(&creg[9], line, 3, match, 0))
161 lefcha 1.17 r = set_job(line, match);
162 lefcha 1.26 else if (!regexec(&creg[10], line, 4, match, 0) ||
163 lefcha 1.27 !regexec(&creg[11], line, 4, match, 0) ||
164     !regexec(&creg[12], line, 4, match, 0))
165 lefcha 1.15 set_options(line, match);
166 lefcha 1.17 else
167 lefcha 1.18 return row;
168    
169 lefcha 1.17 if (r == ERROR_CONFIG_PARSE)
170     return row;
171 lefcha 1.1 }
172 lefcha 1.3
173 lefcha 1.27 for (i = 0; i < 13; i++)
174 lefcha 1.12 regfree(&creg[i]);
175 lefcha 1.18
176 lefcha 1.15 destroy_data();
177 lefcha 1.6
178 lefcha 1.8 return 0;
179 lefcha 1.1 }
180    
181    
182     /*
183 lefcha 1.13 * Set other options found in config file.
184 lefcha 1.11 */
185     void set_options(char *line, regmatch_t * match)
186     {
187 lefcha 1.26 if (!strncasecmp(line + match[2].rm_so, "logfile", 7)) {
188 lefcha 1.19 if (!*logfile)
189 lefcha 1.26 strncat(logfile, line + match[3].rm_so,
190     min((match[3].rm_eo - match[3].rm_so), PATH_MAX - 1));
191 lefcha 1.27 } else if (!strncasecmp(line + match[2].rm_so, "header", 6)) {
192 lefcha 1.26 if (!strncasecmp(line + match[3].rm_so, "yes", 3))
193 lefcha 1.19 options |= OPTION_HEADERS;
194 lefcha 1.25 else
195     options &= ~(OPTION_HEADERS);
196 lefcha 1.28 } else if (!strncasecmp(line + match[2].rm_so, "namespace", 9)) {
197     if (!strncasecmp(line + match[3].rm_so, "yes", 3))
198     options |= OPTION_NAMESPACE;
199     else
200     options &= ~(OPTION_NAMESPACE);
201 lefcha 1.27 } else if (!strncasecmp(line + match[2].rm_so, "timeout", 7)) {
202     errno = 0;
203     timeout = strtol(line + match[3].rm_so, NULL, 10);
204     if (errno)
205     timeout = 0;
206 lefcha 1.34 } else if (!strncasecmp(line + match[2].rm_so, "daemon", 6) &&
207     !(options & OPTION_DAEMON_MODE)) {
208     options |= OPTION_DAEMON_MODE;
209     errno = 0;
210     interval = strtoul(line + match[3].rm_so, NULL, 10);
211     if (errno)
212     interval = 0;
213 lefcha 1.19 }
214 lefcha 1.1 }
215 lefcha 1.29
216    
217     #ifdef ENCRYPTED_PASSWORDS
218     /*
219     * Open password file and call parse_passwords().
220     */
221     int read_passwords(void)
222     {
223     FILE *fd;
224     char pwfile[PATH_MAX];
225 lefcha 1.34
226     if (!(flags & FLAG_BLANK_PASSWORD))
227 lefcha 1.36 return ERROR_CONFIG_PARSE;
228 lefcha 1.31
229     passphr = (char *) smalloc(PASSPHRASE_LEN);
230 lefcha 1.37 *passphr = 0;
231 lefcha 1.29
232     snprintf(pwfile, PATH_MAX, "%s/%s", home, ".imapfilter/passwords");
233     #ifdef DEBUG
234     printf("debug: passwords file: '%s'\n", pwfile);
235     #endif
236    
237     if (!exists_file(pwfile))
238 lefcha 1.36 return ERROR_FILE_OPEN;
239 lefcha 1.29
240     #ifdef CHECK_PERMISSIONS
241     check_file_perms(pwfile, S_IRUSR | S_IWUSR);
242     #endif
243    
244     fd = fopen(pwfile, "r");
245    
246     if (!fd)
247     fatal(ERROR_FILE_OPEN, "imapfilter: opening passwords file %s; %s\n",
248     pwfile, strerror(errno));
249    
250     parse_passwords(fd);
251    
252     fclose(fd);
253    
254     return 0;
255     }
256    
257    
258     /*
259     * Parse unencrypted password file.
260     */
261     int parse_passwords(FILE * fd)
262     {
263     int t = 3;
264     char *pe = NULL;
265     char user[USERNAME_LEN], serv[SERVER_LEN];
266     unsigned char *buf;
267     char *c, *cp, *line;
268     regex_t creg;
269     regmatch_t match[4];
270     const char *reg = "([[:alnum:].-]+) ([[:graph:]]+) ([[:graph:]]+)";
271 lefcha 1.36 int r;
272 lefcha 1.29
273     do {
274 lefcha 1.36 fseek(fd, 0L, SEEK_SET);
275 lefcha 1.29 printf("Enter master passphrase: ");
276     get_password(passphr, PASSPHRASE_LEN);
277 lefcha 1.36 } while ((r = decrypt_passwords(&buf, fd)) && --t);
278 lefcha 1.29
279     if (!t)
280     return ERROR_PASSPHRASE;
281    
282 lefcha 1.31 c = cp = sstrdup(buf);
283 lefcha 1.29
284     regcomp(&creg, reg, REG_EXTENDED | REG_ICASE);
285    
286     while ((line = strsep(&c, "\n")) &&
287     !regexec(&creg, line, 4, match, 0)) {
288     user[0] = serv[0] = 0;
289    
290     strncat(serv, line + match[1].rm_so,
291     min(match[1].rm_eo - match[1].rm_so, SERVER_LEN - 1));
292     strncat(user, line + match[2].rm_so,
293     min(match[2].rm_eo - match[2].rm_so, USERNAME_LEN - 1));
294    
295     if ((pe = (char *) find_password(user, serv)))
296     strncat(pe, line + match[3].rm_so,
297     min(match[3].rm_eo - match[3].rm_so, PASSWORD_LEN - 1));
298     }
299    
300     regfree(&creg);
301 lefcha 1.31 sfree(cp);
302     sfree(buf);
303 lefcha 1.29
304     return 0;
305     }
306    
307    
308     /*
309     * Store encrypted passwords to file.
310     */
311     int store_passwords(account_t * accts[])
312     {
313     char pwfile[PATH_MAX];
314     FILE *fd;
315    
316     snprintf(pwfile, PATH_MAX, "%s/%s", home, ".imapfilter/passwords");
317 lefcha 1.32
318     create_file(pwfile, S_IRUSR | S_IWUSR);
319 lefcha 1.29
320     fd = fopen(pwfile, "w");
321    
322     if (!fd)
323     fatal(ERROR_FILE_OPEN, "imapfilter: opening passwords file %s; %s\n",
324     pwfile, strerror(errno));
325    
326     encrypt_passwords(fd, accts);
327    
328     fclose(fd);
329    
330     return 0;
331     }
332     #endif
333 lefcha 1.31
334    
335     /*
336     * Create $HOME/.imapfilter directory.
337     */
338     int create_homedir(void)
339     {
340 lefcha 1.33 char *hdn = ".imapfilter";
341 lefcha 1.31
342     if (home)
343     if (chdir(home))
344     error("imapfilter: could not change directory; %s\n",
345     strerror(errno));
346    
347 lefcha 1.36 if (!exists_dir(hdn))
348     if (mkdir(hdn, S_IRUSR | S_IWUSR | S_IXUSR))
349     error("imapfilter: could not create directory %s; %s\n", hdn,
350     strerror(errno));
351    
352 lefcha 1.31 return 0;
353     }
354    
355    
356     /*
357     * Check if a file exists.
358     */
359     int exists_file(char *fname)
360     {
361     struct stat fs;
362    
363     if (access(fname, F_OK))
364     return 0;
365    
366     stat(fname, &fs);
367     if (!S_ISREG(fs.st_mode)) {
368     error("imapfilter: file %s not a regular file\n", fname);
369     return ERROR_FILE_OPEN;
370     }
371    
372     return 1;
373     }
374    
375    
376     /*
377     * Check if a directory exists.
378     */
379     int exists_dir(char *dname)
380     {
381     struct stat ds;
382    
383     if (access(dname, F_OK))
384     return 0;
385    
386     stat(dname, &ds);
387     if (!S_ISDIR(ds.st_mode)) {
388     error("imapfilter: file %s not a directory\n", dname);
389     return ERROR_FILE_OPEN;
390     }
391    
392     return 1;
393     }
394    
395    
396     /*
397 lefcha 1.36 * Create a file with the specified permissions.
398 lefcha 1.31 */
399     int create_file(char *fname, mode_t mode)
400     {
401     int fd = 0;
402    
403 lefcha 1.33 if (!exists_file(fname)) {
404     fd = open(fname, O_CREAT | O_WRONLY | O_TRUNC, mode);
405 lefcha 1.31 if (fd == -1) {
406     error("imapfilter: could not create file %s; %s\n", fname,
407     strerror(errno));
408     return ERROR_FILE_OPEN;
409     }
410     close(fd);
411 lefcha 1.33 }
412 lefcha 1.31
413     return 0;
414     }
415    
416    
417     #ifdef CHECK_PERMISSIONS
418     /*
419     * Check the permissions of a file.
420     */
421     int check_file_perms(char *fname, mode_t mode)
422     {
423     struct stat fs;
424 lefcha 1.36
425 lefcha 1.31 if (stat(fname, &fs)) {
426     error("imapfilter: getting file %s status; %s\n", fname,
427     strerror(errno));
428     return ERROR_TRIVIAL;
429     }
430     if (!S_ISREG(fs.st_mode)) {
431     error("imapfilter: file %s not a regular file\n", fname);
432     return ERROR_TRIVIAL;
433     }
434     if ((fs.st_mode & 00777) != mode) {
435     error("imapfilter: warning: improper file %s permissions\n"
436     "imapfilter: warning: file's mode should be %o not %o\n",
437     fname, mode, fs.st_mode & 00777);
438     return ERROR_TRIVIAL;
439     }
440     return 0;
441     }
442    
443    
444     /*
445     * Check the permissions of a directory.
446     */
447     int check_dir_perms(char *dname, mode_t mode)
448     {
449     struct stat ds;
450    
451     if (stat(dname, &ds)) {
452     error("imapfilter: getting file %s status; %s\n", dname,
453     strerror(errno));
454     return ERROR_TRIVIAL;
455     }
456     if (!S_ISDIR(ds.st_mode)) {
457     error("imapfilter: file %s not a directory\n", dname);
458     return ERROR_TRIVIAL;
459     }
460     if ((ds.st_mode & 00777) != mode) {
461     error("imapfilter: warning: improper dir %s permissions\n"
462     "imapfilter: warning: file's mode should be %o not %o\n",
463     dname, mode, ds.st_mode & 00777);
464     return ERROR_TRIVIAL;
465     }
466     return 0;
467     }
468     #endif
469 lefcha 1.33
470    
471 lefcha 1.31

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26