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

Annotation of /imapfilter/file.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.30 - (hide annotations)
Fri Jan 25 17:10:17 2002 UTC (22 years, 2 months ago) by lefcha
Branch: MAIN
Changes since 1.29: +1 -1 lines
File MIME type: text/plain
Merged changes from version 0.7.2.

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

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26