1 /*
2 * Copyright (C) 2013-2022 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
3 * Copyright (C) 2008-2013 Sourcefire, Inc.
4 *
5 * Author: aCaB <acab@clamav.net>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 * MA 02110-1301, USA.
20 */
21
22 #if HAVE_CONFIG_H
23 #include "clamav-config.h"
24 #endif
25
26 #include <stdio.h>
27 #include <string.h>
28 #include <sys/types.h>
29
30 // libclamav
31 #include "regex/regex.h"
32
33 // shared
34 #include "output.h"
35
36 #include "whitelist.h"
37
38 struct WHLST {
39 regex_t preg;
40 struct WHLST *next;
41 };
42
43 struct WHLST *wfrom = NULL;
44 struct WHLST *wto = NULL;
45
46 int skipauth = 0;
47 regex_t authreg;
48
whitelist_free(void)49 void whitelist_free(void)
50 {
51 struct WHLST *w;
52 while (wfrom) {
53 w = wfrom->next;
54 cli_regfree(&wfrom->preg);
55 free(wfrom);
56 wfrom = w;
57 }
58 while (wto) {
59 w = wto->next;
60 cli_regfree(&wto->preg);
61 free(wto);
62 wto = w;
63 }
64 }
65
whitelist_init(const char * fname)66 int whitelist_init(const char *fname)
67 {
68 char buf[2048];
69 FILE *f;
70 struct WHLST *w;
71
72 if (!(f = fopen(fname, "r"))) {
73 logg("!Cannot open whitelist file '%s'\n", fname);
74 return 1;
75 }
76
77 while (fgets(buf, sizeof(buf), f) != NULL) {
78 struct WHLST **addto = &wto;
79 char *ptr = buf;
80 int len;
81
82 if (*buf == '#' || *buf == ':' || *buf == '!')
83 continue;
84
85 if (!strncasecmp("From:", buf, 5)) {
86 ptr += 5;
87 addto = &wfrom;
88 } else if (!strncasecmp("To:", buf, 3))
89 ptr += 3;
90
91 len = strlen(ptr) - 1;
92 for (; len >= 0; len--) {
93 if (ptr[len] != '\n' && ptr[len] != '\r') break;
94 ptr[len] = '\0';
95 }
96 if (!len) continue;
97 if (!(w = (struct WHLST *)malloc(sizeof(*w)))) {
98 logg("!Out of memory loading whitelist file\n");
99 whitelist_free();
100 fclose(f);
101 return 1;
102 }
103 w->next = (*addto);
104 (*addto) = w;
105 if (cli_regcomp(&w->preg, ptr, REG_ICASE | REG_NOSUB)) {
106 logg("!Failed to compile regex '%s' in whitelist file\n", ptr);
107 whitelist_free();
108 fclose(f);
109 return 1;
110 }
111 }
112 fclose(f);
113 return 0;
114 }
115
whitelisted(const char * addr,int from)116 int whitelisted(const char *addr, int from)
117 {
118 struct WHLST *w;
119
120 if (from)
121 w = wfrom;
122 else
123 w = wto;
124
125 while (w) {
126 if (!cli_regexec(&w->preg, addr, 0, NULL, 0))
127 return 1;
128 w = w->next;
129 }
130 return 0;
131 }
132
smtpauth_init(const char * r)133 int smtpauth_init(const char *r)
134 {
135 char *regex = NULL;
136
137 if (!strncmp(r, "file:", 5)) {
138 char buf[2048];
139 FILE *f = fopen(r + 5, "r");
140 int rxsize = 0, rxavail = 0, rxused = 0;
141
142 if (!f) {
143 logg("!Cannot open whitelist file '%s'\n", r + 5);
144 return 1;
145 }
146 while (fgets(buf, sizeof(buf), f) != NULL) {
147 int len;
148 char *ptr;
149
150 if (*buf == '#' || *buf == ':' || *buf == '!')
151 continue;
152 len = strlen(buf) - 1;
153 for (; len >= 0; len--) {
154 if (buf[len] != '\n' && buf[len] != '\r') break;
155 buf[len] = '\0';
156 }
157 if (len <= 0) continue;
158 if (len * 3 + 1 > rxavail) {
159 ptr = regex;
160 regex = realloc(regex, rxsize + 2048);
161 if (!regex) {
162 logg("!Cannot allocate memory for SkipAuthenticated file\n");
163 fclose(f);
164 return 1;
165 }
166 rxavail = 2048;
167 rxsize += 2048;
168 if (!ptr) {
169 regex[0] = '^';
170 regex[1] = '(';
171 rxavail -= 2;
172 rxused = 2;
173 }
174 }
175 ptr = buf;
176 while (*ptr) {
177 if ((*ptr >= 'A' && *ptr <= 'Z') || (*ptr >= 'a' && *ptr <= 'z') || (*ptr >= '0' && *ptr <= '9') || *ptr == '@') {
178 regex[rxused] = *ptr;
179 rxused++;
180 rxavail--;
181 } else {
182 regex[rxused] = '[';
183 regex[rxused + 1] = *ptr;
184 regex[rxused + 2] = ']';
185 rxused += 3;
186 rxavail -= 3;
187 }
188 ptr++;
189 }
190 regex[rxused++] = '|';
191 rxavail--;
192 }
193 if (rxavail < 4 && !(regex = realloc(regex, rxsize + 4))) {
194 logg("!Cannot allocate memory for SkipAuthenticated file\n");
195 fclose(f);
196 return 1;
197 }
198 regex[rxused - 1] = ')';
199 regex[rxused] = '$';
200 regex[rxused + 1] = '\0';
201 r = regex;
202 fclose(f);
203 }
204
205 if (cli_regcomp(&authreg, r, REG_ICASE | REG_NOSUB | REG_EXTENDED)) {
206 logg("!Failed to compile regex '%s' for SkipAuthenticated\n", r);
207 if (regex) free(regex);
208 return 1;
209 }
210 if (regex) free(regex);
211 skipauth = 1;
212 return 0;
213 }
214
smtpauthed(const char * login)215 int smtpauthed(const char *login)
216 {
217 if (skipauth && !cli_regexec(&authreg, login, 0, NULL, 0))
218 return 1;
219 return 0;
220 }
221
222 /*
223 * Local Variables:
224 * mode: c
225 * c-basic-offset: 4
226 * tab-width: 8
227 * End:
228 * vim: set cindent smartindent autoindent softtabstop=4 shiftwidth=4 tabstop=8:
229 */
230