rewrite.c 6.2 KB

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