added (unused) rules.rc parser to so. it will be used later.
[umfw.git] / src / ruleparser.c
blob72222b4892f1edd4edb75e76d7d23c27a263e630
1 /*
2 */
3 #include "config.h"
8 /*
9 newrule
10 app *
11 rule allow:udp:172.16.20.1:53:"DNS query"
12 rule allow:*:127.0.0.1:*:"localhost"
13 rule deny:*:207.38.11.35:*:"motd.gamespy.com"
14 endrule
15 newrule
16 app /opt/logjam/bin/logjam
17 rule allow:tcp:78.152.169.8:80:"my LiveJournal server"
18 endrule
21 static char *loadFile (const char *fname) {
22 char *res = NULL;
23 int fd = open(fname, O_RDONLY | O_NOATIME);
24 if (fd < 0) return NULL;
25 off_t size = lseek(fd, 0, SEEK_END);
26 if (size <= 0) goto done;
27 if (lseek(fd, 0, SEEK_SET) < 0) goto done;
28 res = malloc(size+1);
29 if (!res) goto done;
30 if (read(fd, res, size) != size) { free(res); res = NULL; goto done; }
31 res[size] = 0;
32 done:
33 close(fd);
34 return res;
39 * return NULL or ptr
41 static char *skipBlanks (char **buf) {
42 char *res = *buf;
43 while (*res && (unsigned char)(*res) <= ' ') res++;
44 *buf = res;
45 if (!res[0]) res = NULL;
46 return res;
51 * return NULL or ptr
53 static char *skipLine (char **buf) {
54 char *res = *buf;
55 while (*res && (unsigned char)(*res) != '\n') res++;
56 if (*res) res++;
57 *buf = res;
58 if (!res[0]) res = NULL;
59 return res;
64 * return ptr to the start of the word or NULL
65 * **buf will be changed!
67 static char *getWord (char **buf) {
68 skipBlanks(buf);
69 char *res = *buf;
70 char *end = res;
71 if (*end == '"') {
72 char *s = res;
73 end++;
74 while (*end && *end != '"') {
75 if (*end == '\\') {
76 char ch = end[1]; end += 2;
77 if (!ch) { end--; break; }
78 switch (ch) {
79 case 't': *s++ = '\t'; break;
80 case 'r': *s++ = '\r'; break;
81 case 'n': *s++ = '\n'; break;
82 default: *s++ = ch; break;
84 } else *s++ = *end++;
86 *s = 0;
87 } else {
88 while (*end && (unsigned char)(*end) > ' ') {
89 if (*end == ':') break;
90 end++;
93 if (*end) *end++ = 0;
94 *buf = end;
95 if (!res[0]) res = NULL;
96 return res;
100 /* ok: 0 -- error; -1: ends with dot; 1: normal number; 2: * */
101 static uint16_t getInt (char **buf, int *ok) {
102 *ok = 0;
103 char *word = getWord(buf);
104 if (!word) return 0;
105 if (!strcmp(word, "*")) { *ok = 2; return 0; }
106 uint32_t res = 0;
107 while (*word) {
108 if (*word < '0' || *word > '9') {
109 if (*word == '.') *ok = -1;
110 return (uint16_t)res;
112 res *= 10;
113 res += *word-'0';
114 if (res & 0x10000) return 0;
115 word++;
117 *ok = 1;
118 return (uint16_t)res;
122 static uint16_t parseInt (char **buf, int *ok) {
123 *ok = 0;
124 char *word = *buf;
125 if (!word[0]) return 0;
126 if (!strcmp(word, "*")) { *ok = 2; return 0; }
127 uint32_t res = 0;
128 while (*word) {
129 if (*word < '0' || *word > '9') {
130 if (*word == '.') {
131 *ok = -1;
132 word++;
134 *buf = word;
135 return (uint16_t)res;
137 res *= 10;
138 res += *word-'0';
139 if (res & 0x10000) return 0;
140 word++;
142 *buf = word;
143 *ok = 1;
144 return (uint16_t)res;
148 static uint32_t getIP (char **buf, int *ok) {
149 uint32_t res = 0;
150 *ok = 0;
152 char *word = getWord(buf);
153 if (!word) return 0;
154 if (!strcmp(word, "*")) { *ok = 1; return 0; }
156 int f;
157 for (f = 0; f < 4; f++) {
158 int kk;
159 uint32_t t = parseInt(&word, &kk);
160 /*printf("int: ok=%i, int=%u\n", kk, t);*/
161 if (f == 0 && kk == 2) { *ok = 1; return 0; }
162 if ((f == 3 && kk != 1) || (f != 3 && kk != -1)) return 0;
163 res |= t<<(f*8);
165 *ok = 1;
166 return res;
170 static char *ruleFilePath = NULL;
172 static void parseRulesFile (void) {
173 char *text = NULL, *tpos = NULL;
174 if (!ruleFilePath) return;
175 text = loadFile(ruleFilePath);
176 if (!text) goto error;
178 logMsg(LOGMSG_DEBUG, "parsing rule file: '%s'\n", ruleFilePath);
180 char *word; tpos = text;
181 while ((word = getWord(&tpos))) {
182 #ifdef OPT_RULEPARSER_TEST
183 printf("{%s}\n", word);
184 #endif
185 if (strcmp(word, "newrule")) {
186 skipLine(&tpos);
187 continue;
189 /* scan rule */
190 char *app = NULL;
191 tSessionRule *sRulesH = NULL, *sRulesL = NULL;
192 #ifdef OPT_RULEPARSER_TEST
193 if (sRulesH) printf("!!!\n");
194 #endif
195 while ((word = getWord(&tpos))) {
196 if (!strcmp(word, "endrule")) {
197 #ifdef OPT_RULEPARSER_TEST
198 printf("{%s}\n", word);
199 #endif
200 break;
202 if (!strcmp(word, "app")) {
203 word = getWord(&tpos);
204 if (word && !app) {
205 app = strdup(word);
206 #ifdef OPT_RULEPARSER_TEST
207 printf("{app: %s}\n", app);
208 #endif
210 } else if (!strcmp(word, "rule")) {
211 /* action, proto, ip, port, descr */
212 uint8_t allow, flags = /*IPCR_FLAG_SESSION*/0;
213 uint16_t port;
214 uint32_t ip;
215 do {
216 /* action */
217 word = getWord(&tpos);
218 if (!word) break;
219 if (!strcmp(word, "allow")) allow = 1;
220 else if (!strcmp(word, "deny")) allow = 0;
221 else { skipLine(&tpos); break; }
222 /* proto */
223 word = getWord(&tpos);
224 if (!word) break;
225 if (!strcmp(word, "tcp")) flags |= IPCR_FLAG_TCP;
226 else if (!strcmp(word, "udp")) flags |= IPCR_FLAG_UDP;
227 else if (!strcmp(word, "*")) flags |= IPCR_FLAG_TCP | IPCR_FLAG_UDP;
228 else { skipLine(&tpos); break; }
229 /* ip */
230 int ok;
231 ip = getIP(&tpos, &ok);
232 /*printf("ok=%i; ip=%u\n", ok, ip);*/
233 if (!ok) { skipLine(&tpos); break; }
234 flags |= IPCR_FLAG_IP;
235 if (!ip) flags |= IPCR_FLAG_ANYIP;
236 /* port */
237 port = getInt(&tpos, &ok);
238 /*printf("ok=%i; port=%u\n", ok, port);*/
239 if (!ok) { skipLine(&tpos); break; }
240 flags |= IPCR_FLAG_PORT;
241 if (!port) flags |= IPCR_FLAG_ANYPORT;
242 skipLine(&tpos);
243 #ifdef OPT_RULEPARSER_TEST
244 char dip[512];
245 inet_ntop(AF_INET, &ip, dip, sizeof(dip));
246 printf("rule: allow=%u, flags=0x%02x, port=%u, ip=%s\n", allow, flags, port, dip);
247 #endif
248 addRuleEx(&sRulesH, &sRulesL, ip, port, allow, flags);
249 } while (0);
250 } else skipLine(&tpos);
252 if (app) {
253 if (!strcmp(app, "*") || !strcmp(app, getProcName())) {
254 /* this is our rules! */
255 #ifdef OPT_RULEPARSER_TEST
256 tSessionRule *c = sRulesH;
257 while (c) {
258 char dip[512];
259 inet_ntop(AF_INET, &c->ip, dip, sizeof(dip));
260 printf("OUR rule: allow=%u, flags=0x%02x, port=%u, ip=%s\n", c->allow, c->flags, c->port, dip);
261 c = c->next;
263 #endif
264 clearPermanentRules();
265 /* add to list */
266 if (sRulesLast) sRulesLast->next = sRulesH; else sRules = sRulesH;
267 sRulesLast = sRulesL;
268 sRulesH = NULL;
270 free(app);
272 clearRules(sRulesH);
274 goto done;
275 error:
276 free(ruleFilePath);
277 ruleFilePath = NULL;
278 done:
279 if (text) free(text);
280 #ifdef OPT_RULEPARSER_TEST
281 dumpRules();
282 #endif
286 static void initRuleParser (void) {
287 static int done = 0;
289 if (done) return;
290 #ifdef OPT_RULEPARSER_TEST
291 ruleFilePath = strdup("./umfwGUI/rules.rc");
292 #else
293 char *env = getenv("TUMFW_RULEFILE");
294 if (env) ruleFilePath = strdup(env);
295 #endif
296 parseRulesFile();
297 done = 1;
301 static void updateRuleParser (void) {
302 static int done = 0;
304 if (done) return;
305 done = 1;