1 /*
2 renattach 1.2.4 - Filter that renames/deletes dangerous email attachments
3 Copyright (C) 2003-2006 Jem E. Berkes <jberkes@pc-tools.net>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19 */
20
21 #include "config.h"
22 #include "renattach.h"
23 #include "strings-en.h"
24 #include "utility.h"
25 #include <memory.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29
30 #ifndef HAVE_STRCASECMP
31 #define strcasecmp stricmp
32 #endif
33
34 #ifndef HAVE_STRNCASECMP
35 #define strncasecmp strnicmp
36 #endif
37
38
39
40 /*
41 Iterates through the list and returns the number of entries within.
42 If verbose is specified, each entry is displayed.
43 */
tokenize_list(const char * thelist,int verbose)44 int tokenize_list(const char* thelist, int verbose)
45 {
46 char *tmpbuf, *token;
47 int count=0;
48
49 tmpbuf = malloc(strlen(thelist) + 1);
50 strcpy(tmpbuf, thelist);
51 token = strtok(tmpbuf, LIST_TOKENS);
52 while (token)
53 {
54 if (verbose)
55 {
56 if (count)
57 fprintf(stderr, "|%s", token);
58 else
59 fprintf(stderr, "%s", token);
60 }
61 count++;
62 token = strtok(NULL, LIST_TOKENS);
63 }
64 free(tmpbuf);
65 return count;
66 }
67
68
69 /*
70 Parse the configuration file and fill in the options structure
71 Any errors found are written to stderr. Returns CODE_OK or CODE_FAILURE
72 */
parse_conf(struct config_opts * options)73 int parse_conf(struct config_opts* options)
74 {
75 int linecount = 0;
76 char confline[MAXFIELD];
77 char directive[MAXFIELD], parameter[MAXFIELD];
78 FILE* config = NULL;
79
80 if (options->config_file == NULL)
81 {
82 fprintf(stderr, TXT_INFO_CONFIGFILE TXT_INFO_UNDEF "\n");
83 return CODE_FAILURE;
84 }
85
86 config = fopen(options->config_file, "r");
87 if (!config)
88 {
89 perror(options->config_file);
90 return CODE_FAILURE;
91 }
92
93 while (fgets(confline, sizeof(confline), config))
94 {
95 int syntax_error = 0;
96 linecount++;
97
98 trim_leading(confline);
99 trim_trailing(confline);
100
101 if ((*confline == '#') || (*confline == '\r') || (*confline == '\n'))
102 continue;
103 if (sscanf(confline, "%[^\t =]%*[\t =]%[^\r\n]", directive, parameter) == 2)
104 {
105 int state = OPTION_UNSET;
106 if ( (strncasecmp(parameter, TAG_OPTENABLED, strlen(TAG_OPTENABLED))==0)
107 || (*parameter=='1')) /* 'yes' or 1 */
108 state = OPTION_ENABLED;
109 else if ( (strncasecmp(parameter, TAG_OPTDISABLED, strlen(TAG_OPTDISABLED))==0)
110 || (*parameter=='0')) /* 'no' or 0 */
111 state = OPTION_DISABLED;
112
113 if ((strcasecmp(directive, TAG_DELETE_EXE)==0) && state)
114 options->delete_exe = state;
115 else if ((strcasecmp(directive, TAG_KILL_EXE)==0) && state)
116 options->kill_exe = state;
117 else if ((strcasecmp(directive, TAG_SEARCH_ZIP)==0) && state)
118 options->search_zip = state;
119 else if ((strcasecmp(directive, TAG_PASS_CONTENTID)==0) && state)
120 options->pass_contentid = state;
121 else if ((strcasecmp(directive, TAG_FULL_RENAME)==0) && state)
122 options->full_rename = state;
123 else if ((strcasecmp(directive, TAG_USE_SYSLOG)==0) && state)
124 options->use_syslog = state;
125 else if (strcasecmp(directive, TAG_GENERIC_NAME) == 0)
126 strcpy(options->generic_name, parameter);
127 else if (strcasecmp(directive, TAG_NEW_EXTENSION) == 0)
128 strcpy(options->new_extension, parameter);
129 else if (strcasecmp(directive, TAG_NEW_MIME_TYPE) == 0)
130 strcpy(options->new_mime_type, parameter);
131 else if (strcasecmp(directive, TAG_SUBJ_BANNED) == 0)
132 strcpy(options->subj_banned, parameter);
133 else if (strcasecmp(directive, TAG_SUBJ_EXEC) == 0)
134 strcpy(options->subj_exec, parameter);
135 else if (strcasecmp(directive, TAG_SUBJ_DELETED) == 0)
136 strcpy(options->subj_deleted, parameter);
137 else if (strcasecmp(directive, TAG_SUBJ_RENAMED) == 0)
138 strcpy(options->subj_renamed, parameter);
139 else if (strcasecmp(directive, TAG_ADD_SUBJECT) == 0)
140 strcpy(options->add_subject, parameter);
141 else if (strcasecmp(directive, TAG_HTMLWARN_POS) == 0)
142 strcpy(options->htmlwarn_pos, parameter);
143 else if (strcasecmp(directive, TAG_WARNING_TEXT) == 0)
144 expand_list(&options->warning_text, parameter, "\n");
145 else if (strcasecmp(directive, TAG_WARNING_HTML) == 0)
146 expand_list(&options->warning_html, parameter, "\n");
147 else if (strcasecmp(directive, TAG_ADD_HEADER) == 0)
148 expand_list(&options->add_header, parameter, "\n");
149 else if (strcasecmp(directive, TAG_BANNED_FILES) == 0)
150 expand_list(&options->banned_files, parameter, "\n");
151 else if (strcasecmp(directive, TAG_BADLIST) == 0)
152 expand_list(&options->badlist, parameter, "\n");
153 else if (strcasecmp(directive, TAG_GOODLIST) == 0)
154 expand_list(&options->goodlist, parameter, "\n");
155 else
156 syntax_error = 1;
157 }
158 else
159 syntax_error = 1;
160
161 if (syntax_error)
162 {
163 fprintf(stderr, TXT_ERR_CONFSYNTAX "%d: %s\n", linecount, confline);
164 fclose(config);
165 return CODE_FAILURE;
166 }
167 }
168
169 fclose(config);
170 return CODE_OK;
171 }
172
173
174 /*
175 Check all configuration directives
176 If any are unset, use defaults
177 */
directive_defaults(struct config_opts * options)178 void directive_defaults(struct config_opts* options)
179 {
180 if (options->delete_exe == OPTION_UNSET)
181 options->delete_exe = DEF_DELETE_EXE;
182 if (options->kill_exe == OPTION_UNSET)
183 options->kill_exe = DEF_KILL_EXE;
184 if (options->search_zip == OPTION_UNSET)
185 options->search_zip = DEF_SEARCH_ZIP;
186 if (options->pass_contentid == OPTION_UNSET)
187 options->pass_contentid = DEF_PASS_CONTENTID;
188 if (options->full_rename == OPTION_UNSET)
189 options->full_rename = DEF_FULL_RENAME;
190 if (options->use_syslog == OPTION_UNSET)
191 options->use_syslog = DEF_USE_SYSLOG;
192 if (options->generic_name[0] == '\0')
193 strcpy(options->generic_name, DEF_GENERIC_NAME);
194 if (options->new_extension[0] == '\0')
195 strcpy(options->new_extension, DEF_NEW_EXTENSION);
196 if (options->new_mime_type[0] == '\0')
197 strcpy(options->new_mime_type, DEF_NEW_MIME_TYPE);
198 if (options->subj_banned[0] == '\0')
199 strcpy(options->subj_banned, DEF_SUBJ_BANNED);
200 if (options->subj_exec[0] == '\0')
201 strcpy(options->subj_exec, DEF_SUBJ_EXEC);
202 if (options->subj_deleted[0] == '\0')
203 strcpy(options->subj_deleted, DEF_SUBJ_DELETED);
204 if (options->subj_renamed[0] == '\0')
205 strcpy(options->subj_renamed, DEF_SUBJ_RENAMED);
206 if (options->add_subject[0] == '\0')
207 strcpy(options->add_subject, DEF_ADD_SUBJECT);
208 if (options->htmlwarn_pos[0] == '\0')
209 strcpy(options->htmlwarn_pos, DEF_HTMLWARN_POS);
210 if ( (options->warning_text == NULL) || (options->warning_text[0] == '\0'))
211 expand_list(&options->warning_text, DEF_WARNING_TEXT, "\n");
212 if ( (options->warning_html == NULL) || (options->warning_html[0] == '\0'))
213 expand_list(&options->warning_html, DEF_WARNING_HTML, "\n");
214 if ( (options->add_header == NULL) || (options->add_header[0] == '\0'))
215 expand_list(&options->add_header, DEF_ADD_HEADER, "\n");
216 if ( (options->banned_files == NULL) || (tokenize_list(options->banned_files, 0)==0) )
217 expand_list(&options->banned_files, DEF_BANNED_FILES, "\n");
218 if ( (options->goodlist == NULL) || (tokenize_list(options->goodlist, 0)==0) )
219 expand_list(&options->goodlist, DEF_GOODLIST, "\n");
220 if ( (options->badlist == NULL) || (tokenize_list(options->badlist, 0)==0) )
221 expand_list(&options->badlist, DEF_BADLIST, "\n");
222 }
223
224
225 /*
226 Show current configuration; used in verbose mode
227 */
show_configuration(struct config_opts * options)228 void show_configuration(struct config_opts* options)
229 {
230 /* Where is our configuration file? */
231 fprintf(stderr, TXT_INFO_CONFIGFILE "\n ");
232 if (options->config_file)
233 fprintf(stderr, "%s\n", options->config_file);
234 else
235 fprintf(stderr, TXT_INFO_UNDEF "\n");
236
237 fprintf(stderr, TXT_INFO_OUTPUT "\n ");
238 if (options->pipe_cmd)
239 {
240 int arg = 0;
241 fprintf(stderr, "{");
242 while (options->pipe_cmd[arg])
243 {
244 if (arg) fprintf(stderr, "|");
245 fprintf(stderr, "%s", options->pipe_cmd[arg++]);
246 }
247 fprintf(stderr, "}\n");
248 }
249 else
250 fprintf(stderr, TXT_INFO_STDOUT "\n");
251
252 /* What filtering mode are we using? */
253 fprintf(stderr, TXT_INFO_MODE "\n %s\n", mode2str(options->mode));
254
255 /* What filtering action are we using? */
256 fprintf(stderr, TXT_INFO_ACTION "\n %s\n", act2str(options->action));
257
258 fprintf(stderr, TXT_INFO_CONFOPTS "\n");
259 /* Show status of all settings from renattach.conf */
260 fprintf(stderr, " "TAG_DELETE_EXE ": %s\n", opt2str(options->delete_exe));
261 fprintf(stderr, " "TAG_KILL_EXE ": %s\n", opt2str(options->kill_exe));
262 fprintf(stderr, " "TAG_SEARCH_ZIP ": %s\n", opt2str(options->search_zip));
263 fprintf(stderr, " "TAG_PASS_CONTENTID ": %s\n", opt2str(options->pass_contentid));
264 fprintf(stderr, " "TAG_FULL_RENAME ": %s\n", opt2str(options->full_rename));
265 fprintf(stderr, " "TAG_USE_SYSLOG ": %s\n", opt2str(options->use_syslog));
266 fprintf(stderr, " "TAG_GENERIC_NAME ": \"%s\"\n", options->generic_name);
267 fprintf(stderr, " "TAG_NEW_EXTENSION ": \"%s\"\n", options->new_extension);
268 fprintf(stderr, " "TAG_NEW_MIME_TYPE ": \"%s\"\n", options->new_mime_type);
269 fprintf(stderr, " "TAG_SUBJ_BANNED ": \"%s\"\n", options->subj_banned);
270 fprintf(stderr, " "TAG_SUBJ_EXEC ": \"%s\"\n", options->subj_exec);
271 fprintf(stderr, " "TAG_SUBJ_DELETED ": \"%s\"\n", options->subj_deleted);
272 fprintf(stderr, " "TAG_SUBJ_RENAMED ": \"%s\"\n", options->subj_renamed);
273 fprintf(stderr, " "TAG_ADD_SUBJECT ": \"%s\"\n", options->add_subject);
274 fprintf(stderr, " "TAG_HTMLWARN_POS ": \"%s\"\n", options->htmlwarn_pos);
275 fprintf(stderr, " "TAG_WARNING_TEXT ": %d bytes,\n%s\n",
276 (int)strlen(options->warning_text), options->warning_text);
277 fprintf(stderr, " "TAG_WARNING_HTML ": %d bytes,\n%s\n",
278 (int)strlen(options->warning_html), options->warning_html);
279 fprintf(stderr, " "TAG_ADD_HEADER ": %d bytes,\n%s\n",
280 (int)strlen(options->add_header), options->add_header);
281 fprintf(stderr, " "TAG_BANNED_FILES ": {");
282 tokenize_list(options->banned_files, 1);
283 fprintf(stderr, "}\n "TAG_BADLIST ": {");
284 tokenize_list(options->badlist, 1);
285 fprintf(stderr, "}\n " TAG_GOODLIST ": {");
286 tokenize_list(options->goodlist, 1);
287 fprintf(stderr, "}\n");
288 }
289
290
291 /*
292 Return description of directive state
293 */
opt2str(int state)294 const char* opt2str(int state)
295 {
296 if (state == OPTION_DISABLED)
297 return TAG_OPTDISABLED;
298 else if (state == OPTION_ENABLED)
299 return TAG_OPTENABLED;
300 else
301 return TXT_INFO_UNDEF;
302 }
303
304
305 /*
306 Return description of filter mode
307 */
mode2str(int mode)308 const char* mode2str(int mode)
309 {
310 if (mode == MODE_ALL)
311 return TXT_INFO_MODEALL;
312 else if (mode == MODE_BAD)
313 return TXT_INFO_MODEBAD;
314 else if (mode == MODE_GOOD)
315 return TXT_INFO_MODEGOOD;
316 else
317 return TXT_INFO_UNDEF;
318 }
319
320
321 /*
322 Return description of action type
323 */
act2str(int action)324 const char* act2str(int action)
325 {
326 switch (action)
327 {
328 case ACTION_RENAME:
329 return TAG_ACTRENAME;
330
331 case ACTION_DELETE:
332 return TAG_ACTDELETE;
333
334 case ACTION_KILL:
335 return TAG_ACTKILL;
336
337 case ACTION_SKIP:
338 return TAG_ACTSKIP;
339
340 default:
341 return TXT_INFO_UNDEF;
342 }
343 }
344