2005-10-29 16:26:44 +00:00
|
|
|
#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;
|
|
|
|
|
|
2006-02-11 23:38:55 +00:00
|
|
|
file = abspath("rewrite", UPASLIB, (String *)0);
|
2005-10-29 16:26:44 +00:00
|
|
|
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)
|
2006-02-11 23:38:55 +00:00
|
|
|
fprint(2, "matching %s aginst %s\n", s_to_c(addrp), rp->matchre->base);
|
2005-10-29 16:26:44 +00:00
|
|
|
if(regexec(rp->program, s_to_c(addrp), rp->subexp, NSUBEXP))
|
|
|
|
|
if(s_to_c(addrp) == rp->subexp[0].s.sp)
|
|
|
|
|
if((s_to_c(addrp) + strlen(s_to_c(addrp))) == rp->subexp[0].e.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){
|
2006-02-11 23:38:55 +00:00
|
|
|
fprint(2, "\t->");
|
2005-10-29 16:26:44 +00:00
|
|
|
if(dp->repl1)
|
2006-02-11 23:38:55 +00:00
|
|
|
fprint(2, "%s", s_to_c(dp->repl1));
|
2005-10-29 16:26:44 +00:00
|
|
|
if(dp->repl2)
|
2006-02-11 23:38:55 +00:00
|
|
|
fprint(2, "%s", s_to_c(dp->repl2));
|
|
|
|
|
fprint(2, "\n");
|
2005-10-29 16:26:44 +00:00
|
|
|
}
|
|
|
|
|
s_free(lower);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2006-02-11 23:38:55 +00:00
|
|
|
/* stolen from rc/lex.c */
|
|
|
|
|
static int
|
|
|
|
|
idchr(int c)
|
|
|
|
|
{
|
|
|
|
|
return c>' ' && !strchr("!\"#$%&'()+,-./:;<=>?@[\\]^`{|}~", c);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static char*
|
|
|
|
|
getrcvar(char* p, char** rv)
|
|
|
|
|
{
|
|
|
|
|
char* p0;
|
|
|
|
|
char buf[128];
|
|
|
|
|
char* bufe;
|
|
|
|
|
|
|
|
|
|
*rv = 0;
|
|
|
|
|
p0=p;
|
|
|
|
|
bufe=buf+sizeof buf-1;
|
|
|
|
|
while(p<bufe && idchr(*p))
|
|
|
|
|
p++;
|
|
|
|
|
|
|
|
|
|
memcpy(buf, p0, p-p0);
|
|
|
|
|
buf[p-p0]=0;
|
|
|
|
|
*rv = getenv(buf);
|
|
|
|
|
if (debug)
|
|
|
|
|
fprint(2, "varsubst: %s → %s\n", buf, *rv);
|
|
|
|
|
return p;
|
|
|
|
|
}
|
|
|
|
|
|
2005-10-29 16:26:44 +00:00
|
|
|
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].s.sp != 0)
|
|
|
|
|
for (s = subexp[i].s.sp;
|
|
|
|
|
s < subexp[i].e.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;
|
|
|
|
|
}
|
2006-02-11 23:38:55 +00:00
|
|
|
} else if(*sp == '&') {
|
2005-10-29 16:26:44 +00:00
|
|
|
if(subexp[0].s.sp != 0)
|
|
|
|
|
for (s = subexp[0].s.sp;
|
|
|
|
|
s < subexp[0].e.ep; s++)
|
|
|
|
|
s_putc(stp, *s);
|
2006-02-11 23:38:55 +00:00
|
|
|
} else if(*sp == '$') {
|
|
|
|
|
sp = getrcvar(sp+1, &s);
|
|
|
|
|
s_append(stp, s);
|
|
|
|
|
free(s);
|
2005-10-29 16:26:44 +00:00
|
|
|
} else
|
|
|
|
|
s_putc(stp, *sp);
|
|
|
|
|
sp++;
|
|
|
|
|
}
|
|
|
|
|
s_terminate(stp);
|
|
|
|
|
|
|
|
|
|
return s_restart(stp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
extern void
|
|
|
|
|
regerror(char* s)
|
|
|
|
|
{
|
|
|
|
|
fprint(2, "rewrite: %s\n", 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:"...");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|