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

Annotation of /imapfilter/file.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.10 - (hide annotations)
Sun Aug 26 13:31:57 2001 UTC (22 years, 7 months ago) by lefcha
Branch: MAIN
Changes since 1.9: +38 -4 lines
File MIME type: text/plain
Config file permissions checking.

1 lefcha 1.1 #include <stdio.h>
2     #include <errno.h>
3 lefcha 1.5 #include <sys/types.h>
4 lefcha 1.1 #include <regex.h>
5     #include <string.h>
6     #include <stdlib.h>
7     #include <limits.h>
8 lefcha 1.10 #include <sys/stat.h>
9 lefcha 1.1
10     #include "config.h"
11     #include "imapfilter.h"
12     #include "file.h"
13     #include "log.h"
14    
15    
16 lefcha 1.6 extern char logfile[PATH_MAX];
17 lefcha 1.8
18     account_t *accounts = NULL; /* All accounts. */
19    
20     filter_t *dfilters; /* Filters of DENY type. */
21     filter_t *afilters; /* Filters of ALLOW type. */
22    
23 lefcha 1.4 unsigned int dlimit = 0;
24     unsigned int alimit = 0; /* DENY and ALLOW message size limits. */
25 lefcha 1.1
26    
27     /*
28     * Finds path to configuration file, opens it and calls parse_config().
29     */
30     int read_config(char *cfg)
31     {
32     int r;
33     FILE *fp;
34     char *home = NULL;
35    
36     if (!cfg) {
37     cfg = (char *) malloc(PATH_MAX * sizeof(char));
38    
39 lefcha 1.8
40 lefcha 1.1 home = getenv("HOME");
41    
42     snprintf(cfg, PATH_MAX, "%s/%s", home, ".imapfilterrc");
43     }
44     #ifdef DEBUG
45     printf("debug: configuration file: %s\n", cfg);
46     #endif
47    
48 lefcha 1.10 check_permissions(cfg);
49    
50 lefcha 1.1 fp = fopen(cfg, "r");
51    
52     if (!fp) {
53 lefcha 1.7 fprintf(stderr, "imapfilter: opening config file %s; %s\n",
54 lefcha 1.1 cfg, strerror(errno));
55 lefcha 1.8 return 1;
56 lefcha 1.1 }
57    
58     r = parse_config(fp);
59    
60     fclose(fp);
61    
62     return r;
63     }
64    
65 lefcha 1.6
66 lefcha 1.1 /*
67 lefcha 1.10 * Checks the permissions of the configuration file.
68     */
69     int check_permissions(char *cfg)
70     {
71     struct stat fs;
72    
73     if (stat(cfg, &fs)) {
74     fprintf(stderr, "imapfilter: getting file %s status; %s\n", cfg,
75     strerror(errno));
76     return 1;
77     }
78    
79     if (!S_ISREG(fs.st_mode)) {
80     fprintf(stderr, "imapfilter: file %s not a regular file\n", cfg);
81     return 1;
82     }
83    
84     if ((fs.st_mode & 00777) != (S_IRUSR | S_IWUSR)) {
85     fprintf(stderr,
86     "imapfilter: warning: bad config file %s permissions\n"
87     "imapfilter: warning: file's mode should be 600 not %o\n",
88     cfg, fs.st_mode & 00777);
89     return 1;
90     }
91    
92     return 0;
93     }
94    
95    
96     /*
97 lefcha 1.1 * Parses configuration file.
98     */
99     int parse_config(FILE * fp)
100     {
101     int i;
102     unsigned int row = 0;
103     char line[LINE_MAX];
104 lefcha 1.8 regex_t creg[5];
105 lefcha 1.2 regmatch_t match[4];
106 lefcha 1.4 const char *reg[5] = {
107 lefcha 1.1 "^[[:blank:]]*(SERVER|PORT|USERNAME|PASSWORD|LOGFILE)[[:blank:]]*=[[:blank:]]*([[:graph:]]*)[[:blank:]]*",
108 lefcha 1.2 "^[[:blank:]]*(DENY|ALLOW)[[:blank:]]*=[[:blank:]]*(FROM|CC|BCC|SUBJECT|TO):? ([[:print:]]*)",
109     "^[[:blank:]]*(DENY|ALLOW)[[:blank:]]*=[[:blank:]]*([[:graph:]]+):? ([[:print:]]*)",
110 lefcha 1.4 "^[[:blank:]]*(DENY_LIMIT|ALLOW_LIMIT)[[:blank:]]*=[[:blank:]]*([[:digit:]]*)[[:blank:]]*",
111 lefcha 1.1 "^[[:blank:]]*#{0,1}.*"
112     };
113    
114 lefcha 1.4 for (i = 0; i < 5; i++)
115 lefcha 1.8 regcomp(&creg[i], reg[i], REG_EXTENDED);
116 lefcha 1.1
117     while (fgets(line, LINE_MAX - 1, fp)) {
118     row++;
119 lefcha 1.8 if (!regexec(&creg[0], line, 3, match, 0)) {
120 lefcha 1.9 if (set_account(line, match))
121     return 1;
122 lefcha 1.1 continue;
123 lefcha 1.8 } else if (!regexec(&creg[1], line, 4, match, 0)) {
124 lefcha 1.9 if (standard_filter(line, match))
125     return 1;
126 lefcha 1.1 continue;
127 lefcha 1.8 } else if (!regexec(&creg[2], line, 4, match, 0)) {
128 lefcha 1.9 if (custom_filter(line, match))
129     return 1;
130 lefcha 1.1 continue;
131 lefcha 1.8 } else if (!regexec(&creg[3], line, 3, match, 0)) {
132 lefcha 1.4 set_limits(line, match);
133     continue;
134 lefcha 1.8 } else if (!regexec(&creg[4], line, 1, match, 0))
135 lefcha 1.1 continue;
136     else {
137     fprintf(stderr,
138     "imapfilter: parse error in config file at row %d\n",
139     row);
140 lefcha 1.8 return 1;
141 lefcha 1.1 }
142     }
143 lefcha 1.3
144 lefcha 1.6 /* Fail if no accounts were defined. */
145 lefcha 1.8 if (!accounts) {
146 lefcha 1.6 fprintf(stderr,
147     "imapfilter: no accounts defined in config file\n");
148 lefcha 1.8 return 1;
149 lefcha 1.6 }
150    
151 lefcha 1.8 /* Fail if no filters were defined. */
152     if (!dfilters && !afilters) {
153 lefcha 1.3 fprintf(stderr, "imapfilter: no filters defined in config file\n");
154 lefcha 1.8 return 1;
155 lefcha 1.3 }
156 lefcha 1.6
157 lefcha 1.8 return 0;
158 lefcha 1.1 }
159    
160    
161     /*
162 lefcha 1.9 * Allocates memory for accounts, builds linked list, and NULL terminates
163 lefcha 1.8 * account settings.
164 lefcha 1.4 */
165 lefcha 1.8 account_t *prepare_account(void)
166 lefcha 1.4 {
167 lefcha 1.8 static account_t *ca; /* Current account. */
168    
169     if (!accounts) {
170     accounts = (account_t *) malloc(sizeof(account_t));
171 lefcha 1.9 if (!accounts) {
172     error("imapfilter: allocating memory; %s\n", strerror(errno));
173     return NULL;
174 lefcha 1.10 }
175 lefcha 1.8 ca = accounts;
176     } else {
177     ca->next = (account_t *) malloc(sizeof(account_t));
178 lefcha 1.9 if (!ca->next) {
179     error("imapfilter: allocating memory; %s\n", strerror(errno));
180     return NULL;
181     }
182 lefcha 1.8 ca = ca->next;
183     }
184    
185     ca->next = NULL;
186    
187     ca->server[0] = 0;
188     ca->port = 143;
189     ca->userid[0] = 0;
190     ca->passwd[0] = 0;
191 lefcha 1.6
192 lefcha 1.8 return ca;
193 lefcha 1.4 }
194    
195    
196     /*
197 lefcha 1.1 * An account setting was found from parse_config(), changes the
198     * apropriate variable.
199     */
200 lefcha 1.9 int set_account(char *line, regmatch_t * match)
201 lefcha 1.1 {
202     int s;
203 lefcha 1.8 char p[6];
204     static account_t *ca;
205 lefcha 1.1
206     if (!strncmp(line + match[1].rm_so, "SERVER", 6)) {
207 lefcha 1.9 if (!(ca = prepare_account()))
208     return 1;
209 lefcha 1.1 s = min((match[2].rm_eo - match[2].rm_so), SERVER_MAX - 1);
210 lefcha 1.8 strncpy(ca->server, line + match[2].rm_so, s);
211     ca->server[s] = 0;
212 lefcha 1.6 #ifdef DEBUG
213 lefcha 1.8 printf("debug: account setting SERVER: '%s'\n", ca->server);
214 lefcha 1.6 #endif
215 lefcha 1.8 } else if (accounts) {
216 lefcha 1.6 if (!strncmp(line + match[1].rm_so, "PORT", 4)) {
217 lefcha 1.8 s = min((match[2].rm_eo - match[2].rm_so), sizeof(p));
218     strncpy(p, line + match[2].rm_so, s);
219     p[s] = 0;
220     ca->port = strtoul(p, NULL, 0);
221 lefcha 1.6 #ifdef DEBUG
222 lefcha 1.8 printf("debug: account setting PORT: '%d'\n", ca->port);
223 lefcha 1.7 #endif
224 lefcha 1.6 } else if (!strncmp(line + match[1].rm_so, "USERNAME", 8)) {
225 lefcha 1.8 s = min((match[2].rm_eo - match[2].rm_so), USERID_MAX - 1);
226     strncpy(ca->userid, line + match[2].rm_so, s);
227     ca->userid[s] = 0;
228 lefcha 1.6 #ifdef DEBUG
229 lefcha 1.8 printf("debug: account setting USERNAME: '%s'\n", ca->userid);
230 lefcha 1.7 #endif
231 lefcha 1.6 } else if (!strncmp(line + match[1].rm_so, "PASSWORD", 8)) {
232 lefcha 1.8 s = min((match[2].rm_eo - match[2].rm_so), PASSWD_MAX - 1);
233     strncpy(ca->passwd, line + match[2].rm_so, s);
234     ca->passwd[s] = 0;
235 lefcha 1.6 #ifdef DEBUG
236 lefcha 1.8 printf("debug: account setting PASSWORD: '%s'\n", ca->passwd);
237 lefcha 1.6 #endif
238 lefcha 1.10 } else if (!logfile[0]
239     && !strncmp(line + match[1].rm_so, "LOGFILE", 7)) {
240 lefcha 1.6 s = min((match[2].rm_eo - match[2].rm_so), PATH_MAX - 1);
241     strncpy(logfile, line + match[2].rm_so, s);
242     logfile[s] = 0;
243     }
244 lefcha 1.1 }
245 lefcha 1.10
246 lefcha 1.9 return 0;
247 lefcha 1.1 }
248    
249    
250     /*
251 lefcha 1.4 * A filter entry was found from parse_config() processes it and saves it.
252 lefcha 1.1 */
253 lefcha 1.9 int set_filters(char *line, regmatch_t * match, int csm)
254 lefcha 1.1 {
255     int s;
256 lefcha 1.8 static filter_t *cdf, *caf;
257     filter_t **cf;
258     filter_t **fl;
259 lefcha 1.2
260     if (!(strncmp(line + match[1].rm_so, "DENY", 4))) {
261     #ifdef DEBUG
262     printf("debug: filter entry: DENY");
263     #endif
264 lefcha 1.8 cf = &cdf;
265     fl = &dfilters;
266 lefcha 1.2 } else {
267     #ifdef DEBUG
268     printf("debug: filter entry: ALLOW");
269     #endif
270 lefcha 1.8 cf = &caf;
271     fl = &afilters;
272 lefcha 1.2 }
273 lefcha 1.1
274 lefcha 1.8 /*
275     * Allocate memory for filter entry and build linked list.
276     */
277    
278     if (!(*fl)) {
279     *fl = (filter_t *) malloc(sizeof(filter_t));
280 lefcha 1.9 if (!(*fl)) {
281     error("imapfilter: allocating memory; %s\n", strerror(errno));
282     return 1;
283 lefcha 1.10 }
284 lefcha 1.8 *cf = *fl;
285     } else {
286     (*cf)->next = (filter_t *) malloc(sizeof(filter_t));
287 lefcha 1.9 if (!((*cf)->next)) {
288     error("imapfilter: allocating memory; %s\n", strerror(errno));
289     return 1;
290     }
291 lefcha 1.8 *cf = (*cf)->next;
292     }
293 lefcha 1.2
294 lefcha 1.8 (*cf)->next = NULL;
295 lefcha 1.2
296 lefcha 1.8 (*cf)->custom = csm;
297 lefcha 1.2
298     s = min((match[2].rm_eo - match[2].rm_so), FIELD_NAME_MAX - 1);
299 lefcha 1.8 strncpy((*cf)->name, line + match[2].rm_so, s);
300     (*cf)->name[s] = 0;
301 lefcha 1.2
302     s = min((match[3].rm_eo - match[3].rm_so), FIELD_BODY_MAX - 1);
303 lefcha 1.8 strncpy((*cf)->body, line + match[3].rm_so, s);
304     (*cf)->body[s] = 0;
305 lefcha 1.1
306     #ifdef DEBUG
307 lefcha 1.8 printf(" '%s': '%s'\n", (*cf)->name, (*cf)->body);
308 lefcha 1.1 #endif
309 lefcha 1.9 return 0;
310 lefcha 1.4 }
311    
312    
313     /*
314     * Sets the DENY and ALLOW limits from the values found in config file.
315     */
316     void set_limits(char *line, regmatch_t * match)
317     {
318     int s;
319 lefcha 1.8 char lim[10];
320 lefcha 1.4
321 lefcha 1.8 s = min((match[2].rm_eo - match[2].rm_so), sizeof(lim));
322     strncpy(lim, line + match[2].rm_so, s);
323     lim[s] = 0;
324 lefcha 1.4
325     if (!strncmp(line + match[1].rm_so, "DENY_LIMIT", 10)) {
326 lefcha 1.8 dlimit = strtoul(lim, NULL, 0);
327 lefcha 1.4 } else {
328 lefcha 1.8 alimit = strtoul(lim, NULL, 0);
329 lefcha 1.4 }
330 lefcha 1.1 }

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26