commit - 2d73ea73b1a5ad46925c2c9ec38b4ba984b6c2db
commit + 7da80e474cc43ffc4c26454ae45a58a2cdd8640a
blob - 783c649bf34969be621d58a681bbf239da82c7cb
blob + 10c1cc66485be1a20b5b3ee2cfe6678aa2521e37
--- main.c
+++ main.c
int nqueries;
};
+/*
+ * Use RFC7601 (Authentication-Results), anyway OpenSMTPD reports only pass or fail
+ */
+enum iprev_state {
+ IPREV_NONE,
+ IPREV_PASS,
+ IPREV_FAIL
+};
+
struct header {
struct message *msg;
uint8_t readdone;
int readdone;
};
+struct session {
+ struct osmtpd_ctx *ctx;
+ enum iprev_state iprev;
+};
+
void usage(void);
void auth_conf(const char *, const char *);
+void auth_connect(struct osmtpd_ctx *, const char *, enum osmtpd_status, struct sockaddr_storage *, struct sockaddr_storage *);
void auth_dataline(struct osmtpd_ctx *, const char *);
+void *auth_session_new(struct osmtpd_ctx *);
+void auth_session_free(struct osmtpd_ctx *, void *);
void *auth_message_new(struct osmtpd_ctx *);
void auth_message_free(struct osmtpd_ctx *, void *);
void dkim_header_add(struct osmtpd_ctx *, const char *);
void dkim_body_parse(struct message *, const char *);
void dkim_body_verify(struct dkim_signature *);
void dkim_rr_resolve(struct asr_result *, void *);
+const char *iprev_state2str(enum iprev_state);
void auth_message_verify(struct message *);
ssize_t auth_ar_cat(char **ar, size_t *n, size_t aroff, const char *fmt, ...)
__attribute__((__format__ (printf, 4, 5)));
if ((ectx = EVP_ENCODE_CTX_new()) == NULL)
osmtpd_err(1, "EVP_ENCODE_CTX_new");
+ osmtpd_need(OSMTPD_NEED_FCRDNS);
osmtpd_register_conf(auth_conf);
osmtpd_register_filter_dataline(auth_dataline);
+ osmtpd_register_report_connect(1, auth_connect);
+ osmtpd_local_session(auth_session_new, auth_session_free);
osmtpd_local_message(auth_message_new, auth_message_free);
osmtpd_run();
}
void
+auth_connect(struct osmtpd_ctx *ctx, const char *rdns, enum osmtpd_status fcrdns,
+ struct sockaddr_storage *src, struct sockaddr_storage *dst)
+{
+ struct session *ses = ctx->local_session;
+
+ if (fcrdns == OSMTPD_STATUS_OK)
+ ses->iprev = IPREV_PASS;
+ else
+ ses->iprev = IPREV_FAIL;
+}
+
+void
auth_dataline(struct osmtpd_ctx *ctx, const char *line)
{
struct message *msg = ctx->local_message;
} else {
dkim_body_parse(msg, line);
}
+}
+
+void *
+auth_session_new(struct osmtpd_ctx *ctx)
+{
+ struct session *ses;
+
+ if ((ses = malloc(sizeof(*ses))) == NULL)
+ osmtpd_err(1, "%s: malloc", __func__);
+
+ ses->ctx = ctx;
+ ses->iprev = IPREV_NONE;
+
+ return ses;
+}
+
+void
+auth_session_free(struct osmtpd_ctx *ctx, void *data)
+{
+ struct session *ses = data;
+
+ free(ses);
}
void *
if (digestsz != sig->bhsz || memcmp(digest, sig->bh, digestsz) != 0)
dkim_signature_state(sig, DKIM_FAIL, "bh mismatch");
+}
+
+const char *
+iprev_state2str(enum iprev_state state)
+{
+ switch (state)
+ {
+ case IPREV_NONE:
+ return "none";
+ case IPREV_PASS:
+ return "pass";
+ case IPREV_FAIL:
+ return "fail";
+ }
}
void
auth_message_verify(struct message *msg)
{
+ struct session *ses = msg->ctx->local_session;
struct dkim_signature *sig;
size_t i;
ssize_t n, aroff = 0;
if (aroff == -1)
osmtpd_err(1, "%s: malloc", __func__);
}
+
+ if ((aroff = auth_ar_cat(&line, &linelen, aroff,
+ "; iprev=%s", iprev_state2str(ses->iprev))) == -1)
+ osmtpd_err(1, "%s: malloc", __func__);
+
+ if (aroff == -1)
+ osmtpd_err(1, "%s: malloc", __func__);
+
if (auth_ar_print(msg->ctx, line) != 0) {
osmtpd_warnx(msg->ctx, "Mallformed AR header");
goto fail;
sizeof("dkim=") - 1) == 0) {
ncheckpoint = osmtpd_ltok_skip_keyword(
ncheckpoint + sizeof("dkim=") - 1, 0);
+ } else if (strncmp(ncheckpoint, "iprev=",
+ sizeof("iprev=") - 1) == 0) {
+ ncheckpoint = osmtpd_ltok_skip_keyword(
+ ncheckpoint + sizeof("iprev=") - 1, 0);
/* reasonspec */
} else if (strncmp(ncheckpoint, "reason=",
sizeof("reason=") - 1) == 0) {