2 4f29629b 2020-08-30 martijn * Copyright (c) 2020 Martijn van Duren <martijn@openbsd.org>
4 4f29629b 2020-08-30 martijn * Permission to use, copy, modify, and distribute this software for any
5 4f29629b 2020-08-30 martijn * purpose with or without fee is hereby granted, provided that the above
6 4f29629b 2020-08-30 martijn * copyright notice and this permission notice appear in all copies.
8 4f29629b 2020-08-30 martijn * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 4f29629b 2020-08-30 martijn * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 4f29629b 2020-08-30 martijn * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 4f29629b 2020-08-30 martijn * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 4f29629b 2020-08-30 martijn * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 4f29629b 2020-08-30 martijn * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 4f29629b 2020-08-30 martijn * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 4f29629b 2020-08-30 martijn #include <ctype.h>
18 4f29629b 2020-08-30 martijn #include <errno.h>
19 4f29629b 2020-08-30 martijn #include <stddef.h>
20 4f29629b 2020-08-30 martijn #include <string.h>
21 4f29629b 2020-08-30 martijn #include <strings.h>
23 4f29629b 2020-08-30 martijn #include "mheader.h"
26 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_sp(char *ptr, int optional)
28 4f29629b 2020-08-30 martijn if (ptr[0] == 0x20)
29 4f29629b 2020-08-30 martijn return ptr + 1;
30 4f29629b 2020-08-30 martijn return optional ? ptr : NULL;
34 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_htab(char *ptr, int optional)
36 4f29629b 2020-08-30 martijn if (ptr[0] == 0x9)
37 4f29629b 2020-08-30 martijn return ptr + 1;
38 4f29629b 2020-08-30 martijn return optional ? ptr : NULL;
42 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_wsp(char *ptr, int optional)
44 4f29629b 2020-08-30 martijn char *start = ptr;
46 4f29629b 2020-08-30 martijn if ((ptr = osmtpd_mheader_skip_sp(start, 0)) != NULL ||
47 4f29629b 2020-08-30 martijn (ptr = osmtpd_mheader_skip_htab(start, 0)) != NULL)
48 4f29629b 2020-08-30 martijn return ptr;
49 4f29629b 2020-08-30 martijn return optional ? ptr : NULL;
53 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_crlf(char *ptr, int optional)
55 4f29629b 2020-08-30 martijn if (ptr[0] == 13 && ptr[1] == 10)
56 4f29629b 2020-08-30 martijn return ptr + 2;
57 4f29629b 2020-08-30 martijn return optional ? ptr : NULL;
61 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_vchar(char *ptr, int optional)
63 4f29629b 2020-08-30 martijn if (ptr[0] >= 0x21 && ptr[0] <= 0x7e)
64 4f29629b 2020-08-30 martijn return ptr + 1;
65 4f29629b 2020-08-30 martijn return optional ? ptr : NULL;
69 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_lf(char *ptr, int optional)
71 4f29629b 2020-08-30 martijn if (ptr[0] == 0xa)
72 4f29629b 2020-08-30 martijn return ptr + 1;
73 4f29629b 2020-08-30 martijn return optional ? ptr : NULL;
77 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_cr(char *ptr, int optional)
79 4f29629b 2020-08-30 martijn if (ptr[0] == 0xd)
80 4f29629b 2020-08-30 martijn return ptr + 1;
81 4f29629b 2020-08-30 martijn return optional ? ptr : NULL;
85 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_alpha(char *ptr, int optional)
87 4f29629b 2020-08-30 martijn if ((ptr[0] >= 0x41 && ptr[0] <= 0x5a) ||
88 4f29629b 2020-08-30 martijn (ptr[0] >= 0x61 && ptr[0] <= 0x7a))
89 4f29629b 2020-08-30 martijn return ptr + 1;
90 4f29629b 2020-08-30 martijn return optional ? ptr : NULL;
94 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_digit(char *ptr, int optional)
96 4f29629b 2020-08-30 martijn if (ptr[0] >= 0x30 && ptr[0] <= 0x39)
97 4f29629b 2020-08-30 martijn return ptr + 1;
98 4f29629b 2020-08-30 martijn return optional ? ptr : NULL;
102 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_dquote(char *ptr, int optional)
104 4f29629b 2020-08-30 martijn if (ptr[0] == 0x22)
105 4f29629b 2020-08-30 martijn return ptr + 1;
106 4f29629b 2020-08-30 martijn return optional ? ptr : NULL;
110 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_char(char *ptr, int optional)
112 4f29629b 2020-08-30 martijn if (ptr[0] >= 0x1 && ptr[0] <= 0x7f)
113 4f29629b 2020-08-30 martijn return ptr + 1;
114 4f29629b 2020-08-30 martijn return optional ? ptr : NULL;
118 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_ctl(char *ptr, int optional)
120 4f29629b 2020-08-30 martijn if ((ptr[0] >= 0x0 && ptr[0] <= 0x1f) || ptr[0] == 0x7f)
121 4f29629b 2020-08-30 martijn return ptr + 1;
122 4f29629b 2020-08-30 martijn return optional ? ptr : NULL;
126 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_obs_fws(char *ptr, int optional)
128 4f29629b 2020-08-30 martijn char *start = ptr, *prev;
130 4f29629b 2020-08-30 martijn if ((ptr = osmtpd_mheader_skip_wsp(ptr, 0)) == NULL)
131 4f29629b 2020-08-30 martijn return optional ? start : NULL;
132 4f29629b 2020-08-30 martijn prev = ptr;
133 4f29629b 2020-08-30 martijn while ((ptr = osmtpd_mheader_skip_wsp(ptr, 0)) != NULL)
134 4f29629b 2020-08-30 martijn prev = ptr;
136 4f29629b 2020-08-30 martijn ptr = prev;
137 4f29629b 2020-08-30 martijn while (1) {
138 4f29629b 2020-08-30 martijn if ((ptr = osmtpd_mheader_skip_crlf(ptr, 0)) == NULL)
139 4f29629b 2020-08-30 martijn return prev;
140 4f29629b 2020-08-30 martijn if ((ptr = osmtpd_mheader_skip_wsp(ptr, 0)) == NULL)
141 4f29629b 2020-08-30 martijn return prev;
142 4f29629b 2020-08-30 martijn prev = ptr;
143 4f29629b 2020-08-30 martijn while ((ptr = osmtpd_mheader_skip_wsp(ptr, 0)) != NULL)
144 4f29629b 2020-08-30 martijn prev = ptr;
145 4f29629b 2020-08-30 martijn ptr = prev;
150 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_fws(char *ptr, int optional)
152 4f29629b 2020-08-30 martijn char *start = ptr, *prev = ptr;
154 4f29629b 2020-08-30 martijn while ((ptr = osmtpd_mheader_skip_wsp(ptr, 0)) != NULL)
155 4f29629b 2020-08-30 martijn prev = ptr;
156 4f29629b 2020-08-30 martijn if ((ptr = osmtpd_mheader_skip_crlf(prev, 1)) == prev)
157 4f29629b 2020-08-30 martijn ptr = start;
158 4f29629b 2020-08-30 martijn if ((ptr = osmtpd_mheader_skip_wsp(ptr, 0)) == NULL)
159 4f29629b 2020-08-30 martijn return osmtpd_mheader_skip_obs_fws(start, optional);
160 4f29629b 2020-08-30 martijn prev = ptr;
161 4f29629b 2020-08-30 martijn while ((ptr = osmtpd_mheader_skip_wsp(ptr, 0)) != NULL)
162 4f29629b 2020-08-30 martijn prev = ptr;
163 4f29629b 2020-08-30 martijn return prev;
167 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_obs_no_ws_ctl(char *ptr, int optional)
169 4f29629b 2020-08-30 martijn if ((ptr[0] >= 1 && ptr[0] <= 8) || ptr[0] == 11 || ptr[0] == 12 ||
170 4f29629b 2020-08-30 martijn (ptr[0] >= 14 && ptr[0] <= 31) || ptr[0] == 127)
171 4f29629b 2020-08-30 martijn return ptr + 1;
172 4f29629b 2020-08-30 martijn return optional ? ptr : NULL;
176 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_obs_ctext(char *ptr, int optional)
178 4f29629b 2020-08-30 martijn return osmtpd_mheader_skip_obs_no_ws_ctl(ptr, optional);
182 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_ctext(char *ptr, int optional)
184 4f29629b 2020-08-30 martijn char *start = ptr;
186 4f29629b 2020-08-30 martijn if ((ptr[0] >= 33 && ptr[0] <= 39) || (ptr[0] >= 42 && ptr[0] <= 91) ||
187 4f29629b 2020-08-30 martijn (ptr[0] >= 93 && ptr[0] <= 126))
188 4f29629b 2020-08-30 martijn return ptr + 1;
189 4f29629b 2020-08-30 martijn if ((ptr = osmtpd_mheader_skip_obs_ctext(ptr, 0)) != NULL)
190 4f29629b 2020-08-30 martijn return ptr;
191 4f29629b 2020-08-30 martijn return optional ? start : NULL;
195 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_obs_qp(char *ptr, int optional)
197 4f29629b 2020-08-30 martijn char *start = ptr;
199 4f29629b 2020-08-30 martijn if (ptr[0] == '\\' && (
200 4f29629b 2020-08-30 martijn (ptr = osmtpd_mheader_skip_obs_no_ws_ctl(start + 1, 0)) != NULL ||
201 4f29629b 2020-08-30 martijn (ptr = osmtpd_mheader_skip_lf(start + 1, 0)) != NULL ||
202 4f29629b 2020-08-30 martijn (ptr = osmtpd_mheader_skip_cr(start + 1, 0)) != NULL))
203 4f29629b 2020-08-30 martijn return ptr;
204 4f29629b 2020-08-30 martijn return optional ? start : NULL;
208 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_quoted_pair(char *ptr, int optional)
210 4f29629b 2020-08-30 martijn char *start = ptr;
212 4f29629b 2020-08-30 martijn if (ptr[0] == '\\' && (
213 4f29629b 2020-08-30 martijn (ptr = osmtpd_mheader_skip_vchar(start + 1, 0)) != NULL ||
214 4f29629b 2020-08-30 martijn (ptr = osmtpd_mheader_skip_wsp(start + 1, 0)) != NULL))
215 4f29629b 2020-08-30 martijn return ptr;
216 4f29629b 2020-08-30 martijn return osmtpd_mheader_skip_obs_qp(start, optional);
220 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_ccontent(char *ptr, int optional)
222 4f29629b 2020-08-30 martijn char *start = ptr;
224 4f29629b 2020-08-30 martijn if ((ptr = osmtpd_mheader_skip_ctext(ptr, 0)) != NULL)
225 4f29629b 2020-08-30 martijn return ptr;
226 4f29629b 2020-08-30 martijn if ((ptr = osmtpd_mheader_skip_quoted_pair(start, 0)) != NULL)
227 4f29629b 2020-08-30 martijn return ptr;
228 4f29629b 2020-08-30 martijn if ((ptr = osmtpd_mheader_skip_comment(start, 0)) != NULL)
229 4f29629b 2020-08-30 martijn return ptr;
230 4f29629b 2020-08-30 martijn return optional ? start : NULL;
234 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_comment(char *ptr, int optional)
236 4f29629b 2020-08-30 martijn char *start = ptr;
238 4f29629b 2020-08-30 martijn if (ptr++[0] != '(')
239 4f29629b 2020-08-30 martijn return optional ? start : NULL;
240 4f29629b 2020-08-30 martijn while (1) {
241 4f29629b 2020-08-30 martijn ptr = osmtpd_mheader_skip_fws(ptr, 1);
242 4f29629b 2020-08-30 martijn if (ptr[0] == ')')
243 4f29629b 2020-08-30 martijn return ptr + 1;
244 4f29629b 2020-08-30 martijn if ((ptr = osmtpd_mheader_skip_ccontent(ptr, 0)) == NULL)
245 4f29629b 2020-08-30 martijn return optional ? start : NULL;
250 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_cfws(char *ptr, int optional)
252 4f29629b 2020-08-30 martijn char *start = ptr, *prev;
254 4f29629b 2020-08-30 martijn while (1) {
255 4f29629b 2020-08-30 martijn ptr = osmtpd_mheader_skip_fws(ptr, 1);
256 4f29629b 2020-08-30 martijn prev = ptr;
257 4f29629b 2020-08-30 martijn if ((ptr = osmtpd_mheader_skip_comment(ptr, 0)) == NULL) {
258 4f29629b 2020-08-30 martijn ptr = prev;
262 4f29629b 2020-08-30 martijn return ptr == start && !optional ? NULL : ptr;
266 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_atext(char *ptr, int optional)
268 4f29629b 2020-08-30 martijn char *start = ptr;
270 4f29629b 2020-08-30 martijn if ((ptr = osmtpd_mheader_skip_alpha(start, 0)) != NULL ||
271 4f29629b 2020-08-30 martijn (ptr = osmtpd_mheader_skip_digit(start, 0)) != NULL)
272 4f29629b 2020-08-30 martijn return ptr;
273 4f29629b 2020-08-30 martijn ptr = start;
274 4f29629b 2020-08-30 martijn if (ptr[0] == '!' || ptr[0] == '#' || ptr[0] == '$' || ptr[0] == '%' ||
275 4f29629b 2020-08-30 martijn ptr[0] == '&' || ptr[0] == '\'' || ptr[0] == '*' || ptr[0] == '+' ||
276 4f29629b 2020-08-30 martijn ptr[0] == '-' || ptr[0] == '/' || ptr[0] == '=' || ptr[0] == '?' ||
277 4f29629b 2020-08-30 martijn ptr[0] == '^' || ptr[0] == '_' || ptr[0] == '`' || ptr[0] == '{' ||
278 4f29629b 2020-08-30 martijn ptr[0] == '|' || ptr[0] == '}' || ptr[0] == '~')
279 4f29629b 2020-08-30 martijn return ptr + 1;
280 4f29629b 2020-08-30 martijn return optional ? start : NULL;
284 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_atom(char *ptr, int optional)
286 4f29629b 2020-08-30 martijn char *start = ptr, *prev;
288 4f29629b 2020-08-30 martijn ptr = osmtpd_mheader_skip_cfws(ptr, 1);
289 4f29629b 2020-08-30 martijn if ((ptr = osmtpd_mheader_skip_atext(ptr, 0)) == NULL)
290 4f29629b 2020-08-30 martijn return optional ? start : NULL;
292 4f29629b 2020-08-30 martijn prev = ptr;
293 4f29629b 2020-08-30 martijn ptr = osmtpd_mheader_skip_atext(ptr, 1);
294 4f29629b 2020-08-30 martijn } while (prev != ptr);
295 4f29629b 2020-08-30 martijn return osmtpd_mheader_skip_cfws(ptr, 1);
299 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_dot_atom_text(char *ptr, int optional)
301 4f29629b 2020-08-30 martijn char *start = ptr, *prev;
303 4f29629b 2020-08-30 martijn if ((ptr = osmtpd_mheader_skip_atext(ptr, 0)) == NULL)
304 4f29629b 2020-08-30 martijn return optional ? start : NULL;
306 4f29629b 2020-08-30 martijn prev = ptr;
307 4f29629b 2020-08-30 martijn ptr = osmtpd_mheader_skip_atext(ptr, 1);
308 4f29629b 2020-08-30 martijn } while (ptr != prev);
310 4f29629b 2020-08-30 martijn while (ptr[0] == '.') {
312 4f29629b 2020-08-30 martijn if ((ptr = osmtpd_mheader_skip_atext(ptr, 0)) == NULL)
313 4f29629b 2020-08-30 martijn return prev;
315 4f29629b 2020-08-30 martijn prev = ptr;
316 4f29629b 2020-08-30 martijn ptr = osmtpd_mheader_skip_atext(ptr, 1);
317 4f29629b 2020-08-30 martijn } while (ptr != prev);
319 4f29629b 2020-08-30 martijn return ptr;
323 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_dot_atom(char *ptr, int optional)
325 4f29629b 2020-08-30 martijn char *start = ptr;
327 4f29629b 2020-08-30 martijn ptr = osmtpd_mheader_skip_cfws(ptr, 1);
328 4f29629b 2020-08-30 martijn if ((ptr = osmtpd_mheader_skip_dot_atom_text(ptr, 0)) == NULL)
329 4f29629b 2020-08-30 martijn return optional ? start : NULL;
330 4f29629b 2020-08-30 martijn return osmtpd_mheader_skip_cfws(ptr, 1);
335 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_obs_qtext(char *ptr, int optional)
337 4f29629b 2020-08-30 martijn return osmtpd_mheader_skip_obs_no_ws_ctl(ptr, optional);
341 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_qtext(char *ptr, int optional)
343 4f29629b 2020-08-30 martijn char *start = ptr;
345 4f29629b 2020-08-30 martijn if (ptr[0] == 33 || (ptr[0] >= 35 && ptr[0] <= 91) ||
346 4f29629b 2020-08-30 martijn (ptr[0] >= 93 && ptr[0] <= 126))
347 4f29629b 2020-08-30 martijn return ptr + 1;
348 4f29629b 2020-08-30 martijn if ((ptr = osmtpd_mheader_skip_obs_qtext(ptr, 0)) != NULL)
349 4f29629b 2020-08-30 martijn return ptr;
350 4f29629b 2020-08-30 martijn return optional ? start : NULL;
354 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_qcontent(char *ptr, int optional)
356 4f29629b 2020-08-30 martijn char *start = ptr;
358 4f29629b 2020-08-30 martijn if ((ptr = osmtpd_mheader_skip_qtext(ptr, 0)) != NULL)
359 4f29629b 2020-08-30 martijn return ptr;
360 4f29629b 2020-08-30 martijn return osmtpd_mheader_skip_quoted_pair(start, optional);
364 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_quoted_string(char *ptr, int optional)
366 4f29629b 2020-08-30 martijn char *start = ptr, *prev;
368 4f29629b 2020-08-30 martijn ptr = osmtpd_mheader_skip_cfws(ptr, 1);
369 4f29629b 2020-08-30 martijn if ((ptr = osmtpd_mheader_skip_dquote(ptr, 0)) == NULL)
370 4f29629b 2020-08-30 martijn return optional ? start : NULL;
371 4f29629b 2020-08-30 martijn prev = ptr;
372 4f29629b 2020-08-30 martijn while (1) {
373 4f29629b 2020-08-30 martijn ptr = osmtpd_mheader_skip_fws(ptr, 1);
374 4f29629b 2020-08-30 martijn if ((ptr = osmtpd_mheader_skip_qcontent(ptr, 0)) == NULL)
376 4f29629b 2020-08-30 martijn prev = ptr;
378 4f29629b 2020-08-30 martijn if ((ptr = osmtpd_mheader_skip_dquote(prev, 0)) == NULL)
379 4f29629b 2020-08-30 martijn return optional ? start : NULL;
380 4f29629b 2020-08-30 martijn return osmtpd_mheader_skip_cfws(ptr, 1);
384 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_word(char *ptr, int optional)
386 4f29629b 2020-08-30 martijn char *start = ptr;
388 4f29629b 2020-08-30 martijn if ((ptr = osmtpd_mheader_skip_atom(ptr, 0)) != NULL)
389 4f29629b 2020-08-30 martijn return ptr;
390 4f29629b 2020-08-30 martijn return osmtpd_mheader_skip_quoted_string(start, optional);
394 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_obs_phrase(char *ptr, int optional)
396 4f29629b 2020-08-30 martijn char *start = ptr, *prev;
398 4f29629b 2020-08-30 martijn if ((ptr = osmtpd_mheader_skip_word(ptr, 0)) == NULL)
399 4f29629b 2020-08-30 martijn return optional ? start : NULL;
400 4f29629b 2020-08-30 martijn while (1) {
401 4f29629b 2020-08-30 martijn prev = ptr;
402 4f29629b 2020-08-30 martijn if ((ptr = osmtpd_mheader_skip_word(ptr, 0)) != NULL)
403 4f29629b 2020-08-30 martijn continue;
404 4f29629b 2020-08-30 martijn ptr = prev;
405 4f29629b 2020-08-30 martijn if (ptr[0] == '.')
406 4f29629b 2020-08-30 martijn continue;
407 4f29629b 2020-08-30 martijn if ((ptr = osmtpd_mheader_skip_cfws(ptr, 0)) != NULL)
408 4f29629b 2020-08-30 martijn continue;
409 4f29629b 2020-08-30 martijn return prev;
414 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_phrase(char *ptr, int optional)
416 4f29629b 2020-08-30 martijn /* obs-phrase is a superset of phrae */
417 4f29629b 2020-08-30 martijn return osmtpd_mheader_skip_obs_phrase(ptr, optional);
419 4f29629b 2020-08-30 martijn char *start = ptr, *prev;
421 4f29629b 2020-08-30 martijn if ((ptr = osmtpd_mheader_skip_word(ptr, 0)) == NULL)
422 4f29629b 2020-08-30 martijn return optional ? start : NULL;
423 4f29629b 2020-08-30 martijn while (1) {
424 4f29629b 2020-08-30 martijn prev = ptr;
425 4f29629b 2020-08-30 martijn if ((ptr = osmtpd_mheader_skip_word(ptr, 0)) == NULL)
426 4f29629b 2020-08-30 martijn return prev;
432 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_obs_local_part(char *ptr, int optional)
434 4f29629b 2020-08-30 martijn char *start = ptr, *prev;
436 4f29629b 2020-08-30 martijn if ((ptr = osmtpd_mheader_skip_word(ptr, 0)) == NULL)
437 4f29629b 2020-08-30 martijn return optional ? start : NULL;
438 4f29629b 2020-08-30 martijn prev = ptr;
439 4f29629b 2020-08-30 martijn while (ptr[0] == '.') {
441 4f29629b 2020-08-30 martijn if ((ptr = osmtpd_mheader_skip_word(ptr, 0)) == NULL)
442 4f29629b 2020-08-30 martijn return prev;
443 4f29629b 2020-08-30 martijn prev = ptr;
445 4f29629b 2020-08-30 martijn return ptr;
449 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_local_part(char *ptr, int optional)
451 4f29629b 2020-08-30 martijn char *start = ptr;
453 4f29629b 2020-08-30 martijn if ((ptr = osmtpd_mheader_skip_dot_atom(ptr, 0)) != NULL)
454 4f29629b 2020-08-30 martijn return ptr;
455 4f29629b 2020-08-30 martijn ptr = start;
456 4f29629b 2020-08-30 martijn if ((ptr = osmtpd_mheader_skip_quoted_string(ptr, 0)) != NULL)
457 4f29629b 2020-08-30 martijn return ptr;
458 4f29629b 2020-08-30 martijn return osmtpd_mheader_skip_obs_local_part(start, optional);
462 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_obs_dtext(char *ptr, int optional)
464 4f29629b 2020-08-30 martijn char *start = ptr;
466 4f29629b 2020-08-30 martijn if ((ptr = osmtpd_mheader_skip_obs_no_ws_ctl(ptr, 0)) != NULL)
467 4f29629b 2020-08-30 martijn return ptr;
468 4f29629b 2020-08-30 martijn return osmtpd_mheader_skip_quoted_pair(start, optional);
472 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_dtext(char *ptr, int optional)
474 4f29629b 2020-08-30 martijn if ((ptr[0] >= 33 && ptr[0] <= 90) || (ptr[0] >= 94 && ptr[0] <= 126))
475 4f29629b 2020-08-30 martijn return ptr + 1;
476 4f29629b 2020-08-30 martijn return osmtpd_mheader_skip_obs_dtext(ptr, optional);
481 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_domain_literal(char *ptr, int optional)
483 4f29629b 2020-08-30 martijn char *start = ptr, *prev;
485 4f29629b 2020-08-30 martijn ptr = osmtpd_mheader_skip_cfws(ptr, 1);
486 4f29629b 2020-08-30 martijn if (ptr++[0] != '[')
487 4f29629b 2020-08-30 martijn return optional ? start : NULL;
488 4f29629b 2020-08-30 martijn while (1) {
489 4f29629b 2020-08-30 martijn ptr = osmtpd_mheader_skip_fws(ptr, 1);
490 4f29629b 2020-08-30 martijn prev = ptr;
491 4f29629b 2020-08-30 martijn if ((ptr = osmtpd_mheader_skip_dtext(ptr, 0)) == NULL) {
492 4f29629b 2020-08-30 martijn ptr = prev;
496 4f29629b 2020-08-30 martijn if (ptr[0] != ']')
497 4f29629b 2020-08-30 martijn return optional ? start : NULL;
498 4f29629b 2020-08-30 martijn return osmtpd_mheader_skip_cfws(ptr, 1);
502 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_obs_domain(char *ptr, int optional)
504 4f29629b 2020-08-30 martijn char *start = ptr, *prev;
506 4f29629b 2020-08-30 martijn if ((ptr = osmtpd_mheader_skip_atom(ptr, 0)) == NULL)
507 4f29629b 2020-08-30 martijn return optional ? start : NULL;
508 4f29629b 2020-08-30 martijn prev = ptr;
509 4f29629b 2020-08-30 martijn while (1) {
510 4f29629b 2020-08-30 martijn if (ptr++[0] != '.')
511 4f29629b 2020-08-30 martijn return prev;
512 4f29629b 2020-08-30 martijn if ((ptr = osmtpd_mheader_skip_atom(ptr, 0)) == NULL)
513 4f29629b 2020-08-30 martijn return prev;
514 4f29629b 2020-08-30 martijn prev = ptr;
519 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_domain(char *ptr, int optional)
521 4f29629b 2020-08-30 martijn char *start = ptr;
523 4f29629b 2020-08-30 martijn if ((ptr = osmtpd_mheader_skip_dot_atom(start, 0)) != NULL)
524 4f29629b 2020-08-30 martijn return ptr;
525 4f29629b 2020-08-30 martijn if ((ptr = osmtpd_mheader_skip_domain_literal(start, 0)) != NULL)
526 4f29629b 2020-08-30 martijn return ptr;
527 4f29629b 2020-08-30 martijn return osmtpd_mheader_skip_obs_domain(start, optional);
531 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_display_name(char *ptr, int optional)
533 4f29629b 2020-08-30 martijn return osmtpd_mheader_skip_phrase(ptr, optional);
537 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_obs_domain_list(char *ptr, int optional)
539 4f29629b 2020-08-30 martijn char *start = ptr, *prev;
541 4f29629b 2020-08-30 martijn while (1) {
542 4f29629b 2020-08-30 martijn if (ptr[0] == ',') {
544 4f29629b 2020-08-30 martijn prev = ptr;
545 4f29629b 2020-08-30 martijn continue;
546 4f29629b 2020-08-30 martijn } else if ((ptr = osmtpd_mheader_skip_cfws(ptr, 0)) != NULL) {
547 4f29629b 2020-08-30 martijn prev = ptr;
548 4f29629b 2020-08-30 martijn continue;
552 4f29629b 2020-08-30 martijn ptr = prev;
554 4f29629b 2020-08-30 martijn if (ptr++[0] != '@')
555 4f29629b 2020-08-30 martijn return optional ? start : NULL;
556 4f29629b 2020-08-30 martijn if ((ptr = osmtpd_mheader_skip_domain(ptr, 0)) == NULL)
557 4f29629b 2020-08-30 martijn return optional ? start : NULL;
558 4f29629b 2020-08-30 martijn while (1) {
559 4f29629b 2020-08-30 martijn if (ptr[0] != ',')
562 4f29629b 2020-08-30 martijn ptr = osmtpd_mheader_skip_cfws(ptr, 1);
563 4f29629b 2020-08-30 martijn if (ptr[0] != '@')
564 4f29629b 2020-08-30 martijn continue;
565 4f29629b 2020-08-30 martijn prev = ptr;
566 4f29629b 2020-08-30 martijn if ((ptr = osmtpd_mheader_skip_domain(ptr + 1, 0)) == NULL) {
567 4f29629b 2020-08-30 martijn ptr = prev;
571 4f29629b 2020-08-30 martijn return ptr;
575 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_obs_route(char *ptr, int optional)
577 4f29629b 2020-08-30 martijn char *start = ptr;
579 4f29629b 2020-08-30 martijn if ((ptr = osmtpd_mheader_skip_obs_domain_list(ptr, 0)) == NULL)
580 4f29629b 2020-08-30 martijn return optional ? start : NULL;
581 4f29629b 2020-08-30 martijn if (ptr++[0] != ':')
582 4f29629b 2020-08-30 martijn return optional ? start : NULL;
583 4f29629b 2020-08-30 martijn return ptr;
587 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_addr_spec(char *ptr, int optional)
589 4f29629b 2020-08-30 martijn char *start = ptr;
591 4f29629b 2020-08-30 martijn if ((ptr = osmtpd_mheader_skip_local_part(ptr, 0)) == NULL)
592 4f29629b 2020-08-30 martijn return optional ? start : NULL;
593 4f29629b 2020-08-30 martijn if (ptr++[0] != '@')
594 4f29629b 2020-08-30 martijn return optional ? start : NULL;
595 4f29629b 2020-08-30 martijn if ((ptr = osmtpd_mheader_skip_domain(ptr, 0)) == NULL)
596 4f29629b 2020-08-30 martijn return optional ? start : NULL;
597 4f29629b 2020-08-30 martijn return ptr;
601 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_obs_angle_addr(char *ptr, int optional)
603 4f29629b 2020-08-30 martijn char *start = ptr;
605 4f29629b 2020-08-30 martijn ptr = osmtpd_mheader_skip_cfws(ptr, 1);
606 4f29629b 2020-08-30 martijn if (ptr++[0] != '<')
607 4f29629b 2020-08-30 martijn return optional ? start : NULL;
608 4f29629b 2020-08-30 martijn if ((ptr = osmtpd_mheader_skip_obs_route(ptr, 0)) == NULL)
609 4f29629b 2020-08-30 martijn return optional ? start : NULL;
610 4f29629b 2020-08-30 martijn if ((ptr = osmtpd_mheader_skip_addr_spec(ptr, 0)) == NULL)
611 4f29629b 2020-08-30 martijn return optional ? start : NULL;
612 4f29629b 2020-08-30 martijn if (ptr++[0] != '>')
613 4f29629b 2020-08-30 martijn return optional ? start : NULL;
614 4f29629b 2020-08-30 martijn return osmtpd_mheader_skip_cfws(ptr, 1);
618 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_angle_addr(char *ptr, int optional)
620 4f29629b 2020-08-30 martijn char *start = ptr;
622 4f29629b 2020-08-30 martijn ptr = osmtpd_mheader_skip_cfws(ptr, 1);
623 4f29629b 2020-08-30 martijn if (ptr++[0] != '<')
624 4f29629b 2020-08-30 martijn return osmtpd_mheader_skip_obs_angle_addr(start, optional);
625 4f29629b 2020-08-30 martijn if ((ptr = osmtpd_mheader_skip_addr_spec(ptr, 0)) == NULL)
626 4f29629b 2020-08-30 martijn return osmtpd_mheader_skip_obs_angle_addr(start, optional);
627 4f29629b 2020-08-30 martijn if (ptr++[0] != '>')
628 4f29629b 2020-08-30 martijn return osmtpd_mheader_skip_obs_angle_addr(start, optional);
629 4f29629b 2020-08-30 martijn return osmtpd_mheader_skip_cfws(ptr, 1);
633 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_name_addr(char *ptr, int optional)
635 4f29629b 2020-08-30 martijn char *start = ptr;
637 4f29629b 2020-08-30 martijn ptr = osmtpd_mheader_skip_display_name(ptr, 1);
638 4f29629b 2020-08-30 martijn if ((ptr = osmtpd_mheader_skip_angle_addr(ptr, 0)) == NULL)
639 4f29629b 2020-08-30 martijn return optional ? start : NULL;
640 4f29629b 2020-08-30 martijn return ptr;
643 4f29629b 2020-08-30 martijn /* RFC 2045 */
645 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_tspecials(char *ptr, int optional)
647 4f29629b 2020-08-30 martijn if (ptr[0] == '(' || ptr[0] == ')' || ptr[0] == '<' || ptr[0] == '>' ||
648 4f29629b 2020-08-30 martijn ptr[0] == '@' || ptr[0] == ',' || ptr[0] == ';' || ptr[0] == ':' ||
649 4f29629b 2020-08-30 martijn ptr[0] == '\\' || ptr[0] == '\'' || ptr[0] == '/' ||
650 4f29629b 2020-08-30 martijn ptr[0] == '[' || ptr[0] == ']' || ptr[0] == '?' || ptr[0] == '=')
651 4f29629b 2020-08-30 martijn return ptr + 1;
652 4f29629b 2020-08-30 martijn return optional ? ptr : NULL;
657 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_token(char *ptr, int optional)
659 4f29629b 2020-08-30 martijn if (osmtpd_mheader_skip_char(ptr, 0) == NULL)
660 4f29629b 2020-08-30 martijn return optional ? ptr : NULL;
661 4f29629b 2020-08-30 martijn /* Can't find the official definition for SPACE, so use WSP */
662 4f29629b 2020-08-30 martijn if (osmtpd_mheader_skip_wsp(ptr, 0) != NULL)
663 4f29629b 2020-08-30 martijn return optional ? ptr : NULL;
664 4f29629b 2020-08-30 martijn if (osmtpd_mheader_skip_ctl(ptr, 0) != NULL)
665 4f29629b 2020-08-30 martijn return optional ? ptr : NULL;
666 4f29629b 2020-08-30 martijn if (osmtpd_mheader_skip_tspecials(ptr, 0) != NULL)
667 4f29629b 2020-08-30 martijn return optional ? ptr : NULL;
669 4f29629b 2020-08-30 martijn while (1) {
670 4f29629b 2020-08-30 martijn if (osmtpd_mheader_skip_char(ptr, 0) == NULL)
671 4f29629b 2020-08-30 martijn return ptr;
672 4f29629b 2020-08-30 martijn if (osmtpd_mheader_skip_wsp(ptr, 0) != NULL)
673 4f29629b 2020-08-30 martijn return ptr;
674 4f29629b 2020-08-30 martijn if (osmtpd_mheader_skip_ctl(ptr, 0) != NULL)
675 4f29629b 2020-08-30 martijn return ptr;
676 4f29629b 2020-08-30 martijn if (osmtpd_mheader_skip_tspecials(ptr, 0) != NULL)
677 4f29629b 2020-08-30 martijn return ptr;
683 4f29629b 2020-08-30 martijn osmtpd_mheader_skip_value(char *ptr, int optional)
685 4f29629b 2020-08-30 martijn char *start = ptr;
687 4f29629b 2020-08-30 martijn if ((ptr = osmtpd_mheader_skip_token(ptr, 0)) == NULL)
688 4f29629b 2020-08-30 martijn return osmtpd_mheader_skip_quoted_string(start, optional);
689 4f29629b 2020-08-30 martijn return ptr;
692 4f29629b 2020-08-30 martijn /* Return the domain component of the first mailbox */
694 4f29629b 2020-08-30 martijn osmtpd_mheader_from_domain(char *ptr)
696 4f29629b 2020-08-30 martijn char *tmp;
698 4f29629b 2020-08-30 martijn /* from */
699 4f29629b 2020-08-30 martijn if (strncasecmp(ptr, "from:", 5) == 0) {
700 4f29629b 2020-08-30 martijn ptr += 5;
701 4f29629b 2020-08-30 martijn /* obs-from */
702 4f29629b 2020-08-30 martijn } else if (strncasecmp(ptr, "from", 4) == 0) {
703 4f29629b 2020-08-30 martijn ptr += 4;
705 4f29629b 2020-08-30 martijn tmp = ptr;
706 4f29629b 2020-08-30 martijn } while ((ptr = osmtpd_mheader_skip_wsp(ptr, 0)) != NULL);
707 4f29629b 2020-08-30 martijn ptr = tmp;
708 4f29629b 2020-08-30 martijn if (ptr++[0] != ':')
709 4f29629b 2020-08-30 martijn return NULL;
710 4f29629b 2020-08-30 martijn } else {
711 4f29629b 2020-08-30 martijn errno = EINVAL;
712 4f29629b 2020-08-30 martijn return NULL;
715 4f29629b 2020-08-30 martijn /* Both from and obs-from use Mailbox-list CRLF */
716 4f29629b 2020-08-30 martijn /* obs-mbox-list has just a prefix compared to mailbox-list */
717 4f29629b 2020-08-30 martijn while (1) {
718 4f29629b 2020-08-30 martijn tmp = ptr;
719 4f29629b 2020-08-30 martijn ptr = osmtpd_mheader_skip_cfws(ptr, 1);
720 4f29629b 2020-08-30 martijn if (ptr++[0] != ',') {
721 4f29629b 2020-08-30 martijn ptr = tmp;
725 4f29629b 2020-08-30 martijn /* We're only interested in the first mailbox */
726 4f29629b 2020-08-30 martijn if (osmtpd_mheader_skip_name_addr(ptr, 0) != NULL) {
727 4f29629b 2020-08-30 martijn ptr = osmtpd_mheader_skip_display_name(ptr, 1);
728 4f29629b 2020-08-30 martijn ptr = osmtpd_mheader_skip_cfws(ptr, 1);
731 4f29629b 2020-08-30 martijn /* addr-spec */
732 4f29629b 2020-08-30 martijn ptr = osmtpd_mheader_skip_local_part(ptr, 0);
735 4f29629b 2020-08-30 martijn tmp = osmtpd_mheader_skip_domain(ptr, 0);
736 4f29629b 2020-08-30 martijn return strndup(ptr, tmp - ptr);
738 4f29629b 2020-08-30 martijn if (osmtpd_mheader_skip_addr_spec(ptr, 0) != NULL) {
739 4f29629b 2020-08-30 martijn ptr = osmtpd_mheader_skip_local_part(ptr, 0);
742 4f29629b 2020-08-30 martijn tmp = osmtpd_mheader_skip_domain(ptr, 0);
743 4f29629b 2020-08-30 martijn return strndup(ptr, tmp - ptr);
745 4f29629b 2020-08-30 martijn errno = EINVAL;
746 4f29629b 2020-08-30 martijn return NULL;