smtpd.y 6.8 KB

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