summaryrefslogtreecommitdiff
path: root/usr.sbin/smtpd/mfa.c
diff options
context:
space:
mode:
authorJacek Masiulaniec <jacekm@cvs.openbsd.org>2009-02-18 22:39:13 +0000
committerJacek Masiulaniec <jacekm@cvs.openbsd.org>2009-02-18 22:39:13 +0000
commit6f6865a18f21f0e17a7d198d39a86162292fa969 (patch)
tree982e8dd326522574479c819d8b7ca29b2abb06ff /usr.sbin/smtpd/mfa.c
parentda8a9fe09342881e691db6ec87d6f0aa33c59f98 (diff)
- add basic syntax checking to mfa
- decline source routing at MAIL FROM, strip at RCPT TO ok gilles@
Diffstat (limited to 'usr.sbin/smtpd/mfa.c')
-rw-r--r--usr.sbin/smtpd/mfa.c78
1 files changed, 64 insertions, 14 deletions
diff --git a/usr.sbin/smtpd/mfa.c b/usr.sbin/smtpd/mfa.c
index 21f2498ed58..1ae047dc44b 100644
--- a/usr.sbin/smtpd/mfa.c
+++ b/usr.sbin/smtpd/mfa.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mfa.c,v 1.13 2009/02/18 16:42:30 jacekm Exp $ */
+/* $OpenBSD: mfa.c,v 1.14 2009/02/18 22:39:12 jacekm Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -26,6 +26,7 @@
#include <netinet/in.h>
#include <arpa/inet.h>
+#include <ctype.h>
#include <event.h>
#include <pwd.h>
#include <stdio.h>
@@ -45,11 +46,14 @@ void mfa_setup_events(struct smtpd *);
void mfa_disable_events(struct smtpd *);
void mfa_timeout(int, short, void *);
+void mfa_test_mail(struct smtpd *, struct message *, int);
void mfa_test_rcpt(struct smtpd *, struct message_recipient *, int);
int mfa_ruletest_rcpt(struct smtpd *, struct path *, struct sockaddr_storage *);
int mfa_check_source(struct map *, struct sockaddr_storage *);
int mfa_match_mask(struct sockaddr_storage *, struct netaddr *);
+int strip_source_route(char *, size_t);
+
void
mfa_sig_handler(int sig, short event, void *p)
{
@@ -145,20 +149,9 @@ mfa_dispatch_smtp(int sig, short event, void *p)
break;
switch (imsg.hdr.type) {
- case IMSG_MFA_MAIL: {
- struct message *m;
- struct submit_status ss;
-
- m = imsg.data;
- log_debug("mfa_dispatch_smtp: testing return path");
- ss.id = m->id;
- ss.code = 250;
- ss.u.path = m->sender;
-
- imsg_compose(env->sc_ibufs[PROC_LKA], IMSG_LKA_MAIL, 0,
- 0, -1, &ss, sizeof(ss));
+ case IMSG_MFA_MAIL:
+ mfa_test_mail(env, imsg.data, PROC_SMTP);
break;
- }
case IMSG_MFA_RCPT:
mfa_test_rcpt(env, imsg.data, PROC_SMTP);
break;
@@ -406,6 +399,41 @@ msg_cmp(struct message *m1, struct message *m2)
}
void
+mfa_test_mail(struct smtpd *env, struct message *m, int sender)
+{
+ struct submit_status ss;
+
+ ss.id = m->id;
+ ss.code = 530;
+ ss.u.path = m->sender;
+
+ if (strip_source_route(ss.u.path.user, sizeof(ss.u.path.user)))
+ goto refuse;
+
+ if (! valid_localpart(ss.u.path.user) ||
+ ! valid_domainpart(ss.u.path.domain)) {
+ /*
+ * "MAIL FROM:<>" is the exception we allow.
+ */
+ if (!(ss.u.path.user[0] == '\0' && ss.u.path.domain[0] == '\0'))
+ goto refuse;
+ }
+
+ /* Current policy is to allow all well-formed addresses. */
+ goto accept;
+
+refuse:
+ imsg_compose(env->sc_ibufs[sender], IMSG_MFA_MAIL, 0, 0, -1, &ss,
+ sizeof(ss));
+ return;
+
+accept:
+ ss.code = 250;
+ imsg_compose(env->sc_ibufs[PROC_LKA], IMSG_LKA_MAIL, 0,
+ 0, -1, &ss, sizeof(ss));
+}
+
+void
mfa_test_rcpt(struct smtpd *env, struct message_recipient *mr, int sender)
{
struct submit_status ss;
@@ -418,12 +446,19 @@ mfa_test_rcpt(struct smtpd *env, struct message_recipient *mr, int sender)
ss.flags = mr->flags;
+ strip_source_route(ss.u.path.user, sizeof(ss.u.path.user));
+
+ if (! valid_localpart(ss.u.path.user) ||
+ ! valid_domainpart(ss.u.path.domain))
+ goto refuse;
+
if (sender == PROC_SMTP && (ss.flags & F_MESSAGE_AUTHENTICATED))
goto accept;
if (mfa_ruletest_rcpt(env, &ss.u.path, &ss.ss))
goto accept;
+refuse:
imsg_compose(env->sc_ibufs[sender], IMSG_MFA_RCPT, 0, 0, -1, &ss,
sizeof(ss));
return;
@@ -539,4 +574,19 @@ mfa_match_mask(struct sockaddr_storage *ss, struct netaddr *ssmask)
return (0);
}
+int
+strip_source_route(char *buf, size_t len)
+{
+ char *p;
+
+ p = strchr(buf, ':');
+ if (p != NULL) {
+ p++;
+ memmove(buf, p, strlen(p) + 1);
+ return 1;
+ }
+
+ return 0;
+}
+
SPLAY_GENERATE(msgtree, message, nodes, msg_cmp);