smtpd.y 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. %{
  2. #include "common.h"
  3. #include <ctype.h>
  4. #include "smtpd.h"
  5. #define YYSTYPE yystype
  6. typedef struct quux yystype;
  7. struct quux {
  8. String *s;
  9. int c;
  10. };
  11. Biobuf *yyfp;
  12. YYSTYPE *bang;
  13. extern Biobuf bin;
  14. extern int debug;
  15. YYSTYPE cat(YYSTYPE*, YYSTYPE*, YYSTYPE*, YYSTYPE*, YYSTYPE*, YYSTYPE*, YYSTYPE*);
  16. int yyparse(void);
  17. int yylex(void);
  18. YYSTYPE anonymous(void);
  19. %}
  20. %term SPACE
  21. %term CNTRL
  22. %term CRLF
  23. %start conversation
  24. %%
  25. conversation : cmd
  26. | conversation cmd
  27. ;
  28. cmd : error
  29. | 'h' 'e' 'l' 'o' spaces sdomain CRLF
  30. { hello($6.s, 0); }
  31. | 'e' 'h' 'l' 'o' spaces sdomain CRLF
  32. { hello($6.s, 1); }
  33. | 'm' 'a' 'i' 'l' spaces 'f' 'r' 'o' 'm' ':' spath CRLF
  34. { sender($11.s); }
  35. | 'm' 'a' 'i' 'l' spaces 'f' 'r' 'o' 'm' ':' spath spaces 'a' 'u' 't' 'h' '=' sauth CRLF
  36. { sender($11.s); }
  37. | 'r' 'c' 'p' 't' spaces 't' 'o' ':' spath CRLF
  38. { receiver($9.s); }
  39. | 'd' 'a' 't' 'a' CRLF
  40. { data(); }
  41. | 'r' 's' 'e' 't' CRLF
  42. { reset(); }
  43. | 's' 'e' 'n' 'd' spaces 'f' 'r' 'o' 'm' ':' spath CRLF
  44. { sender($11.s); }
  45. | 's' 'o' 'm' 'l' spaces 'f' 'r' 'o' 'm' ':' spath CRLF
  46. { sender($11.s); }
  47. | 's' 'a' 'm' 'l' spaces 'f' 'r' 'o' 'm' ':' spath CRLF
  48. { sender($11.s); }
  49. | 'v' 'r' 'f' 'y' spaces string CRLF
  50. { verify($6.s); }
  51. | 'e' 'x' 'p' 'n' spaces string CRLF
  52. { verify($6.s); }
  53. | 'h' 'e' 'l' 'p' CRLF
  54. { help(0); }
  55. | 'h' 'e' 'l' 'p' spaces string CRLF
  56. { help($6.s); }
  57. | 'n' 'o' 'o' 'p' CRLF
  58. { noop(); }
  59. | 'q' 'u' 'i' 't' CRLF
  60. { quit(); }
  61. | 't' 'u' 'r' 'n' CRLF
  62. { turn(); }
  63. | 's' 't' 'a' 'r' 't' 't' 'l' 's' CRLF
  64. { starttls(); }
  65. | 'a' 'u' 't' 'h' spaces name spaces string CRLF
  66. { auth($6.s, $8.s); }
  67. | 'a' 'u' 't' 'h' spaces name CRLF
  68. { auth($6.s, nil); }
  69. | CRLF
  70. { reply("501 illegal command or bad syntax\r\n"); }
  71. ;
  72. path : '<' '>' ={ $$ = anonymous(); }
  73. | '<' mailbox '>' ={ $$ = $2; }
  74. | '<' a_d_l ':' mailbox '>' ={ $$ = cat(&$2, bang, &$4, 0, 0 ,0, 0); }
  75. ;
  76. spath : path ={ $$ = $1; }
  77. | spaces path ={ $$ = $2; }
  78. ;
  79. auth : path ={ $$ = $1; }
  80. | mailbox ={ $$ = $1; }
  81. ;
  82. sauth : auth ={ $$ = $1; }
  83. | spaces auth ={ $$ = $2; }
  84. ;
  85. ;
  86. a_d_l : at_domain ={ $$ = cat(&$1, 0, 0, 0, 0 ,0, 0); }
  87. | at_domain ',' a_d_l ={ $$ = cat(&$1, bang, &$3, 0, 0, 0, 0); }
  88. ;
  89. at_domain : '@' domain ={ $$ = cat(&$2, 0, 0, 0, 0 ,0, 0); }
  90. ;
  91. sdomain : domain ={ $$ = $1; }
  92. | domain spaces ={ $$ = $1; }
  93. ;
  94. domain : element ={ $$ = cat(&$1, 0, 0, 0, 0 ,0, 0); }
  95. | element '.' ={ $$ = cat(&$1, 0, 0, 0, 0 ,0, 0); }
  96. | element '.' domain ={ $$ = cat(&$1, &$2, &$3, 0, 0 ,0, 0); }
  97. ;
  98. element : name ={ $$ = cat(&$1, 0, 0, 0, 0 ,0, 0); }
  99. | '#' number ={ $$ = cat(&$1, &$2, 0, 0, 0 ,0, 0); }
  100. | '[' ']' ={ $$ = cat(&$1, &$2, 0, 0, 0 ,0, 0); }
  101. | '[' dotnum ']' ={ $$ = cat(&$1, &$2, &$3, 0, 0 ,0, 0); }
  102. ;
  103. mailbox : local_part ={ $$ = cat(&$1, 0, 0, 0, 0 ,0, 0); }
  104. | local_part '@' domain ={ $$ = cat(&$3, bang, &$1, 0, 0 ,0, 0); }
  105. ;
  106. local_part : dot_string ={ $$ = cat(&$1, 0, 0, 0, 0 ,0, 0); }
  107. | quoted_string ={ $$ = cat(&$1, 0, 0, 0, 0 ,0, 0); }
  108. ;
  109. name : let_dig ={ $$ = cat(&$1, 0, 0, 0, 0 ,0, 0); }
  110. | let_dig ld_str ={ $$ = cat(&$1, &$2, 0, 0, 0 ,0, 0); }
  111. | let_dig ldh_str ld_str ={ $$ = cat(&$1, &$2, &$3, 0, 0 ,0, 0); }
  112. ;
  113. ld_str : let_dig
  114. | let_dig ld_str ={ $$ = cat(&$1, &$2, 0, 0, 0 ,0, 0); }
  115. ;
  116. ldh_str : hunder
  117. | ld_str hunder ={ $$ = cat(&$1, &$2, 0, 0, 0 ,0, 0); }
  118. | ldh_str ld_str hunder ={ $$ = cat(&$1, &$2, &$3, 0, 0 ,0, 0); }
  119. ;
  120. let_dig : a
  121. | d
  122. ;
  123. dot_string : string ={ $$ = cat(&$1, 0, 0, 0, 0 ,0, 0); }
  124. | string '.' dot_string ={ $$ = cat(&$1, &$2, &$3, 0, 0 ,0, 0); }
  125. ;
  126. string : char ={ $$ = cat(&$1, 0, 0, 0, 0 ,0, 0); }
  127. | string char ={ $$ = cat(&$1, &$2, 0, 0, 0 ,0, 0); }
  128. ;
  129. quoted_string : '"' qtext '"' ={ $$ = cat(&$1, &$2, &$3, 0, 0 ,0, 0); }
  130. ;
  131. qtext : '\\' x ={ $$ = cat(&$2, 0, 0, 0, 0 ,0, 0); }
  132. | qtext '\\' x ={ $$ = cat(&$1, &$3, 0, 0, 0 ,0, 0); }
  133. | q
  134. | qtext q ={ $$ = cat(&$1, &$2, 0, 0, 0 ,0, 0); }
  135. ;
  136. char : c
  137. | '\\' x ={ $$ = $2; }
  138. ;
  139. dotnum : snum '.' snum '.' snum '.' snum ={ $$ = cat(&$1, &$2, &$3, &$4, &$5, &$6, &$7); }
  140. ;
  141. number : d ={ $$ = cat(&$1, 0, 0, 0, 0 ,0, 0); }
  142. | number d ={ $$ = cat(&$1, &$2, 0, 0, 0 ,0, 0); }
  143. ;
  144. snum : number ={ if(atoi(s_to_c($1.s)) > 255) print("bad snum\n"); }
  145. ;
  146. spaces : SPACE ={ $$ = $1; }
  147. | SPACE spaces ={ $$ = $1; }
  148. ;
  149. hunder : '-' | '_'
  150. ;
  151. special1 : CNTRL
  152. | '(' | ')' | ',' | '.'
  153. | ':' | ';' | '<' | '>' | '@'
  154. ;
  155. special : special1 | '\\' | '"'
  156. ;
  157. notspecial : '!' | '#' | '$' | '%' | '&' | '\''
  158. | '*' | '+' | '-' | '/'
  159. | '=' | '?'
  160. | '[' | ']' | '^' | '_' | '`' | '{' | '|' | '}' | '~'
  161. ;
  162. a : 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i'
  163. | 'j' | 'k' | 'l' | 'm' | 'n' | 'o' | 'p' | 'q' | 'r'
  164. | 's' | 't' | 'u' | 'v' | 'w' | 'x' | 'y' | 'z'
  165. ;
  166. d : '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
  167. ;
  168. c : a | d | notspecial
  169. ;
  170. q : a | d | special1 | notspecial | SPACE
  171. ;
  172. x : a | d | special | notspecial | SPACE
  173. ;
  174. %%
  175. void
  176. parseinit(void)
  177. {
  178. bang = (YYSTYPE*)malloc(sizeof(YYSTYPE));
  179. bang->c = '!';
  180. bang->s = 0;
  181. yyfp = &bin;
  182. }
  183. yylex(void)
  184. {
  185. int c;
  186. for(;;){
  187. c = Bgetc(yyfp);
  188. if(c == -1)
  189. return 0;
  190. if(debug)
  191. fprint(2, "%c", c);
  192. yylval.c = c = c & 0x7F;
  193. if(c == '\n'){
  194. return CRLF;
  195. }
  196. if(c == '\r'){
  197. c = Bgetc(yyfp);
  198. if(c != '\n'){
  199. Bungetc(yyfp);
  200. c = '\r';
  201. } else {
  202. if(debug)
  203. fprint(2, "%c", c);
  204. return CRLF;
  205. }
  206. }
  207. if(isalpha(c))
  208. return tolower(c);
  209. if(isspace(c))
  210. return SPACE;
  211. if(iscntrl(c))
  212. return CNTRL;
  213. return c;
  214. }
  215. }
  216. YYSTYPE
  217. cat(YYSTYPE *y1, YYSTYPE *y2, YYSTYPE *y3, YYSTYPE *y4, YYSTYPE *y5, YYSTYPE *y6, YYSTYPE *y7)
  218. {
  219. YYSTYPE rv;
  220. if(y1->s)
  221. rv.s = y1->s;
  222. else {
  223. rv.s = s_new();
  224. s_putc(rv.s, y1->c);
  225. s_terminate(rv.s);
  226. }
  227. if(y2){
  228. if(y2->s){
  229. s_append(rv.s, s_to_c(y2->s));
  230. s_free(y2->s);
  231. } else {
  232. s_putc(rv.s, y2->c);
  233. s_terminate(rv.s);
  234. }
  235. } else
  236. return rv;
  237. if(y3){
  238. if(y3->s){
  239. s_append(rv.s, s_to_c(y3->s));
  240. s_free(y3->s);
  241. } else {
  242. s_putc(rv.s, y3->c);
  243. s_terminate(rv.s);
  244. }
  245. } else
  246. return rv;
  247. if(y4){
  248. if(y4->s){
  249. s_append(rv.s, s_to_c(y4->s));
  250. s_free(y4->s);
  251. } else {
  252. s_putc(rv.s, y4->c);
  253. s_terminate(rv.s);
  254. }
  255. } else
  256. return rv;
  257. if(y5){
  258. if(y5->s){
  259. s_append(rv.s, s_to_c(y5->s));
  260. s_free(y5->s);
  261. } else {
  262. s_putc(rv.s, y5->c);
  263. s_terminate(rv.s);
  264. }
  265. } else
  266. return rv;
  267. if(y6){
  268. if(y6->s){
  269. s_append(rv.s, s_to_c(y6->s));
  270. s_free(y6->s);
  271. } else {
  272. s_putc(rv.s, y6->c);
  273. s_terminate(rv.s);
  274. }
  275. } else
  276. return rv;
  277. if(y7){
  278. if(y7->s){
  279. s_append(rv.s, s_to_c(y7->s));
  280. s_free(y7->s);
  281. } else {
  282. s_putc(rv.s, y7->c);
  283. s_terminate(rv.s);
  284. }
  285. } else
  286. return rv;
  287. return rv;
  288. }
  289. void
  290. yyerror(char *x)
  291. {
  292. USED(x);
  293. }
  294. /*
  295. * an anonymous user
  296. */
  297. YYSTYPE
  298. anonymous(void)
  299. {
  300. YYSTYPE rv;
  301. rv.s = s_copy("/dev/null");
  302. return rv;
  303. }