comparison src/context.cpp @ 75:1142e46be550

start coding on new config syntax
author carl
date Wed, 13 Jul 2005 23:04:14 -0700
parents b7449114ebb0
children 81f1e400e8ab
comparison
equal deleted inserted replaced
74:b7449114ebb0 75:1142e46be550
26 char *token_html_tags; 26 char *token_html_tags;
27 char *token_ignore; 27 char *token_ignore;
28 char *token_include; 28 char *token_include;
29 char *token_inherit; 29 char *token_inherit;
30 char *token_lbrace; 30 char *token_lbrace;
31 char *token_mailhost;
31 char *token_many; 32 char *token_many;
32 char *token_off; 33 char *token_off;
34 char *token_ok2;
33 char *token_ok; 35 char *token_ok;
34 char *token_ok2;
35 char *token_on; 36 char *token_on;
36 char *token_rbrace; 37 char *token_rbrace;
37 char *token_semi; 38 char *token_semi;
38 char *token_soft; 39 char *token_soft;
40 char *token_substitute;
39 char *token_tld; 41 char *token_tld;
40 char *token_unknown; 42 char *token_unknown;
41 char *token_white; 43 char *token_white;
42 44
43 string_set all_strings; // owns all the strings, only modified by the config loader thread 45 string_set all_strings; // owns all the strings, only modified by the config loader thread
46 const int maxlen = 1000;
44 47
45 DNSBL::DNSBL(char *n, char *s, char *m) { 48 DNSBL::DNSBL(char *n, char *s, char *m) {
46 name = n; 49 name = n;
47 suffix = s; 50 suffix = s;
48 message = m; 51 message = m;
72 default_context = con; 75 default_context = con;
73 } 76 }
74 } 77 }
75 78
76 79
77 CONTEXTP CONFIG::find_context(char *to, char *from) { 80 void CONFIG::add_to(char *to, CONTEXTP con) {
78 CONTEXTP con = NULL; 81 context_map::iterator i = env_to.find(to);
79 context_map::iterator i = env_to.find(from);
80 if (i != env_to.end()) { 82 if (i != env_to.end()) {
81 con = (*i).second; 83 CONTEXTP c = (*i).second;
82 return con->find_from_context(from); 84 if ((c != con) && (c != con->get_parent())) {
83 } 85 char oldname[maxlen];
86 char newname[maxlen];
87 char *oldn = c->get_full_name(oldname, maxlen);
88 char *newn = con->get_full_name(newname, maxlen);
89 char buf[maxlen*3];
90 snprintf(buf, maxlen*3, "both %s and %s claim envelope to %s, the second one wins", oldn, newn, to);
91 my_syslog(buf);
92 }
93 }
94 env_to[to] = con;
95 }
96
97
98 CONTEXTP CONFIG::find_context(char *to) {
99 context_map::iterator i = env_to.find(to);
100 if (i != env_to.end()) return (*i).second; // found user@domain.tld key
84 char *x = strchr(to, '@'); 101 char *x = strchr(to, '@');
85 if (x) { 102 if (x) {
86 x++; 103 x++;
87 i = env_to.find(x); 104 i = env_to.find(x);
88 if (i != env_to.end()) { 105 if (i != env_to.end()) return (*i).second; // found domain.tld key
89 con = (*i).second; 106 char y = *x;
90 return con->find_from_context(from); 107 *x = '\0';
91 } 108 i = env_to.find(to);
92 } 109 *x = y;
93 return default_context->find_from_context(from); 110 if (i != env_to.end()) return (*i).second; // found user@ key
111 }
112 return default_context;
94 } 113 }
95 114
96 115
97 void CONFIG::dump() { 116 void CONFIG::dump() {
98 if (default_context) default_context->dump(); 117 if (default_context) default_context->dump();
99 for (context_list::iterator i=contexts.begin(); i!=contexts.end(); i++) { 118 for (context_list::iterator i=contexts.begin(); i!=contexts.end(); i++) {
100 CONTEXTP c = *i; 119 CONTEXTP c = *i;
101 CONTEXTP p = c->get_parent(); 120 CONTEXTP p = c->get_parent();
102 if (!p && (c != default_context)) c->dump(); 121 if (!p && (c != default_context)) c->dump();
122 }
123 char buf[maxlen];
124 for (context_map::iterator i=env_to.begin(); i!=env_to.end(); i++) {
125 char *to = (*i).first;
126 CONTEXTP con = (*i).second;
127 printf("// envelope to %s \t-> context %s \n", to, con->get_full_name(buf,maxlen));
103 } 128 }
104 } 129 }
105 130
106 131
107 CONTEXT::CONTEXT(CONTEXTP parent_, char *name_) { 132 CONTEXT::CONTEXT(CONTEXTP parent_, char *name_) {
109 name = name_; 134 name = name_;
110 env_from_default = (parent) ? token_inherit : token_unknown; 135 env_from_default = (parent) ? token_inherit : token_unknown;
111 content_filtering = (parent) ? parent->content_filtering : false; 136 content_filtering = (parent) ? parent->content_filtering : false;
112 content_suffix = NULL; 137 content_suffix = NULL;
113 content_message = NULL; 138 content_message = NULL;
114 host_limit = 0; 139 host_limit = (parent) ? parent->host_limit : 0;
115 host_limit_message = NULL; 140 host_limit_message = NULL;
116 host_random = false; 141 host_random = (parent) ? parent->host_random : false;
117 tag_limit = 0; 142 tag_limit = (parent) ? parent->tag_limit : 0;
118 tag_limit_message = NULL; 143 tag_limit_message = NULL;
119 } 144 }
120 145
121 146
122 CONTEXT::~CONTEXT() { 147 CONTEXT::~CONTEXT() {
128 } 153 }
129 154
130 155
131 char *CONTEXT::get_full_name(char *buffer, int size) { 156 char *CONTEXT::get_full_name(char *buffer, int size) {
132 if (!parent) return name; 157 if (!parent) return name;
133 const int maxlen = 1000;
134 char buf[maxlen]; 158 char buf[maxlen];
135 snprintf(buffer, size, "%s.%s", parent->get_full_name(buf, maxlen), name); 159 snprintf(buffer, size, "%s.%s", parent->get_full_name(buf, maxlen), name);
136 return buffer; 160 return buffer;
137 } 161 }
138 162
139 163
140 bool CONTEXT::cover_env_to(char *to) { 164 bool CONTEXT::cover_env_to(char *to) {
141 const int maxlen = 1000;
142 char buffer[maxlen]; 165 char buffer[maxlen];
143 char *x = strchr(to, '@'); 166 char *x = strchr(to, '@');
144 if (x) x++; 167 if (x) x++;
145 else x = to; 168 else x = to;
169 if (*x == '\0') return true; // always allow covering addresses with no domain name, eg abuse@
146 string_set::iterator i = env_to.find(x); 170 string_set::iterator i = env_to.find(x);
147 if (i != env_to.end()) return true; 171 if (i != env_to.end()) return true;
148 return (parent) ? parent->cover_env_to(to) : false; 172 return false;
149 } 173 }
150 174
151 175
152 char *CONTEXT::find_from(char *from) { 176 char *CONTEXT::find_from(char *from) {
153 // do we have a white/black/unknown for this full from value?
154 string_map::iterator i = env_from.find(from); 177 string_map::iterator i = env_from.find(from);
155 if (i != env_from.end()) return (*i).second; 178 if (i != env_from.end()) return (*i).second; // found user@domain.tld key
156 // do we have a white/black/unknown for the source domain name?
157 char *x = strchr(from, '@'); 179 char *x = strchr(from, '@');
158 if (x) { 180 if (x) {
159 x++; 181 x++;
160 i = env_from.find(x); 182 i = env_from.find(x);
161 if (i != env_from.end()) return (*i).second; 183 if (i != env_from.end()) return (*i).second; // found domain.tld key
184 char y = *x;
185 *x = '\0';
186 i = env_from.find(from);
187 *x = y;
188 if (i != env_from.end()) return (*i).second; // found user@ key
162 } 189 }
163 if ((env_from_default == token_inherit) && parent) { 190 if ((env_from_default == token_inherit) && parent) {
164 return parent->find_from(from); 191 return parent->find_from(from);
165 } 192 }
166 return env_from_default; 193 return (env_from_default == token_inherit) ? token_unknown : env_from_default;
167 } 194 }
168 195
169 196
170 CONTEXTP CONTEXT::find_from_context(char *from) { 197 CONTEXTP CONTEXT::find_context(char *from) {
171 // do we have a special child context for this full from value? 198 context_map::iterator i = env_from_context.find(from);
172 context_map::iterator j = env_from_context.find(from); 199 if (i != env_from_context.end()) return (*i).second; // found user@domain.tld key
173 if (j != env_from_context.end()) {
174 CONTEXTP con = (*j).second;
175 return con->find_from_context(from);
176 }
177 char *x = strchr(from, '@'); 200 char *x = strchr(from, '@');
178 if (x) { 201 if (x) {
179 x++; 202 x++;
180 // do we have a special context for the source domain name? 203 i = env_from_context.find(x);
181 j = env_from_context.find(x); 204 if (i != env_from_context.end()) return (*i).second; // found domain.tld key
182 if (j != env_from_context.end()) { 205 char y = *x;
183 CONTEXTP con = (*j).second; 206 *x = '\0';
184 return con->find_from_context(from); 207 i = env_from_context.find(from);
185 } 208 *x = y;
209 if (i != env_from_context.end()) return (*i).second; // found user@ key
186 } 210 }
187 return this; 211 return this;
188 } 212 }
189 213
190 214
214 } 238 }
215 } 239 }
216 240
217 241
218 void CONTEXT::dump(int level) { 242 void CONTEXT::dump(int level) {
219 const int maxlen = 1000;
220 char indent[maxlen]; 243 char indent[maxlen];
221 int i = min(maxlen-1, level*4); 244 int i = min(maxlen-1, level*4);
222 memset(indent, ' ', i); 245 memset(indent, ' ', i);
223 indent[i] = '\0'; 246 indent[i] = '\0';
224 printf("%s context %s { \n", indent, name); 247 char buf[maxlen];
248 char *fullname = get_full_name(buf,maxlen);
249 printf("%s context %s { \t// %s\n", indent, name, fullname);
225 250
226 for (dnsblp_map::iterator i=dnsbl_names.begin(); i!=dnsbl_names.end(); i++) { 251 for (dnsblp_map::iterator i=dnsbl_names.begin(); i!=dnsbl_names.end(); i++) {
227 char *n = (*i).first; 252 char *n = (*i).first;
228 DNSBL &d = *(*i).second; 253 DNSBL &d = *(*i).second;
229 printf("%s dnsbl %s %s \"%s\"; \n", indent, n, d.suffix, d.message); 254 printf("%s dnsbl %s %s \"%s\"; \n", indent, n, d.suffix, d.message);
274 } 299 }
275 else { 300 else {
276 printf("%s host_limit off; \n", indent); 301 printf("%s host_limit off; \n", indent);
277 } 302 }
278 if (tag_limit_message) { 303 if (tag_limit_message) {
279 printf("%s tag_limit on %d \"%s\"; \n", indent, tag_limit, tag_limit_message); 304 printf("%s html_limit on %d \"%s\"; \n", indent, tag_limit, tag_limit_message);
280 } 305 }
281 else { 306 else {
282 printf("%s tag_limit off; \n", indent); 307 printf("%s html_limit off; \n", indent);
283 } 308 }
284 printf("%s }; \n", indent); 309 printf("%s }; \n", indent);
285 } 310 }
286 else { 311 else {
287 printf("%s content off {}; \n", indent, env_from_default); 312 printf("%s content off {}; \n", indent, env_from_default);
288 } 313 }
289 314
290 printf("%s env_to { \n", indent); 315 printf("%s env_to { \t// %s\n", indent, fullname);
291 for (string_set::iterator i=env_to.begin(); i!=env_to.end(); i++) { 316 for (string_set::iterator i=env_to.begin(); i!=env_to.end(); i++) {
292 printf("%s %s; \n", indent, *i); 317 printf("%s %s; \n", indent, *i);
293 } 318 }
294 printf("%s }; \n", indent); 319 printf("%s }; \n", indent);
295 320
296 for (context_map::iterator i=children.begin(); i!=children.end(); i++) { 321 for (context_map::iterator i=children.begin(); i!=children.end(); i++) {
297 CONTEXTP c = (*i).second; 322 CONTEXTP c = (*i).second;
298 c->dump(level+1); 323 c->dump(level+1);
299 } 324 }
300 325
301 printf("%s env_from %s { \n", indent, env_from_default); 326 printf("%s env_from %s { \t// %s\n", indent, env_from_default, fullname);
302 if (!env_from.empty()) { 327 if (!env_from.empty()) {
303 printf("%s // white/black/unknown \n", indent); 328 printf("%s // white/black/unknown \n", indent);
304 for (string_map::iterator i=env_from.begin(); i!=env_from.end(); i++) { 329 for (string_map::iterator i=env_from.begin(); i!=env_from.end(); i++) {
305 char *f = (*i).first; 330 char *f = (*i).first;
306 char *t = (*i).second; 331 char *t = (*i).second;
307 printf("%s %s \t %s; \n", indent, f, t); 332 printf("%s %s \t%s; \n", indent, f, t);
308 } 333 }
309 } 334 }
310 if (!env_from_context.empty()) { 335 if (!env_from_context.empty()) {
311 printf("%s // child contexts \n", indent); 336 printf("%s // child contexts \n", indent);
312 for (context_map::iterator j=env_from_context.begin(); j!=env_from_context.end(); j++) { 337 for (context_map::iterator j=env_from_context.begin(); j!=env_from_context.end(); j++) {
313 char *f = (*j).first; 338 char *f = (*j).first;
314 CONTEXTP t = (*j).second; 339 CONTEXTP t = (*j).second;
315 printf("%s %s \t %s; \n", indent, f, t->name); 340 printf("%s %s \t%s; \n", indent, f, t->name);
316 } 341 }
317 } 342 }
318 printf("%s }; \n", indent); 343 printf("%s }; \n", indent);
319 344
320 printf("%s }; \n", indent); 345 printf("%s }; \n", indent);
400 425
401 //////////////////////////////////////////////// 426 ////////////////////////////////////////////////
402 // 427 //
403 bool parse_content(TOKEN &tok, CONFIG &dc, CONTEXT &me); 428 bool parse_content(TOKEN &tok, CONFIG &dc, CONTEXT &me);
404 bool parse_content(TOKEN &tok, CONFIG &dc, CONTEXT &me) { 429 bool parse_content(TOKEN &tok, CONFIG &dc, CONTEXT &me) {
430 bool topdefault = (!me.get_parent()) && (!dc.default_context);
405 char *setting = tok.next(); 431 char *setting = tok.next();
406 if (setting == token_on) { 432 if (setting == token_on) {
407 me.set_content_filtering(true); 433 me.set_content_filtering(true);
408 } 434 }
409 else if (setting == token_off) { 435 else if (setting == token_off) {
416 if (!tsa(tok, token_lbrace)) return false; 442 if (!tsa(tok, token_lbrace)) return false;
417 while (true) { 443 while (true) {
418 char *have = tok.next(); 444 char *have = tok.next();
419 if (!have) break; 445 if (!have) break;
420 if (have == token_filter) { 446 if (have == token_filter) {
421 me.set_content_suffix(tok.next()); 447 char *suffix = tok.next();
422 me.set_content_message(tok.next()); 448 char *messag = tok.next();
449 if (topdefault) {
450 me.set_content_suffix(suffix);
451 me.set_content_message(messag);
452 }
423 if (!tsa(tok, token_semi)) return false; 453 if (!tsa(tok, token_semi)) return false;
454 if (!topdefault) tok.token_error("content filters may only be speciried in the top default context");
424 } 455 }
425 else if (have == token_ignore) { 456 else if (have == token_ignore) {
426 if (!tsa(tok, token_lbrace)) return false; 457 if (!tsa(tok, token_lbrace)) return false;
427 while (true) { 458 while (true) {
428 if (!have) break; 459 if (!have) break;
443 if (!have) break; 474 if (!have) break;
444 if (have == token_rbrace) { 475 if (have == token_rbrace) {
445 break; // done 476 break; // done
446 } 477 }
447 else { 478 else {
448 me.add_tld(have); 479 if (topdefault) me.add_tld(have);
449 } 480 }
450 } 481 }
451 if (!tsa(tok, token_semi)) return false; 482 if (!tsa(tok, token_semi)) return false;
483 if (!topdefault) tok.token_error("tld values may only be specified in the top default context");
452 } 484 }
453 else if (have == token_html_limit) { 485 else if (have == token_html_limit) {
454 have = tok.next(); 486 have = tok.next();
455 if (have == token_on) { 487 if (have == token_on) {
456 me.set_tag_limit(tok.nextint()); 488 me.set_tag_limit(tok.nextint());
473 if (!have) break; 505 if (!have) break;
474 if (have == token_rbrace) { 506 if (have == token_rbrace) {
475 break; // done 507 break; // done
476 } 508 }
477 else { 509 else {
478 me.add_tag(have); 510 if (topdefault) me.add_tag(have);
479 } 511 }
480 } 512 }
481 if (!tsa(tok, token_semi)) return false; 513 if (!tsa(tok, token_semi)) return false;
514 if (!topdefault) tok.token_error("html tags may only be specified in the top default context");
482 } 515 }
483 else if (have == token_host_limit) { 516 else if (have == token_host_limit) {
484 have = tok.next(); 517 have = tok.next();
485 if (have == token_on) { 518 if (have == token_on) {
486 me.set_host_limit(tok.nextint()); 519 me.set_host_limit(tok.nextint());
550 me.add_to(have); 583 me.add_to(have);
551 dc.add_to(have, &me); 584 dc.add_to(have, &me);
552 } 585 }
553 } 586 }
554 } 587 }
588 else if (have == token_substitute) {
589 if (tok.next() == token_mailhost) {
590 have = tok.next();
591 if (keeping) {
592 if (me.allow_env_to(have)) {
593 me.add_to(have);
594 dc.add_to(have, &me);
595 }
596 }
597 }
598 }
555 tok.skipeol(); 599 tok.skipeol();
556 } 600 }
557 } 601 }
558 else if (me.allow_env_to(have)) { 602 else if (me.allow_env_to(have)) {
559 me.add_to(have); 603 me.add_to(have);
560 dc.add_to(have, &me); 604 dc.add_to(have, &me);
561 } 605 }
562 else { 606 else {
563 tok.token_error("valid env_to address or domain name", have); 607 tok.token_error("user@ or user@domain.tld or domain.tld where domain.tld allowed by parent context", have);
564 return false; 608 return false;
565 } 609 }
566 } 610 }
567 return tsa(tok, token_semi); 611 return tsa(tok, token_semi);
568 } 612 }
571 //////////////////////////////////////////////// 615 ////////////////////////////////////////////////
572 // 616 //
573 bool parse_envfrom(TOKEN &tok, CONFIG &dc, CONTEXT &me); 617 bool parse_envfrom(TOKEN &tok, CONFIG &dc, CONTEXT &me);
574 bool parse_envfrom(TOKEN &tok, CONFIG &dc, CONTEXT &me) { 618 bool parse_envfrom(TOKEN &tok, CONFIG &dc, CONTEXT &me) {
575 char *st = tok.next(); 619 char *st = tok.next();
576 if ((st == token_black) || (st == token_white) || (st == token_unknown)) { 620 if ((st == token_black) || (st == token_white) || (st == token_unknown) || (st == token_inherit)) {
577 me.set_from_default(st); 621 me.set_from_default(st);
578 } 622 }
579 else { 623 else {
580 tok.push(st); 624 tok.push(st);
581 } 625 }
610 continue; 654 continue;
611 } 655 }
612 if (have == token_envfrom) { 656 if (have == token_envfrom) {
613 have = tok.next(); 657 have = tok.next();
614 if (keeping) { 658 if (keeping) {
659 me.add_from(have, (many) ? token_black : token_white);
660 }
661 }
662 else if (have == token_substitute) {
663 if (tok.next() == token_mailhost) {
664 have = tok.next();
615 me.add_from(have, (many) ? token_black : token_white); 665 me.add_from(have, (many) ? token_black : token_white);
616 } 666 }
617 } 667 }
618 tok.skipeol(); 668 tok.skipeol();
619 } 669 }
728 token_html_tags = register_string("html_tags"); 778 token_html_tags = register_string("html_tags");
729 token_ignore = register_string("ignore"); 779 token_ignore = register_string("ignore");
730 token_include = register_string("include"); 780 token_include = register_string("include");
731 token_inherit = register_string("inherit"); 781 token_inherit = register_string("inherit");
732 token_lbrace = register_string("{"); 782 token_lbrace = register_string("{");
783 token_mailhost = register_string("mail_host");
733 token_many = register_string("many"); 784 token_many = register_string("many");
734 token_off = register_string("off"); 785 token_off = register_string("off");
735 token_ok = register_string("ok"); 786 token_ok = register_string("ok");
736 token_ok2 = register_string("ok2"); 787 token_ok2 = register_string("ok2");
737 token_on = register_string("on"); 788 token_on = register_string("on");
738 token_rbrace = register_string("}"); 789 token_rbrace = register_string("}");
739 token_semi = register_string(";"); 790 token_semi = register_string(";");
740 token_soft = register_string("soft"); 791 token_soft = register_string("soft");
792 token_substitute = register_string("substitute");
741 token_tld = register_string("tld"); 793 token_tld = register_string("tld");
742 token_unknown = register_string("unknown"); 794 token_unknown = register_string("unknown");
743 token_white = register_string("white"); 795 token_white = register_string("white");
744 } 796 }