Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include "common.h"
2
#include "send.h"
3
 
4
extern int debug;
5
 
6
/* 
7
 *	Routines for dealing with the rewrite rules.
8
 */
9
 
10
/* globals */
11
typedef struct rule rule;
12
 
13
#define NSUBEXP 10
14
struct rule {
15
	String *matchre;	/* address match */
16
	String *repl1;		/* first replacement String */
17
	String *repl2;		/* second replacement String */
18
	d_status type;		/* type of rule */
19
	Reprog *program;
20
	Resub subexp[NSUBEXP];
21
	rule *next;
22
};
23
static rule *rulep;
24
static rule *rlastp;
25
 
26
/* predeclared */
27
static String *substitute(String *, Resub *, message *);
28
static rule *findrule(String *, int);
29
 
30
 
31
/*
32
 *  Get the next token from `line'.  The symbol `\l' is replaced by
33
 *  the name of the local system.
34
 */
35
extern String *
36
rule_parse(String *line, char *system, int *backl)
37
{
38
	String *token;
39
	String *expanded;
40
	char *cp;
41
 
42
	token = s_parse(line, 0);
43
	if(token == 0)
44
		return(token);
45
	if(strchr(s_to_c(token), '\\')==0)
46
		return(token);
47
	expanded = s_new();
48
	for(cp = s_to_c(token); *cp; cp++) {
49
		if(*cp == '\\') switch(*++cp) {
50
		case 'l':
51
			s_append(expanded, system);
52
			*backl = 1;
53
			break;
54
		case '\\':
55
			s_putc(expanded, '\\');
56
			break;
57
		default:
58
			s_putc(expanded, '\\');
59
			s_putc(expanded, *cp);
60
			break;
61
		} else
62
			s_putc(expanded, *cp);
63
	}
64
	s_free(token);
65
	s_terminate(expanded);
66
	return(expanded);
67
}
68
 
69
static int
70
getrule(String *line, String *type, char *system)
71
{
72
	rule	*rp;
73
	String	*re;
74
	int	backl;
75
 
76
	backl = 0;
77
 
78
	/* get a rule */
79
	re = rule_parse(s_restart(line), system, &backl);
80
	if(re == 0)
81
		return 0;
82
	rp = (rule *)malloc(sizeof(rule));
83
	if(rp == 0) {
84
		perror("getrules:");
85
		exit(1);
86
	}
87
	rp->next = 0;
88
	s_tolower(re);
89
	rp->matchre = s_new();
90
	s_append(rp->matchre, s_to_c(re));
91
	s_restart(rp->matchre);
92
	s_free(re);
93
	s_parse(line, s_restart(type));
94
	rp->repl1 = rule_parse(line, system, &backl);
95
	rp->repl2 = rule_parse(line, system, &backl);
96
	rp->program = 0;
97
	if(strcmp(s_to_c(type), "|") == 0)
98
		rp->type = d_pipe;
99
	else if(strcmp(s_to_c(type), ">>") == 0)
100
		rp->type = d_cat;
101
	else if(strcmp(s_to_c(type), "alias") == 0)
102
		rp->type = d_alias;
103
	else if(strcmp(s_to_c(type), "translate") == 0)
104
		rp->type = d_translate;
105
	else if(strcmp(s_to_c(type), "auth") == 0)
106
		rp->type = d_auth;
107
	else {
108
		s_free(rp->matchre);
109
		s_free(rp->repl1);
110
		s_free(rp->repl2);
111
		free((char *)rp);
112
		fprint(2,"illegal rewrite rule: %s\n", s_to_c(line));
113
		return 0;
114
	}
115
	if(rulep == 0)
116
		rulep = rlastp = rp;
117
	else
118
		rlastp = rlastp->next = rp;
119
	return backl;
120
}
121
 
122
/*
123
 *  rules are of the form:
124
 *	<reg exp> <String> <repl exp> [<repl exp>]
125
 */
126
extern int
127
getrules(void)
128
{
129
	Biobuf	*rfp;
130
	String	*line;
131
	String	*type;
132
	String	*file;
133
 
134
	file = abspath("rewrite", UPASLIB, (String *)0);
135
	rfp = sysopen(s_to_c(file), "r", 0);
136
	if(rfp == 0) {
137
		rulep = 0;
138
		return -1;
139
	}
140
	rlastp = 0;
141
	line = s_new();
142
	type = s_new();
143
	while(s_getline(rfp, s_restart(line)))
144
		if(getrule(line, type, thissys) && altthissys)
145
			getrule(s_restart(line), type, altthissys);
146
	s_free(type);
147
	s_free(line);
148
	s_free(file);
149
	sysclose(rfp);
150
	return 0;
151
}
152
 
153
/* look up a matching rule */
154
static rule *
155
findrule(String *addrp, int authorized)
156
{
157
	rule *rp;
158
	static rule defaultrule;
159
 
160
	if(rulep == 0)
161
		return &defaultrule;
162
	for (rp = rulep; rp != 0; rp = rp->next) {
163
		if(rp->type==d_auth && authorized)
164
			continue;
165
		if(rp->program == 0)
166
			rp->program = regcomp(rp->matchre->base);
167
		if(rp->program == 0)
168
			continue;
169
		memset(rp->subexp, 0, sizeof(rp->subexp));
170
		if(debug)
171
			fprint(2, "matching %s against %s\n", s_to_c(addrp),
172
				rp->matchre->base);
173
		if(regexec(rp->program, s_to_c(addrp), rp->subexp, NSUBEXP))
174
		if(s_to_c(addrp) == rp->subexp[0].sp)
175
		if((s_to_c(addrp) + strlen(s_to_c(addrp))) == rp->subexp[0].ep)
176
			return rp;
177
	}
178
	return 0;
179
}
180
 
181
/*  Transforms the address into a command.
182
 *  Returns:	-1 ifaddress not matched by reules
183
 *		 0 ifaddress matched and ok to forward
184
 *		 1 ifaddress matched and not ok to forward
185
 */
186
extern int
187
rewrite(dest *dp, message *mp)
188
{
189
	rule *rp;		/* rewriting rule */
190
	String *lower;		/* lower case version of destination */
191
 
192
	/*
193
	 *  Rewrite the address.  Matching is case insensitive.
194
	 */
195
	lower = s_clone(dp->addr);
196
	s_tolower(s_restart(lower));
197
	rp = findrule(lower, dp->authorized);
198
	if(rp == 0){
199
		s_free(lower);
200
		return -1;
201
	}
202
	strcpy(s_to_c(lower), s_to_c(dp->addr));
203
	dp->repl1 = substitute(rp->repl1, rp->subexp, mp);
204
	dp->repl2 = substitute(rp->repl2, rp->subexp, mp);
205
	dp->status = rp->type;
206
	if(debug){
207
		fprint(2, "\t->");
208
		if(dp->repl1)
209
			fprint(2, "%s", s_to_c(dp->repl1));
210
		if(dp->repl2)
211
			fprint(2, "%s", s_to_c(dp->repl2));
212
		fprint(2, "\n");
213
	}
214
	s_free(lower);
215
	return 0;
216
}
217
 
218
static String *
219
substitute(String *source, Resub *subexp, message *mp)
220
{
221
	int i;
222
	char *s;
223
	char *sp;
224
	String *stp;
225
 
226
	if(source == 0)
227
		return 0;
228
	sp = s_to_c(source);
229
 
230
	/* someplace to put it */
231
	stp = s_new();
232
 
233
	/* do the substitution */
234
	while (*sp != '\0') {
235
		if(*sp == '\\') {
236
			switch (*++sp) {
237
			case '0': case '1': case '2': case '3': case '4':
238
			case '5': case '6': case '7': case '8': case '9':
239
				i = *sp-'0';
240
				if(subexp[i].sp != 0)
241
					for (s = subexp[i].sp;
242
					     s < subexp[i].ep;
243
					     s++)
244
						s_putc(stp, *s);
245
				break;
246
			case '\\':
247
				s_putc(stp, '\\');
248
				break;
249
			case '\0':
250
				sp--;
251
				break;
252
			case 's':
253
				for(s = s_to_c(mp->replyaddr); *s; s++)
254
					s_putc(stp, *s);
255
				break;
256
			case 'p':
257
				if(mp->bulk)
258
					s = "bulk";
259
				else
260
					s = "normal";
261
				for(;*s; s++)
262
					s_putc(stp, *s);
263
				break;
264
			default:
265
				s_putc(stp, *sp);
266
				break;
267
			}
268
		} else if(*sp == '&') {				
269
			if(subexp[0].sp != 0)
270
				for (s = subexp[0].sp;
271
				     s < subexp[0].ep; s++)
272
					s_putc(stp, *s);
273
		} else
274
			s_putc(stp, *sp);
275
		sp++;
276
	}
277
	s_terminate(stp);
278
 
279
	return s_restart(stp);
280
}
281
 
282
extern void
283
regerror(char* s)
284
{
285
	fprint(2, "rewrite: %s\n", s);
286
	/* make sure the message is seen locally */
287
	syslog(0, "mail", "regexp error in rewrite: %s", s);
288
}
289
 
290
extern void
291
dumprules(void)
292
{
293
	rule *rp;
294
 
295
	for (rp = rulep; rp != 0; rp = rp->next) {
296
		fprint(2, "'%s'", rp->matchre->base);
297
		switch (rp->type) {
298
		case d_pipe:
299
			fprint(2, " |");
300
			break;
301
		case d_cat:
302
			fprint(2, " >>");
303
			break;
304
		case d_alias:
305
			fprint(2, " alias");
306
			break;
307
		case d_translate:
308
			fprint(2, " translate");
309
			break;
310
		default:
311
			fprint(2, " UNKNOWN");
312
			break;
313
		}
314
		fprint(2, " '%s'", rp->repl1 ? rp->repl1->base:"...");
315
		fprint(2, " '%s'\n", rp->repl2 ? rp->repl2->base:"...");
316
	}
317
}
318