2 * Copyright (c) 2020 Martijn van Duren <martijn@openbsd.org>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
27 osmtpd_mheader_skip_sp(char *ptr, int optional)
31 return optional ? ptr : NULL;
35 osmtpd_mheader_skip_htab(char *ptr, int optional)
39 return optional ? ptr : NULL;
43 osmtpd_mheader_skip_wsp(char *ptr, int optional)
47 if ((ptr = osmtpd_mheader_skip_sp(start, 0)) != NULL ||
48 (ptr = osmtpd_mheader_skip_htab(start, 0)) != NULL)
50 return optional ? ptr : NULL;
54 osmtpd_mheader_skip_crlf(char *ptr, int optional)
56 if (ptr[0] == 13 && ptr[1] == 10)
58 return optional ? ptr : NULL;
62 osmtpd_mheader_skip_vchar(char *ptr, int optional)
64 if (ptr[0] >= 0x21 && ptr[0] <= 0x7e)
66 return optional ? ptr : NULL;
70 osmtpd_mheader_skip_lf(char *ptr, int optional)
74 return optional ? ptr : NULL;
78 osmtpd_mheader_skip_cr(char *ptr, int optional)
82 return optional ? ptr : NULL;
86 osmtpd_mheader_skip_alpha(char *ptr, int optional)
88 if ((ptr[0] >= 0x41 && ptr[0] <= 0x5a) ||
89 (ptr[0] >= 0x61 && ptr[0] <= 0x7a))
91 return optional ? ptr : NULL;
95 osmtpd_mheader_skip_digit(char *ptr, int optional)
97 if (ptr[0] >= 0x30 && ptr[0] <= 0x39)
99 return optional ? ptr : NULL;
103 osmtpd_mheader_skip_dquote(char *ptr, int optional)
107 return optional ? ptr : NULL;
111 osmtpd_mheader_skip_obs_fws(char *ptr, int optional)
113 char *start = ptr, *prev;
115 if ((ptr = osmtpd_mheader_skip_wsp(ptr, 0)) == NULL)
116 return optional ? start : NULL;
118 while ((ptr = osmtpd_mheader_skip_wsp(ptr, 0)) != NULL)
123 if ((ptr = osmtpd_mheader_skip_crlf(ptr, 0)) == NULL)
125 if ((ptr = osmtpd_mheader_skip_wsp(ptr, 0)) == NULL)
128 while ((ptr = osmtpd_mheader_skip_wsp(ptr, 0)) != NULL)
135 osmtpd_mheader_skip_fws(char *ptr, int optional)
137 char *start = ptr, *prev = ptr;
139 while ((ptr = osmtpd_mheader_skip_wsp(ptr, 0)) != NULL)
141 if ((ptr = osmtpd_mheader_skip_crlf(prev, 1)) == prev)
143 if ((ptr = osmtpd_mheader_skip_wsp(ptr, 0)) == NULL)
144 return osmtpd_mheader_skip_obs_fws(start, optional);
146 while ((ptr = osmtpd_mheader_skip_wsp(ptr, 0)) != NULL)
152 osmtpd_mheader_skip_obs_no_ws_ctl(char *ptr, int optional)
154 if ((ptr[0] >= 1 && ptr[0] <= 8) || ptr[0] == 11 || ptr[0] == 12 ||
155 (ptr[0] >= 14 && ptr[0] <= 31) || ptr[0] == 127)
157 return optional ? ptr : NULL;
161 osmtpd_mheader_skip_obs_ctext(char *ptr, int optional)
163 return osmtpd_mheader_skip_obs_no_ws_ctl(ptr, optional);
167 osmtpd_mheader_skip_ctext(char *ptr, int optional)
171 if ((ptr[0] >= 33 && ptr[0] <= 39) || (ptr[0] >= 42 && ptr[0] <= 91) ||
172 (ptr[0] >= 93 && ptr[0] <= 126))
174 if ((ptr = osmtpd_mheader_skip_obs_ctext(ptr, 0)) != NULL)
176 return optional ? start : NULL;
180 osmtpd_mheader_skip_obs_qp(char *ptr, int optional)
184 if (ptr[0] == '\\' && (
185 (ptr = osmtpd_mheader_skip_obs_no_ws_ctl(start + 1, 0)) != NULL ||
186 (ptr = osmtpd_mheader_skip_lf(start + 1, 0)) != NULL ||
187 (ptr = osmtpd_mheader_skip_cr(start + 1, 0)) != NULL))
189 return optional ? start : NULL;
193 osmtpd_mheader_skip_quoted_pair(char *ptr, int optional)
197 if (ptr[0] == '\\' && (
198 (ptr = osmtpd_mheader_skip_vchar(start + 1, 0)) != NULL ||
199 (ptr = osmtpd_mheader_skip_wsp(start + 1, 0)) != NULL))
201 return osmtpd_mheader_skip_obs_qp(start, optional);
205 osmtpd_mheader_skip_ccontent(char *ptr, int optional)
209 if ((ptr = osmtpd_mheader_skip_ctext(ptr, 0)) != NULL)
211 if ((ptr = osmtpd_mheader_skip_quoted_pair(start, 0)) != NULL)
213 if ((ptr = osmtpd_mheader_skip_comment(start, 0)) != NULL)
215 return optional ? start : NULL;
219 osmtpd_mheader_skip_comment(char *ptr, int optional)
224 return optional ? start : NULL;
226 ptr = osmtpd_mheader_skip_fws(ptr, 1);
229 if ((ptr = osmtpd_mheader_skip_ccontent(ptr, 0)) == NULL)
230 return optional ? start : NULL;
235 osmtpd_mheader_skip_cfws(char *ptr, int optional)
237 char *start = ptr, *prev;
240 ptr = osmtpd_mheader_skip_fws(ptr, 1);
242 if ((ptr = osmtpd_mheader_skip_comment(ptr, 0)) == NULL) {
247 return ptr == start && !optional ? NULL : ptr;
251 osmtpd_mheader_skip_atext(char *ptr, int optional)
255 if ((ptr = osmtpd_mheader_skip_alpha(start, 0)) != NULL ||
256 (ptr = osmtpd_mheader_skip_digit(start, 0)) != NULL)
259 if (ptr[0] == '!' || ptr[0] == '#' || ptr[0] == '$' || ptr[0] == '%' ||
260 ptr[0] == '&' || ptr[0] == '\'' || ptr[0] == '*' || ptr[0] == '+' ||
261 ptr[0] == '-' || ptr[0] == '/' || ptr[0] == '=' || ptr[0] == '?' ||
262 ptr[0] == '^' || ptr[0] == '_' || ptr[0] == '`' || ptr[0] == '{' ||
263 ptr[0] == '|' || ptr[0] == '}' || ptr[0] == '~')
265 return optional ? start : NULL;
269 osmtpd_mheader_skip_atom(char *ptr, int optional)
271 char *start = ptr, *prev;
273 ptr = osmtpd_mheader_skip_cfws(ptr, 1);
274 if ((ptr = osmtpd_mheader_skip_atext(ptr, 0)) == NULL)
275 return optional ? start : NULL;
278 ptr = osmtpd_mheader_skip_atext(ptr, 1);
279 } while (prev != ptr);
280 return osmtpd_mheader_skip_cfws(ptr, 1);
284 osmtpd_mheader_skip_dot_atom_text(char *ptr, int optional)
286 char *start = ptr, *prev;
288 if ((ptr = osmtpd_mheader_skip_atext(ptr, 0)) == NULL)
289 return optional ? start : NULL;
292 ptr = osmtpd_mheader_skip_atext(ptr, 1);
293 } while (ptr != prev);
295 while (ptr[0] == '.') {
297 if ((ptr = osmtpd_mheader_skip_atext(ptr, 0)) == NULL)
301 ptr = osmtpd_mheader_skip_atext(ptr, 1);
302 } while (ptr != prev);
308 osmtpd_mheader_skip_dot_atom(char *ptr, int optional)
312 ptr = osmtpd_mheader_skip_cfws(ptr, 1);
313 if ((ptr = osmtpd_mheader_skip_dot_atom_text(ptr, 0)) == NULL)
314 return optional ? start : NULL;
315 return osmtpd_mheader_skip_cfws(ptr, 1);
320 osmtpd_mheader_skip_obs_qtext(char *ptr, int optional)
322 return osmtpd_mheader_skip_obs_no_ws_ctl(ptr, optional);
326 osmtpd_mheader_skip_qtext(char *ptr, int optional)
330 if (ptr[0] == 33 || (ptr[0] >= 35 && ptr[0] <= 91) ||
331 (ptr[0] >= 93 && ptr[0] <= 126))
333 if ((ptr = osmtpd_mheader_skip_obs_qtext(ptr, 0)) != NULL)
335 return optional ? start : NULL;
339 osmtpd_mheader_skip_qcontent(char *ptr, int optional)
343 if ((ptr = osmtpd_mheader_skip_qtext(ptr, 0)) != NULL)
345 return osmtpd_mheader_skip_quoted_pair(start, optional);
349 osmtpd_mheader_skip_quoted_string(char *ptr, int optional)
351 char *start = ptr, *prev;
353 ptr = osmtpd_mheader_skip_cfws(ptr, 1);
354 if ((ptr = osmtpd_mheader_skip_dquote(ptr, 0)) == NULL)
355 return optional ? start : NULL;
358 ptr = osmtpd_mheader_skip_fws(ptr, 1);
359 if ((ptr = osmtpd_mheader_skip_qcontent(ptr, 0)) == NULL)
363 if ((ptr = osmtpd_mheader_skip_dquote(prev, 0)) == NULL)
364 return optional ? start : NULL;
365 return osmtpd_mheader_skip_cfws(ptr, 1);
369 osmtpd_mheader_skip_word(char *ptr, int optional)
373 if ((ptr = osmtpd_mheader_skip_atom(ptr, 0)) != NULL)
375 return osmtpd_mheader_skip_quoted_string(start, optional);
379 osmtpd_mheader_skip_obs_phrase(char *ptr, int optional)
381 char *start = ptr, *prev;
383 if ((ptr = osmtpd_mheader_skip_word(ptr, 0)) == NULL)
384 return optional ? start : NULL;
387 if ((ptr = osmtpd_mheader_skip_word(ptr, 0)) != NULL)
394 if ((ptr = osmtpd_mheader_skip_cfws(ptr, 0)) != NULL)
401 osmtpd_mheader_skip_phrase(char *ptr, int optional)
403 /* obs-phrase is a superset of phrae */
404 return osmtpd_mheader_skip_obs_phrase(ptr, optional);
406 char *start = ptr, *prev;
408 if ((ptr = osmtpd_mheader_skip_word(ptr, 0)) == NULL)
409 return optional ? start : NULL;
412 if ((ptr = osmtpd_mheader_skip_word(ptr, 0)) == NULL)
419 osmtpd_mheader_skip_obs_local_part(char *ptr, int optional)
421 char *start = ptr, *prev;
423 if ((ptr = osmtpd_mheader_skip_word(ptr, 0)) == NULL)
424 return optional ? start : NULL;
426 while (ptr[0] == '.') {
428 if ((ptr = osmtpd_mheader_skip_word(ptr, 0)) == NULL)
436 osmtpd_mheader_skip_local_part(char *ptr, int optional)
440 if ((ptr = osmtpd_mheader_skip_dot_atom(ptr, 0)) != NULL)
443 if ((ptr = osmtpd_mheader_skip_quoted_string(ptr, 0)) != NULL)
445 return osmtpd_mheader_skip_obs_local_part(start, optional);
449 osmtpd_mheader_skip_obs_dtext(char *ptr, int optional)
453 if ((ptr = osmtpd_mheader_skip_obs_no_ws_ctl(ptr, 0)) != NULL)
455 return osmtpd_mheader_skip_quoted_pair(start, optional);
459 osmtpd_mheader_skip_dtext(char *ptr, int optional)
461 if ((ptr[0] >= 33 && ptr[0] <= 90) || (ptr[0] >= 94 && ptr[0] <= 126))
463 return osmtpd_mheader_skip_obs_dtext(ptr, optional);
468 osmtpd_mheader_skip_domain_literal(char *ptr, int optional)
470 char *start = ptr, *prev;
472 ptr = osmtpd_mheader_skip_cfws(ptr, 1);
474 return optional ? start : NULL;
476 ptr = osmtpd_mheader_skip_fws(ptr, 1);
478 if ((ptr = osmtpd_mheader_skip_dtext(ptr, 0)) == NULL) {
484 return optional ? start : NULL;
486 return osmtpd_mheader_skip_cfws(ptr, 1);
490 osmtpd_mheader_skip_obs_domain(char *ptr, int optional)
492 char *start = ptr, *prev;
494 if ((ptr = osmtpd_mheader_skip_atom(ptr, 0)) == NULL)
495 return optional ? start : NULL;
500 if ((ptr = osmtpd_mheader_skip_atom(ptr, 0)) == NULL)
507 osmtpd_mheader_skip_domain(char *ptr, int optional)
511 if ((ptr = osmtpd_mheader_skip_dot_atom(start, 0)) != NULL)
513 if ((ptr = osmtpd_mheader_skip_domain_literal(start, 0)) != NULL)
515 return osmtpd_mheader_skip_obs_domain(start, optional);
519 osmtpd_mheader_skip_display_name(char *ptr, int optional)
521 return osmtpd_mheader_skip_phrase(ptr, optional);
525 osmtpd_mheader_skip_obs_domain_list(char *ptr, int optional)
527 char *start = ptr, *prev = ptr;
534 } else if ((ptr = osmtpd_mheader_skip_cfws(ptr, 0)) != NULL) {
543 return optional ? start : NULL;
544 if ((ptr = osmtpd_mheader_skip_domain(ptr, 0)) == NULL)
545 return optional ? start : NULL;
550 ptr = osmtpd_mheader_skip_cfws(ptr, 1);
554 if ((ptr = osmtpd_mheader_skip_domain(ptr + 1, 0)) == NULL) {
563 osmtpd_mheader_skip_obs_route(char *ptr, int optional)
567 if ((ptr = osmtpd_mheader_skip_obs_domain_list(ptr, 0)) == NULL)
568 return optional ? start : NULL;
570 return optional ? start : NULL;
575 osmtpd_mheader_skip_addr_spec(char *ptr, int optional)
579 if ((ptr = osmtpd_mheader_skip_local_part(ptr, 0)) == NULL)
580 return optional ? start : NULL;
582 return optional ? start : NULL;
583 if ((ptr = osmtpd_mheader_skip_domain(ptr, 0)) == NULL)
584 return optional ? start : NULL;
589 osmtpd_mheader_skip_obs_angle_addr(char *ptr, int optional)
593 ptr = osmtpd_mheader_skip_cfws(ptr, 1);
595 return optional ? start : NULL;
596 if ((ptr = osmtpd_mheader_skip_obs_route(ptr, 0)) == NULL)
597 return optional ? start : NULL;
598 if ((ptr = osmtpd_mheader_skip_addr_spec(ptr, 0)) == NULL)
599 return optional ? start : NULL;
601 return optional ? start : NULL;
602 return osmtpd_mheader_skip_cfws(ptr, 1);
606 osmtpd_mheader_skip_angle_addr(char *ptr, int optional)
610 ptr = osmtpd_mheader_skip_cfws(ptr, 1);
612 return osmtpd_mheader_skip_obs_angle_addr(start, optional);
613 if ((ptr = osmtpd_mheader_skip_addr_spec(ptr, 0)) == NULL)
614 return osmtpd_mheader_skip_obs_angle_addr(start, optional);
616 return osmtpd_mheader_skip_obs_angle_addr(start, optional);
617 return osmtpd_mheader_skip_cfws(ptr, 1);
621 osmtpd_mheader_skip_name_addr(char *ptr, int optional)
625 ptr = osmtpd_mheader_skip_display_name(ptr, 1);
626 if ((ptr = osmtpd_mheader_skip_angle_addr(ptr, 0)) == NULL)
627 return optional ? start : NULL;
632 osmtpd_mheader_domain_uncomment(char *ptr)
634 char *domain0, *domain, *tmp, *end;
636 if (osmtpd_mheader_skip_dot_atom(ptr, 0) != NULL) {
637 ptr = osmtpd_mheader_skip_cfws(ptr, 1);
639 osmtpd_mheader_skip_dot_atom_text(ptr, 0) - ptr);
641 if ((tmp = osmtpd_mheader_skip_domain_literal(ptr, 0)) != NULL) {
642 ptr = osmtpd_mheader_skip_cfws(ptr, 1) + 1;
643 domain0 = domain = strndup(ptr, (size_t)(tmp - ptr));
646 end = domain0 + (tmp - ptr) + 1;
649 tmp = osmtpd_mheader_skip_fws(domain, 1);
651 memmove(domain, tmp, end - tmp);
652 end -= (tmp - domain);
654 tmp = osmtpd_mheader_skip_dtext(domain, 0);
659 /* domain[0] == ']' */
663 return strndup(ptr, osmtpd_mheader_skip_obs_domain(ptr, 1) - ptr);
666 /* Return the domain component of the first mailbox */
668 osmtpd_mheader_from_domain(char *ptr)
673 if (strncasecmp(ptr, "from:", 5) == 0) {
676 } else if (strncasecmp(ptr, "from", 4) == 0) {
680 } while ((ptr = osmtpd_mheader_skip_wsp(ptr, 0)) != NULL);
689 /* Both from and obs-from use Mailbox-list CRLF */
690 /* obs-mbox-list has just a prefix compared to mailbox-list */
693 ptr = osmtpd_mheader_skip_cfws(ptr, 1);
694 if (ptr++[0] != ',') {
699 /* We're only interested in the first mailbox */
700 if (osmtpd_mheader_skip_name_addr(ptr, 0) != NULL) {
701 ptr = osmtpd_mheader_skip_display_name(ptr, 1);
702 ptr = osmtpd_mheader_skip_cfws(ptr, 1);
706 ptr = osmtpd_mheader_skip_local_part(ptr, 0);
709 return osmtpd_mheader_domain_uncomment(ptr);
711 if (osmtpd_mheader_skip_addr_spec(ptr, 0) != NULL) {
712 ptr = osmtpd_mheader_skip_local_part(ptr, 0);
715 return osmtpd_mheader_domain_uncomment(ptr);