1877 lines
43 KiB
C
1877 lines
43 KiB
C
/*
|
|
* Copyright (c) 2020-2022 Martijn van Duren <martijn@openbsd.org>
|
|
*
|
|
* Permission to use, copy, modify, and distribute this software for any
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
* copyright notice and this permission notice appear in all copies.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
|
|
#include <ctype.h>
|
|
#include <errno.h>
|
|
#include <stddef.h>
|
|
#include <string.h>
|
|
#include <strings.h>
|
|
|
|
#include "ltok.h"
|
|
|
|
/* RFC 5234 - Augmented BNF for Syntax Specifications: ABNF */
|
|
const char *
|
|
osmtpd_ltok_skip_alpha(const char *ptr, int optional)
|
|
{
|
|
if ((ptr[0] >= 0x41 && ptr[0] <= 0x5a) ||
|
|
(ptr[0] >= 0x61 && ptr[0] <= 0x7a))
|
|
return ptr + 1;
|
|
return optional ? ptr : NULL;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_bit(const char *ptr, int optional)
|
|
{
|
|
if (ptr[0] == '0' || ptr[0] == '1')
|
|
return ptr + 1;
|
|
return optional ? ptr : NULL;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_char(const char *ptr, int optional)
|
|
{
|
|
if (ptr[0] >= 0x01 && ptr[0] <= 0x7f)
|
|
return ptr + 1;
|
|
return optional ? ptr : NULL;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_cr(const char *ptr, int optional)
|
|
{
|
|
if (ptr[0] == 0xd)
|
|
return ptr + 1;
|
|
return optional ? ptr : NULL;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_crlf(const char *ptr, int optional)
|
|
{
|
|
if (ptr[0] == 13 && ptr[1] == 10)
|
|
return ptr + 2;
|
|
return optional ? ptr : NULL;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_ctl(const char *ptr, int optional)
|
|
{
|
|
if ((ptr[0] >= 0x00 && ptr[0] <= 0x1f) || ptr[0] == 0x7f)
|
|
return ptr + 1;
|
|
return optional ? ptr : NULL;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_digit(const char *ptr, int optional)
|
|
{
|
|
if (ptr[0] >= 0x30 && ptr[0] <= 0x39)
|
|
return ptr + 1;
|
|
return optional ? ptr : NULL;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_dquote(const char *ptr, int optional)
|
|
{
|
|
if (ptr[0] == 0x22)
|
|
return ptr + 1;
|
|
return optional ? ptr : NULL;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_hexdig(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
char l;
|
|
|
|
if ((ptr = osmtpd_ltok_skip_digit(ptr, 0)) != NULL)
|
|
return ptr;
|
|
l = tolower(start[0]);
|
|
if (l == 'a' || l == 'b' || l == 'c' || l == 'd' ||
|
|
l == 'e' || l == 'f')
|
|
return start + 1;
|
|
return optional ? start : NULL;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_htab(const char *ptr, int optional)
|
|
{
|
|
if (ptr[0] == 0x9)
|
|
return ptr + 1;
|
|
return optional ? ptr : NULL;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_lf(const char *ptr, int optional)
|
|
{
|
|
if (ptr[0] == 0xa)
|
|
return ptr + 1;
|
|
return optional ? ptr : NULL;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_octet(const char *ptr, int optional)
|
|
{
|
|
return ptr + 1;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_sp(const char *ptr, int optional)
|
|
{
|
|
if (ptr[0] == 0x20)
|
|
return ptr + 1;
|
|
return optional ? ptr : NULL;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_vchar(const char *ptr, int optional)
|
|
{
|
|
if (ptr[0] >= 0x21 && ptr[0] <= 0x7e)
|
|
return ptr + 1;
|
|
return optional ? ptr : NULL;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_wsp(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if ((ptr = osmtpd_ltok_skip_sp(start, 0)) != NULL ||
|
|
(ptr = osmtpd_ltok_skip_htab(start, 0)) != NULL)
|
|
return ptr;
|
|
return optional ? start : NULL;
|
|
}
|
|
|
|
/* RFC 5321 - Simple Mail Transfer Protocol */
|
|
const char *
|
|
osmtpd_ltok_skip_keyword(const char *ptr, int optional)
|
|
{
|
|
return osmtpd_ltok_skip_ldh_string(ptr, optional);
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_sub_domain(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if ((ptr = osmtpd_ltok_skip_let_dig(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
return osmtpd_ltok_skip_ldh_string(ptr, 1);
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_let_dig(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if ((ptr = osmtpd_ltok_skip_alpha(start, 0)) == NULL &&
|
|
(ptr = osmtpd_ltok_skip_digit(start, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
return ptr;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_ldh_string(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr, *prev;
|
|
int letdig = 0;
|
|
|
|
while (1) {
|
|
prev = ptr;
|
|
if ((ptr = osmtpd_ltok_skip_alpha(prev, 0)) != NULL ||
|
|
(ptr = osmtpd_ltok_skip_digit(prev, 0)) != NULL) {
|
|
letdig = 1;
|
|
continue;
|
|
}
|
|
if (prev[0] == '-') {
|
|
letdig = 0;
|
|
ptr = prev + 1;
|
|
continue;
|
|
}
|
|
ptr = prev;
|
|
break;
|
|
}
|
|
if (letdig)
|
|
return ptr;
|
|
if (ptr == start)
|
|
return optional ? start : NULL;
|
|
return ptr;
|
|
}
|
|
|
|
/* RFC 5322 - Internet Message Format */
|
|
const char *
|
|
osmtpd_ltok_skip_quoted_pair(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if (ptr[0] == '\\' && (
|
|
(ptr = osmtpd_ltok_skip_vchar(start + 1, 0)) != NULL ||
|
|
(ptr = osmtpd_ltok_skip_wsp(start + 1, 0)) != NULL))
|
|
return ptr;
|
|
return osmtpd_ltok_skip_obs_qp(start, optional);
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_fws(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr, *prev = ptr;
|
|
|
|
while ((ptr = osmtpd_ltok_skip_wsp(ptr, 0)) != NULL)
|
|
prev = ptr;
|
|
if ((ptr = osmtpd_ltok_skip_crlf(prev, 1)) == prev)
|
|
ptr = start;
|
|
if ((ptr = osmtpd_ltok_skip_wsp(ptr, 0)) == NULL)
|
|
return osmtpd_ltok_skip_obs_fws(start, optional);
|
|
prev = ptr;
|
|
while ((ptr = osmtpd_ltok_skip_wsp(ptr, 0)) != NULL)
|
|
prev = ptr;
|
|
return prev;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_ctext(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if ((ptr[0] >= 33 && ptr[0] <= 39) || (ptr[0] >= 42 && ptr[0] <= 91) ||
|
|
(ptr[0] >= 93 && ptr[0] <= 126))
|
|
return ptr + 1;
|
|
if ((ptr = osmtpd_ltok_skip_obs_ctext(ptr, 0)) != NULL)
|
|
return ptr;
|
|
return optional ? start : NULL;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_ccontent(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if ((ptr = osmtpd_ltok_skip_ctext(ptr, 0)) != NULL)
|
|
return ptr;
|
|
if ((ptr = osmtpd_ltok_skip_quoted_pair(start, 0)) != NULL)
|
|
return ptr;
|
|
if ((ptr = osmtpd_ltok_skip_comment(start, 0)) != NULL)
|
|
return ptr;
|
|
return optional ? start : NULL;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_comment(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if (ptr++[0] != '(')
|
|
return optional ? start : NULL;
|
|
while (1) {
|
|
ptr = osmtpd_ltok_skip_fws(ptr, 1);
|
|
if (ptr[0] == ')')
|
|
return ptr + 1;
|
|
if ((ptr = osmtpd_ltok_skip_ccontent(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
}
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_cfws(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr, *prev;
|
|
|
|
while (1) {
|
|
ptr = osmtpd_ltok_skip_fws(ptr, 1);
|
|
prev = ptr;
|
|
if ((ptr = osmtpd_ltok_skip_comment(ptr, 0)) == NULL) {
|
|
ptr = prev;
|
|
break;
|
|
}
|
|
}
|
|
return ptr == start && !optional ? NULL : ptr;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_atext(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if ((ptr = osmtpd_ltok_skip_alpha(start, 0)) != NULL ||
|
|
(ptr = osmtpd_ltok_skip_digit(start, 0)) != NULL)
|
|
return ptr;
|
|
ptr = start;
|
|
if (ptr[0] == '!' || ptr[0] == '#' || ptr[0] == '$' || ptr[0] == '%' ||
|
|
ptr[0] == '&' || ptr[0] == '\'' || ptr[0] == '*' || ptr[0] == '+' ||
|
|
ptr[0] == '-' || ptr[0] == '/' || ptr[0] == '=' || ptr[0] == '?' ||
|
|
ptr[0] == '^' || ptr[0] == '_' || ptr[0] == '`' || ptr[0] == '{' ||
|
|
ptr[0] == '|' || ptr[0] == '}' || ptr[0] == '~')
|
|
return ptr + 1;
|
|
return optional ? start : NULL;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_atom(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr, *prev;
|
|
|
|
ptr = osmtpd_ltok_skip_cfws(ptr, 1);
|
|
if ((ptr = osmtpd_ltok_skip_atext(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
do {
|
|
prev = ptr;
|
|
ptr = osmtpd_ltok_skip_atext(ptr, 1);
|
|
} while (prev != ptr);
|
|
return osmtpd_ltok_skip_cfws(ptr, 1);
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_dot_atom_text(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr, *prev;
|
|
|
|
if ((ptr = osmtpd_ltok_skip_atext(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
do {
|
|
prev = ptr;
|
|
ptr = osmtpd_ltok_skip_atext(ptr, 1);
|
|
} while (ptr != prev);
|
|
|
|
while (ptr[0] == '.') {
|
|
ptr++;
|
|
if ((ptr = osmtpd_ltok_skip_atext(ptr, 0)) == NULL)
|
|
return prev;
|
|
do {
|
|
prev = ptr;
|
|
ptr = osmtpd_ltok_skip_atext(ptr, 1);
|
|
} while (ptr != prev);
|
|
}
|
|
return ptr;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_dot_atom(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
ptr = osmtpd_ltok_skip_cfws(ptr, 1);
|
|
if ((ptr = osmtpd_ltok_skip_dot_atom_text(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
return osmtpd_ltok_skip_cfws(ptr, 1);
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_qtext(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if (ptr[0] == 33 || (ptr[0] >= 35 && ptr[0] <= 91) ||
|
|
(ptr[0] >= 93 && ptr[0] <= 126))
|
|
return ptr + 1;
|
|
if ((ptr = osmtpd_ltok_skip_obs_qtext(ptr, 0)) != NULL)
|
|
return ptr;
|
|
return optional ? start : NULL;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_qcontent(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if ((ptr = osmtpd_ltok_skip_qtext(ptr, 0)) != NULL)
|
|
return ptr;
|
|
return osmtpd_ltok_skip_quoted_pair(start, optional);
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_quoted_string(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr, *prev;
|
|
|
|
ptr = osmtpd_ltok_skip_cfws(ptr, 1);
|
|
if ((ptr = osmtpd_ltok_skip_dquote(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
prev = ptr;
|
|
while (1) {
|
|
ptr = osmtpd_ltok_skip_fws(ptr, 1);
|
|
if ((ptr = osmtpd_ltok_skip_qcontent(ptr, 0)) == NULL)
|
|
break;
|
|
prev = ptr;
|
|
}
|
|
if ((ptr = osmtpd_ltok_skip_dquote(prev, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
return osmtpd_ltok_skip_cfws(ptr, 1);
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_word(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if ((ptr = osmtpd_ltok_skip_atom(ptr, 0)) != NULL)
|
|
return ptr;
|
|
return osmtpd_ltok_skip_quoted_string(start, optional);
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_phrase(const char *ptr, int optional)
|
|
{
|
|
/* obs-phrase is a superset of phrae */
|
|
return osmtpd_ltok_skip_obs_phrase(ptr, optional);
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_name_addr(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
ptr = osmtpd_ltok_skip_display_name(ptr, 1);
|
|
if ((ptr = osmtpd_ltok_skip_angle_addr(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
return ptr;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_angle_addr(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
ptr = osmtpd_ltok_skip_cfws(ptr, 1);
|
|
if (ptr++[0] != '<')
|
|
return osmtpd_ltok_skip_obs_angle_addr(start, optional);
|
|
if ((ptr = osmtpd_ltok_skip_addr_spec(ptr, 0)) == NULL)
|
|
return osmtpd_ltok_skip_obs_angle_addr(start, optional);
|
|
if (ptr++[0] != '>')
|
|
return osmtpd_ltok_skip_obs_angle_addr(start, optional);
|
|
return osmtpd_ltok_skip_cfws(ptr, 1);
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_display_name(const char *ptr, int optional)
|
|
{
|
|
return osmtpd_ltok_skip_phrase(ptr, optional);
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_addr_spec(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if ((ptr = osmtpd_ltok_skip_local_part(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
if (ptr++[0] != '@')
|
|
return optional ? start : NULL;
|
|
if ((ptr = osmtpd_ltok_skip_domain(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
return ptr;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_local_part(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if ((ptr = osmtpd_ltok_skip_dot_atom(ptr, 0)) != NULL)
|
|
return ptr;
|
|
ptr = start;
|
|
if ((ptr = osmtpd_ltok_skip_quoted_string(ptr, 0)) != NULL)
|
|
return ptr;
|
|
return osmtpd_ltok_skip_obs_local_part(start, optional);
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_domain(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if ((ptr = osmtpd_ltok_skip_dot_atom(start, 0)) != NULL)
|
|
return ptr;
|
|
if ((ptr = osmtpd_ltok_skip_domain_literal(start, 0)) != NULL)
|
|
return ptr;
|
|
return osmtpd_ltok_skip_obs_domain(start, optional);
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_domain_literal(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr, *prev;
|
|
|
|
ptr = osmtpd_ltok_skip_cfws(ptr, 1);
|
|
if (ptr++[0] != '[')
|
|
return optional ? start : NULL;
|
|
while (1) {
|
|
ptr = osmtpd_ltok_skip_fws(ptr, 1);
|
|
prev = ptr;
|
|
if ((ptr = osmtpd_ltok_skip_dtext(ptr, 0)) == NULL) {
|
|
ptr = prev;
|
|
break;
|
|
}
|
|
}
|
|
if (ptr[0] != ']')
|
|
return optional ? start : NULL;
|
|
ptr++;
|
|
return osmtpd_ltok_skip_cfws(ptr, 1);
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_dtext(const char *ptr, int optional)
|
|
{
|
|
if ((ptr[0] >= 33 && ptr[0] <= 90) || (ptr[0] >= 94 && ptr[0] <= 126))
|
|
return ptr + 1;
|
|
return osmtpd_ltok_skip_obs_dtext(ptr, optional);
|
|
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_field_name(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if ((ptr = osmtpd_ltok_skip_ftext(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
while (1) {
|
|
start = ptr;
|
|
if ((ptr = osmtpd_ltok_skip_ftext(ptr, 0)) == NULL)
|
|
return start;
|
|
}
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_ftext(const char *ptr, int optional)
|
|
{
|
|
if ((ptr[0] >= 33 && ptr[0] <= 57) ||
|
|
(ptr[0] >= 59 && ptr[0] <= 126))
|
|
return ptr + 1;
|
|
return optional ? ptr : NULL;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_obs_no_ws_ctl(const char *ptr, int optional)
|
|
{
|
|
if ((ptr[0] >= 1 && ptr[0] <= 8) || ptr[0] == 11 || ptr[0] == 12 ||
|
|
(ptr[0] >= 14 && ptr[0] <= 31) || ptr[0] == 127)
|
|
return ptr + 1;
|
|
return optional ? ptr : NULL;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_obs_ctext(const char *ptr, int optional)
|
|
{
|
|
return osmtpd_ltok_skip_obs_no_ws_ctl(ptr, optional);
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_obs_qtext(const char *ptr, int optional)
|
|
{
|
|
return osmtpd_ltok_skip_obs_no_ws_ctl(ptr, optional);
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_obs_qp(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if (ptr[0] == '\\' && (
|
|
(ptr = osmtpd_ltok_skip_obs_no_ws_ctl(start + 1, 0)) != NULL ||
|
|
(ptr = osmtpd_ltok_skip_lf(start + 1, 0)) != NULL ||
|
|
(ptr = osmtpd_ltok_skip_cr(start + 1, 0)) != NULL))
|
|
return ptr;
|
|
return optional ? start : NULL;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_obs_phrase(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr, *prev;
|
|
|
|
if ((ptr = osmtpd_ltok_skip_word(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
while (1) {
|
|
prev = ptr;
|
|
if ((ptr = osmtpd_ltok_skip_word(ptr, 0)) != NULL)
|
|
continue;
|
|
ptr = prev;
|
|
if (ptr[0] == '.') {
|
|
ptr++;
|
|
continue;
|
|
}
|
|
if ((ptr = osmtpd_ltok_skip_cfws(ptr, 0)) != NULL)
|
|
continue;
|
|
return prev;
|
|
}
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_obs_fws(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr, *prev;
|
|
|
|
if ((ptr = osmtpd_ltok_skip_wsp(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
prev = ptr;
|
|
while ((ptr = osmtpd_ltok_skip_wsp(ptr, 0)) != NULL)
|
|
prev = ptr;
|
|
|
|
ptr = prev;
|
|
while (1) {
|
|
if ((ptr = osmtpd_ltok_skip_crlf(ptr, 0)) == NULL)
|
|
return prev;
|
|
if ((ptr = osmtpd_ltok_skip_wsp(ptr, 0)) == NULL)
|
|
return prev;
|
|
prev = ptr;
|
|
while ((ptr = osmtpd_ltok_skip_wsp(ptr, 0)) != NULL)
|
|
prev = ptr;
|
|
ptr = prev;
|
|
}
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_obs_angle_addr(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
ptr = osmtpd_ltok_skip_cfws(ptr, 1);
|
|
if (ptr++[0] != '<')
|
|
return optional ? start : NULL;
|
|
if ((ptr = osmtpd_ltok_skip_obs_route(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
if ((ptr = osmtpd_ltok_skip_addr_spec(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
if (ptr++[0] != '>')
|
|
return optional ? start : NULL;
|
|
return osmtpd_ltok_skip_cfws(ptr, 1);
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_obs_route(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if ((ptr = osmtpd_ltok_skip_obs_domain_list(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
if (ptr++[0] != ':')
|
|
return optional ? start : NULL;
|
|
return ptr;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_obs_domain_list(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr, *prev = ptr;
|
|
|
|
while (1) {
|
|
if (ptr[0] == ',') {
|
|
ptr++;
|
|
prev = ptr;
|
|
continue;
|
|
} else if ((ptr = osmtpd_ltok_skip_cfws(ptr, 0)) != NULL) {
|
|
prev = ptr;
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
ptr = prev;
|
|
|
|
if (ptr++[0] != '@')
|
|
return optional ? start : NULL;
|
|
if ((ptr = osmtpd_ltok_skip_domain(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
while (1) {
|
|
if (ptr[0] != ',')
|
|
break;
|
|
ptr++;
|
|
ptr = osmtpd_ltok_skip_cfws(ptr, 1);
|
|
if (ptr[0] != '@')
|
|
continue;
|
|
prev = ptr;
|
|
if ((ptr = osmtpd_ltok_skip_domain(ptr + 1, 0)) == NULL) {
|
|
ptr = prev;
|
|
break;
|
|
}
|
|
}
|
|
return ptr;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_obs_local_part(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr, *prev;
|
|
|
|
if ((ptr = osmtpd_ltok_skip_word(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
prev = ptr;
|
|
while (ptr[0] == '.') {
|
|
ptr++;
|
|
if ((ptr = osmtpd_ltok_skip_word(ptr, 0)) == NULL)
|
|
return prev;
|
|
prev = ptr;
|
|
}
|
|
return ptr;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_obs_domain(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr, *prev;
|
|
|
|
if ((ptr = osmtpd_ltok_skip_atom(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
prev = ptr;
|
|
while (1) {
|
|
if (ptr++[0] != '.')
|
|
return prev;
|
|
if ((ptr = osmtpd_ltok_skip_atom(ptr, 0)) == NULL)
|
|
return prev;
|
|
prev = ptr;
|
|
}
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_obs_dtext(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if ((ptr = osmtpd_ltok_skip_obs_no_ws_ctl(ptr, 0)) != NULL)
|
|
return ptr;
|
|
return osmtpd_ltok_skip_quoted_pair(start, optional);
|
|
}
|
|
|
|
/* RFC 2045 - Multipurpose Internet Mail Extensions */
|
|
const char *
|
|
osmtpd_ltok_skip_value(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if ((ptr = osmtpd_ltok_skip_token(start, 0)) != NULL)
|
|
return ptr;
|
|
if ((ptr = osmtpd_ltok_skip_quoted_string(start, 0)) != NULL)
|
|
return ptr;
|
|
return optional ? start : NULL;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_token(const char *ptr, int optional)
|
|
{
|
|
const char *start;
|
|
int first = 1;
|
|
|
|
while (1) {
|
|
start = ptr;
|
|
if ((ptr = osmtpd_ltok_skip_char(start, 0)) != NULL &&
|
|
osmtpd_ltok_skip_sp(start, 0) == NULL &&
|
|
osmtpd_ltok_skip_ctl(start, 0) == NULL &&
|
|
osmtpd_ltok_skip_tspecials(start, 0) == NULL) {
|
|
first = 0;
|
|
continue;
|
|
}
|
|
return optional || !first ? start : NULL;
|
|
}
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_tspecials(const char *ptr, int optional)
|
|
{
|
|
if (ptr[0] == '(' || ptr[0] == ')' || ptr[0] == '<' || ptr[0] == '>' ||
|
|
ptr[0] == '@' || ptr[0] == ',' || ptr[0] == ';' || ptr[0] == ':' ||
|
|
ptr[0] == '\\' || ptr[0] == '"' || ptr[0] == '/' || ptr[0] == '[' ||
|
|
ptr[0] == ']' || ptr[0] == '?' || ptr[0] == '=')
|
|
return ptr + 1;
|
|
return optional ? ptr : NULL;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_qp_section(const char *ptr, int optional)
|
|
{
|
|
const char *prev, *last = ptr;
|
|
|
|
while (1) {
|
|
prev = ptr;
|
|
if ((ptr = osmtpd_ltok_skip_ptext(prev, 0)) != NULL)
|
|
last = ptr;
|
|
else if ((ptr = osmtpd_ltok_skip_sp(prev, 0)) == NULL &&
|
|
(ptr = osmtpd_ltok_skip_htab(prev, 0)) == NULL)
|
|
return last;
|
|
}
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_ptext(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if ((ptr = osmtpd_ltok_skip_hex_octet(start, 0)) == NULL &&
|
|
(ptr = osmtpd_ltok_skip_safe_char(start, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
return ptr;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_safe_char(const char *ptr, int optional)
|
|
{
|
|
if ((ptr[0] >= 33 && ptr[0] <= 60) || (ptr[0] >= 62 && ptr[0] <= 126))
|
|
return ptr + 1;
|
|
return optional ? ptr : NULL;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_hex_octet(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
char l;
|
|
|
|
if (ptr[0] != '=')
|
|
return optional ? start : NULL;
|
|
ptr++;
|
|
l = tolower(ptr[0]);
|
|
if (l == 'a' || l == 'b' || l == 'c' || l == 'd' ||
|
|
l == 'e' || l == 'f')
|
|
ptr++;
|
|
else if ((ptr = osmtpd_ltok_skip_digit(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
l = tolower(ptr[0]);
|
|
start = ptr;
|
|
if (l == 'a' || l == 'b' || l == 'c' || l == 'd' ||
|
|
l == 'e' || l == 'f')
|
|
ptr++;
|
|
else if ((ptr = osmtpd_ltok_skip_digit(ptr, 0)) == NULL)
|
|
return start;
|
|
return ptr;
|
|
}
|
|
|
|
/* RFC 6376 - DomainKeys Identified Mail (DKIM) Signatures */
|
|
const char *
|
|
osmtpd_ltok_skip_hyphenated_word(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr, *end;
|
|
|
|
if ((ptr = osmtpd_ltok_skip_alpha(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
|
|
end = ptr;
|
|
while (1) {
|
|
start = ptr;
|
|
if ((ptr = osmtpd_ltok_skip_alpha(start, 0)) != NULL ||
|
|
(ptr = osmtpd_ltok_skip_digit(start, 0)) != NULL) {
|
|
end = ptr;
|
|
} else if (start[0] == '-')
|
|
ptr = start + 1;
|
|
else
|
|
break;
|
|
}
|
|
return end;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_alphadigitps(const char *ptr, int optional)
|
|
{
|
|
const char *end;
|
|
|
|
if ((end = osmtpd_ltok_skip_alpha(ptr, 0)) == NULL &&
|
|
(end = osmtpd_ltok_skip_digit(ptr, 0)) == NULL &&
|
|
ptr[0] != '+' && ptr[0] != '/')
|
|
return optional ? ptr : NULL;
|
|
return end == NULL ? ptr + 1 : end;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_base64string(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if ((ptr = osmtpd_ltok_skip_alphadigitps(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
while (1) {
|
|
start = ptr;
|
|
ptr = osmtpd_ltok_skip_fws(ptr, 1);
|
|
if ((ptr = osmtpd_ltok_skip_alphadigitps(ptr, 0)) == NULL)
|
|
break;
|
|
}
|
|
ptr = start;
|
|
ptr = osmtpd_ltok_skip_fws(ptr, 1);
|
|
if (ptr[0] == '=') {
|
|
ptr++;
|
|
start = ptr;
|
|
ptr = osmtpd_ltok_skip_fws(ptr, 1);
|
|
if (ptr[0] == '=')
|
|
ptr++;
|
|
else
|
|
ptr = start;
|
|
} else
|
|
ptr = start;
|
|
return ptr;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_hdr_name(const char *ptr, int optional)
|
|
{
|
|
return osmtpd_ltok_skip_field_name(ptr, optional);
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_qp_hdr_value(const char *ptr, int optional)
|
|
{
|
|
return osmtpd_ltok_skip_dkim_quoted_printable(ptr, optional);
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_dkim_quoted_printable(const char *ptr, int optional)
|
|
{
|
|
const char *start;
|
|
|
|
while (1) {
|
|
start = ptr;
|
|
if ((ptr = osmtpd_ltok_skip_fws(start, 0)) != NULL)
|
|
continue;
|
|
if ((ptr = osmtpd_ltok_skip_hex_octet(start, 0)) != NULL)
|
|
continue;
|
|
ptr = osmtpd_ltok_skip_dkim_safe_char(start, 0);
|
|
if (ptr == NULL)
|
|
break;
|
|
}
|
|
return start;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_dkim_safe_char(const char *ptr, int optional)
|
|
{
|
|
if ((ptr[0] >= 0x21 && ptr[0] <= 0x3a) || ptr[0] == 0x3c ||
|
|
(ptr[0] >= 0x3e && ptr[0] <= 0x7e))
|
|
return ptr + 1;
|
|
return optional ? ptr : NULL;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_selector(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if ((ptr = osmtpd_ltok_skip_sub_domain(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
while (1) {
|
|
start = ptr;
|
|
if (ptr[0] != '.')
|
|
return start;
|
|
ptr++;
|
|
if ((ptr = osmtpd_ltok_skip_sub_domain(ptr, 0)) == NULL)
|
|
return start;
|
|
}
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_tag_list(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if ((ptr = osmtpd_ltok_skip_tag_spec(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
while (1) {
|
|
/* Starting or trailing ';' */
|
|
if (ptr[0] != ';')
|
|
return ptr;
|
|
ptr++;
|
|
start = ptr;
|
|
if ((ptr = osmtpd_ltok_skip_tag_spec(ptr, 0)) == NULL)
|
|
return start;
|
|
}
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_tag_spec(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
ptr = osmtpd_ltok_skip_fws(ptr, 1);
|
|
if ((ptr = osmtpd_ltok_skip_tag_name(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
ptr = osmtpd_ltok_skip_fws(ptr, 1);
|
|
if (ptr[0] != '=')
|
|
return optional ? start : NULL;
|
|
ptr++;
|
|
ptr = osmtpd_ltok_skip_fws(ptr, 1);
|
|
if ((ptr = osmtpd_ltok_skip_tag_value(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
return osmtpd_ltok_skip_fws(ptr, 1);
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_tag_name(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr, *prev;
|
|
|
|
if ((ptr = osmtpd_ltok_skip_alpha(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
prev = ptr;
|
|
while ((ptr = osmtpd_ltok_skip_alnumpunc(ptr, 0)) != NULL)
|
|
prev = ptr;
|
|
return prev;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_tag_value(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr, *prev;
|
|
|
|
if ((ptr = osmtpd_ltok_skip_tval(ptr, 0)) == NULL)
|
|
return start;
|
|
|
|
while (1) {
|
|
start = ptr;
|
|
/* FWS contains WSP */
|
|
if ((ptr = osmtpd_ltok_skip_fws(ptr, 0)) == NULL)
|
|
return start;
|
|
prev = ptr;
|
|
while ((ptr = osmtpd_ltok_skip_fws(ptr, 0)) != NULL)
|
|
prev = ptr;
|
|
ptr = prev;
|
|
if ((ptr = osmtpd_ltok_skip_tval(ptr, 0)) == NULL)
|
|
return start;
|
|
}
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_tval(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr, *prev;
|
|
|
|
if ((ptr = osmtpd_ltok_skip_valchar(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
prev = ptr;
|
|
while ((ptr = osmtpd_ltok_skip_valchar(ptr, 0)) != NULL)
|
|
prev = ptr;
|
|
return prev;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_valchar(const char *ptr, int optional)
|
|
{
|
|
if ((ptr[0] >= 0x21 && ptr[0] <= 0x3A) ||
|
|
(ptr[0] >= 0x3C && ptr[0] <= 0x7E))
|
|
return ptr + 1;
|
|
return optional ? ptr : NULL;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_alnumpunc(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if ((ptr = osmtpd_ltok_skip_alpha(start, 0)) != NULL)
|
|
return ptr;
|
|
if ((ptr = osmtpd_ltok_skip_digit(start, 0)) != NULL)
|
|
return ptr;
|
|
if (start[0] == '_')
|
|
return start + 1;
|
|
return optional ? start : NULL;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_sig_v_tag(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if (ptr[0] != 0x76)
|
|
return optional ? start : NULL;
|
|
ptr = osmtpd_ltok_skip_fws(ptr + 1, 1);
|
|
if (ptr[0] != '=')
|
|
return optional ? start : NULL;
|
|
ptr = osmtpd_ltok_skip_fws(ptr, 1);
|
|
if ((ptr = osmtpd_ltok_skip_sig_v_tag_value(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
return ptr;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_sig_v_tag_value(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr, *prev;
|
|
|
|
if ((ptr = osmtpd_ltok_skip_digit(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
while (1) {
|
|
prev = ptr;
|
|
if ((ptr = osmtpd_ltok_skip_digit(ptr, 0)) == NULL)
|
|
return prev;
|
|
}
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_sig_a_tag(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if (ptr[0] != 0x61)
|
|
return optional ? start : NULL;
|
|
ptr = osmtpd_ltok_skip_fws(ptr + 1, 1);
|
|
if (ptr[0] != '=')
|
|
return optional ? start : NULL;
|
|
ptr = osmtpd_ltok_skip_fws(ptr, 1);
|
|
if ((ptr = osmtpd_ltok_skip_sig_a_tag_value(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
return ptr;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_sig_a_tag_value(const char *ptr, int optional)
|
|
{
|
|
return osmtpd_ltok_skip_sig_a_tag_alg(ptr, optional);
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_sig_a_tag_alg(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if ((ptr = osmtpd_ltok_skip_sig_a_tag_k(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
if (ptr[0] != '-')
|
|
return optional ? start : NULL;
|
|
ptr++;
|
|
if ((ptr = osmtpd_ltok_skip_sig_a_tag_h(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
return ptr;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_sig_a_tag_k(const char *ptr, int optional)
|
|
{
|
|
/* sha1 / sha256 covered by x-sig-a-tag-k */
|
|
return osmtpd_ltok_skip_x_sig_a_tag_k(ptr, optional);
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_sig_a_tag_h(const char *ptr, int optional)
|
|
{
|
|
/* rsa / ed25519 covered by x-sig-a-tag-h */
|
|
return osmtpd_ltok_skip_x_sig_a_tag_h(ptr, optional);
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_x_sig_a_tag_k(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr, *prev, *end;
|
|
|
|
if ((ptr = osmtpd_ltok_skip_alpha(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
prev = ptr;
|
|
while ((end = osmtpd_ltok_skip_alpha(ptr, 0)) != NULL ||
|
|
(end = osmtpd_ltok_skip_digit(ptr, 0)) != NULL) {
|
|
ptr = end;
|
|
prev = end;
|
|
}
|
|
return prev;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_x_sig_a_tag_h(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr, *prev, *end;
|
|
|
|
if ((ptr = osmtpd_ltok_skip_alpha(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
prev = ptr;
|
|
while ((end = osmtpd_ltok_skip_alpha(ptr, 0)) != NULL ||
|
|
(end = osmtpd_ltok_skip_digit(ptr, 0)) != NULL) {
|
|
ptr = end;
|
|
prev = end;
|
|
}
|
|
return prev;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_sig_b_tag(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if (ptr[0] != 0x62)
|
|
return optional ? start : NULL;
|
|
ptr = osmtpd_ltok_skip_fws(ptr + 1, 1);
|
|
if (ptr[0] != '=')
|
|
return optional ? start : NULL;
|
|
ptr = osmtpd_ltok_skip_fws(ptr, 1);
|
|
if ((ptr = osmtpd_ltok_skip_sig_b_tag_value(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
return ptr;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_sig_b_tag_value(const char *ptr, int optional)
|
|
{
|
|
return osmtpd_ltok_skip_sig_b_tag_data(ptr, optional);
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_sig_b_tag_data(const char *ptr, int optional)
|
|
{
|
|
return osmtpd_ltok_skip_base64string(ptr, optional);
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_sig_bh_tag(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if (ptr[0] != 0x62 && ptr[0] != 0x68)
|
|
return optional ? start : NULL;
|
|
ptr = osmtpd_ltok_skip_fws(ptr + 2, 1);
|
|
if (ptr[0] != '=')
|
|
return optional ? start : NULL;
|
|
ptr = osmtpd_ltok_skip_fws(ptr, 1);
|
|
if ((ptr = osmtpd_ltok_skip_sig_bh_tag_value(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
return ptr;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_sig_bh_tag_value(const char *ptr, int optional)
|
|
{
|
|
return osmtpd_ltok_skip_sig_bh_tag_data(ptr, optional);
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_sig_bh_tag_data(const char *ptr, int optional)
|
|
{
|
|
return osmtpd_ltok_skip_base64string(ptr, optional);
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_sig_c_tag(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if (ptr[0] != 0x63)
|
|
return optional ? start : NULL;
|
|
ptr = osmtpd_ltok_skip_fws(ptr + 1, 1);
|
|
if (ptr[0] != '=')
|
|
return optional ? start : NULL;
|
|
ptr = osmtpd_ltok_skip_fws(ptr, 1);
|
|
if ((ptr = osmtpd_ltok_skip_sig_c_tag_value(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
return ptr;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_sig_c_tag_value(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if ((ptr = osmtpd_ltok_skip_sig_c_tag_alg(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
if (ptr[0] == '/') {
|
|
start = ptr;
|
|
if ((ptr = osmtpd_ltok_skip_sig_c_tag_alg(ptr, 0)) == NULL)
|
|
return start;
|
|
}
|
|
return ptr;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_sig_c_tag_alg(const char *ptr, int optional)
|
|
{
|
|
/* simple / relaxed covered by x-sig-c-tag-alga */
|
|
return osmtpd_ltok_skip_x_sig_c_tag_alg(ptr, optional);
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_x_sig_c_tag_alg(const char *ptr, int optional)
|
|
{
|
|
return osmtpd_ltok_skip_hyphenated_word(ptr, optional);
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_sig_d_tag(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if (ptr[0] != 0x64)
|
|
return optional ? start : NULL;
|
|
ptr = osmtpd_ltok_skip_fws(ptr + 1, 1);
|
|
if (ptr[0] != '=')
|
|
return optional ? start : NULL;
|
|
ptr = osmtpd_ltok_skip_fws(ptr, 1);
|
|
if ((ptr = osmtpd_ltok_skip_sig_d_tag_value(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
return ptr;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_sig_d_tag_value(const char *ptr, int optional)
|
|
{
|
|
return osmtpd_ltok_skip_domain_name(ptr, optional);
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_domain_name(const char *ptr, int optional)
|
|
{
|
|
const char *prev = ptr;
|
|
|
|
if ((ptr = osmtpd_ltok_skip_sub_domain(ptr, 0)) == NULL)
|
|
return optional ? prev : NULL;
|
|
while (1) {
|
|
prev = ptr;
|
|
if (ptr[0] != '.' ||
|
|
(ptr = osmtpd_ltok_skip_sub_domain(ptr + 1, 0)) == NULL)
|
|
return prev;
|
|
}
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_sig_h_tag(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if (ptr[0] != 0x68)
|
|
return optional ? start : NULL;
|
|
ptr = osmtpd_ltok_skip_fws(ptr + 1, 1);
|
|
if (ptr[0] != '=')
|
|
return optional ? start : NULL;
|
|
ptr = osmtpd_ltok_skip_fws(ptr, 1);
|
|
if ((ptr = osmtpd_ltok_skip_sig_h_tag_value(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
return ptr;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_sig_h_tag_value(const char *ptr, int optional)
|
|
{
|
|
const char *prev = ptr;
|
|
|
|
if ((ptr = osmtpd_ltok_skip_hdr_name(ptr, 0)) == NULL)
|
|
return optional ? prev : NULL;
|
|
while (1) {
|
|
prev = ptr;
|
|
ptr = osmtpd_ltok_skip_fws(ptr, 1);
|
|
if (ptr[0] != ':')
|
|
return prev;
|
|
ptr = osmtpd_ltok_skip_fws(ptr + 1, 1);
|
|
if ((ptr = osmtpd_ltok_skip_hdr_name(ptr, 0)) == NULL)
|
|
return prev;
|
|
}
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_sig_i_tag(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if (ptr[0] != 0x69)
|
|
return optional ? start : NULL;
|
|
ptr = osmtpd_ltok_skip_fws(ptr + 1, 1);
|
|
if (ptr[0] != '=')
|
|
return optional ? start : NULL;
|
|
ptr = osmtpd_ltok_skip_fws(ptr, 1);
|
|
if ((ptr = osmtpd_ltok_skip_sig_i_tag_value(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
return ptr;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_sig_i_tag_value(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
ptr = osmtpd_ltok_skip_local_part(ptr, 1);
|
|
if (ptr[0] != '@' ||
|
|
(ptr = osmtpd_ltok_skip_domain_name(ptr + 1, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
return ptr;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_sig_l_tag(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if (ptr[0] != 0x6c)
|
|
return optional ? start : NULL;
|
|
ptr = osmtpd_ltok_skip_fws(ptr + 1, 1);
|
|
if (ptr[0] != '=')
|
|
return optional ? start : NULL;
|
|
ptr = osmtpd_ltok_skip_fws(ptr, 1);
|
|
if ((ptr = osmtpd_ltok_skip_sig_l_tag_value(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
return ptr;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_sig_l_tag_value(const char *ptr, int optional)
|
|
{
|
|
size_t i;
|
|
|
|
for (i = 0; i < 76; i++) {
|
|
if (osmtpd_ltok_skip_digit(ptr + i, 0) == NULL)
|
|
break;
|
|
}
|
|
if (i >= 1 && i <= 76)
|
|
return ptr + i;
|
|
return optional ? ptr : NULL;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_sig_q_tag(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if (ptr[0] != 0x71)
|
|
return optional ? start : NULL;
|
|
ptr = osmtpd_ltok_skip_fws(ptr + 1, 1);
|
|
if (ptr[0] != '=')
|
|
return optional ? start : NULL;
|
|
ptr = osmtpd_ltok_skip_fws(ptr, 1);
|
|
if ((ptr = osmtpd_ltok_skip_sig_q_tag_value(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
return ptr;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_sig_q_tag_value(const char *ptr, int optional)
|
|
{
|
|
const char *prev = ptr;
|
|
if ((ptr = osmtpd_ltok_skip_sig_q_tag_method(ptr, 0)) == NULL)
|
|
return optional ? prev : NULL;
|
|
while (1) {
|
|
prev = ptr;
|
|
ptr = osmtpd_ltok_skip_fws(ptr, 1);
|
|
if (ptr[0] != ':')
|
|
return prev;
|
|
ptr = osmtpd_ltok_skip_fws(ptr + 1, 1);
|
|
if ((ptr = osmtpd_ltok_skip_sig_q_tag_method(ptr, 0)) == NULL)
|
|
return prev;
|
|
}
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_sig_q_tag_method(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
/* dns/txt covered by x-sig-q-tag-type ["/" x-sig-q-tag-args] */
|
|
if ((ptr = osmtpd_ltok_skip_x_sig_q_tag_type(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
start = ptr;
|
|
if (ptr[0] != '/')
|
|
return ptr;
|
|
if ((ptr = osmtpd_ltok_skip_x_sig_q_tag_args(ptr, 0)) == NULL)
|
|
return start;
|
|
return ptr;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_x_sig_q_tag_type(const char *ptr, int optional)
|
|
{
|
|
return osmtpd_ltok_skip_hyphenated_word(ptr, optional);
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_x_sig_q_tag_args(const char *ptr, int optional)
|
|
{
|
|
return osmtpd_ltok_skip_qp_hdr_value(ptr, optional);
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_sig_s_tag(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if (ptr[0] != 0x73)
|
|
return optional ? start : NULL;
|
|
ptr = osmtpd_ltok_skip_fws(ptr + 1, 1);
|
|
if (ptr[0] != '=')
|
|
return optional ? start : NULL;
|
|
ptr = osmtpd_ltok_skip_fws(ptr, 1);
|
|
if ((ptr = osmtpd_ltok_skip_sig_s_tag_value(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
return ptr;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_sig_s_tag_value(const char *ptr, int optional)
|
|
{
|
|
return osmtpd_ltok_skip_selector(ptr, optional);
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_sig_t_tag(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if (ptr[0] != 0x74)
|
|
return optional ? start : NULL;
|
|
ptr = osmtpd_ltok_skip_fws(ptr + 1, 1);
|
|
if (ptr[0] != '=')
|
|
return optional ? start : NULL;
|
|
ptr = osmtpd_ltok_skip_fws(ptr, 1);
|
|
if ((ptr = osmtpd_ltok_skip_sig_t_tag_value(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
return ptr;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_sig_t_tag_value(const char *ptr, int optional)
|
|
{
|
|
size_t i;
|
|
|
|
for (i = 0; i < 12; i++) {
|
|
if (osmtpd_ltok_skip_digit(ptr + i, 0) == NULL)
|
|
break;
|
|
}
|
|
if (i >= 1 && i <= 12)
|
|
return ptr + i;
|
|
return optional ? ptr : NULL;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_sig_x_tag(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if (ptr[0] != 0x78)
|
|
return optional ? start : NULL;
|
|
ptr = osmtpd_ltok_skip_fws(ptr + 1, 1);
|
|
if (ptr[0] != '=')
|
|
return optional ? start : NULL;
|
|
ptr = osmtpd_ltok_skip_fws(ptr, 1);
|
|
if ((ptr = osmtpd_ltok_skip_sig_x_tag_value(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
return ptr;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_sig_x_tag_value(const char *ptr, int optional)
|
|
{
|
|
size_t i;
|
|
|
|
for (i = 0; i < 12; i++) {
|
|
if (osmtpd_ltok_skip_digit(ptr + i, 0) == NULL)
|
|
break;
|
|
}
|
|
if (i >= 1 && i <= 12)
|
|
return ptr + i;
|
|
return optional ? ptr : NULL;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_sig_z_tag(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if (ptr[0] != 0x7a)
|
|
return optional ? start : NULL;
|
|
ptr = osmtpd_ltok_skip_fws(ptr + 1, 1);
|
|
if (ptr[0] != '=')
|
|
return optional ? start : NULL;
|
|
ptr = osmtpd_ltok_skip_fws(ptr, 1);
|
|
if ((ptr = osmtpd_ltok_skip_sig_z_tag_value(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
return ptr;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_sig_z_tag_value(const char *ptr, int optional)
|
|
{
|
|
const char *prev = ptr;
|
|
|
|
if ((ptr = osmtpd_ltok_skip_sig_z_tag_copy(ptr, 0)) == NULL)
|
|
return optional ? ptr : NULL;
|
|
while (1) {
|
|
prev = ptr;
|
|
if (ptr[0] != '|')
|
|
return prev;
|
|
ptr = osmtpd_ltok_skip_fws(ptr + 1, 1);
|
|
if ((ptr = osmtpd_ltok_skip_sig_z_tag_copy(ptr, 0)) == NULL)
|
|
return prev;
|
|
}
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_sig_z_tag_copy(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if ((ptr = osmtpd_ltok_skip_hdr_name(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
ptr = osmtpd_ltok_skip_fws(ptr, 1);
|
|
if (ptr[0] != ':')
|
|
return optional ? start : NULL;
|
|
if ((ptr = osmtpd_ltok_skip_qp_hdr_value(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
return ptr;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_key_v_tag(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if (ptr[0] != 0x76)
|
|
return optional ? start : NULL;
|
|
ptr = osmtpd_ltok_skip_fws(ptr + 1, 1);
|
|
if (ptr[0] != '=')
|
|
return optional ? start : NULL;
|
|
ptr = osmtpd_ltok_skip_fws(ptr, 1);
|
|
if ((ptr = osmtpd_ltok_skip_key_v_tag_value(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
return ptr;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_key_v_tag_value(const char *ptr, int optional)
|
|
{
|
|
if (ptr[0] == 0x44 && ptr[1] == 0x4b && ptr[2] == 0x49 &&
|
|
ptr[3] == 0x4d && ptr[4] == 0x31)
|
|
return ptr + 5;
|
|
return optional ? ptr : NULL;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_key_h_tag(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if (ptr[0] != 0x68)
|
|
return optional ? start : NULL;
|
|
ptr = osmtpd_ltok_skip_fws(ptr + 1, 1);
|
|
if (ptr[0] != '=')
|
|
return optional ? start : NULL;
|
|
ptr = osmtpd_ltok_skip_fws(ptr, 1);
|
|
if ((ptr = osmtpd_ltok_skip_key_h_tag_value(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
return ptr;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_key_h_tag_value(const char *ptr, int optional)
|
|
{
|
|
const char *prev = ptr;
|
|
|
|
if ((ptr = osmtpd_ltok_skip_key_h_tag_alg(ptr, 0)) == NULL)
|
|
return optional ? prev : NULL;
|
|
while (1) {
|
|
prev = ptr;
|
|
ptr = osmtpd_ltok_skip_fws(ptr, 1);
|
|
if (ptr[0] != ':')
|
|
return prev;
|
|
ptr = osmtpd_ltok_skip_fws(ptr + 1, 1);
|
|
if ((ptr = osmtpd_ltok_skip_key_h_tag_alg(ptr, 0)) == NULL)
|
|
return prev;
|
|
}
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_key_h_tag_alg(const char *ptr, int optional)
|
|
{
|
|
/* sha1 / sha256 covered by x-key-h-tag-alg */
|
|
return osmtpd_ltok_skip_x_key_h_tag_alg(ptr, optional);
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_x_key_h_tag_alg(const char *ptr, int optional)
|
|
{
|
|
return osmtpd_ltok_skip_hyphenated_word(ptr, optional);
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_key_k_tag(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if (ptr[0] != 0x6b)
|
|
return optional ? start : NULL;
|
|
ptr = osmtpd_ltok_skip_fws(ptr + 1, 1);
|
|
if (ptr[0] != '=')
|
|
return optional ? start : NULL;
|
|
ptr = osmtpd_ltok_skip_fws(ptr, 1);
|
|
if ((ptr = osmtpd_ltok_skip_key_k_tag_value(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
return ptr;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_key_k_tag_value(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if ((ptr = osmtpd_ltok_skip_key_k_tag_type(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
return ptr;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_key_k_tag_type(const char *ptr, int optional)
|
|
{
|
|
/* rsa covered by x-key-k-tag-type */
|
|
return osmtpd_ltok_skip_x_key_k_tag_type(ptr, optional);
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_x_key_k_tag_type(const char *ptr, int optional)
|
|
{
|
|
return osmtpd_ltok_skip_hyphenated_word(ptr, optional);
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_key_n_tag(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if (ptr[0] != 0x6e)
|
|
return optional ? start : NULL;
|
|
ptr = osmtpd_ltok_skip_fws(ptr + 1, 1);
|
|
if (ptr[0] != '=')
|
|
return optional ? start : NULL;
|
|
ptr = osmtpd_ltok_skip_fws(ptr, 1);
|
|
if ((ptr = osmtpd_ltok_skip_key_n_tag_value(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
return ptr;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_key_n_tag_value(const char *ptr, int optional)
|
|
{
|
|
return osmtpd_ltok_skip_qp_section(ptr, optional);
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_key_p_tag(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if (ptr[0] != 0x70)
|
|
return optional ? start : NULL;
|
|
ptr = osmtpd_ltok_skip_fws(ptr + 1, 1);
|
|
if (ptr[0] != '=')
|
|
return optional ? start : NULL;
|
|
ptr = osmtpd_ltok_skip_fws(ptr, 1);
|
|
if ((ptr = osmtpd_ltok_skip_key_p_tag_value(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
return ptr;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_key_p_tag_value(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if ((ptr = osmtpd_ltok_skip_base64string(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
return ptr;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_key_s_tag(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if (ptr[0] != 0x73)
|
|
return optional ? start : NULL;
|
|
ptr = osmtpd_ltok_skip_fws(ptr + 1, 1);
|
|
if (ptr[0] != '=')
|
|
return optional ? start : NULL;
|
|
ptr = osmtpd_ltok_skip_fws(ptr, 1);
|
|
if ((ptr = osmtpd_ltok_skip_key_s_tag_value(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
return ptr;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_key_s_tag_value(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if ((ptr = osmtpd_ltok_skip_key_s_tag_type(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
while (1) {
|
|
start = ptr;
|
|
ptr = osmtpd_ltok_skip_fws(ptr, 1);
|
|
if (ptr[0] != ':')
|
|
return start;
|
|
ptr = osmtpd_ltok_skip_fws(ptr + 1, 1);
|
|
ptr = osmtpd_ltok_skip_key_s_tag_type(ptr, 0);
|
|
if (ptr == NULL)
|
|
return start;
|
|
}
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_key_s_tag_type(const char *ptr, int optional)
|
|
{
|
|
if (ptr[0] == '*')
|
|
return ptr + 1;
|
|
/* email covered by x-key-s-tag-type */
|
|
return osmtpd_ltok_skip_x_key_s_tag_type(ptr, optional);
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_x_key_s_tag_type(const char *ptr, int optional)
|
|
{
|
|
return osmtpd_ltok_skip_hyphenated_word(ptr, optional);
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_key_t_tag(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if (ptr[0] != 0x74)
|
|
return optional ? start : NULL;
|
|
ptr = osmtpd_ltok_skip_fws(ptr + 1, 1);
|
|
if (ptr[0] != '=')
|
|
return optional ? start : NULL;
|
|
ptr = osmtpd_ltok_skip_fws(ptr, 1);
|
|
if ((ptr = osmtpd_ltok_skip_key_t_tag_value(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
return ptr;
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_key_t_tag_value(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr;
|
|
|
|
if ((ptr = osmtpd_ltok_skip_key_t_tag_flag(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
while (1) {
|
|
start = ptr;
|
|
ptr = osmtpd_ltok_skip_fws(ptr, 1);
|
|
if (ptr[0] != ':')
|
|
return start;
|
|
ptr = osmtpd_ltok_skip_fws(ptr + 1, 1);
|
|
ptr = osmtpd_ltok_skip_key_t_tag_flag(ptr, 0);
|
|
if (ptr == NULL)
|
|
return start;
|
|
}
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_key_t_tag_flag(const char *ptr, int optional)
|
|
{
|
|
/* y / s covered by x-key-t-tag-flag */
|
|
return osmtpd_ltok_skip_x_key_t_tag_flag(ptr, optional);
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_x_key_t_tag_flag(const char *ptr, int optional)
|
|
{
|
|
return osmtpd_ltok_skip_hyphenated_word(ptr, optional);
|
|
}
|
|
|
|
const char *
|
|
osmtpd_ltok_skip_ar_pvalue(const char *ptr, int optional)
|
|
{
|
|
const char *start = ptr, *tmp;
|
|
|
|
ptr = osmtpd_ltok_skip_cfws(ptr, 1);
|
|
if ((tmp = osmtpd_ltok_skip_value(ptr, 0)) != NULL)
|
|
return tmp;
|
|
ptr = osmtpd_ltok_skip_local_part(ptr, 1);
|
|
if (ptr[0] == '@')
|
|
ptr++;
|
|
if ((ptr = osmtpd_ltok_skip_domain(ptr, 0)) == NULL)
|
|
return optional ? start : NULL;
|
|
return ptr;
|
|
}
|