123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317 |
- #include "common.h"
- #include "send.h"
- extern int debug;
- /*
- * Routines for dealing with the rewrite rules.
- */
- /* globals */
- typedef struct rule rule;
- #define NSUBEXP 10
- struct rule {
- String *matchre; /* address match */
- String *repl1; /* first replacement String */
- String *repl2; /* second replacement String */
- d_status type; /* type of rule */
- Reprog *program;
- Resub subexp[NSUBEXP];
- rule *next;
- };
- static rule *rulep;
- static rule *rlastp;
- /* predeclared */
- static String *substitute(String *, Resub *, message *);
- static rule *findrule(String *, int);
- /*
- * Get the next token from `line'. The symbol `\l' is replaced by
- * the name of the local system.
- */
- extern String *
- rule_parse(String *line, char *system, int *backl)
- {
- String *token;
- String *expanded;
- char *cp;
- token = s_parse(line, 0);
- if(token == 0)
- return(token);
- if(strchr(s_to_c(token), '\\')==0)
- return(token);
- expanded = s_new();
- for(cp = s_to_c(token); *cp; cp++) {
- if(*cp == '\\') switch(*++cp) {
- case 'l':
- s_append(expanded, system);
- *backl = 1;
- break;
- case '\\':
- s_putc(expanded, '\\');
- break;
- default:
- s_putc(expanded, '\\');
- s_putc(expanded, *cp);
- break;
- } else
- s_putc(expanded, *cp);
- }
- s_free(token);
- s_terminate(expanded);
- return(expanded);
- }
- static int
- getrule(String *line, String *type, char *system)
- {
- rule *rp;
- String *re;
- int backl;
- backl = 0;
- /* get a rule */
- re = rule_parse(s_restart(line), system, &backl);
- if(re == 0)
- return 0;
- rp = (rule *)malloc(sizeof(rule));
- if(rp == 0) {
- perror("getrules:");
- exit(1);
- }
- rp->next = 0;
- s_tolower(re);
- rp->matchre = s_new();
- s_append(rp->matchre, s_to_c(re));
- s_restart(rp->matchre);
- s_free(re);
- s_parse(line, s_restart(type));
- rp->repl1 = rule_parse(line, system, &backl);
- rp->repl2 = rule_parse(line, system, &backl);
- rp->program = 0;
- if(strcmp(s_to_c(type), "|") == 0)
- rp->type = d_pipe;
- else if(strcmp(s_to_c(type), ">>") == 0)
- rp->type = d_cat;
- else if(strcmp(s_to_c(type), "alias") == 0)
- rp->type = d_alias;
- else if(strcmp(s_to_c(type), "translate") == 0)
- rp->type = d_translate;
- else if(strcmp(s_to_c(type), "auth") == 0)
- rp->type = d_auth;
- else {
- s_free(rp->matchre);
- s_free(rp->repl1);
- s_free(rp->repl2);
- free((char *)rp);
- fprint(2,"illegal rewrite rule: %s\n", s_to_c(line));
- return 0;
- }
- if(rulep == 0)
- rulep = rlastp = rp;
- else
- rlastp = rlastp->next = rp;
- return backl;
- }
- /*
- * rules are of the form:
- * <reg exp> <String> <repl exp> [<repl exp>]
- */
- extern int
- getrules(void)
- {
- Biobuf *rfp;
- String *line;
- String *type;
- String *file;
- file = abspath("rewrite", UPASLIB, (String *)0);
- rfp = sysopen(s_to_c(file), "r", 0);
- if(rfp == 0) {
- rulep = 0;
- return -1;
- }
- rlastp = 0;
- line = s_new();
- type = s_new();
- while(s_getline(rfp, s_restart(line)))
- if(getrule(line, type, thissys) && altthissys)
- getrule(s_restart(line), type, altthissys);
- s_free(type);
- s_free(line);
- s_free(file);
- sysclose(rfp);
- return 0;
- }
- /* look up a matching rule */
- static rule *
- findrule(String *addrp, int authorized)
- {
- rule *rp;
- static rule defaultrule;
- if(rulep == 0)
- return &defaultrule;
- for (rp = rulep; rp != 0; rp = rp->next) {
- if(rp->type==d_auth && authorized)
- continue;
- if(rp->program == 0)
- rp->program = regcomp(rp->matchre->base);
- if(rp->program == 0)
- continue;
- memset(rp->subexp, 0, sizeof(rp->subexp));
- if(debug)
- print("matching %s aginst %s\n", s_to_c(addrp), rp->matchre->base);
- if(regexec(rp->program, s_to_c(addrp), rp->subexp, NSUBEXP))
- if(s_to_c(addrp) == rp->subexp[0].sp)
- if((s_to_c(addrp) + strlen(s_to_c(addrp))) == rp->subexp[0].ep)
- return rp;
- }
- return 0;
- }
- /* Transforms the address into a command.
- * Returns: -1 ifaddress not matched by reules
- * 0 ifaddress matched and ok to forward
- * 1 ifaddress matched and not ok to forward
- */
- extern int
- rewrite(dest *dp, message *mp)
- {
- rule *rp; /* rewriting rule */
- String *lower; /* lower case version of destination */
- /*
- * Rewrite the address. Matching is case insensitive.
- */
- lower = s_clone(dp->addr);
- s_tolower(s_restart(lower));
- rp = findrule(lower, dp->authorized);
- if(rp == 0){
- s_free(lower);
- return -1;
- }
- strcpy(s_to_c(lower), s_to_c(dp->addr));
- dp->repl1 = substitute(rp->repl1, rp->subexp, mp);
- dp->repl2 = substitute(rp->repl2, rp->subexp, mp);
- dp->status = rp->type;
- if(debug){
- print("\t->");
- if(dp->repl1)
- print("%s", s_to_c(dp->repl1));
- if(dp->repl2)
- print("%s", s_to_c(dp->repl2));
- print("\n");
- }
- s_free(lower);
- return 0;
- }
- static String *
- substitute(String *source, Resub *subexp, message *mp)
- {
- int i;
- char *s;
- char *sp;
- String *stp;
-
- if(source == 0)
- return 0;
- sp = s_to_c(source);
- /* someplace to put it */
- stp = s_new();
- /* do the substitution */
- while (*sp != '\0') {
- if(*sp == '\\') {
- switch (*++sp) {
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- i = *sp-'0';
- if(subexp[i].sp != 0)
- for (s = subexp[i].sp;
- s < subexp[i].ep;
- s++)
- s_putc(stp, *s);
- break;
- case '\\':
- s_putc(stp, '\\');
- break;
- case '\0':
- sp--;
- break;
- case 's':
- for(s = s_to_c(mp->replyaddr); *s; s++)
- s_putc(stp, *s);
- break;
- case 'p':
- if(mp->bulk)
- s = "bulk";
- else
- s = "normal";
- for(;*s; s++)
- s_putc(stp, *s);
- break;
- default:
- s_putc(stp, *sp);
- break;
- }
- } else if(*sp == '&') {
- if(subexp[0].sp != 0)
- for (s = subexp[0].sp;
- s < subexp[0].ep; s++)
- s_putc(stp, *s);
- } else
- s_putc(stp, *sp);
- sp++;
- }
- s_terminate(stp);
- return s_restart(stp);
- }
- extern void
- regerror(char* s)
- {
- fprint(2, "rewrite: %s\n", s);
- /* make sure the message is seen locally */
- syslog(0, "mail", "error in rewrite: %s", s);
- }
- extern void
- dumprules(void)
- {
- rule *rp;
- for (rp = rulep; rp != 0; rp = rp->next) {
- fprint(2, "'%s'", rp->matchre->base);
- switch (rp->type) {
- case d_pipe:
- fprint(2, " |");
- break;
- case d_cat:
- fprint(2, " >>");
- break;
- case d_alias:
- fprint(2, " alias");
- break;
- case d_translate:
- fprint(2, " translate");
- break;
- default:
- fprint(2, " UNKNOWN");
- break;
- }
- fprint(2, " '%s'", rp->repl1 ? rp->repl1->base:"...");
- fprint(2, " '%s'\n", rp->repl2 ? rp->repl2->base:"...");
- }
- }
|