commit - d581ea1c4ec789b14e6f7c7b7f5d760621490d77
commit + 1dfc270c08266f12a19daed475ca28230803eca6
blob - 38083ccf225d30596bad793c94bece12182afead
blob + b552b4115c3dd713d6870fa2161de9af309e7395
--- LICENSE
+++ LICENSE
+Copyright (c) 2023-2024 Kirill A. Korinsky <kirill@korins.ky>
Copyright (c) 2019 Martijn van Duren <martijn@openbsd.org>
Permission to use, copy, modify, and distribute this software for any
blob - 024829c9ff003efd27ebd99bc42ae8588f09ddc9
blob + f656ce731648806bc4f71f3e3f2714f33788bd1c
--- filter-dkimsign.8
+++ filter-dkimsign.8
.Os
.Sh NAME
.Nm filter-dkimsign
-.Nd add dkim signature to messages
+.Nd add DKIM or ARC signature to messages
.Sh SYNOPSIS
.Nm
.Op Fl tz
.Fl s Ar selector
.Sh DESCRIPTION
.Nm
-adds a dkim signature to the message.
+adds a DKIM or ARC signature to the message.
The following flags are supported:
.Bl -tag -width Ds
+.It Fl A
+Produce ARC signature, and use
+.Em i
+from the first
+.Em ARC-Message-Signature
+header.
.It Fl a Ar algorithm
The
.Ar algorithm
.It Fl k Ar file
.Ar file
should point to a file containing the RSA private key to sign the messages.
+.It Fl S
+Produce ARC seal, and use
+.Em i
+and
+.Em arc
+property as
+.Em cv
+from the first
+.Em ARC-Message-Signature
+header.
.It Fl s Ar selector
The selector within the _domainkey subdomain of
.Ar domain
where the public key can be found.
.It Fl t
-Add the time of signing to the dkim header.
+Add the time of signing to the header.
.It Fl x Ar seconds
Add the amount of
.Ar seconds
-the signature is valid to the dkim header.
+the signature is valid to the header.
.It Fl z
-Add the mail headers used in the dkim signature to the dkim header.
+Add the mail headers used in the signature to the header.
If a second
.Fl z
-is specified all headers will be included in the dkim header.
+is specified all headers will be included in the header.
Useful for debugging purposes.
.El
.Sh SEE ALSO
.%R RFC 8463
.%T A New Cryptographic Signature Method for DomainKeys Identified Mail
.Re
+.Pp
+.Rs
+.%A M. Kucherawy
+.%D May 2019
+.%R RFC 8601
+.%T Message Header Field for Indicating Message Authentication Status
+.Re
+.Pp
+.Rs
+.%A K. Andersen
+.%Q LinkedIn
+.%A B. Long, Ed.
+.%Q Google
+.%A S. Blank, Ed.
+.%Q Valimail
+.%A M. Kucherawy, Ed.
+.%D July 2019
+.%R RFC 8601
+.%T The Authenticated Received Chain (ARC) Protocol
+.Re
.Sh AUTHORS
+.An Kirill A. Korinsky Aq Mt kirill@korins.ky
.An Martijn van Duren Aq Mt martijn@openbsd.org
blob - a50b631bf778c06b1848ae143a26deeec21e78ec
blob + 2bc891d305ac93903394ac86f93e0d71f218239e
--- main.c
+++ main.c
/*
+ * Copyright (c) 2024 Kirill A. Korinsky <kirill@korins.ky>
* Copyright (c) 2019 Martijn van Duren <martijn@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
+#include <inttypes.h>
+#include <libgen.h>
+#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "opensmtpd.h"
#include "mheader.h"
-struct dkim_signature {
+#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
+
+/* RFC 8617 Section 3.9 */
+enum ar_chain_status {
+ AR_UNKNOWN,
+ AR_NONE,
+ AR_PASS,
+ AR_FAIL
+};
+
+struct signature {
char *signature;
size_t size;
size_t len;
};
-struct dkim_message {
+struct message {
FILE *origf;
+ int arc_i;
+ char *arc_ar;
+ enum ar_chain_status arc_cv;
int parsing_headers;
char **headers;
int lastheader;
size_t body_whitelines;
int has_body;
- struct dkim_signature signature;
+ struct signature signature;
EVP_MD_CTX *dctx;
};
/* RFC 6376 section 5.4.1 */
-static char *dsign_headers[] = {
- "from",
- "reply-to",
- "subject",
- "date",
- "to",
- "cc",
- "resent-date",
- "resent-from",
- "resent-to",
- "resent-cc",
- "in-reply-to",
- "references",
- "list-id",
- "list-help",
- "list-unsubscribe",
- "list-subscribe",
- "list-post",
- "list-owner",
- "list-archive"
+static char *dkim_headers[] = {
+ "From",
+ "Reply-To",
+ "Subject",
+ "Date",
+ "To",
+ "Cc",
+ "Resent-Date",
+ "Resent-From",
+ "Resent-To",
+ "Resent-Cc",
+ "In-Reply-To",
+ "References",
+ "List-Id",
+ "List-Help",
+ "List-Unsubscribe",
+ "List-Subscribe",
+ "List-Post",
+ "List-Owner",
+ "List-rchive"
};
-static char **sign_headers = dsign_headers;
-static size_t nsign_headers = sizeof(dsign_headers) / sizeof(*dsign_headers);
+/* RFC 6376 section 5.4.1 + RFC8617 Section 4.1.2 */
+static char *arc_sign_headers[] = {
+ "From",
+ "Reply-To",
+ "Subject",
+ "Date",
+ "To",
+ "Cc",
+ "Resent-Date",
+ "Resent-From",
+ "Resent-To",
+ "Resent-Cc",
+ "In-Reply-To",
+ "References",
+ "List-Id",
+ "List-Help",
+ "List-Unsubscribe",
+ "List-Subscribe",
+ "List-Post",
+ "List-Owner",
+ "List-rchive",
+ "DKIM-Signature"
+};
+
+/* RFC8617 Section 5.1.1 */
+static char *arc_seal_headers[] = {
+ "ARC-Authentication-Results",
+ "ARC-Message-Signature",
+ "ARC-Seal"
+};
+
+static char **sign_headers = dkim_headers;
+static size_t nsign_headers = nitems(dkim_headers);
+
static char *hashalg = "sha256";
static char *cryptalg = "rsa";
static int keyid = EVP_PKEY_RSA;
static int sephash = 0;
-#define DKIM_SIGNATURE_LINELEN 78
+#define SIGNATURE_LINELEN 78
+/* RFC 8617 Section 4.2.1 */
+#define ARC_MIN_I 1
+#define ARC_MAX_I 50
+
+enum mode {
+ DKIMSIGN,
+ ARCSIGN,
+ ARCSEAL
+} mode = DKIMSIGN;
+
void usage(void);
-void dkim_adddomain(char *);
-void dkim_headers_set(char *);
-void dkim_dataline(struct osmtpd_ctx *, const char *);
-void *dkim_message_new(struct osmtpd_ctx *);
-void dkim_message_free(struct osmtpd_ctx *, void *);
-void dkim_parse_header(struct dkim_message *, char *, int);
-void dkim_parse_body(struct dkim_message *, char *);
-void dkim_sign(struct osmtpd_ctx *);
-int dkim_signature_printheader(struct dkim_message *, const char *);
-int dkim_signature_printf(struct dkim_message *, char *, ...)
+void sign_adddomain(char *);
+void sign_headers_set(char *);
+void sign_dataline(struct osmtpd_ctx *, const char *);
+void *message_new(struct osmtpd_ctx *);
+void message_free(struct osmtpd_ctx *, void *);
+void sign_parse_header(struct message *, char *, int);
+void sign_parse_body(struct message *, char *);
+const char *ar_chain_status2str(enum ar_chain_status);
+void sign_sign(struct osmtpd_ctx *);
+int signature_printheader(struct message *, const char *);
+void signature_printf(struct message *, char *, ...)
__attribute__((__format__ (printf, 2, 3)));
-int dkim_signature_normalize(struct dkim_message *);
-const char *dkim_domain_select(struct dkim_message *, char *);
-int dkim_signature_need(struct dkim_message *, size_t);
-int dkim_sign_init(struct dkim_message *);
+void signature_normalize(struct message *);
+const char *sign_domain_select(struct message *, char *);
+void signature_need(struct message *, size_t);
+int sign_sign_init(struct message *);
int
main(int argc, char *argv[])
char *line;
size_t linesz;
ssize_t linelen;
+ char argv0[PATH_MAX];
+ char *name;
const char *errstr;
+ const char *dkimsignopstr = "a:c:D:d:h:k:s:tx:z";
+ const char *arcsignoptstr = "a:c:D:d:h:k:s:tx:";
+ const char *arcsealoptstr = "a:D:d:k:s:tx:z";
+ const char *optstr = dkimsignopstr;
- while ((ch = getopt(argc, argv, "a:c:D:d:h:k:s:tx:z")) != -1) {
+ strlcpy(argv0, argv[0], sizeof(argv0));
+ name = basename(argv0);
+ if (strcmp(name, "filter-arcsign") == 0) {
+ mode = ARCSIGN;
+ optstr = arcsignoptstr;
+ sign_headers = arc_sign_headers;
+ nsign_headers = nitems(arc_sign_headers);
+ } else if (strcmp(name, "filter-arcseal") == 0) {
+ mode = ARCSEAL;
+ canonheader = CANON_RELAXED;
+ sign_headers = arc_seal_headers;
+ nsign_headers = nitems(arc_seal_headers);
+ optstr = arcsealoptstr;
+ } else if (strcmp(name, "filter-dkimsign") != 0)
+ usage();
+
+ while ((ch = getopt(argc, argv, optstr)) != -1) {
switch (ch) {
case 'a':
if (strncmp(optarg, "rsa-", 4) == 0) {
line[linelen - 1] = '\0';
if (line[0] == '#')
continue;
- dkim_adddomain(line);
+ sign_adddomain(line);
}
} while (linelen != -1);
if (ferror(file))
fclose(file);
break;
case 'd':
- dkim_adddomain(optarg);
+ sign_adddomain(optarg);
break;
case 'h':
- dkim_headers_set(optarg);
+ sign_headers_set(optarg);
break;
case 'k':
if ((file = fopen(optarg, "r")) == NULL)
if (EVP_PKEY_id(pkey) != keyid)
osmtpd_errx(1, "Key is not of type %s", cryptalg);
- osmtpd_register_filter_dataline(dkim_dataline);
- osmtpd_local_message(dkim_message_new, dkim_message_free);
+ osmtpd_register_filter_dataline(sign_dataline);
+ osmtpd_local_message(message_new, message_free);
osmtpd_run();
return 0;
}
void
-dkim_adddomain(char *d)
+sign_adddomain(char *d)
{
domain = reallocarray(domain, ndomains + 1, sizeof(*domain));
if (domain == NULL)
}
void
-dkim_dataline(struct osmtpd_ctx *ctx, const char *line)
+sign_dataline(struct osmtpd_ctx *ctx, const char *line)
{
- struct dkim_message *message = ctx->local_message;
+ struct message *message = ctx->local_message;
char *linedup;
size_t linelen;
osmtpd_errx(1, "Couldn't write to tempfile");
if (line[0] == '.' && line[1] =='\0') {
- dkim_sign(ctx);
+ sign_sign(ctx);
} else if (linelen != 0 && message->parsing_headers) {
if (line[0] == '.')
line++;
if ((linedup = strdup(line)) == NULL)
osmtpd_err(1, "%s: strdup", __func__);
- dkim_parse_header(message, linedup, 0);
+ sign_parse_header(message, linedup, 0);
free(linedup);
} else if (linelen == 0 && message->parsing_headers) {
- if (addheaders > 0 && !dkim_signature_printf(message, "; "))
- return;
+ if (mode == DKIMSIGN && addheaders > 0)
+ signature_printf(message, "; ");
message->parsing_headers = 0;
- } else {
+ } else if (mode == DKIMSIGN || mode == ARCSIGN) {
if (line[0] == '.')
line++;
if ((linedup = strdup(line)) == NULL)
osmtpd_err(1, "%s: strdup", __func__);
- dkim_parse_body(message, linedup);
+ sign_parse_body(message, linedup);
free(linedup);
}
}
void *
-dkim_message_new(struct osmtpd_ctx *ctx)
+message_new(struct osmtpd_ctx *ctx)
{
- struct dkim_message *message;
+ struct message *message;
if ((message = calloc(1, sizeof(*message))) == NULL) {
osmtpd_err(1, "%s: calloc", __func__);
if ((message->origf = tmpfile()) == NULL) {
osmtpd_warn(NULL, "Failed to open tempfile");
- goto fail;
+ return NULL;
}
message->parsing_headers = 1;
message->signature.size = 0;
message->signature.len = 0;
- if (!dkim_signature_printf(message,
- "DKIM-Signature: v=%s; a=%s-%s; c=%s/%s; s=%s; ", "1",
- cryptalg, hashalg,
- canonheader == CANON_SIMPLE ? "simple" : "relaxed",
- canonbody == CANON_SIMPLE ? "simple" : "relaxed", selector))
- goto fail;
- if (addheaders > 0 && !dkim_signature_printf(message, "z="))
- goto fail;
+ switch (mode) {
+ case DKIMSIGN:
+ signature_printf(message,
+ "DKIM-Signature: v=%s; a=%s-%s; c=%s/%s; s=%s; ", "1",
+ cryptalg, hashalg,
+ canonheader == CANON_SIMPLE ? "simple" : "relaxed",
+ canonbody == CANON_SIMPLE ? "simple" : "relaxed", selector);
+ if (addheaders > 0)
+ signature_printf(message, "z=");
+ break;
+ case ARCSIGN:
+ signature_printf(message, "ARC-Message-Signature: ");
+ break;
+ case ARCSEAL:
+ signature_printf(message, "ARC-Seal: ");
+ }
if ((message->dctx = EVP_MD_CTX_new()) == NULL)
osmtpd_errx(1, "EVP_MD_CTX_new");
if (EVP_DigestInit_ex(message->dctx, hash_md, NULL) <= 0)
osmtpd_errx(1, "EVP_DigestInit_ex");
return message;
-fail:
- dkim_message_free(ctx, message);
- return NULL;
}
void
-dkim_message_free(struct osmtpd_ctx *ctx, void *data)
+message_free(struct osmtpd_ctx *ctx, void *data)
{
- struct dkim_message *message = data;
+ struct message *message = data;
size_t i;
fclose(message->origf);
}
void
-dkim_headers_set(char *headers)
+sign_headers_set(char *headers)
{
size_t i;
int has_from = 0;
}
void
-dkim_parse_header(struct dkim_message *message, char *line, int force)
+sign_parse_header(struct message *message, char *line, int force)
{
+ long li;
size_t i;
size_t r, w;
size_t linelen;
char *htmp;
char *tmp;
- if (addheaders == 2 && !force &&
- !dkim_signature_printheader(message, line))
+ if (mode == DKIMSIGN && addheaders == 2 && !force &&
+ !signature_printheader(message, line))
return;
- if ((line[0] == ' ' || line[0] == '\t') && !message->lastheader)
- return;
+ if ((line[0] == ' ' || line[0] == '\t')) {
+ /* concat ARC-AR header */
+ if (message->arc_i == -1) {
+ linelen = 1;
+ linelen += strlen(line);
+ linelen += strlen(message->arc_ar);
+ htmp = reallocarray(message->arc_ar, linelen, sizeof(*htmp));
+ if (htmp == NULL) {
+ osmtpd_err(1, "malloc");
+ return;
+ }
+ message->arc_ar = htmp;
+ if (strlcat(htmp, line, linelen) >= linelen) {
+ osmtpd_errx(1, "malloc");
+ return;
+ }
+ }
+ if (!message->lastheader)
+ return;
+ }
if ((line[0] != ' ' && line[0] != '\t')) {
message->lastheader = 0;
+ /* The next header, parse captured ARC-AR */
+ if (message->arc_i == -1) {
+ message->arc_i = -2;
+ hlen = 0;
+ if (message->arc_ar[hlen] != 'i')
+ goto skpi_arc_ar;
+ hlen++;
+ while (message->arc_ar[hlen] == ' ' ||
+ message->arc_ar[hlen] == '\t')
+ hlen++;
+ if (message->arc_ar[hlen] != '=')
+ goto skpi_arc_ar;
+ hlen++;
+ li = strtol(message->arc_ar + hlen, &htmp, 10);
+ if (li < ARC_MIN_I || li > ARC_MAX_I)
+ goto skpi_arc_ar;
+ message->arc_i = li;
+ hlen = htmp - message->arc_ar;
+ while (message->arc_ar[hlen] != '\0') {
+ while (message->arc_ar[hlen] != '\0' &&
+ message->arc_ar[hlen] != ' ' &&
+ message->arc_ar[hlen] != '\t') {
+ /* skip quoted strings */
+ if (message->arc_ar[hlen] == '"')
+ while (message->arc_ar[hlen] != '\0' &&
+ message->arc_ar[hlen] != '"')
+ hlen++;
+ hlen++;
+ }
+ while (message->arc_ar[hlen] == ' ' ||
+ message->arc_ar[hlen] == '\t')
+ hlen++;
+ if (message->arc_ar[hlen] == '\0')
+ break;
+ if (strncasecmp("arc", message->arc_ar + hlen, 3) != 0) {
+ hlen++;
+ continue;
+ }
+ hlen += 3;
+ while (message->arc_ar[hlen] == ' ' ||
+ message->arc_ar[hlen] == '\t')
+ hlen++;
+ if (message->arc_ar[hlen] != '=')
+ continue;
+ hlen++;
+ while (message->arc_ar[hlen] == ' ' ||
+ message->arc_ar[hlen] == '\t')
+ hlen++;
+ if (message->arc_i == ARC_MIN_I &&
+ !strncasecmp("none", message->arc_ar + hlen, 4)) {
+ hlen += 4;
+ message->arc_cv = AR_NONE;
+ }
+ else if (!strncasecmp("pass", message->arc_ar + hlen, 4)) {
+ hlen += 4;
+ message->arc_cv = AR_PASS;
+ } else
+ message->arc_cv = AR_FAIL;
+ if (message->arc_ar[hlen] != '\0' &&
+ message->arc_ar[hlen] != ' ' &&
+ message->arc_ar[hlen] != '\t' &&
+ message->arc_ar[hlen] != ';')
+ message->arc_cv = AR_FAIL;
+ break;
+ }
+ }
+skpi_arc_ar:
+ /* Capture the first ARC-AR header */
+ hlen = sizeof("ARC-Authentication-Results:") - 1;
+ if ((mode == ARCSIGN || mode == ARCSEAL) &&
+ message->arc_ar == NULL &&
+ strncasecmp("ARC-Authentication-Results:",
+ line, hlen) == 0) {
+ while (line[hlen] == ' ' || line[hlen] == '\t')
+ hlen++;
+ message->arc_i = -1;
+ if ((message->arc_ar = strdup(line + hlen)) == NULL) {
+ osmtpd_err(1, "malloc");
+ return;
+ }
+ }
for (i = 0; i < nsign_headers; i++) {
hlen = strlen(sign_headers[i]);
if (strncasecmp(line, sign_headers[i], hlen) == 0) {
return;
}
- if (addheaders == 1 && !force &&
- !dkim_signature_printheader(message, line))
+ if (mode == DKIMSIGN && addheaders == 1 && !force &&
+ !signature_printheader(message, line))
return;
if (canonheader == CANON_RELAXED) {
}
void
-dkim_parse_body(struct dkim_message *message, char *line)
+sign_parse_body(struct message *message, char *line)
{
size_t r, w;
size_t linelen;
osmtpd_errx(1, "EVP_DigestUpdate");
}
+const char *
+ar_chain_status2str(enum ar_chain_status status)
+{
+ switch (status)
+ {
+ case AR_UNKNOWN:
+ return "unknown";
+ case AR_NONE:
+ return "none";
+ case AR_PASS:
+ return "pass";
+ case AR_FAIL:
+ return "fail";
+ }
+}
+
void
-dkim_sign(struct osmtpd_ctx *ctx)
+sign_sign(struct osmtpd_ctx *ctx)
{
- struct dkim_message *message = ctx->local_message;
+ struct message *message = ctx->local_message;
/* Use largest hash size here */
unsigned char bdigest[EVP_MAX_MD_SIZE];
unsigned char digest[(((sizeof(bdigest) + 2) / 3) * 4) + 1];
size_t linelen = 0;
char *tmp, *tmp2;
unsigned int digestsz;
+
+ if ((mode == ARCSIGN || mode == ARCSEAL) &&
+ message->arc_i < ARC_MIN_I) {
+ fprintf(stderr, "%016"PRIx64
+ " skip due to missed or invalid"
+ " ARC-Authentication-Results\n",
+ ctx->reqid);
+ goto skip_sign;
+ }
+ if (mode == ARCSIGN || mode == ARCSEAL)
+ signature_printf(message,
+ "i=%d; a=%s-%s; s=%s; ",
+ message->arc_i, cryptalg, hashalg, selector);
+
+ if (mode == ARCSIGN)
+ signature_printf(message, "c=%s/%s; ",
+ canonheader == CANON_SIMPLE ? "simple" : "relaxed",
+ canonbody == CANON_SIMPLE ? "simple" : "relaxed");
+
+ if (mode == ARCSEAL)
+ signature_printf(message, "cv=%s; ",
+ ar_chain_status2str(message->arc_cv));
+
if (addtime || addexpire)
now = time(NULL);
- if (addtime && !dkim_signature_printf(message, "t=%lld; ",
- (long long)now))
- goto fail;
- if (addexpire != 0 && !dkim_signature_printf(message, "x=%lld; ",
- now + addexpire < now ? INT64_MAX : now + addexpire))
- goto fail;
+ if (addtime)
+ signature_printf(message, "t=%lld; ", (long long)now);
+ if ((mode == DKIMSIGN || mode == ARCSIGN) && addexpire != 0)
+ signature_printf(message, "x=%lld; ",
+ now + addexpire < now ? INT64_MAX : now + addexpire);
+ if(mode == ARCSEAL)
+ goto skip_seal;
+
if (canonbody == CANON_SIMPLE && !message->has_body) {
if (EVP_DigestUpdate(message->dctx, "\r\n", 2) <= 0)
osmtpd_errx(1, "EVP_DigestUpdate");
if (EVP_DigestFinal_ex(message->dctx, bdigest, &digestsz) == 0)
osmtpd_errx(1, "EVP_DigestFinal_ex");
EVP_EncodeBlock(digest, bdigest, digestsz);
- if (!dkim_signature_printf(message, "bh=%s; h=", digest))
- goto fail;
+ signature_printf(message, "bh=%s; h=", digest);
+
+skip_seal:
/* Reverse order for ease of use of RFC6367 section 5.4.2 */
for (i = 0; message->headers[i] != NULL; i++)
continue;
EVP_DigestUpdate(message->dctx, "\r\n", 2) <= 0)
osmtpd_errx(1, "EVP_DigestSignUpdate");
}
- if ((tsdomain = dkim_domain_select(message, message->headers[i])) != NULL)
+ if ((tsdomain = sign_domain_select(message, message->headers[i])) != NULL)
sdomain = tsdomain;
/* We're done with the cached header after hashing */
for (tmp = message->headers[i]; tmp[0] != ':'; tmp++) {
tmp[0] = tolower(tmp[0]);
}
tmp[0] = '\0';
- if (!dkim_signature_printf(message, "%s%s",
- message->headers[i + 1] == NULL ? "" : ":",
- message->headers[i]))
- goto fail;
+ if (mode == DKIMSIGN || mode == ARCSIGN)
+ signature_printf(message, "%s%s",
+ message->headers[i + 1] == NULL ? "" : ":",
+ message->headers[i]);
}
- dkim_signature_printf(message, "; d=%s; b=", sdomain);
- if (!dkim_signature_normalize(message))
- goto fail;
+ if (mode == DKIMSIGN || mode == ARCSIGN)
+ signature_printf(message, "; d=%s; b=", sdomain);
+ else if (mode == ARCSEAL)
+ signature_printf(message, "d=%s; b=", sdomain);
+ signature_normalize(message);
if ((tmp = strdup(message->signature.signature)) == NULL)
osmtpd_err(1, "%s: strdup", __func__);
- dkim_parse_header(message, tmp, 1);
+ sign_parse_header(message, tmp, 1);
if (!sephash) {
if (EVP_DigestSignUpdate(message->dctx, tmp,
strlen(tmp)) != 1)
osmtpd_err(1, "%s: malloc", __func__);
EVP_EncodeBlock(b, tmp, linelen);
free(tmp);
- dkim_signature_printf(message, "%s\r\n", b);
+ signature_printf(message, "%s\r\n", b);
free(b);
- dkim_signature_normalize(message);
+ signature_normalize(message);
tmp = message->signature.signature;
while ((tmp2 = strchr(tmp, '\r')) != NULL) {
tmp2[0] = '\0';
osmtpd_filter_dataline(ctx, "%s", tmp);
tmp = tmp2 + 2;
}
+skip_sign:
tmp = NULL;
linelen = 0;
rewind(message->origf);
}
free(tmp);
return;
-fail:
- osmtpd_filter_dataline(ctx, ".");
}
-int
-dkim_signature_normalize(struct dkim_message *message)
+void
+signature_normalize(struct message *message)
{
size_t i;
size_t linelen;
}
continue;
}
- if (linelen > DKIM_SIGNATURE_LINELEN && checkpoint != 0) {
+ if (linelen > SIGNATURE_LINELEN && checkpoint != 0) {
for (skip = checkpoint + 1;
sig[skip] == ' ' || sig[skip] == '\t';
skip++)
continue;
skip -= checkpoint + 1;
- if (!dkim_signature_need(message,
- skip > 3 ? 0 : 3 - skip + 1))
- return 0;
+ signature_need(message, skip > 3 ? 0 : 3 - skip + 1);
sig = message->signature.signature;
memmove(sig + checkpoint + 3,
tag = sig[i];
}
}
- return 1;
}
int
-dkim_signature_printheader(struct dkim_message *message, const char *header)
+signature_printheader(struct message *message, const char *header)
{
size_t i, j, len;
static char *fmtheader = NULL;
(void) sprintf(fmtheader + j, "=%02hhX=%02hhX", (unsigned char) '\r',
(unsigned char) '\n');
- return dkim_signature_printf(message, "%s", fmtheader);
+ signature_printf(message, "%s", fmtheader);
+ return 1;
}
-int
-dkim_signature_printf(struct dkim_message *message, char *fmt, ...)
+void
+signature_printf(struct message *message, char *fmt, ...)
{
- struct dkim_signature *sig = &(message->signature);
+ struct signature *sig = &(message->signature);
va_list ap;
size_t len;
if ((len = vsnprintf(sig->signature + sig->len, sig->size - sig->len,
fmt, ap)) >= sig->size - sig->len) {
va_end(ap);
- if (!dkim_signature_need(message, len + 1))
- return 0;
+ signature_need(message, len + 1);
va_start(ap, fmt);
if ((len = vsnprintf(sig->signature + sig->len,
sig->size - sig->len, fmt, ap)) >= sig->size - sig->len)
}
sig->len += len;
va_end(ap);
- return 1;
}
const char *
-dkim_domain_select(struct dkim_message *message, char *from)
+sign_domain_select(struct message *message, char *from)
{
char *mdomain0, *mdomain;
size_t i;
return NULL;
}
-int
-dkim_signature_need(struct dkim_message *message, size_t len)
+void
+signature_need(struct message *message, size_t len)
{
- struct dkim_signature *sig = &(message->signature);
+ struct signature *sig = &(message->signature);
char *tmp;
if (sig->len + len < sig->size)
- return 1;
+ return;
sig->size = (((len + sig->len) / 512) + 1) * 512;
if ((tmp = realloc(sig->signature, sig->size)) == NULL)
osmtpd_err(1, "%s: malloc", __func__);
sig->signature = tmp;
- return 1;
+ return;
}
__dead void
usage(void)
{
fprintf(stderr, "usage: filter-dkimsign [-tz] [-a signalg] "
- "[-c canonicalization] \n [-h headerfields]"
+ "[-c canonicalization] \n [-h headerfields] "
"[-x seconds] -D file -d domain -k keyfile -s selector\n");
+ fprintf(stderr, "usage: filter-arcsign [-t] [-a signalg] "
+ "[-c canonicalization] \n [-h headerfields] "
+ "[-x seconds] -D file -d domain -k keyfile -s selector\n");
+ fprintf(stderr, "usage: filter-arcseal [-t] [-a signalg] "
+ "\n [-x seconds] -D file -d domain -k keyfile "
+ "-s selector\n");
exit(1);
}