commit - 5c6a65504e44766a5cf8d0b9131bd2c2331ee8ca
commit + 4e2dd90f1001dd3bf2b8e342bbd73d01231bb065
blob - 5a6d7c794505e09b9725140560776db03b94882f
blob + ef1d207bcdc89ba8d2ddfbcdb12558593fa667dc
--- Makefile
+++ Makefile
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
#include "opensmtpd.h"
#include "unpack_dns.h"
-#include "mheader.h"
+#include "ltok.h"
/*
* Use RFC8601 (Authentication-Results) codes instead of RFC6376 codes,
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;
#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;
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 *);
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;
void
dkim_conf(const char *key, const char *value)
{
- char *end;
+ const char *end;
if (key == NULL) {
if (authservid == NULL)
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);
}
}
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;
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 &&
{
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");
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)
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;
}
}
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) {
}
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");
}
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")];
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;
}
}
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;
}
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;
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++;
}
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");
}
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;
}
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) {
}
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;
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");
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);
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;
}
}
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;
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;
}
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");
}
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;
}
}
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;
}
}
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;
}
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;
}
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;
}
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;
}
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");
}
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;
}
{
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)
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;
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) {
}
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;
}
}
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 */
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;
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))
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 ||
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;
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:
break;
}
- key = osmtpd_mheader_skip_fws(key, 1);
+ key = osmtpd_ltok_skip_fws(key, 1);
if (key[0] == ';')
key++;
else if (key[0] != '\0')
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)
}
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;
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
+/*
+ * Copyright (c) 2020 Martijn van Duren <martijn@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <ctype.h>
+#include <errno.h>
+#include <stddef.h>
+#include <string.h>
+#include <strings.h>
+
+#include "ltok.h"
+
+#include <stdio.h>
+
+/* RFC 5234 - Augmented BNF for Syntax Specifications: ABNF */
+const char *
+osmtpd_ltok_skip_alpha(const char *ptr, int optional)
+{
+ if ((ptr[0] >= 0x41 && ptr[0] <= 0x5a) ||
+ (ptr[0] >= 0x61 && ptr[0] <= 0x7a))
+ return ptr + 1;
+ return optional ? ptr : NULL;
+}
+
+const char *
+osmtpd_ltok_skip_bit(const char *ptr, int optional)
+{
+ if (ptr[0] == '0' || ptr[0] == '1')
+ return ptr + 1;
+ return optional ? ptr : NULL;
+}
+
+const char *
+osmtpd_ltok_skip_char(const char *ptr, int optional)
+{
+ if (ptr[0] >= 0x01 && ptr[0] <= 0x7f)
+ return ptr + 1;
+ return optional ? ptr : NULL;
+}
+
+const char *
+osmtpd_ltok_skip_cr(const char *ptr, int optional)
+{
+ if (ptr[0] == 0xd)
+ return ptr + 1;
+ return optional ? ptr : NULL;
+}
+
+const char *
+osmtpd_ltok_skip_crlf(const char *ptr, int optional)
+{
+ if (ptr[0] == 13 && ptr[1] == 10)
+ return ptr + 2;
+ return optional ? ptr : NULL;
+}
+
+const char *
+osmtpd_ltok_skip_ctl(const char *ptr, int optional)
+{
+ if ((ptr[0] >= 0x00 && ptr[0] <= 0x1f) || ptr[0] == 0x7f)
+ return ptr + 1;
+ return optional ? ptr : NULL;
+}
+
+const char *
+osmtpd_ltok_skip_digit(const char *ptr, int optional)
+{
+ if (ptr[0] >= 0x30 && ptr[0] <= 0x39)
+ return ptr + 1;
+ return optional ? ptr : NULL;
+}
+
+const char *
+osmtpd_ltok_skip_dquote(const char *ptr, int optional)
+{
+ if (ptr[0] == 0x22)
+ return ptr + 1;
+ return optional ? ptr : NULL;
+}
+
+const char *
+osmtpd_ltok_skip_hexdig(const char *ptr, int optional)
+{
+ const char *start = ptr;
+ char l;
+
+ if ((ptr = osmtpd_ltok_skip_digit(ptr, 0)) != NULL)
+ return ptr;
+ l = tolower(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
-/*
- * Copyright (c) 2020 Martijn van Duren <martijn@openbsd.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <ctype.h>
-#include <errno.h>
-#include <stddef.h>
-#include <string.h>
-#include <strings.h>
-
-#include "mheader.h"
-
-#include <stdio.h>
-
-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
+/*
+ * Copyright (c) 2020 Martijn van Duren <martijn@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* 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
-/*
- * Copyright (c) 2020 Martijn van Duren <martijn@openbsd.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-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 *);