commit 4e2dd90f1001dd3bf2b8e342bbd73d01231bb065 from: Martijn van Duren date: Sat Mar 26 19:59:24 2022 UTC Rework the entire mheader file - Rename mheader to ltok (lexical token) - Make all skip functions const - Add a few missing functions commit - 5c6a65504e44766a5cf8d0b9131bd2c2331ee8ca commit + 4e2dd90f1001dd3bf2b8e342bbd73d01231bb065 blob - 5a6d7c794505e09b9725140560776db03b94882f blob + ef1d207bcdc89ba8d2ddfbcdb12558593fa667dc --- Makefile +++ Makefile @@ -4,7 +4,7 @@ MAN= filter-dkimverify.8 BINDIR= ${LOCALBASE}/libexec/smtpd/ MANDIR= ${LOCALBASE}/man/man -SRCS+= main.c mheader.c unpack_dns.c +SRCS+= ltok.c main.c unpack_dns.c CFLAGS+=-I${LOCALBASE}/include CFLAGS+=-Wall -I${.CURDIR} blob - b20aa0b202fd630f75db94bf7facc5cbdcea8b07 blob + 1292720beba141660a45ac4b9c01d2aa1b99b57a --- main.c +++ main.c @@ -39,7 +39,7 @@ #include "opensmtpd.h" #include "unpack_dns.h" -#include "mheader.h" +#include "ltok.h" /* * Use RFC8601 (Authentication-Results) codes instead of RFC6376 codes, @@ -60,13 +60,13 @@ struct signature { enum state state; const char *state_reason; int v; - char *a; + const char *a; size_t asz; int ak; const EVP_MD *ah; char *b; size_t bsz; - char *bheader; + const char *bheader; /* Make sure padding bits for base64 decoding fit */ char bh[EVP_MAX_MD_SIZE + (3 - (EVP_MAX_MD_SIZE % 3))]; size_t bhsz; @@ -81,7 +81,7 @@ struct signature { #define CANON_DONE 1 << 2 char d[HOST_NAME_MAX + 1]; char **h; - char *i; + const char *i; size_t isz; ssize_t l; int q; @@ -130,20 +130,20 @@ void *dkim_message_new(struct osmtpd_ctx *); void dkim_message_free(struct osmtpd_ctx *, void *); void dkim_header_add(struct osmtpd_ctx *, const char *); void dkim_signature_parse(struct header *); -void dkim_signature_parse_v(struct signature *, char *, char *); -void dkim_signature_parse_a(struct signature *, char *, char *); -void dkim_signature_parse_b(struct signature *, char *, char *); -void dkim_signature_parse_bh(struct signature *, char *, char *); -void dkim_signature_parse_c(struct signature *, char *, char *); -void dkim_signature_parse_d(struct signature *, char *, char *); -void dkim_signature_parse_h(struct signature *, char *, char *); -void dkim_signature_parse_i(struct signature *, char *, char *); -void dkim_signature_parse_l(struct signature *, char *, char *); -void dkim_signature_parse_q(struct signature *, char *, char *); -void dkim_signature_parse_s(struct signature *, char *, char *); -void dkim_signature_parse_t(struct signature *, char *, char *); -void dkim_signature_parse_x(struct signature *, char *, char *); -void dkim_signature_parse_z(struct signature *, char *, char *); +void dkim_signature_parse_v(struct signature *, const char *, const char *); +void dkim_signature_parse_a(struct signature *, const char *, const char *); +void dkim_signature_parse_b(struct signature *, const char *, const char *); +void dkim_signature_parse_bh(struct signature *, const char *, const char *); +void dkim_signature_parse_c(struct signature *, const char *, const char *); +void dkim_signature_parse_d(struct signature *, const char *, const char *); +void dkim_signature_parse_h(struct signature *, const char *, const char *); +void dkim_signature_parse_i(struct signature *, const char *, const char *); +void dkim_signature_parse_l(struct signature *, const char *, const char *); +void dkim_signature_parse_q(struct signature *, const char *, const char *); +void dkim_signature_parse_s(struct signature *, const char *, const char *); +void dkim_signature_parse_t(struct signature *, const char *, const char *); +void dkim_signature_parse_x(struct signature *, const char *, const char *); +void dkim_signature_parse_z(struct signature *, const char *, const char *); void dkim_signature_verify(struct signature *); void dkim_signature_header(EVP_MD_CTX *, struct signature *, struct header *); void dkim_signature_state(struct signature *, enum state, const char *); @@ -155,8 +155,8 @@ void dkim_rr_resolve(struct asr_result *, void *); void dkim_message_verify(struct message *); ssize_t dkim_ar_cat(char **ar, size_t *n, size_t aroff, const char *fmt, ...) __attribute__((__format__ (printf, 4, 5))); -void dkim_ar_print(struct osmtpd_ctx *, char *); -int dkim_key_text_parse(struct signature *, char *); +void dkim_ar_print(struct osmtpd_ctx *, const char *); +int dkim_key_text_parse(struct signature *, const char *); char *authservid; EVP_ENCODE_CTX *ectx = NULL; @@ -187,7 +187,7 @@ main(int argc, char *argv[]) void dkim_conf(const char *key, const char *value) { - char *end; + const char *end; if (key == NULL) { if (authservid == NULL) @@ -197,10 +197,9 @@ dkim_conf(const char *key, const char *value) if (strcmp(key, "admd") == 0 && authservid == NULL) { if ((authservid = strdup(value)) == NULL) osmtpd_err(1, "malloc"); - end = osmtpd_mheader_skip_value(authservid, 0); + end = osmtpd_ltok_skip_value(authservid, 0); if (authservid + strlen(authservid) != end) osmtpd_errx(1, "Invalid authservid"); - osmtpd_mheader_quoted_string_normalize(authservid); } } @@ -314,7 +313,7 @@ void dkim_header_add(struct osmtpd_ctx *ctx, const char *line) { struct message *msg = ctx->local_message; - char *start, *end, *verify; + const char *start, *end, *verify; struct header *headers; size_t i; @@ -323,10 +322,10 @@ dkim_header_add(struct osmtpd_ctx *ctx, const char *li if (line[0] != ' ' && line[0] != '\t') { msg->header[msg->nheaders - 1].readdone = 1; start = msg->header[msg->nheaders - 1].buf; - end = osmtpd_mheader_skip_fieldname(start, 0); + end = osmtpd_ltok_skip_field_name(start, 0); /* In case someone uses an obs-optional */ if (end != NULL) - verify = osmtpd_mheader_skip_wsp(end, 1); + verify = osmtpd_ltok_skip_wsp(end, 1); if (end != NULL && strncasecmp( start, "DKIM-Signature", end - start) == 0 && @@ -385,14 +384,14 @@ dkim_signature_parse(struct header *header) { struct signature *sig; struct asr_query *query; - char *buf, *i; - char *end, tagname[3]; + const char *buf, *i, *end; + char tagname[3]; char subdomain[HOST_NAME_MAX + 1]; size_t ilen, dlen; /* Format checked by dkim_header_add */ - buf = osmtpd_mheader_skip_fieldname(header->buf, 0); - buf = osmtpd_mheader_skip_wsp(buf, 1) + 1; + buf = osmtpd_ltok_skip_field_name(header->buf, 0); + buf = osmtpd_ltok_skip_wsp(buf, 1) + 1; if ((header->sig = calloc(1, sizeof(*header->sig))) == NULL) { dkim_err(header->msg, "malloc"); @@ -404,25 +403,25 @@ dkim_signature_parse(struct header *header) sig->t = -1; sig->x = -1; - end = osmtpd_mheader_skip_dkimsig_taglist(buf, 0); + end = osmtpd_ltok_skip_tag_list(buf, 0); if (end == NULL || end[0] != '\0') { - dkim_signature_state(sig, DKIM_PERMERROR, "Invalid taglist"); + dkim_signature_state(sig, DKIM_PERMERROR, "Invalid tag-list"); return; } while (buf[0] != '\0') { - buf = osmtpd_mheader_skip_fws(buf, 1); - end = osmtpd_mheader_skip_dkimsig_tagname(buf, 0); + buf = osmtpd_ltok_skip_fws(buf, 1); + end = osmtpd_ltok_skip_tag_name(buf, 0); /* Unknown tag-name */ if ((size_t)(end - buf) >= sizeof(tagname)) tagname[0] = '\0'; else strlcpy(tagname, buf, (end - buf) + 1); - buf = osmtpd_mheader_skip_fws(end, 1); + buf = osmtpd_ltok_skip_fws(end, 1); /* '=' */ - buf = osmtpd_mheader_skip_fws(buf + 1, 1); - end = osmtpd_mheader_skip_dkimsig_tagvalue(buf, 1); + buf = osmtpd_ltok_skip_fws(buf + 1, 1); + end = osmtpd_ltok_skip_tag_value(buf, 1); if (strcmp(tagname, "v") == 0) dkim_signature_parse_v(sig, buf, end); else if (strcmp(tagname, "a") == 0) @@ -452,12 +451,12 @@ dkim_signature_parse(struct header *header) else if (strcmp(tagname, "z") == 0) dkim_signature_parse_z(sig, buf, end); - buf = osmtpd_mheader_skip_fws(end, 1); + buf = osmtpd_ltok_skip_fws(end, 1); if (buf[0] == ';') buf++; else if (buf[0] != '\0') { dkim_signature_state(sig, DKIM_PERMERROR, - "Invalid taglist"); + "Invalid tag-list"); return; } } @@ -482,7 +481,7 @@ dkim_signature_parse(struct header *header) return; if (sig->i != NULL) { - i = osmtpd_mheader_skip_local_part(sig->i, 1) + 1; + i = osmtpd_ltok_skip_local_part(sig->i, 1) + 1; ilen = strlen(i); dlen = strlen(sig->d); if (ilen < dlen) { @@ -521,7 +520,7 @@ dkim_signature_parse(struct header *header) } void -dkim_signature_parse_v(struct signature *sig, char *start, char *end) +dkim_signature_parse_v(struct signature *sig, const char *start, const char *end) { if (sig->v != 0) { /* Duplicate tag */ dkim_signature_state(sig, DKIM_PERMERROR, "Duplicate v tag"); @@ -535,7 +534,7 @@ dkim_signature_parse_v(struct signature *sig, char *st } void -dkim_signature_parse_a(struct signature *sig, char *start, char *end) +dkim_signature_parse_a(struct signature *sig, const char *start, const char *end) { char ah[sizeof("sha256")]; @@ -544,7 +543,7 @@ dkim_signature_parse_a(struct signature *sig, char *st return; } - if (osmtpd_mheader_skip_dkimsig_sigatagalg(start, 0) != end) { + if (osmtpd_ltok_skip_sig_a_tag_alg(start, 0) != end) { dkim_signature_state(sig, DKIM_PERMERROR, "Invalid a tag"); return; } @@ -578,7 +577,7 @@ dkim_signature_parse_a(struct signature *sig, char *st } void -dkim_signature_parse_b(struct signature *sig, char *start, char *end) +dkim_signature_parse_b(struct signature *sig, const char *start, const char *end) { int decodesz; @@ -608,9 +607,9 @@ dkim_signature_parse_b(struct signature *sig, char *st } void -dkim_signature_parse_bh(struct signature *sig, char *start, char *end) +dkim_signature_parse_bh(struct signature *sig, const char *start, const char *end) { - char *b64; + const char *b64; size_t n; int decodesz; @@ -625,15 +624,15 @@ dkim_signature_parse_bh(struct signature *sig, char *s b64 = start; n = 0; while (1) { - b64 = osmtpd_mheader_skip_fws(b64, 1); - if (osmtpd_mheader_skip_alphadigitps(b64, 0) == NULL) + b64 = osmtpd_ltok_skip_fws(b64, 1); + if (osmtpd_ltok_skip_alphadigitps(b64, 0) == NULL) break; n++; b64++; } if (b64[0] == '=') { n++; - b64 = osmtpd_mheader_skip_fws(b64 + 1, 1); + b64 = osmtpd_ltok_skip_fws(b64 + 1, 1); if (b64[0] == '=') { n++; b64++; @@ -662,7 +661,7 @@ dkim_signature_parse_bh(struct signature *sig, char *s } void -dkim_signature_parse_c(struct signature *sig, char *start, char *end) +dkim_signature_parse_c(struct signature *sig, const char *start, const char *end) { if (sig->c != 0) { dkim_signature_state(sig, DKIM_PERMERROR, "Duplicate c tag"); @@ -701,13 +700,13 @@ dkim_signature_parse_c(struct signature *sig, char *st } void -dkim_signature_parse_d(struct signature *sig, char *start, char *end) +dkim_signature_parse_d(struct signature *sig, const char *start, const char *end) { if (sig->d[0] != '\0') { dkim_signature_state(sig, DKIM_PERMERROR, "Duplicate d tag"); return; } - if (osmtpd_mheader_skip_domain(start, 0) != end || + if (osmtpd_ltok_skip_domain(start, 0) != end || (size_t)(end - start) >= sizeof(sig->d)) { dkim_signature_state(sig, DKIM_PERMERROR, "Invalid d tag"); return; @@ -716,9 +715,9 @@ dkim_signature_parse_d(struct signature *sig, char *st } void -dkim_signature_parse_h(struct signature *sig, char *start, char *end) +dkim_signature_parse_h(struct signature *sig, const char *start, const char *end) { - char *h; + const char *h; size_t n = 0; if (sig->h != NULL) { @@ -727,7 +726,7 @@ dkim_signature_parse_h(struct signature *sig, char *st } h = start; while (1) { - if ((h = osmtpd_mheader_skip_hdrname(h, 0)) == NULL) { + if ((h = osmtpd_ltok_skip_hdr_name(h, 0)) == NULL) { dkim_signature_state(sig, DKIM_PERMERROR, "Invalid h tag"); return; @@ -738,10 +737,10 @@ dkim_signature_parse_h(struct signature *sig, char *st h = end; break; } - h = osmtpd_mheader_skip_fws(h, 1); + h = osmtpd_ltok_skip_fws(h, 1); if (h[0] != ':') break; - h = osmtpd_mheader_skip_fws(h + 1, 1); + h = osmtpd_ltok_skip_fws(h + 1, 1); } if (h != end) { dkim_signature_state(sig, DKIM_PERMERROR, "Invalid h tag"); @@ -754,7 +753,7 @@ dkim_signature_parse_h(struct signature *sig, char *st n = 0; h = start; while (1) { - h = osmtpd_mheader_skip_hdrname(start, 0); + h = osmtpd_ltok_skip_hdr_name(start, 0); /* ';' is part of hdr-name */ if (h > end) { sig->h[n] = strndup(start, end - start); @@ -764,28 +763,28 @@ dkim_signature_parse_h(struct signature *sig, char *st dkim_err(sig->header->msg, "malloc"); return; } - start = osmtpd_mheader_skip_fws(h, 1); + start = osmtpd_ltok_skip_fws(h, 1); if (start[0] != ':') break; - start = osmtpd_mheader_skip_fws(start + 1, 1); + start = osmtpd_ltok_skip_fws(start + 1, 1); } } void -dkim_signature_parse_i(struct signature *sig, char *start, char *end) +dkim_signature_parse_i(struct signature *sig, const char *start, const char *end) { - char *i; + const char *i; if (sig->i != NULL) { dkim_signature_state(sig, DKIM_PERMERROR, "Duplicate i tag"); return; } - i = osmtpd_mheader_skip_local_part(start, 1); + i = osmtpd_ltok_skip_local_part(start, 1); if (i[0] != '@') { dkim_signature_state(sig, DKIM_PERMERROR, "Invalid i tag"); return; } - if (osmtpd_mheader_skip_domain(i + 1, 0) != end) { + if (osmtpd_ltok_skip_domain(i + 1, 0) != end) { dkim_signature_state(sig, DKIM_PERMERROR, "Invalid i tag"); return; } @@ -794,7 +793,7 @@ dkim_signature_parse_i(struct signature *sig, char *st } void -dkim_signature_parse_l(struct signature *sig, char *start, char *end) +dkim_signature_parse_l(struct signature *sig, const char *start, const char *end) { long long l; char *lend; @@ -806,7 +805,7 @@ dkim_signature_parse_l(struct signature *sig, char *st errno = 0; l = strtoll(start, &lend, 10); /* > 76 digits in stroll is an overflow */ - if (osmtpd_mheader_skip_digit(start, 0) == NULL || + if (osmtpd_ltok_skip_digit(start, 0) == NULL || lend != end || errno != 0) { dkim_signature_state(sig, DKIM_PERMERROR, "Invalid l tag"); return; @@ -819,9 +818,9 @@ dkim_signature_parse_l(struct signature *sig, char *st } void -dkim_signature_parse_q(struct signature *sig, char *start, char *end) +dkim_signature_parse_q(struct signature *sig, const char *start, const char *end) { - char *qend; + const char *qend; if (sig->q != 0) { dkim_signature_state(sig, DKIM_PERMERROR, "Duplicate q tag"); @@ -829,15 +828,15 @@ dkim_signature_parse_q(struct signature *sig, char *st } while (1) { - start = osmtpd_mheader_skip_fws(start, 1); - qend = osmtpd_mheader_skip_dkimsig_sigqtagmethod(start, 0); + start = osmtpd_ltok_skip_fws(start, 1); + qend = osmtpd_ltok_skip_sig_q_tag_method(start, 0); if (qend == NULL) { dkim_signature_state(sig, DKIM_PERMERROR, "Invalid q tag"); return; } if (strncmp(start, "dns/txt", qend - start) == 0) sig->q = 1; - start = osmtpd_mheader_skip_fws(qend, 1); + start = osmtpd_ltok_skip_fws(qend, 1); if (start[0] != ':') break; } @@ -853,13 +852,13 @@ dkim_signature_parse_q(struct signature *sig, char *st } void -dkim_signature_parse_s(struct signature *sig, char *start, char *end) +dkim_signature_parse_s(struct signature *sig, const char *start, const char *end) { if (sig->s[0] != '\0') { dkim_signature_state(sig, DKIM_PERMERROR, "Duplicate s tag"); return; } - if (osmtpd_mheader_skip_dkimsig_selector(start, 0) != end) { + if (osmtpd_ltok_skip_selector(start, 0) != end) { dkim_signature_state(sig, DKIM_PERMERROR, "Invalid s tag"); return; } @@ -867,7 +866,7 @@ dkim_signature_parse_s(struct signature *sig, char *st } void -dkim_signature_parse_t(struct signature *sig, char *start, char *end) +dkim_signature_parse_t(struct signature *sig, const char *start, const char *end) { char *tend; @@ -877,7 +876,7 @@ dkim_signature_parse_t(struct signature *sig, char *st } errno = 0; sig->t = strtoll(start, &tend, 10); - if (osmtpd_mheader_skip_digit(start, 0) == NULL || tend != end || + if (osmtpd_ltok_skip_digit(start, 0) == NULL || tend != end || tend - start > 12 || errno != 0) { dkim_signature_state(sig, DKIM_PERMERROR, "Invalid t tag"); return; @@ -885,7 +884,7 @@ dkim_signature_parse_t(struct signature *sig, char *st } void -dkim_signature_parse_x(struct signature *sig, char *start, char *end) +dkim_signature_parse_x(struct signature *sig, const char *start, const char *end) { char *xend; @@ -895,7 +894,7 @@ dkim_signature_parse_x(struct signature *sig, char *st } errno = 0; sig->x = strtoll(start, &xend, 10); - if (osmtpd_mheader_skip_digit(start, 0) == NULL || xend != end || + if (osmtpd_ltok_skip_digit(start, 0) == NULL || xend != end || xend - start > 12 || errno != 0) { dkim_signature_state(sig, DKIM_PERMERROR, "Invalid x tag"); return; @@ -903,7 +902,7 @@ dkim_signature_parse_x(struct signature *sig, char *st } void -dkim_signature_parse_z(struct signature *sig, char *start, char *end) +dkim_signature_parse_z(struct signature *sig, const char *start, const char *end) { if (sig->z != 0) { dkim_signature_state(sig, DKIM_PERMERROR, "Duplicate z tag"); @@ -911,7 +910,7 @@ dkim_signature_parse_z(struct signature *sig, char *st } sig->z = 1; - if (osmtpd_mheader_skip_dkimsig_sigztagvalue(start, 0) != end) { + if (osmtpd_ltok_skip_sig_z_tag_value(start, 0) != end) { dkim_signature_state(sig, DKIM_PERMERROR, "Invalid z tag"); return; } @@ -922,7 +921,7 @@ dkim_signature_verify(struct signature *sig) { struct message *msg = sig->header->msg; static EVP_MD_CTX *bctx = NULL; - char *end; + const char *end; size_t i, header; if (sig->state != DKIM_UNKNOWN) @@ -951,7 +950,7 @@ dkim_signature_verify(struct signature *sig) strlen(sig->h[header])) != 0 || msg->header[i].sig == sig) continue; - end = osmtpd_mheader_skip_fws( + end = osmtpd_ltok_skip_fws( msg->header[i].buf + strlen(sig->h[header]), 1); if (end[0] != ':') continue; @@ -968,21 +967,22 @@ void dkim_signature_header(EVP_MD_CTX *bctx, struct signature *sig, struct header *header) { - char c, *ptr = header->buf, *end; + char c; + const char *ptr = header->buf, *end; int inhdrname = 1; int canon = sig->c & CANON_HEADER; for (ptr = header->buf; ptr[0] != '\0'; ptr++) { if (inhdrname) { if (canon == CANON_HEADER_RELAXED) { - ptr = osmtpd_mheader_skip_fws(ptr, 1); + ptr = osmtpd_ltok_skip_fws(ptr, 1); c = tolower(ptr[0]); } else c = ptr[0]; if (c == ':') { inhdrname = 0; if (canon == CANON_HEADER_RELAXED) - ptr = osmtpd_mheader_skip_fws( + ptr = osmtpd_ltok_skip_fws( ptr + 1, 1) - 1; } if (EVP_DigestVerifyUpdate(bctx, &c, 1) == 0) { @@ -992,10 +992,10 @@ dkim_signature_header(EVP_MD_CTX *bctx, struct signatu } continue; } - end = osmtpd_mheader_skip_fws(ptr, 1); + end = osmtpd_ltok_skip_fws(ptr, 1); if (end == ptr) { if (sig->header == header && ptr == sig->bheader) { - ptr = osmtpd_mheader_skip_dkimsig_tagvalue( + ptr = osmtpd_ltok_skip_tag_value( ptr, 0) - 1; continue; } @@ -1163,58 +1163,59 @@ dkim_rr_resolve(struct asr_result *ar, void *arg) } int -dkim_key_text_parse(struct signature *sig, char *key) +dkim_key_text_parse(struct signature *sig, const char *key) { - char *end, *tagvend, tagname; - char tmp, pkraw[UINT16_MAX] = "", pkimp[UINT16_MAX]; + char tagname, *hashname; + const char *end, *tagvend; + char pkraw[UINT16_MAX] = "", pkimp[UINT16_MAX]; size_t pkoff, linelen; int h = 0, k = 0, n = 0, p = 0, s = 0, t = 0; BIO *bio; - key = osmtpd_mheader_skip_fws(key, 1); + key = osmtpd_ltok_skip_fws(key, 1); /* Validate syntax early */ - if ((end = osmtpd_mheader_skip_dkimsig_taglist(key, 0)) == NULL) + if ((end = osmtpd_ltok_skip_tag_list(key, 0)) == NULL) return 0; /* * RFC 6376 section 3.6.1, v=: * RECOMMENDED...This tag MUST be the first tag in the record. */ - if (osmtpd_mheader_skip_dkimsig_tagname(key, 0) - key == 1 && + if (osmtpd_ltok_skip_tag_name(key, 0) - key == 1 && key[0] == 'v') { - key = osmtpd_mheader_skip_dkimsig_tagname(key, 0); - key = osmtpd_mheader_skip_fws(key, 1); + key = osmtpd_ltok_skip_tag_name(key, 0); + key = osmtpd_ltok_skip_fws(key, 1); key++; /* = */ - key = osmtpd_mheader_skip_fws(key, 1); - end = osmtpd_mheader_skip_dkimsig_tagvalue(key, 0); + key = osmtpd_ltok_skip_fws(key, 1); + end = osmtpd_ltok_skip_tag_value(key, 0); if (end - key != 5 || strncmp(key, "DKIM1", 5) != 0) return 0; key += 5; - key = osmtpd_mheader_skip_fws(key, 1); + key = osmtpd_ltok_skip_fws(key, 1); if (key[0] == ';') key++; } while (key[0] != '\0') { - key = osmtpd_mheader_skip_fws(key, 1); - end = osmtpd_mheader_skip_dkimsig_tagname(key, 0); + key = osmtpd_ltok_skip_fws(key, 1); + end = osmtpd_ltok_skip_tag_name(key, 0); if ((size_t)(end - key) != 1) { - key = osmtpd_mheader_skip_fws(end, 1); + key = osmtpd_ltok_skip_fws(end, 1); /* '=' */ key++; - key = osmtpd_mheader_skip_fws(key, 1); - key = osmtpd_mheader_skip_dkimsig_tagvalue(key, 0); - key = osmtpd_mheader_skip_fws(key, 1); + key = osmtpd_ltok_skip_fws(key, 1); + key = osmtpd_ltok_skip_tag_value(key, 0); + key = osmtpd_ltok_skip_fws(key, 1); if (key[0] == ';') key++; continue; } tagname = key[0]; - key = osmtpd_mheader_skip_fws(end, 1); + key = osmtpd_ltok_skip_fws(end, 1); /* '=' */ key++; - key = osmtpd_mheader_skip_fws(key, 1); - end = osmtpd_mheader_skip_dkimsig_tagvalue(key, 0); + key = osmtpd_ltok_skip_fws(key, 1); + end = osmtpd_ltok_skip_tag_value(key, 0); switch (tagname) { case 'v': /* tagname in wrong position */ @@ -1223,26 +1224,29 @@ dkim_key_text_parse(struct signature *sig, char *key) if (h != 0) /* Duplicate tag */ return 0; /* Invalid tag value */ - if (osmtpd_mheader_skip_dkimsig_keyhtagvalue( + if (osmtpd_ltok_skip_key_h_tag_value( key, 0) != end) return 0; while (1) { if ((tagvend = - osmtpd_mheader_skip_dkimsig_keyhtagvalue( + osmtpd_ltok_skip_key_h_tag_value( key, 0)) == NULL) break; - tmp = tagvend[0]; - tagvend[0] = '\0'; - if (EVP_get_digestbyname(key) == sig->ah) { - tagvend[0] = tmp; + hashname = strndup(key, tagvend - key); + if (hashname == NULL) { + dkim_err(sig->header->msg, "malloc"); + return 0; + } + if (EVP_get_digestbyname(hashname) == sig->ah) { + free(hashname); h = 1; break; } - tagvend[0] = tmp; - key = osmtpd_mheader_skip_fws(tagvend, 1); + free(hashname); + key = osmtpd_ltok_skip_fws(tagvend, 1); if (key[0] != ':') break; - key = osmtpd_mheader_skip_fws(key + 1, 1); + key = osmtpd_ltok_skip_fws(key + 1, 1); } if (h != 1) return 0; @@ -1260,13 +1264,15 @@ dkim_key_text_parse(struct signature *sig, char *key) if (n != 0) /* Duplicate tag */ return 0; n = 1; + if (osmtpd_ltok_skip_key_n_tag_value(key, 0) != end) + return 0; key = end; break; case 'p': if (p != 0) /* Duplicate tag */ return 0; p = 1; - tagvend = osmtpd_mheader_skip_base64string(key, 1); + tagvend = osmtpd_ltok_skip_base64string(key, 1); /* Invalid tag value */ if (tagvend != end || (size_t)(end - key) >= sizeof(pkraw)) @@ -1278,12 +1284,12 @@ dkim_key_text_parse(struct signature *sig, char *key) if (s != 0) /* Duplicate tag */ return 0; /* Invalid tag value */ - if (osmtpd_mheader_skip_dkimsig_keystagvalue(key, 0) != + if (osmtpd_ltok_skip_key_s_tag_value(key, 0) != end) return 0; while (1) { if ((tagvend = - osmtpd_mheader_skip_dkimsig_keystagtype( + osmtpd_ltok_skip_key_s_tag_type( key, 0)) == NULL) break; if (strncmp(key, "*", tagvend - key) == 0 || @@ -1291,10 +1297,10 @@ dkim_key_text_parse(struct signature *sig, char *key) s = 1; break; } - key = osmtpd_mheader_skip_fws(tagvend, 1); + key = osmtpd_ltok_skip_fws(tagvend, 1); if (key[0] != ':') break; - key = osmtpd_mheader_skip_fws(key + 1, 1); + key = osmtpd_ltok_skip_fws(key + 1, 1); } if (s != 1) return 0; @@ -1304,21 +1310,21 @@ dkim_key_text_parse(struct signature *sig, char *key) if (t != 0) /* Duplicate tag */ return 0; t = 1; - if (osmtpd_mheader_skip_dkimsig_keystagtype(key, 0) != + if (osmtpd_ltok_skip_key_s_tag_type(key, 0) != end) return 0; while (1) { tagvend = - osmtpd_mheader_skip_dkimsig_keyttagflag( + osmtpd_ltok_skip_key_t_tag_flag( key, 0); if (strncmp(key, "y", tagvend - key) == 0) sig->kt |= KT_Y; else if (strncmp(key, "s", tagvend - key) == 0) sig->kt |= KT_S; - key = osmtpd_mheader_skip_fws(tagvend, 1); + key = osmtpd_ltok_skip_fws(tagvend, 1); if (key[0] != ':') break; - key = osmtpd_mheader_skip_fws(key + 1, 1); + key = osmtpd_ltok_skip_fws(key + 1, 1); } break; default: @@ -1326,7 +1332,7 @@ dkim_key_text_parse(struct signature *sig, char *key) break; } - key = osmtpd_mheader_skip_fws(key, 1); + key = osmtpd_ltok_skip_fws(key, 1); if (key[0] == ';') key++; else if (key[0] != '\0') @@ -1356,7 +1362,7 @@ dkim_key_text_parse(struct signature *sig, char *key) pkimp[pkoff++] = '\n'; linelen = 0; } - key = osmtpd_mheader_skip_fws(key + 1, 1); + key = osmtpd_ltok_skip_fws(key + 1, 1); } /* Leverage pkoff check in loop */ if (linelen != 0) @@ -1579,14 +1585,14 @@ dkim_message_verify(struct message *msg) } void -dkim_ar_print(struct osmtpd_ctx *ctx, char *start) +dkim_ar_print(struct osmtpd_ctx *ctx, const char *start) { - char *scan, *checkpoint, *ncheckpoint; + const char *scan, *checkpoint, *ncheckpoint; size_t arlen = 0; int first = 1, arid = 1; checkpoint = start; - ncheckpoint = osmtpd_mheader_skip_hdrname(start, 0) + 1; + ncheckpoint = osmtpd_ltok_skip_hdr_name(start, 0) + 1; for (scan = start; scan[0] != '\0'; scan++) { if (scan[0] == '\t') arlen = (arlen + 8) & ~7; @@ -1596,33 +1602,33 @@ dkim_ar_print(struct osmtpd_ctx *ctx, char *start) osmtpd_filter_dataline(ctx, "%s%.*s", first ? "" : "\t", (int)((checkpoint == start ? ncheckpoint : checkpoint) - start), start); - start = osmtpd_mheader_skip_cfws(checkpoint, 1); + start = osmtpd_ltok_skip_cfws(checkpoint, 1); scan = start; arlen = 8; first = 0; } if (scan == ncheckpoint) { checkpoint = ncheckpoint; - ncheckpoint = osmtpd_mheader_skip_cfws(ncheckpoint, 1); + ncheckpoint = osmtpd_ltok_skip_cfws(ncheckpoint, 1); /* authserv-id */ if (arid) { - ncheckpoint = osmtpd_mheader_skip_value( + ncheckpoint = osmtpd_ltok_skip_value( ncheckpoint, 0); arid = 0; /* methodspec */ } else if (strncmp(ncheckpoint, "dkim", sizeof("dkim") - 1) == 0) { - ncheckpoint = osmtpd_mheader_skip_keyword( + ncheckpoint = osmtpd_ltok_skip_keyword( ncheckpoint + sizeof("dkim"), 0); /* reasonspec */ } else if (strncmp(ncheckpoint, "reason", sizeof("reason") - 1) == 0) { - ncheckpoint = osmtpd_mheader_skip_value( + ncheckpoint = osmtpd_ltok_skip_value( ncheckpoint + sizeof("reason"), 0); /* propspec */ } else { ncheckpoint += sizeof("header.x=") - 1; - ncheckpoint = osmtpd_mheader_skip_ar_pvalue( + ncheckpoint = osmtpd_ltok_skip_ar_pvalue( ncheckpoint, 0); if (ncheckpoint[0] == ';') ncheckpoint++; blob - /dev/null blob + 117b867d4dfc0e4fb5b0439df53f83d56c3f852d (mode 644) --- /dev/null +++ ltok.c @@ -0,0 +1,1882 @@ +/* + * Copyright (c) 2020 Martijn van Duren + * + * 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 +#include +#include +#include +#include + +#include "ltok.h" + +#include + +/* 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(ptr[0]); + if (l == 'a' || l == 'b' || l == 'c' || l == 'd' || + l == 'e' || l == 'f') + return ptr + 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, *hyphen; + + if ((ptr = osmtpd_ltok_skip_alpha(ptr, 0)) == NULL) + return optional ? start : NULL; + + end = ptr; + while (1) { + if (ptr[0] == '-') { + hyphen = hyphen == NULL ? ptr - 1 : hyphen; + ptr++; + continue; + } + start = ptr; + if ((ptr = osmtpd_ltok_skip_alpha(start, 0)) == NULL && + (ptr = osmtpd_ltok_skip_digit(start, 0)) == NULL) + break; + hyphen = NULL; + end = ptr; + + } + return hyphen == NULL ? end : hyphen; +} + +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, 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 ((prev = 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; +} blob - e57f15bdb8c8c4014114be0ac5b8eb26391c82e3 (mode 644) blob + /dev/null --- mheader.c +++ /dev/null @@ -1,1394 +0,0 @@ -/* - * Copyright (c) 2020 Martijn van Duren - * - * 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 -#include -#include -#include -#include - -#include "mheader.h" - -#include - -char * -osmtpd_mheader_skip_sp(char *ptr, int optional) -{ - if (ptr[0] == 0x20) - return ptr + 1; - return optional ? ptr : NULL; -} - -char * -osmtpd_mheader_skip_htab(char *ptr, int optional) -{ - if (ptr[0] == 0x9) - return ptr + 1; - return optional ? ptr : NULL; -} - -char * -osmtpd_mheader_skip_char(char *ptr, int optional) -{ - if (ptr[0] >= 0x01 && ptr[0] <= 0x7f) - return ptr + 1; - return optional ? ptr : NULL; -} - -char * -osmtpd_mheader_skip_ctl(char *ptr, int optional) -{ - if ((ptr[0] >= 0x00 && ptr[0] <= 0x1f) || ptr[0] == 0x7f) - return ptr + 1; - return optional ? ptr : NULL; -} - -char * -osmtpd_mheader_skip_wsp(char *ptr, int optional) -{ - char *start = ptr; - - if ((ptr = osmtpd_mheader_skip_sp(start, 0)) != NULL || - (ptr = osmtpd_mheader_skip_htab(start, 0)) != NULL) - return ptr; - return optional ? start : NULL; -} - -char * -osmtpd_mheader_skip_crlf(char *ptr, int optional) -{ - if (ptr[0] == 13 && ptr[1] == 10) - return ptr + 2; - return optional ? ptr : NULL; -} - -char * -osmtpd_mheader_skip_vchar(char *ptr, int optional) -{ - if (ptr[0] >= 0x21 && ptr[0] <= 0x7e) - return ptr + 1; - return optional ? ptr : NULL; -} - -char * -osmtpd_mheader_skip_lf(char *ptr, int optional) -{ - if (ptr[0] == 0xa) - return ptr + 1; - return optional ? ptr : NULL; -} - -char * -osmtpd_mheader_skip_cr(char *ptr, int optional) -{ - if (ptr[0] == 0xd) - return ptr + 1; - return optional ? ptr : NULL; -} - -char * -osmtpd_mheader_skip_alpha(char *ptr, int optional) -{ - if ((ptr[0] >= 0x41 && ptr[0] <= 0x5a) || - (ptr[0] >= 0x61 && ptr[0] <= 0x7a)) - return ptr + 1; - return optional ? ptr : NULL; -} - -char * -osmtpd_mheader_skip_digit(char *ptr, int optional) -{ - if (ptr[0] >= 0x30 && ptr[0] <= 0x39) - return ptr + 1; - return optional ? ptr : NULL; -} - -char * -osmtpd_mheader_skip_letdig(char *ptr, int optional) -{ - char *start = ptr; - - if ((ptr = osmtpd_mheader_skip_alpha(start, 0)) == NULL && - (ptr = osmtpd_mheader_skip_digit(start, 0)) == NULL) - return optional ? start : NULL; - return ptr; -} - -char * -osmtpd_mheader_skip_ldhstring(char *ptr, int optional) -{ - char *start = ptr, *prev; - int letdig = 0; - - while (1) { - prev = ptr; - if ((ptr = osmtpd_mheader_skip_alpha(prev, 0)) != NULL || - (ptr = osmtpd_mheader_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; -} - -char * -osmtpd_mheader_skip_dquote(char *ptr, int optional) -{ - if (ptr[0] == 0x22) - return ptr + 1; - return optional ? ptr : NULL; -} - -char * -osmtpd_mheader_skip_hexoctet(char *ptr, int optional) -{ - char *start = ptr; - - if (ptr[0] != '=') - return optional ? ptr : NULL; - ptr++; - if (ptr[0] == 'A' || ptr[0] == 'B' || ptr[0] == 'C' || ptr[0] == 'D' || - ptr[0] == 'E' || ptr[0] == 'F') - ptr++; - else if ((ptr = osmtpd_mheader_skip_digit(ptr, 0)) == NULL) - return optional ? start : NULL; - if (ptr[0] == 'A' || ptr[0] == 'B' || ptr[0] == 'C' || ptr[0] == 'D' || - ptr[0] == 'E' || ptr[0] == 'F') - ptr++; - else if ((ptr = osmtpd_mheader_skip_digit(ptr, 0)) == NULL) - return optional ? start : NULL; - return ptr; -} - -char * -osmtpd_mheader_skip_obs_fws(char *ptr, int optional) -{ - char *start = ptr, *prev; - - if ((ptr = osmtpd_mheader_skip_wsp(ptr, 0)) == NULL) - return optional ? start : NULL; - prev = ptr; - while ((ptr = osmtpd_mheader_skip_wsp(ptr, 0)) != NULL) - prev = ptr; - - ptr = prev; - while (1) { - if ((ptr = osmtpd_mheader_skip_crlf(ptr, 0)) == NULL) - return prev; - if ((ptr = osmtpd_mheader_skip_wsp(ptr, 0)) == NULL) - return prev; - prev = ptr; - while ((ptr = osmtpd_mheader_skip_wsp(ptr, 0)) != NULL) - prev = ptr; - ptr = prev; - } -} - -char * -osmtpd_mheader_skip_fws(char *ptr, int optional) -{ - char *start = ptr, *prev = ptr; - - while ((ptr = osmtpd_mheader_skip_wsp(ptr, 0)) != NULL) - prev = ptr; - if ((ptr = osmtpd_mheader_skip_crlf(prev, 1)) == prev) - ptr = start; - if ((ptr = osmtpd_mheader_skip_wsp(ptr, 0)) == NULL) - return osmtpd_mheader_skip_obs_fws(start, optional); - prev = ptr; - while ((ptr = osmtpd_mheader_skip_wsp(ptr, 0)) != NULL) - prev = ptr; - return prev; -} - -char * -osmtpd_mheader_skip_obs_no_ws_ctl(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; -} - -char * -osmtpd_mheader_skip_obs_ctext(char *ptr, int optional) -{ - return osmtpd_mheader_skip_obs_no_ws_ctl(ptr, optional); -} - -char * -osmtpd_mheader_skip_ctext(char *ptr, int optional) -{ - 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_mheader_skip_obs_ctext(ptr, 0)) != NULL) - return ptr; - return optional ? start : NULL; -} - -char * -osmtpd_mheader_skip_obs_qp(char *ptr, int optional) -{ - char *start = ptr; - - if (ptr[0] == '\\' && ( - (ptr = osmtpd_mheader_skip_obs_no_ws_ctl(start + 1, 0)) != NULL || - (ptr = osmtpd_mheader_skip_lf(start + 1, 0)) != NULL || - (ptr = osmtpd_mheader_skip_cr(start + 1, 0)) != NULL)) - return ptr; - return optional ? start : NULL; -} - -char * -osmtpd_mheader_skip_quoted_pair(char *ptr, int optional) -{ - char *start = ptr; - - if (ptr[0] == '\\' && ( - (ptr = osmtpd_mheader_skip_vchar(start + 1, 0)) != NULL || - (ptr = osmtpd_mheader_skip_wsp(start + 1, 0)) != NULL)) - return ptr; - return osmtpd_mheader_skip_obs_qp(start, optional); -} - -char * -osmtpd_mheader_skip_ccontent(char *ptr, int optional) -{ - char *start = ptr; - - if ((ptr = osmtpd_mheader_skip_ctext(ptr, 0)) != NULL) - return ptr; - if ((ptr = osmtpd_mheader_skip_quoted_pair(start, 0)) != NULL) - return ptr; - if ((ptr = osmtpd_mheader_skip_comment(start, 0)) != NULL) - return ptr; - return optional ? start : NULL; -} - -char * -osmtpd_mheader_skip_comment(char *ptr, int optional) -{ - char *start = ptr; - - if (ptr++[0] != '(') - return optional ? start : NULL; - while (1) { - ptr = osmtpd_mheader_skip_fws(ptr, 1); - if (ptr[0] == ')') - return ptr + 1; - if ((ptr = osmtpd_mheader_skip_ccontent(ptr, 0)) == NULL) - return optional ? start : NULL; - } -} - -char * -osmtpd_mheader_skip_cfws(char *ptr, int optional) -{ - char *start = ptr, *prev; - - while (1) { - ptr = osmtpd_mheader_skip_fws(ptr, 1); - prev = ptr; - if ((ptr = osmtpd_mheader_skip_comment(ptr, 0)) == NULL) { - ptr = prev; - break; - } - } - return ptr == start && !optional ? NULL : ptr; -} - -char * -osmtpd_mheader_skip_atext(char *ptr, int optional) -{ - char *start = ptr; - - if ((ptr = osmtpd_mheader_skip_alpha(start, 0)) != NULL || - (ptr = osmtpd_mheader_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; -} - -char * -osmtpd_mheader_skip_atom(char *ptr, int optional) -{ - char *start = ptr, *prev; - - ptr = osmtpd_mheader_skip_cfws(ptr, 1); - if ((ptr = osmtpd_mheader_skip_atext(ptr, 0)) == NULL) - return optional ? start : NULL; - do { - prev = ptr; - ptr = osmtpd_mheader_skip_atext(ptr, 1); - } while (prev != ptr); - return osmtpd_mheader_skip_cfws(ptr, 1); -} - -char * -osmtpd_mheader_skip_dot_atom_text(char *ptr, int optional) -{ - char *start = ptr, *prev; - - if ((ptr = osmtpd_mheader_skip_atext(ptr, 0)) == NULL) - return optional ? start : NULL; - do { - prev = ptr; - ptr = osmtpd_mheader_skip_atext(ptr, 1); - } while (ptr != prev); - - while (ptr[0] == '.') { - ptr++; - if ((ptr = osmtpd_mheader_skip_atext(ptr, 0)) == NULL) - return prev; - do { - prev = ptr; - ptr = osmtpd_mheader_skip_atext(ptr, 1); - } while (ptr != prev); - } - return ptr; -} - -char * -osmtpd_mheader_skip_dot_atom(char *ptr, int optional) -{ - char *start = ptr; - - ptr = osmtpd_mheader_skip_cfws(ptr, 1); - if ((ptr = osmtpd_mheader_skip_dot_atom_text(ptr, 0)) == NULL) - return optional ? start : NULL; - return osmtpd_mheader_skip_cfws(ptr, 1); -} - -char * -osmtpd_mheader_skip_obs_qtext(char *ptr, int optional) -{ - return osmtpd_mheader_skip_obs_no_ws_ctl(ptr, optional); -} - -char * -osmtpd_mheader_skip_qtext(char *ptr, int optional) -{ - 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_mheader_skip_obs_qtext(ptr, 0)) != NULL) - return ptr; - return optional ? start : NULL; -} - -char * -osmtpd_mheader_skip_qcontent(char *ptr, int optional) -{ - char *start = ptr; - - if ((ptr = osmtpd_mheader_skip_qtext(ptr, 0)) != NULL) - return ptr; - return osmtpd_mheader_skip_quoted_pair(start, optional); -} - -char * -osmtpd_mheader_skip_quoted_string(char *ptr, int optional) -{ - char *start = ptr, *prev; - - ptr = osmtpd_mheader_skip_cfws(ptr, 1); - if ((ptr = osmtpd_mheader_skip_dquote(ptr, 0)) == NULL) - return optional ? start : NULL; - prev = ptr; - while (1) { - ptr = osmtpd_mheader_skip_fws(ptr, 1); - if ((ptr = osmtpd_mheader_skip_qcontent(ptr, 0)) == NULL) - break; - prev = ptr; - } - if ((ptr = osmtpd_mheader_skip_dquote(prev, 0)) == NULL) - return optional ? start : NULL; - return osmtpd_mheader_skip_cfws(ptr, 1); -} - -char * -osmtpd_mheader_skip_keyword(char *ptr, int optional) -{ - return osmtpd_mheader_skip_ldhstring(ptr, optional); -} - -char * -osmtpd_mheader_skip_word(char *ptr, int optional) -{ - char *start = ptr; - - if ((ptr = osmtpd_mheader_skip_atom(ptr, 0)) != NULL) - return ptr; - return osmtpd_mheader_skip_quoted_string(start, optional); -} - -char * -osmtpd_mheader_skip_obs_phrase(char *ptr, int optional) -{ - char *start = ptr, *prev; - - if ((ptr = osmtpd_mheader_skip_word(ptr, 0)) == NULL) - return optional ? start : NULL; - while (1) { - prev = ptr; - if ((ptr = osmtpd_mheader_skip_word(ptr, 0)) != NULL) - continue; - ptr = prev; - if (ptr[0] == '.') { - ptr++; - continue; - } - if ((ptr = osmtpd_mheader_skip_cfws(ptr, 0)) != NULL) - continue; - return prev; - } -} - -char * -osmtpd_mheader_skip_phrase(char *ptr, int optional) -{ - /* obs-phrase is a superset of phrae */ - return osmtpd_mheader_skip_obs_phrase(ptr, optional); -#if 0 - char *start = ptr, *prev; - - if ((ptr = osmtpd_mheader_skip_word(ptr, 0)) == NULL) - return optional ? start : NULL; - while (1) { - prev = ptr; - if ((ptr = osmtpd_mheader_skip_word(ptr, 0)) == NULL) - return prev; - } -#endif -} - -char * -osmtpd_mheader_skip_obs_local_part(char *ptr, int optional) -{ - char *start = ptr, *prev; - - if ((ptr = osmtpd_mheader_skip_word(ptr, 0)) == NULL) - return optional ? start : NULL; - prev = ptr; - while (ptr[0] == '.') { - ptr++; - if ((ptr = osmtpd_mheader_skip_word(ptr, 0)) == NULL) - return prev; - prev = ptr; - } - return ptr; -} - -char * -osmtpd_mheader_skip_local_part(char *ptr, int optional) -{ - char *start = ptr; - - if ((ptr = osmtpd_mheader_skip_dot_atom(ptr, 0)) != NULL) - return ptr; - ptr = start; - if ((ptr = osmtpd_mheader_skip_quoted_string(ptr, 0)) != NULL) - return ptr; - return osmtpd_mheader_skip_obs_local_part(start, optional); -} - -char * -osmtpd_mheader_skip_subdomain(char *ptr, int optional) -{ - char *start = ptr; - - if ((ptr = osmtpd_mheader_skip_letdig(ptr, 0)) == NULL) - return optional ? start : NULL; - return osmtpd_mheader_skip_ldhstring(ptr, 1); -} - -char * -osmtpd_mheader_skip_obs_dtext(char *ptr, int optional) -{ - char *start = ptr; - - if ((ptr = osmtpd_mheader_skip_obs_no_ws_ctl(ptr, 0)) != NULL) - return ptr; - return osmtpd_mheader_skip_quoted_pair(start, optional); -} - -char * -osmtpd_mheader_skip_dtext(char *ptr, int optional) -{ - if ((ptr[0] >= 33 && ptr[0] <= 90) || (ptr[0] >= 94 && ptr[0] <= 126)) - return ptr + 1; - return osmtpd_mheader_skip_obs_dtext(ptr, optional); - -} - -char * -osmtpd_mheader_skip_domain_literal(char *ptr, int optional) -{ - char *start = ptr, *prev; - - ptr = osmtpd_mheader_skip_cfws(ptr, 1); - if (ptr++[0] != '[') - return optional ? start : NULL; - while (1) { - ptr = osmtpd_mheader_skip_fws(ptr, 1); - prev = ptr; - if ((ptr = osmtpd_mheader_skip_dtext(ptr, 0)) == NULL) { - ptr = prev; - break; - } - } - if (ptr[0] != ']') - return optional ? start : NULL; - ptr++; - return osmtpd_mheader_skip_cfws(ptr, 1); -} - -char * -osmtpd_mheader_skip_obs_domain(char *ptr, int optional) -{ - char *start = ptr, *prev; - - if ((ptr = osmtpd_mheader_skip_atom(ptr, 0)) == NULL) - return optional ? start : NULL; - prev = ptr; - while (1) { - if (ptr++[0] != '.') - return prev; - if ((ptr = osmtpd_mheader_skip_atom(ptr, 0)) == NULL) - return prev; - prev = ptr; - } -} - -char * -osmtpd_mheader_skip_domain(char *ptr, int optional) -{ - char *start = ptr; - - if ((ptr = osmtpd_mheader_skip_dot_atom(start, 0)) != NULL) - return ptr; - if ((ptr = osmtpd_mheader_skip_domain_literal(start, 0)) != NULL) - return ptr; - return osmtpd_mheader_skip_obs_domain(start, optional); -} - -char * -osmtpd_mheader_skip_display_name(char *ptr, int optional) -{ - return osmtpd_mheader_skip_phrase(ptr, optional); -} - -char * -osmtpd_mheader_skip_obs_domain_list(char *ptr, int optional) -{ - char *start = ptr, *prev = ptr; - - while (1) { - if (ptr[0] == ',') { - ptr++; - prev = ptr; - continue; - } else if ((ptr = osmtpd_mheader_skip_cfws(ptr, 0)) != NULL) { - prev = ptr; - continue; - } - break; - } - ptr = prev; - - if (ptr++[0] != '@') - return optional ? start : NULL; - if ((ptr = osmtpd_mheader_skip_domain(ptr, 0)) == NULL) - return optional ? start : NULL; - while (1) { - if (ptr[0] != ',') - break; - ptr++; - ptr = osmtpd_mheader_skip_cfws(ptr, 1); - if (ptr[0] != '@') - continue; - prev = ptr; - if ((ptr = osmtpd_mheader_skip_domain(ptr + 1, 0)) == NULL) { - ptr = prev; - break; - } - } - return ptr; -} - -char * -osmtpd_mheader_skip_obs_route(char *ptr, int optional) -{ - char *start = ptr; - - if ((ptr = osmtpd_mheader_skip_obs_domain_list(ptr, 0)) == NULL) - return optional ? start : NULL; - if (ptr++[0] != ':') - return optional ? start : NULL; - return ptr; -} - -char * -osmtpd_mheader_skip_addr_spec(char *ptr, int optional) -{ - char *start = ptr; - - if ((ptr = osmtpd_mheader_skip_local_part(ptr, 0)) == NULL) - return optional ? start : NULL; - if (ptr++[0] != '@') - return optional ? start : NULL; - if ((ptr = osmtpd_mheader_skip_domain(ptr, 0)) == NULL) - return optional ? start : NULL; - return ptr; -} - -char * -osmtpd_mheader_skip_obs_angle_addr(char *ptr, int optional) -{ - char *start = ptr; - - ptr = osmtpd_mheader_skip_cfws(ptr, 1); - if (ptr++[0] != '<') - return optional ? start : NULL; - if ((ptr = osmtpd_mheader_skip_obs_route(ptr, 0)) == NULL) - return optional ? start : NULL; - if ((ptr = osmtpd_mheader_skip_addr_spec(ptr, 0)) == NULL) - return optional ? start : NULL; - if (ptr++[0] != '>') - return optional ? start : NULL; - return osmtpd_mheader_skip_cfws(ptr, 1); -} - -char * -osmtpd_mheader_skip_angle_addr(char *ptr, int optional) -{ - char *start = ptr; - - ptr = osmtpd_mheader_skip_cfws(ptr, 1); - if (ptr++[0] != '<') - return osmtpd_mheader_skip_obs_angle_addr(start, optional); - if ((ptr = osmtpd_mheader_skip_addr_spec(ptr, 0)) == NULL) - return osmtpd_mheader_skip_obs_angle_addr(start, optional); - if (ptr++[0] != '>') - return osmtpd_mheader_skip_obs_angle_addr(start, optional); - return osmtpd_mheader_skip_cfws(ptr, 1); -} - -char * -osmtpd_mheader_skip_name_addr(char *ptr, int optional) -{ - char *start = ptr; - - ptr = osmtpd_mheader_skip_display_name(ptr, 1); - if ((ptr = osmtpd_mheader_skip_angle_addr(ptr, 0)) == NULL) - return optional ? start : NULL; - return ptr; -} - -char * -osmtpd_mheader_skip_alphadigitps(char *ptr, int optional) -{ - char *end; - - if ((end = osmtpd_mheader_skip_alpha(ptr, 0)) == NULL && - (end = osmtpd_mheader_skip_digit(ptr, 0)) == NULL && - ptr[0] != '+' && ptr[0] != '/') - return optional ? ptr : NULL; - return end == NULL ? ptr + 1 : end; -} - -char * -osmtpd_mheader_skip_base64string(char *ptr, int optional) -{ - char *start = ptr; - - if ((ptr = osmtpd_mheader_skip_alphadigitps(ptr, 0)) == NULL) - return optional ? start : NULL; - while (1) { - start = ptr; - ptr = osmtpd_mheader_skip_fws(ptr, 1); - if ((ptr = osmtpd_mheader_skip_alphadigitps(ptr, 0)) == NULL) - break; - } - ptr = start; - ptr = osmtpd_mheader_skip_fws(ptr, 1); - if (ptr[0] == '=') { - ptr++; - start = ptr; - ptr = osmtpd_mheader_skip_fws(ptr, 1); - if (ptr[0] == '=') - ptr++; - else - ptr = start; - } else - ptr = start; - return ptr; -} - -char * -osmtpd_mheader_skip_hyphenatedword(char *ptr, int optional) -{ - char *start = ptr, *end, *hyphen; - - if ((ptr = osmtpd_mheader_skip_alpha(ptr, 0)) == NULL) - return optional ? start : NULL; - - end = ptr; - while (1) { - if (ptr[0] == '-') { - hyphen = hyphen == NULL ? ptr - 1 : hyphen; - ptr++; - continue; - } - start = ptr; - if ((ptr = osmtpd_mheader_skip_alpha(start, 0)) == NULL && - (ptr = osmtpd_mheader_skip_digit(start, 0)) == NULL) - break; - hyphen = NULL; - end = ptr; - - } - return hyphen == NULL ? end : hyphen; -} - -char * -osmtpd_mheader_skip_ftext(char *ptr, int optional) -{ - if ((ptr[0] >= 33 && ptr[0] <= 57) || - (ptr[0] >= 59 && ptr[0] <= 126)) - return ptr + 1; - return optional ? ptr : NULL; -} - -char * -osmtpd_mheader_skip_fieldname(char *ptr, int optional) -{ - char *start = ptr; - - if ((ptr = osmtpd_mheader_skip_ftext(ptr, 0)) == NULL) - return optional ? start : NULL; - while (1) { - start = ptr; - if ((ptr = osmtpd_mheader_skip_ftext(ptr, 0)) == NULL) - return start; - } -} - -char * -osmtpd_mheader_skip_hdrname(char *ptr, int optional) -{ - return osmtpd_mheader_skip_fieldname(ptr, optional); -} - -char * -osmtpd_mheader_skip_tspecials(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; -} - -char * -osmtpd_mheader_skip_token(char *ptr, int optional) -{ - char *start; - int first = 1; - - while (1) { - start = ptr; - if ((ptr = osmtpd_mheader_skip_char(start, 0)) != NULL && - osmtpd_mheader_skip_sp(start, 0) == NULL && - osmtpd_mheader_skip_ctl(start, 0) == NULL && - osmtpd_mheader_skip_tspecials(start, 0) == NULL) { - first = 0; - continue; - } - return optional || !first ? start : NULL; - } -} - -char * -osmtpd_mheader_skip_value(char *ptr, int optional) -{ - char *start = ptr; - - if ((ptr = osmtpd_mheader_skip_token(start, 0)) != NULL) - return ptr; - if ((ptr = osmtpd_mheader_skip_quoted_string(start, 0)) != NULL) - return ptr; - return optional ? start : NULL; -} - -char * -osmtpd_mheader_skip_dkim_safe_char(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; -} - -char * -osmtpd_mheader_skip_dkim_quoted_printable(char *ptr, int optional) -{ - char *start; - - while (1) { - start = ptr; - if ((ptr = osmtpd_mheader_skip_fws(start, 0)) != NULL) - continue; - if ((ptr = osmtpd_mheader_skip_hexoctet(start, 0)) != NULL) - continue; - ptr = osmtpd_mheader_skip_dkim_safe_char(start, 0); - if (ptr == NULL) - break; - } - return start; -} - -char * -osmtpd_mheader_skip_dkim_qp_hdr_value(char *ptr, int optional) -{ - return osmtpd_mheader_skip_dkim_quoted_printable(ptr, optional); -} - -char * -osmtpd_mheader_skip_dkimsig_alnumpunc(char *ptr, int optional) -{ - char *start = ptr; - - if ((ptr = osmtpd_mheader_skip_alpha(start, 0)) != NULL) - return ptr; - if ((ptr = osmtpd_mheader_skip_digit(start, 0)) != NULL) - return ptr; - if (start[0] == '_') - return start + 1; - return optional ? start : NULL; -} - -char * -osmtpd_mheader_skip_dkimsig_valchar(char *ptr, int optional) -{ - if ((ptr[0] >= 0x21 && ptr[0] <= 0x3A) || - (ptr[0] >= 0x3C && ptr[0] <= 0x7E)) - return ptr + 1; - return optional ? ptr : NULL; -} - -char * -osmtpd_mheader_skip_dkimsig_tval(char *ptr, int optional) -{ - char *start = ptr, *prev; - - if ((ptr = osmtpd_mheader_skip_dkimsig_valchar(ptr, 0)) == NULL) - return optional ? start : NULL; - prev = ptr; - while ((ptr = osmtpd_mheader_skip_dkimsig_valchar(ptr, 0)) != NULL) - prev = ptr; - return prev; -} - -char * -osmtpd_mheader_skip_dkimsig_tagvalue(char *ptr, int optional) -{ - char *start = ptr, *prev; - - if ((ptr = osmtpd_mheader_skip_dkimsig_tval(ptr, 0)) == NULL) - return start; - - while (1) { - start = ptr; - /* FWS contains WSP */ - if ((ptr = osmtpd_mheader_skip_fws(ptr, 0)) == NULL) - return start; - prev = ptr; - while ((ptr = osmtpd_mheader_skip_fws(ptr, 0)) != NULL) - prev = ptr; - ptr = prev; - if ((ptr = osmtpd_mheader_skip_dkimsig_tval(ptr, 0)) == NULL) - return start; - } -} - -char * -osmtpd_mheader_skip_dkimsig_tagname(char *ptr, int optional) -{ - char *start = ptr, *prev; - - if ((ptr = osmtpd_mheader_skip_alpha(ptr, 0)) == NULL) - return optional ? start : NULL; - prev = ptr; - while ((ptr = osmtpd_mheader_skip_dkimsig_alnumpunc(ptr, 0)) != NULL) - prev = ptr; - return prev; -} - -char * -osmtpd_mheader_skip_dkimsig_tagspec(char *ptr, int optional) -{ - char *start = ptr; - - ptr = osmtpd_mheader_skip_fws(ptr, 1); - if ((ptr = osmtpd_mheader_skip_dkimsig_tagname(ptr, 0)) == NULL) - return optional ? start : NULL; - ptr = osmtpd_mheader_skip_fws(ptr, 1); - if (ptr[0] != '=') - return optional ? start : NULL; - ptr++; - ptr = osmtpd_mheader_skip_fws(ptr, 1); - if ((ptr = osmtpd_mheader_skip_dkimsig_tagvalue(ptr, 0)) == NULL) - return optional ? start : NULL; - return osmtpd_mheader_skip_fws(ptr, 1); -} - -char * -osmtpd_mheader_skip_dkimsig_taglist(char *ptr, int optional) -{ - char *start = ptr; - - if ((ptr = osmtpd_mheader_skip_dkimsig_tagspec(ptr, 0)) == NULL) - return optional ? start : NULL; - while (1) { - /* Starting or trailing ';' */ - if (ptr[0] != ';') - return ptr; - ptr++; - start = ptr; - if ((ptr = osmtpd_mheader_skip_dkimsig_tagspec(ptr, 0)) == NULL) - return start; - } -} - -char * -osmtpd_mheader_skip_dkimsig_xsigatagh(char *ptr, int optional) -{ - char *start = ptr, *prev, *end; - - if ((ptr = osmtpd_mheader_skip_alpha(ptr, 0)) == NULL) - return optional ? start : NULL; - prev = ptr; - while ((end = osmtpd_mheader_skip_alpha(ptr, 0)) != NULL || - (end = osmtpd_mheader_skip_digit(ptr, 0)) != NULL) { - ptr = end; - prev = end; - } - return prev; -} - -char * -osmtpd_mheader_skip_dkimsig_xsigatagk(char *ptr, int optional) -{ - char *start = ptr, *prev, *end; - - if ((ptr = osmtpd_mheader_skip_alpha(ptr, 0)) == NULL) - return optional ? start : NULL; - prev = ptr; - while ((end = osmtpd_mheader_skip_alpha(ptr, 0)) != NULL || - (end = osmtpd_mheader_skip_digit(ptr, 0)) != NULL) { - ptr = end; - prev = end; - } - return prev; -} - -char * -osmtpd_mheader_skip_dkimsig_sigatagh(char *ptr, int optional) -{ - /* rsa / ed25519 covered by x-sig-a-tag-h */ - return osmtpd_mheader_skip_dkimsig_xsigatagh(ptr, optional); -} - -char * -osmtpd_mheader_skip_dkimsig_sigatagk(char *ptr, int optional) -{ - /* sha1 / sha256 covered by x-sig-a-tag-k */ - return osmtpd_mheader_skip_dkimsig_xsigatagk(ptr, optional); -} - -char * -osmtpd_mheader_skip_dkimsig_sigatagalg(char *ptr, int optional) -{ - char *start = ptr; - - if ((ptr = osmtpd_mheader_skip_dkimsig_sigatagk(ptr, 0)) == NULL) - return optional ? start : NULL; - if (ptr[0] != '-') - return optional ? start : NULL; - ptr++; - if ((ptr = osmtpd_mheader_skip_dkimsig_sigatagh(ptr, 0)) == NULL) - return optional ? start : NULL; - return ptr; -} - -char * -osmtpd_mheader_skip_dkimsig_xsigctagalg(char *ptr, int optional) -{ - return osmtpd_mheader_skip_hyphenatedword(ptr, optional); -} - -char * -osmtpd_mheader_skip_dkimsig_sigctagalg(char *ptr, int optional) -{ - /* simple / relaxed covered by x-sig-c-tag-alga */ - return osmtpd_mheader_skip_dkimsig_xsigctagalg(ptr, optional); -} - -char * -osmtpd_mheader_skip_dkimsig_xkeyhtagalg(char *ptr, int optional) -{ - return osmtpd_mheader_skip_hyphenatedword(ptr, optional); -} - -char * -osmtpd_mheader_skip_dkimsig_keyhtagalg(char *ptr, int optional) -{ - /* sha1 / sha256 covered by x-key-h-tag-alg */ - return osmtpd_mheader_skip_dkimsig_xkeyhtagalg(ptr, optional); -} - -char * -osmtpd_mheader_skip_dkimsig_keyhtagvalue(char *ptr, int optional) -{ - char *start = ptr; - - if ((ptr = osmtpd_mheader_skip_dkimsig_keyhtagalg(ptr, 0)) == NULL) - return optional ? start : NULL; - while (1) { - start = ptr; - ptr = osmtpd_mheader_skip_fws(ptr, 1); - if (ptr[0] != ':') - return start; - ptr = osmtpd_mheader_skip_fws(ptr + 1, 1); - ptr = osmtpd_mheader_skip_dkimsig_keyhtagalg(ptr, 0); - if (ptr == NULL) - return start; - } -} - -char * -osmtpd_mheader_skip_dkimsig_xsigqtagargs(char *ptr, int optional) -{ - return osmtpd_mheader_skip_dkim_qp_hdr_value(ptr, optional); -} - -char * -osmtpd_mheader_skip_dkimsig_xsigqtagtype(char *ptr, int optional) -{ - return osmtpd_mheader_skip_hyphenatedword(ptr, optional); -} - -char * -osmtpd_mheader_skip_dkimsig_sigqtagmethod(char *ptr, int optional) -{ - char *start = ptr; - - /* dns/txt covered by x-sig-q-tag-type ["/" x-sig-q-tag-args] */ - if ((ptr = osmtpd_mheader_skip_dkimsig_xsigqtagtype(ptr, 0)) == NULL) - return optional ? start : NULL; - start = ptr; - if (ptr[0] != '/') - return ptr; - if ((ptr = osmtpd_mheader_skip_dkimsig_xsigqtagargs(ptr, 0)) == NULL) - return start; - return ptr; -} - -char * -osmtpd_mheader_skip_dkimsig_sigztagcopy(char *ptr, int optional) -{ - char *start = ptr; - - if ((ptr = osmtpd_mheader_skip_hdrname(ptr, 0)) == NULL) - return optional ? start : NULL; - ptr = osmtpd_mheader_skip_fws(ptr, 1); - if (ptr[0] != ':') - return optional ? start : NULL; - if ((ptr = osmtpd_mheader_skip_dkim_qp_hdr_value(ptr, 0)) == NULL) - return optional ? start : NULL; - return ptr; -} - -char * -osmtpd_mheader_skip_dkimsig_sigztagvalue(char *ptr, int optional) -{ - char *start = ptr; - - if ((ptr = osmtpd_mheader_skip_dkimsig_sigztagcopy(ptr, 0)) == NULL) - return optional ? start : NULL; - while (1) { - start = ptr; - if (ptr[0] != '|') - return start; - osmtpd_mheader_skip_fws(ptr + 1, 1); - ptr = osmtpd_mheader_skip_dkimsig_sigztagcopy(ptr, 0); - if (ptr == NULL) - return start; - } -} - -char * -osmtpd_mheader_skip_dkimsig_xkeystagtype(char *ptr, int optional) -{ - return osmtpd_mheader_skip_hyphenatedword(ptr, optional); -} - -char * -osmtpd_mheader_skip_dkimsig_keystagtype(char *ptr, int optional) -{ - if (ptr[0] == '*') - return ptr + 1; - /* email covered by x-key-s-tag-type */ - return osmtpd_mheader_skip_dkimsig_xkeystagtype(ptr, optional); -} - -char * -osmtpd_mheader_skip_dkimsig_keystagvalue(char *ptr, int optional) -{ - char *start = ptr; - - if ((ptr = osmtpd_mheader_skip_dkimsig_keystagtype(ptr, 0)) == NULL) - return optional ? start : NULL; - while (1) { - start = ptr; - ptr = osmtpd_mheader_skip_fws(ptr, 1); - if (ptr[0] != ':') - return start; - ptr = osmtpd_mheader_skip_fws(ptr + 1, 1); - ptr = osmtpd_mheader_skip_dkimsig_keystagtype(ptr, 0); - if (ptr == NULL) - return start; - } - -} - -char * -osmtpd_mheader_skip_dkimsig_xkeyttagflag(char *ptr, int optional) -{ - return osmtpd_mheader_skip_hyphenatedword(ptr, optional); -} - -char * -osmtpd_mheader_skip_dkimsig_keyttagflag(char *ptr, int optional) -{ - /* y / s covered by x-key-t-tag-flag */ - return osmtpd_mheader_skip_dkimsig_xkeyttagflag(ptr, optional); -} - -char * -osmtpd_mheader_skip_dkimsig_keyttagvalue(char *ptr, int optional) -{ - char *start = ptr; - - if ((ptr = osmtpd_mheader_skip_dkimsig_keyttagflag(ptr, 0)) == NULL) - return optional ? start : NULL; - while (1) { - start = ptr; - ptr = osmtpd_mheader_skip_fws(ptr, 1); - if (ptr[0] != ':') - return start; - ptr = osmtpd_mheader_skip_fws(ptr + 1, 1); - ptr = osmtpd_mheader_skip_dkimsig_keyttagflag(ptr, 0); - if (ptr == NULL) - return start; - } -} - -char * -osmtpd_mheader_skip_dkimsig_selector(char *ptr, int optional) -{ - char *start = ptr; - - if ((ptr = osmtpd_mheader_skip_subdomain(ptr, 0)) == NULL) - return optional ? start : NULL; - while (1) { - start = ptr; - if (ptr[0] != '.') - return start; - ptr++; - if ((ptr = osmtpd_mheader_skip_subdomain(ptr, 0)) == NULL) - return start; - } -} - -char * -osmtpd_mheader_skip_ar_pvalue(char *ptr, int optional) -{ - char *start = ptr, *tmp; - - ptr = osmtpd_mheader_skip_cfws(ptr, 1); - if ((tmp = osmtpd_mheader_skip_value(ptr, 0)) != NULL) - return tmp; - ptr = osmtpd_mheader_skip_local_part(ptr, 1); - if (ptr[0] == '@') - ptr++; - if ((ptr = osmtpd_mheader_skip_domain(ptr, 0)) == NULL) - return optional ? start : NULL; - return ptr; -} - -char * -osmtpd_mheader_domain_uncomment(char *ptr) -{ - char *domain0, *domain, *tmp, *end; - - if (osmtpd_mheader_skip_dot_atom(ptr, 0) != NULL) { - ptr = osmtpd_mheader_skip_cfws(ptr, 1); - return strndup(ptr, - osmtpd_mheader_skip_dot_atom_text(ptr, 0) - ptr); - } - if ((tmp = osmtpd_mheader_skip_domain_literal(ptr, 0)) != NULL) { - ptr = osmtpd_mheader_skip_cfws(ptr, 1) + 1; - domain0 = domain = strndup(ptr, (size_t)(tmp - ptr)); - if (domain0 == NULL) - return NULL; - end = domain0 + (tmp - ptr) + 1; - domain++; - while (1) { - tmp = osmtpd_mheader_skip_fws(domain, 1); - if (tmp != domain) { - memmove(domain, tmp, end - tmp); - end -= (tmp - domain); - } - tmp = osmtpd_mheader_skip_dtext(domain, 0); - if (tmp == NULL) - break; - domain = tmp; - } - /* domain[0] == ']' */ - domain[0] = '\0'; - return domain0; - } - return strndup(ptr, osmtpd_mheader_skip_obs_domain(ptr, 1) - ptr); -} - -/* Return the domain component of the first mailbox */ -char * -osmtpd_mheader_from_domain(char *ptr) -{ - char *tmp; - - /* from */ - if (strncasecmp(ptr, "from:", 5) == 0) { - ptr += 5; - /* obs-from */ - } else if (strncasecmp(ptr, "from", 4) == 0) { - ptr += 4; - do { - tmp = ptr; - } while ((ptr = osmtpd_mheader_skip_wsp(ptr, 0)) != NULL); - ptr = tmp; - if (ptr++[0] != ':') - return NULL; - } else { - errno = EINVAL; - return NULL; - } - - /* Both from and obs-from use Mailbox-list CRLF */ - /* obs-mbox-list has just a prefix compared to mailbox-list */ - while (1) { - tmp = ptr; - ptr = osmtpd_mheader_skip_cfws(ptr, 1); - if (ptr++[0] != ',') { - ptr = tmp; - break; - } - } - /* We're only interested in the first mailbox */ - if (osmtpd_mheader_skip_name_addr(ptr, 0) != NULL) { - ptr = osmtpd_mheader_skip_display_name(ptr, 1); - ptr = osmtpd_mheader_skip_cfws(ptr, 1); - /* < */ - ptr++; - /* addr-spec */ - ptr = osmtpd_mheader_skip_local_part(ptr, 0); - /* @ */ - ptr++; - return osmtpd_mheader_domain_uncomment(ptr); - } - if (osmtpd_mheader_skip_addr_spec(ptr, 0) != NULL) { - ptr = osmtpd_mheader_skip_local_part(ptr, 0); - /* @ */ - ptr++; - return osmtpd_mheader_domain_uncomment(ptr); - } - errno = EINVAL; - return NULL; -} - -char * -osmtpd_mheader_quoted_string_normalize(char *ptr) -{ - char *end; - size_t d = 0, s; - - end = osmtpd_mheader_skip_cfws(ptr, 1); - s = end - ptr; - if (osmtpd_mheader_skip_dquote(end, 0) == NULL) - return NULL; - ptr[d++] = ptr[s++]; - while (ptr[s] != '\0') { - if (osmtpd_mheader_skip_quoted_pair(ptr + s, 0) != NULL) { - end = osmtpd_mheader_skip_qtext(ptr + s + 1, 0); - if (end != NULL) - s++; - else - ptr[d++] = ptr[s++]; - ptr[d++] = ptr[s++]; - continue; - } else if (osmtpd_mheader_skip_qtext(ptr + s, 0) != NULL) { - ptr[d++] = ptr[s++]; - } else if ((end = osmtpd_mheader_skip_fws( - ptr + s, 0)) != NULL) { - ptr[d++] = ' '; - s = end - ptr; - } else - return NULL; - } - if (osmtpd_mheader_skip_dquote(end, 0) == NULL) - return NULL; - ptr[d++] = ptr[s++]; - end = osmtpd_mheader_skip_cfws(ptr + s, 1); - if (end[0] != '\0') - return NULL; - ptr[d] = '\0'; - return ptr; -} blob - /dev/null blob + 53f593f7ff572b8a02bdb6d3b2822dad66daccc0 (mode 644) --- /dev/null +++ ltok.h @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2020 Martijn van Duren + * + * 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. + */ + +/* RFC 5234 - Augmented BNF for Syntax Specifications: ABNF */ +const char *osmtpd_ltok_skip_alpha(const char *, int); +const char *osmtpd_ltok_skip_bit(const char *, int); +const char *osmtpd_ltok_skip_char(const char *, int); +const char *osmtpd_ltok_skip_cr(const char *, int); +const char *osmtpd_ltok_skip_crlf(const char *, int); +const char *osmtpd_ltok_skip_ctl(const char *, int); +const char *osmtpd_ltok_skip_digit(const char *, int); +const char *osmtpd_ltok_skip_dquote(const char *, int); +const char *osmtpd_ltok_skip_hexdig(const char *, int); +const char *osmtpd_ltok_skip_htab(const char *, int); +const char *osmtpd_ltok_skip_lf(const char *, int); +const char *osmtpd_ltok_skip_octet(const char *, int); +const char *osmtpd_ltok_skip_sp(const char *, int); +const char *osmtpd_ltok_skip_vchar(const char *, int); +const char *osmtpd_ltok_skip_wsp(const char *, int); + +/* RFC 5321 - Simple Mail Transfer Protocol */ +const char *osmtpd_ltok_skip_keyword(const char *, int); +const char *osmtpd_ltok_skip_sub_domain(const char *, int); +const char *osmtpd_ltok_skip_let_dig(const char *, int); +const char *osmtpd_ltok_skip_ldh_string(const char *, int); + +/* RFC 5322 - Internet Message Format */ +const char *osmtpd_ltok_skip_quoted_pair(const char *, int); +const char *osmtpd_ltok_skip_fws(const char *, int); +const char *osmtpd_ltok_skip_ctext(const char *, int); +const char *osmtpd_ltok_skip_ccontent(const char *, int); +const char *osmtpd_ltok_skip_comment(const char *, int); +const char *osmtpd_ltok_skip_cfws(const char *, int); +const char *osmtpd_ltok_skip_atext(const char *, int); +const char *osmtpd_ltok_skip_atom(const char *, int); +const char *osmtpd_ltok_skip_dot_atom_text(const char *, int); +const char *osmtpd_ltok_skip_dot_atom(const char *, int); +const char *osmtpd_ltok_skip_qtext(const char *, int); +const char *osmtpd_ltok_skip_qcontent(const char *, int); +const char *osmtpd_ltok_skip_quoted_string(const char *, int); +const char *osmtpd_ltok_skip_word(const char *, int); +const char *osmtpd_ltok_skip_phrase(const char *, int); +const char *osmtpd_ltok_skip_name_addr(const char *, int); +const char *osmtpd_ltok_skip_angle_addr(const char *, int); +const char *osmtpd_ltok_skip_display_name(const char *, int); +const char *osmtpd_ltok_skip_addr_spec(const char *, int); +const char *osmtpd_ltok_skip_local_part(const char *, int); +const char *osmtpd_ltok_skip_domain(const char *, int); +const char *osmtpd_ltok_skip_domain_literal(const char *, int); +const char *osmtpd_ltok_skip_dtext(const char *, int); +const char *osmtpd_ltok_skip_field_name(const char *, int); +const char *osmtpd_ltok_skip_ftext(const char *, int); +const char *osmtpd_ltok_skip_obs_no_ws_ctl(const char *, int); +const char *osmtpd_ltok_skip_obs_ctext(const char *, int); +const char *osmtpd_ltok_skip_obs_qtext(const char *, int); +const char *osmtpd_ltok_skip_obs_qp(const char *, int); +const char *osmtpd_ltok_skip_obs_phrase(const char *, int); +const char *osmtpd_ltok_skip_obs_fws(const char *, int); +const char *osmtpd_ltok_skip_obs_angle_addr(const char *, int); +const char *osmtpd_ltok_skip_obs_route(const char *, int); +const char *osmtpd_ltok_skip_obs_domain_list(const char *, int); +const char *osmtpd_ltok_skip_obs_local_part(const char *, int); +const char *osmtpd_ltok_skip_obs_domain(const char *, int); +const char *osmtpd_ltok_skip_obs_dtext(const char *, int); + +/* RFC 2045 - Multipurpose Internet Mail Extensions */ +const char *osmtpd_ltok_skip_value(const char *, int); +const char *osmtpd_ltok_skip_token(const char *, int); +const char *osmtpd_ltok_skip_tspecials(const char *, int); +const char *osmtpd_ltok_skip_qp_section(const char *, int); +const char *osmtpd_ltok_skip_ptext(const char *, int); +const char *osmtpd_ltok_skip_safe_char(const char *, int); +const char *osmtpd_ltok_skip_hex_octet(const char *, int); + +/* RFC 6376 - DomainKeys Identified Mail (DKIM) Signatures */ +const char *osmtpd_ltok_skip_hyphenated_word(const char *, int); +const char *osmtpd_ltok_skip_alphadigitps(const char *, int); +const char *osmtpd_ltok_skip_base64string(const char *, int); +const char *osmtpd_ltok_skip_hdr_name(const char *, int); +const char *osmtpd_ltok_skip_qp_hdr_value(const char *, int); +const char *osmtpd_ltok_skip_dkim_quoted_printable(const char *, int); +const char *osmtpd_ltok_skip_dkim_safe_char(const char *, int); +const char *osmtpd_ltok_skip_selector(const char *, int); +const char *osmtpd_ltok_skip_tag_list(const char *, int); +const char *osmtpd_ltok_skip_tag_spec(const char *, int); +const char *osmtpd_ltok_skip_tag_name(const char *, int); +const char *osmtpd_ltok_skip_tag_value(const char *, int); +const char *osmtpd_ltok_skip_tval(const char *, int); +const char *osmtpd_ltok_skip_valchar(const char *, int); +const char *osmtpd_ltok_skip_alnumpunc(const char *, int); +const char *osmtpd_ltok_skip_sig_v_tag(const char *, int); +const char *osmtpd_ltok_skip_sig_v_tag_value(const char *, int); +const char *osmtpd_ltok_skip_sig_a_tag(const char *, int); +const char *osmtpd_ltok_skip_sig_a_tag_value(const char *, int); +const char *osmtpd_ltok_skip_sig_a_tag_alg(const char *, int); +const char *osmtpd_ltok_skip_sig_a_tag_k(const char *, int); +const char *osmtpd_ltok_skip_sig_a_tag_h(const char *, int); +const char *osmtpd_ltok_skip_x_sig_a_tag_k(const char *, int); +const char *osmtpd_ltok_skip_x_sig_a_tag_h(const char *, int); +const char *osmtpd_ltok_skip_sig_b_tag(const char *, int); +const char *osmtpd_ltok_skip_sig_b_tag_value(const char *, int); +const char *osmtpd_ltok_skip_sig_b_tag_data(const char *, int); +const char *osmtpd_ltok_skip_sig_bh_tag(const char *, int); +const char *osmtpd_ltok_skip_sig_bh_tag_value(const char *, int); +const char *osmtpd_ltok_skip_sig_bh_tag_data(const char *, int); +const char *osmtpd_ltok_skip_sig_c_tag(const char *, int); +const char *osmtpd_ltok_skip_sig_c_tag_value(const char *, int); +const char *osmtpd_ltok_skip_sig_c_tag_alg(const char *, int); +const char *osmtpd_ltok_skip_x_sig_c_tag_alg(const char *, int); +const char *osmtpd_ltok_skip_sig_d_tag(const char *, int); +const char *osmtpd_ltok_skip_sig_d_tag_value(const char *, int); +const char *osmtpd_ltok_skip_domain_name(const char *, int); +const char *osmtpd_ltok_skip_sig_h_tag(const char *, int); +const char *osmtpd_ltok_skip_sig_h_tag_value(const char *, int); +const char *osmtpd_ltok_skip_sig_i_tag(const char *, int); +const char *osmtpd_ltok_skip_sig_i_tag_value(const char *, int); +const char *osmtpd_ltok_skip_sig_l_tag(const char *, int); +const char *osmtpd_ltok_skip_sig_l_tag_value(const char *, int); +const char *osmtpd_ltok_skip_sig_q_tag(const char *, int); +const char *osmtpd_ltok_skip_sig_q_tag_value(const char *, int); +const char *osmtpd_ltok_skip_sig_q_tag_method(const char *, int); +const char *osmtpd_ltok_skip_x_sig_q_tag_type(const char *, int); +const char *osmtpd_ltok_skip_x_sig_q_tag_args(const char *, int); +const char *osmtpd_ltok_skip_sig_s_tag(const char *, int); +const char *osmtpd_ltok_skip_sig_s_tag_value(const char *, int); +const char *osmtpd_ltok_skip_sig_t_tag(const char *, int); +const char *osmtpd_ltok_skip_sig_t_tag_value(const char *, int); +const char *osmtpd_ltok_skip_sig_x_tag(const char *, int); +const char *osmtpd_ltok_skip_sig_x_tag_value(const char *, int); +const char *osmtpd_ltok_skip_sig_z_tag(const char *, int); +const char *osmtpd_ltok_skip_sig_z_tag_value(const char *, int); +const char *osmtpd_ltok_skip_sig_z_tag_copy(const char *, int); +const char *osmtpd_ltok_skip_key_v_tag(const char *, int); +const char *osmtpd_ltok_skip_key_v_tag_value(const char *, int); +const char *osmtpd_ltok_skip_key_h_tag(const char *, int); +const char *osmtpd_ltok_skip_key_h_tag_value(const char *, int); +const char *osmtpd_ltok_skip_key_h_tag_alg(const char *, int); +const char *osmtpd_ltok_skip_x_key_h_tag_alg(const char *, int); +const char *osmtpd_ltok_skip_key_k_tag(const char *, int); +const char *osmtpd_ltok_skip_key_k_tag_value(const char *, int); +const char *osmtpd_ltok_skip_key_k_tag_type(const char *, int); +const char *osmtpd_ltok_skip_x_key_k_tag_type(const char *, int); +const char *osmtpd_ltok_skip_key_n_tag(const char *, int); +const char *osmtpd_ltok_skip_key_n_tag_value(const char *, int); +const char *osmtpd_ltok_skip_key_p_tag(const char *, int); +const char *osmtpd_ltok_skip_key_p_tag_value(const char *, int); +const char *osmtpd_ltok_skip_key_s_tag(const char *, int); +const char *osmtpd_ltok_skip_key_s_tag_value(const char *, int); +const char *osmtpd_ltok_skip_key_s_tag_type(const char *, int); +const char *osmtpd_ltok_skip_x_key_s_tag_type(const char *, int); +const char *osmtpd_ltok_skip_key_t_tag(const char *, int); +const char *osmtpd_ltok_skip_key_t_tag_value(const char *, int); +const char *osmtpd_ltok_skip_key_t_tag_flag(const char *, int); +const char *osmtpd_ltok_skip_x_key_t_tag_flag(const char *, int); + +/* Authentication-Results */ +const char *osmtpd_ltok_skip_ar_pvalue(const char *, int); + +const char *osmtpd_ltok_domain_uncomment(const char *); +const char *osmtpd_ltok_from_domain(const char *); + +const char *osmtpd_ltok_quoted_string_normalize(const char *); blob - 7a68b1f66b7e086387bc60bc77076b4a36d5f149 (mode 644) blob + /dev/null --- mheader.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2020 Martijn van Duren - * - * 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. - */ - -char *osmtpd_mheader_skip_sp(char *, int); -char *osmtpd_mheader_skip_htab(char *, int); -char *osmtpd_mheader_skip_char(char *, int); -char *osmtpd_mheader_skip_ctl(char *, int); -char *osmtpd_mheader_skip_wsp(char *, int); -char *osmtpd_mheader_skip_crlf(char *, int); -char *osmtpd_mheader_skip_vchar(char *, int); -char *osmtpd_mheader_skip_lf(char *, int); -char *osmtpd_mheader_skip_cr(char *, int); -char *osmtpd_mheader_skip_alpha(char *, int); -char *osmtpd_mheader_skip_digit(char *, int); -char *osmtpd_mheader_skip_letdig(char *, int); -char *osmtpd_mheader_skip_ldhstring(char *, int); -char *osmtpd_mheader_skip_dquote(char *, int); -char *osmtpd_mheader_skip_hexoctet(char *, int); -char *osmtpd_mheader_skip_obs_fws(char *, int); -char *osmtpd_mheader_skip_fws(char *, int); -char *osmtpd_mheader_skip_obs_no_ws_ctl(char *, int); -char *osmtpd_mheader_skip_obs_ctext(char *, int); -char *osmtpd_mheader_skip_obs_qp(char *, int); -char *osmtpd_mheader_skip_quoted_pair(char *, int); -char *osmtpd_mheader_skip_ctext(char *, int); -char *osmtpd_mheader_skip_ccontent(char *, int); -char *osmtpd_mheader_skip_comment(char *, int); -char *osmtpd_mheader_skip_cfws(char *, int); -char *osmtpd_mheader_skip_atext(char *, int); -char *osmtpd_mheader_skip_atom(char *, int); -char *osmtpd_mheader_skip_dot_atom_text(char *, int); -char *osmtpd_mheader_skip_dot_atom(char *, int); -char *osmtpd_mheader_skip_obs_qtext(char *, int); -char *osmtpd_mheader_skip_qtext(char *, int); -char *osmtpd_mheader_skip_qcontent(char *, int); -char *osmtpd_mheader_skip_quoted_string(char *, int); -char *osmtpd_mheader_skip_keyword(char *, int); -char *osmtpd_mheader_skip_word(char *, int); -char *osmtpd_mheader_skip_obs_phrase(char *, int); -char *osmtpd_mheader_skip_phrase(char *, int); -char *osmtpd_mheader_skip_obs_local_part(char *, int); -char *osmtpd_mheader_skip_local_part(char *, int); -char *osmtpd_mheader_skip_subdomain(char *, int); -char *osmtpd_mheader_skip_obs_dtext(char *, int); -char *osmtpd_mheader_skip_dtext(char *, int); -char *osmtpd_mheader_skip_domain_literal(char *, int); -char *osmtpd_mheader_skip_obs_domain(char *, int); -char *osmtpd_mheader_skip_domain(char *, int); -char *osmtpd_mheader_skip_display_name(char *, int); -char *osmtpd_mheader_skip_obs_domain_list(char *, int); -char *osmtpd_mheader_skip_obs_route(char *, int); -char *osmtpd_mheader_skip_addr_spec(char *, int); -char *osmtpd_mheader_skip_obs_angle_addr(char *, int); -char *osmtpd_mheader_skip_angle_addr(char *, int); -char *osmtpd_mheader_skip_name_addr(char *, int); -char *osmtpd_mheader_skip_alphadigitps(char *, int); -char *osmtpd_mheader_skip_base64string(char *, int); -char *osmtpd_mheader_skip_hyphenatedword(char *, int); -char *osmtpd_mheader_skip_ftext(char *, int); -char *osmtpd_mheader_skip_fieldname(char *, int); -char *osmtpd_mheader_skip_hdrname(char *, int); -char *osmtpd_mheader_skip_tspecials(char *, int); -char *osmtpd_mheader_skip_token(char *, int); -char *osmtpd_mheader_skip_value(char *, int); - -/* DKIM-Signature */ -char *osmtpd_mheader_skip_dkim_safe_char(char *, int); -char *osmtpd_mheader_skip_dkim_quoted_printable(char *, int); -char *osmtpd_mheader_skip_dkim_qp_hdr_value(char *, int); -char *osmtpd_mheader_skip_dkimsig_alnumpunc(char *, int); -char *osmtpd_mheader_skip_dkimsig_valchar(char *, int); -char *osmtpd_mheader_skip_dkimsig_tval(char *, int); -char *osmtpd_mheader_skip_dkimsig_tagvalue(char *, int); -char *osmtpd_mheader_skip_dkimsig_tagname(char *, int); -char *osmtpd_mheader_skip_dkimsig_tagspec(char *, int); -char *osmtpd_mheader_skip_dkimsig_taglist(char *, int); -char *osmtpd_mheader_skip_dkimsig_xsigatagh(char *, int); -char *osmtpd_mheader_skip_dkimsig_xsigatagk(char *, int); -char *osmtpd_mheader_skip_dkimsig_sigatagh(char *, int); -char *osmtpd_mheader_skip_dkimsig_sigatagk(char *, int); -char *osmtpd_mheader_skip_dkimsig_sigatagalg(char *, int); -char *osmtpd_mheader_skip_dkimsig_xsigctagalg(char *, int); -char *osmtpd_mheader_skip_dkimsig_sigctagalg(char *, int); -char *osmtpd_mheader_skip_dkimsig_xkeyhtagalg(char *, int); -char *osmtpd_mheader_skip_dkimsig_xsigqtagargs(char *, int); -char *osmtpd_mheader_skip_dkimsig_xsigqtagtype(char *, int); -char *osmtpd_mheader_skip_dkimsig_sigqtagmethod(char *, int); -char *osmtpd_mheader_skip_dkimsig_sigztagcopy(char *, int); -char *osmtpd_mheader_skip_dkimsig_sigztagvalue(char *, int); -char *osmtpd_mheader_skip_dkimsig_keyhtagalg(char *, int); -char *osmtpd_mheader_skip_dkimsig_keyhtagvalue(char *, int); -char *osmtpd_mheader_skip_dkimsig_xkeystagtype(char *, int); -char *osmtpd_mheader_skip_dkimsig_keystagtype(char *, int); -char *osmtpd_mheader_skip_dkimsig_keystagvalue(char *, int); -char *osmtpd_mheader_skip_dkimsig_xkeyttagflag(char *, int); -char *osmtpd_mheader_skip_dkimsig_keyttagflag(char *, int); -char *osmtpd_mheader_skip_dkimsig_keyttagvalue(char *, int); -char *osmtpd_mheader_skip_dkimsig_selector(char *, int); - -/* Authentication-Results */ -char *osmtpd_mheader_skip_ar_pvalue(char *, int); - -char *osmtpd_mheader_domain_uncomment(char *); -char *osmtpd_mheader_from_domain(char *); - -char *osmtpd_mheader_quoted_string_normalize(char *);