summaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/smtpd/forward.c5
-rw-r--r--usr.sbin/smtpd/lka.c442
-rw-r--r--usr.sbin/smtpd/mfa.c131
-rw-r--r--usr.sbin/smtpd/queue.c97
-rw-r--r--usr.sbin/smtpd/smtp.c23
-rw-r--r--usr.sbin/smtpd/smtp_session.c13
-rw-r--r--usr.sbin/smtpd/smtpd.h10
7 files changed, 349 insertions, 372 deletions
diff --git a/usr.sbin/smtpd/forward.c b/usr.sbin/smtpd/forward.c
index 8289d9678cf..7613f729940 100644
--- a/usr.sbin/smtpd/forward.c
+++ b/usr.sbin/smtpd/forward.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: forward.c,v 1.7 2009/01/01 16:15:47 jacekm Exp $ */
+/* $OpenBSD: forward.c,v 1.8 2009/01/04 00:58:59 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -30,6 +30,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include "smtpd.h"
@@ -40,10 +41,10 @@ forwards_get(struct aliaseslist *aliases, char *username)
struct alias alias;
struct alias *aliasp;
char pathname[MAXPATHLEN];
- struct passwd *pw;
char *buf, *lbuf;
size_t len;
struct stat sb;
+ struct passwd *pw;
pw = getpwnam(username);
if (pw == NULL)
diff --git a/usr.sbin/smtpd/lka.c b/usr.sbin/smtpd/lka.c
index 2e38c7aa619..5e50b653426 100644
--- a/usr.sbin/smtpd/lka.c
+++ b/usr.sbin/smtpd/lka.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: lka.c,v 1.12 2009/01/01 16:15:47 jacekm Exp $ */
+/* $OpenBSD: lka.c,v 1.13 2009/01/04 00:58:59 gilles Exp $ */
/*
* Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -47,7 +47,6 @@ void lka_dispatch_runner(int, short, void *);
void lka_setup_events(struct smtpd *);
void lka_disable_events(struct smtpd *);
int lka_verify_mail(struct smtpd *, struct path *);
-int lka_verify_rcpt(struct smtpd *, struct path *, struct sockaddr_storage *);
int lka_resolve_mail(struct smtpd *, struct rule *, struct path *);
int lka_resolve_rcpt(struct smtpd *, struct rule *, struct path *);
int lka_forward_file(struct passwd *);
@@ -55,13 +54,15 @@ size_t getmxbyname(char *, char ***);
int lka_expand(char *, size_t, struct path *);
int aliases_exist(struct smtpd *, char *);
int aliases_get(struct smtpd *, struct aliaseslist *, char *);
-int lka_resolve_alias(struct smtpd *, struct imsgbuf *, struct message *, struct alias *);
+int lka_resolve_alias(struct smtpd *, struct path *, struct alias *);
int lka_parse_include(char *);
int forwards_get(struct aliaseslist *, char *);
int lka_check_source(struct smtpd *, struct map *, struct sockaddr_storage *);
int lka_match_mask(struct sockaddr_storage *, struct netaddr *);
int aliases_virtual_get(struct smtpd *, struct aliaseslist *, struct path *);
int aliases_virtual_exist(struct smtpd *, struct path *);
+int lka_resolve_path(struct smtpd *, struct path *);
+int lka_expand_aliases(struct smtpd *, struct aliaseslist *, struct path *);
void
lka_sig_handler(int sig, short event, void *p)
@@ -176,21 +177,67 @@ lka_dispatch_mfa(int sig, short event, void *p)
break;
}
case IMSG_LKA_RCPT: {
- struct submit_status *ss;
+ struct submit_status *ss;
+ struct alias *alias;
+ struct aliaseslist aliases;
+ struct message message;
+ int expret;
ss = imsg.data;
ss->code = 530;
- if (lka_verify_rcpt(env, &ss->u.path, &ss->ss))
- ss->code = 250;
- else if (ss->flags & F_MESSAGE_AUTHENTICATED) {
- log_debug("accepting for authenticated user");
- ss->code = 250;
+ if (! lka_resolve_path(env, &ss->u.path)) {
+ imsg_compose(ibuf, IMSG_LKA_RCPT, 0, 0, -1,
+ ss, sizeof(*ss));
}
+ else {
+ ss->code = 250;
- imsg_compose(ibuf, IMSG_LKA_RCPT, 0, 0, -1,
- ss, sizeof(*ss));
-
+ TAILQ_INIT(&aliases);
+
+ expret = lka_expand_aliases(env, &aliases, &ss->u.path);
+ if (expret < 0) {
+ log_debug("loop detected, rejecting recipient");
+ ss->code = 530;
+ imsg_compose(ibuf, IMSG_LKA_RCPT, 0, 0, -1,
+ ss, sizeof(*ss));
+ }
+ else if (expret == 0) {
+ log_debug("expansion resulted in empty list");
+ if (! (ss->u.path.flags & F_ACCOUNT)) {
+ ss->code = 530;
+ imsg_compose(ibuf, IMSG_LKA_RCPT, 0, 0, -1,
+ ss, sizeof(*ss));
+ }
+ else {
+ message = ss->msg;
+ message.recipient = ss->u.path;
+ imsg_compose(env->sc_ibufs[PROC_QUEUE],
+ IMSG_QUEUE_SUBMIT_ENVELOPE, 0, 0, -1, &message,
+ sizeof (struct message));
+ imsg_compose(env->sc_ibufs[PROC_QUEUE],
+ IMSG_QUEUE_COMMIT_ENVELOPES, 0, 0, -1, &message,
+ sizeof (struct message));
+ }
+ }
+ else {
+ log_debug("a list of aliases is available");
+ message = ss->msg;
+ while ((alias = TAILQ_FIRST(&aliases)) != NULL) {
+ bzero(&message.recipient, sizeof (struct path));
+ lka_resolve_alias(env, &message.recipient, alias);
+ imsg_compose(env->sc_ibufs[PROC_QUEUE],
+ IMSG_QUEUE_SUBMIT_ENVELOPE, 0, 0, -1, &message,
+ sizeof (struct message));
+
+ TAILQ_REMOVE(&aliases, alias, entry);
+ free(alias);
+ }
+ imsg_compose(env->sc_ibufs[PROC_QUEUE],
+ IMSG_QUEUE_COMMIT_ENVELOPES, 0, 0, -1, &message,
+ sizeof (struct message));
+ }
+ }
break;
}
default:
@@ -311,153 +358,6 @@ lka_dispatch_queue(int sig, short event, void *p)
break;
switch (imsg.hdr.type) {
-
- case IMSG_LKA_ALIAS: {
- struct message *messagep;
- struct alias *alias;
- struct alias *remalias;
- struct path *path;
- struct aliaseslist aliases;
- u_int8_t done = 0;
- size_t nbiterations = 5;
- int ret;
-
- messagep = imsg.data;
- path = &messagep->recipient;
-
- if (path->flags & F_EXPANDED)
- break;
-
- TAILQ_INIT(&aliases);
-
- if (path->flags & F_ALIAS) {
- ret = aliases_get(env, &aliases, path->user);
- }
-
- if (path->flags & F_VIRTUAL) {
- ret = aliases_virtual_get(env, &aliases, path);
- }
-
- if (! ret) {
- /*
- * Aliases could not be retrieved, this happens
- * if the aliases database is regenerated while
- * the message is being processed. It is not an
- * error necessarily so just ignore this and it
- * will be handled by the queue process.
- */
- imsg_compose(ibuf, IMSG_QUEUE_REMOVE_SUBMISSION, 0, 0, -1, messagep,
- sizeof(struct message));
- break;
- }
-
- /* First pass, figure out if some of the usernames that
- * are in the list are actually aliases and expand them
- * if they are. The resolution will be tried five times
- * at most with an early exit if list did not change in
- * a pass.
- */
- while (!done && nbiterations--) {
- done = 1;
- remalias = NULL;
- TAILQ_FOREACH(alias, &aliases, entry) {
- if (remalias) {
- TAILQ_REMOVE(&aliases, remalias, entry);
- free(remalias);
- remalias = NULL;
- }
-
- if (alias->type == ALIAS_ADDRESS) {
- if (aliases_virtual_get(env, &aliases, &alias->u.path)) {
- done = 0;
- remalias = alias;
- }
- }
-
- else if (alias->type == ALIAS_USERNAME) {
- if (aliases_get(env, &aliases, alias->u.username)) {
- done = 0;
- remalias = alias;
- }
- }
- }
- if (remalias) {
- TAILQ_REMOVE(&aliases, remalias, entry);
- free(remalias);
- remalias = NULL;
- }
- }
-
- /* Second pass, the list no longer contains aliases and
- * the message can be sent back to queue process with a
- * modified path.
- */
- TAILQ_FOREACH(alias, &aliases, entry) {
- struct message message = *messagep;
- lka_resolve_alias(env, ibuf, &message, alias);
- imsg_compose(ibuf, IMSG_LKA_ALIAS, 0, 0, -1,
- &message, sizeof(struct message));
- }
-
- imsg_compose(ibuf, IMSG_QUEUE_REMOVE_SUBMISSION, 0, 0, -1,
- messagep, sizeof(struct message));
-
- while ((alias = TAILQ_FIRST(&aliases))) {
- TAILQ_REMOVE(&aliases, alias, entry);
- free(alias);
- }
- break;
- }
-
- case IMSG_LKA_FORWARD: {
- struct message *messagep;
- struct aliaseslist aliases;
- struct alias *alias;
-
- messagep = imsg.data;
-
- /* this is the tenth time the message has been forwarded
- * internally, break out of the loop.
- */
- if (messagep->recipient.forwardcnt == 10) {
- imsg_compose(ibuf, IMSG_QUEUE_REMOVE_SUBMISSION, 0, 0, -1, messagep,
- sizeof(struct message));
- break;
- }
- messagep->recipient.forwardcnt++;
-
- TAILQ_INIT(&aliases);
- if (! forwards_get(&aliases, messagep->recipient.pw_name)) {
- messagep->recipient.flags |= F_NOFORWARD;
- imsg_compose(ibuf, IMSG_LKA_FORWARD, 0, 0, -1,
- messagep, sizeof(struct message));
- imsg_compose(ibuf, IMSG_QUEUE_REMOVE_SUBMISSION,
- 0, 0, -1, messagep, sizeof(struct message));
- break;
- }
-
- TAILQ_FOREACH(alias, &aliases, entry) {
- struct message message = *messagep;
- lka_resolve_alias(env, ibuf, &message, alias);
- if (strcmp(messagep->recipient.pw_name, alias->u.username) == 0) {
-
- message.recipient.flags |= F_FORWARDED;
- }
- imsg_compose(ibuf, IMSG_LKA_FORWARD, 0, 0, -1,
- &message, sizeof(struct message));
- }
-
- imsg_compose(ibuf, IMSG_QUEUE_REMOVE_SUBMISSION, 0, 0,
- -1, messagep, sizeof(struct message));
-
- while ((alias = TAILQ_FIRST(&aliases))) {
- TAILQ_REMOVE(&aliases, alias, entry);
- free(alias);
- }
-
- break;
- }
-
default:
log_debug("lka_dispatch_queue: unexpected imsg %d",
imsg.hdr.type);
@@ -711,58 +611,6 @@ lka_verify_mail(struct smtpd *env, struct path *path)
}
int
-lka_verify_rcpt(struct smtpd *env, struct path *path, struct sockaddr_storage *ss)
-{
- struct rule *r;
- struct cond *cond;
- struct map *map;
- struct mapel *me;
-
- TAILQ_FOREACH(r, env->sc_rules, r_entry) {
-
- TAILQ_FOREACH(cond, &r->r_conditions, c_entry) {
-
- if (cond->c_type == C_ALL) {
- path->rule = *r;
-
- if (! lka_check_source(env, r->r_sources, ss))
- return 0;
-
- if (r->r_action == A_MBOX ||
- r->r_action == A_MAILDIR) {
- return lka_resolve_rcpt(env, r, path);
- }
- return 1;
- }
-
- if (cond->c_type == C_DOM) {
-
- cond->c_match = map_find(env, cond->c_map);
- if (cond->c_match == NULL)
- fatal("lka failed to lookup map.");
-
- map = cond->c_match;
- TAILQ_FOREACH(me, &map->m_contents, me_entry) {
- if (strcasecmp(me->me_key.med_string,
- path->domain) == 0) {
- path->rule = *r;
- if (! lka_check_source(env, r->r_sources, ss))
- return 0;
-
- if (IS_MAILBOX(r->r_action) ||
- IS_EXT(r->r_action)) {
- return lka_resolve_rcpt(env, r, path);
- }
- return 1;
- }
- }
- }
- }
- }
- return 0;
-}
-
-int
lka_resolve_mail(struct smtpd *env, struct rule *rule, struct path *path)
{
char username[MAXLOGNAME];
@@ -943,41 +791,32 @@ lka_expand(char *buf, size_t len, struct path *path)
}
int
-lka_resolve_alias(struct smtpd *env, struct imsgbuf *ibuf, struct message *messagep, struct alias *alias)
+lka_resolve_alias(struct smtpd *env, struct path *path, struct alias *alias)
{
- struct path *rpath = &messagep->recipient;
-
- rpath->flags &= ~F_ALIAS;
- rpath->flags |= F_EXPANDED;
-
switch (alias->type) {
case ALIAS_USERNAME:
- if (strlcpy(rpath->pw_name, alias->u.username,
- sizeof(rpath->pw_name)) >= sizeof(rpath->pw_name))
+ log_debug("USERNAME: %s", alias->u.username);
+ if (strlcpy(path->pw_name, alias->u.username,
+ sizeof(path->pw_name)) >= sizeof(path->pw_name))
return 0;
- lka_verify_rcpt(env, rpath, NULL);
break;
case ALIAS_FILENAME:
- rpath->rule.r_action = A_FILENAME;
- strlcpy(rpath->u.filename, alias->u.filename, MAXPATHLEN);
+ log_debug("FILENAME: %s", alias->u.filename);
+ path->rule.r_action = A_FILENAME;
+ strlcpy(path->u.filename, alias->u.filename, MAXPATHLEN);
break;
case ALIAS_FILTER:
- rpath->rule.r_action = A_EXT;
- strlcpy(rpath->rule.r_value.command, alias->u.filter + 2, MAXPATHLEN);
- rpath->rule.r_value.command[strlen(rpath->rule.r_value.command) - 1] = '\0';
+ log_debug("FILTER: %s", alias->u.filter);
+ path->rule.r_action = A_EXT;
+ strlcpy(path->rule.r_value.command, alias->u.filter + 2, MAXPATHLEN);
+ path->rule.r_value.command[strlen(path->rule.r_value.command) - 1] = '\0';
break;
case ALIAS_ADDRESS:
- *rpath = alias->u.path;
- lka_verify_rcpt(env, rpath, NULL);
- if (IS_MAILBOX(rpath->rule.r_action) ||
- IS_EXT(rpath->rule.r_action))
- messagep->type = T_MDA_MESSAGE;
- else
- messagep->type = T_MTA_MESSAGE;
-
+ log_debug("ADDRESS: %s@%s", alias->u.path.user, alias->u.path.domain);
+ *path = alias->u.path;
break;
default:
/* ALIAS_INCLUDE cannot happen here, make gcc shut up */
@@ -987,68 +826,103 @@ lka_resolve_alias(struct smtpd *env, struct imsgbuf *ibuf, struct message *messa
}
int
-lka_check_source(struct smtpd *env, struct map *map, struct sockaddr_storage *ss)
+lka_expand_aliases(struct smtpd *env, struct aliaseslist *aliases, struct path *path)
{
- struct mapel *me;
+ u_int8_t done = 0;
+ size_t iterations = 5;
+ struct alias *rmalias = NULL;
+ int ret;
+ struct alias *alias;
+
+ log_debug("RESOLVE ALIASES/.FORWARD FILES");
+ log_debug("path->user: %s", path->user);
+ log_debug("path->domain: %s", path->domain);
+
+ if (path->flags & F_ACCOUNT)
+ ret = forwards_get(aliases, path->pw_name);
+ else if (path->flags & F_ALIAS)
+ ret = aliases_get(env, aliases, path->user);
+ else if (path->flags & F_VIRTUAL)
+ ret = aliases_virtual_get(env, aliases, path);
+
+ if (! ret)
+ return 0;
+
+
+ while (!done && iterations--) {
+ done = 1;
+ rmalias = NULL;
+ TAILQ_FOREACH(alias, aliases, entry) {
+ if (rmalias) {
+ TAILQ_REMOVE(aliases, rmalias, entry);
+ free(rmalias);
+ rmalias = NULL;
+ }
- if (ss == NULL) {
- /* This happens when caller is part of an internal
- * lookup (ie: alias resolved to a remote address)
- */
- return 1;
+ if (alias->type == ALIAS_ADDRESS) {
+ if (aliases_virtual_get(env, aliases, &alias->u.path)) {
+ done = 0;
+ rmalias = alias;
+ }
+ }
+
+ else if (alias->type == ALIAS_USERNAME) {
+ if (aliases_get(env, aliases, alias->u.username) ||
+ forwards_get(aliases, alias->u.username)) {
+ done = 0;
+ rmalias = alias;
+ }
+ }
+ }
+ if (rmalias) {
+ TAILQ_REMOVE(aliases, rmalias, entry);
+ free(rmalias);
+ rmalias = NULL;
+ }
}
- TAILQ_FOREACH(me, &map->m_contents, me_entry) {
-
- if (ss->ss_family != me->me_key.med_addr.ss.ss_family)
- continue;
-
- if (ss->ss_len == me->me_key.med_addr.ss.ss_len)
- continue;
+ /* Loop detected, empty list */
+ if (!done) {
+ while ((alias = TAILQ_FIRST(aliases)) != NULL) {
+ TAILQ_REMOVE(aliases, alias, entry);
+ free(alias);
+ }
+ return -1;
+ }
- if (lka_match_mask(ss, &me->me_key.med_addr))
- return 1;
+ if (TAILQ_FIRST(aliases) == NULL)
+ return 0;
- }
- return 0;
+ return 1;
}
int
-lka_match_mask(struct sockaddr_storage *ss, struct netaddr *ssmask)
+lka_resolve_path(struct smtpd *env, struct path *path)
{
- if (ss->ss_family == AF_INET) {
- struct sockaddr_in *ssin = (struct sockaddr_in *)ss;
- struct sockaddr_in *ssinmask = (struct sockaddr_in *)&ssmask->ss;
-
- if ((ssin->sin_addr.s_addr & ssinmask->sin_addr.s_addr) ==
- ssinmask->sin_addr.s_addr)
- return (1);
- return (0);
- }
+ char username[MAXLOGNAME];
+ struct passwd *pw;
+ char *p;
- if (ss->ss_family == AF_INET6) {
- struct in6_addr *in;
- struct in6_addr *inmask;
- struct in6_addr mask;
- int i;
-
- bzero(&mask, sizeof(mask));
- for (i = 0; i < (128 - ssmask->masked) / 8; i++)
- mask.s6_addr[i] = 0xff;
- i = ssmask->masked % 8;
- if (i)
- mask.s6_addr[ssmask->masked / 8] = 0xff00 >> i;
-
- in = &((struct sockaddr_in6 *)ss)->sin6_addr;
- inmask = &((struct sockaddr_in6 *)&ssmask->ss)->sin6_addr;
-
- for (i = 0; i < 16; i++) {
- if ((in->s6_addr[i] & mask.s6_addr[i]) !=
- inmask->s6_addr[i])
- return (0);
- }
- return (1);
+ (void)strlcpy(username, path->user, MAXLOGNAME);
+
+ for (p = &username[0]; *p != '\0' && *p != '+'; ++p)
+ *p = tolower((int)*p);
+ *p = '\0';
+
+ if (aliases_virtual_exist(env, path))
+ path->flags |= F_VIRTUAL;
+ else if (aliases_exist(env, username))
+ path->flags |= F_ALIAS;
+ else {
+ path->flags |= F_ACCOUNT;
+ pw = getpwnam(username);
+ if (pw == NULL)
+ return 0;
+ (void)strlcpy(path->pw_name, pw->pw_name, MAXLOGNAME);
+ if (lka_expand(path->rule.r_value.path, MAXPATHLEN, path) >=
+ MAXPATHLEN)
+ return 0;
}
- return (0);
+ return 1;
}
diff --git a/usr.sbin/smtpd/mfa.c b/usr.sbin/smtpd/mfa.c
index 2be0f399fa9..18d6fcc7d21 100644
--- a/usr.sbin/smtpd/mfa.c
+++ b/usr.sbin/smtpd/mfa.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mfa.c,v 1.5 2009/01/01 16:15:47 jacekm Exp $ */
+/* $OpenBSD: mfa.c,v 1.6 2009/01/04 00:58:59 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -23,10 +23,14 @@
#include <sys/param.h>
#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
#include <event.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
+#include <strings.h>
#include <unistd.h>
#include "smtpd.h"
@@ -40,6 +44,10 @@ void mfa_setup_events(struct smtpd *);
void mfa_disable_events(struct smtpd *);
void mfa_timeout(int, short, void *);
+int mfa_check_rcpt(struct smtpd *, struct path *, struct sockaddr_storage *);
+int mfa_check_source(struct smtpd *, struct map *, struct sockaddr_storage *);
+int mfa_match_mask(struct sockaddr_storage *, struct netaddr *);
+
void
mfa_sig_handler(int sig, short event, void *p)
{
@@ -156,14 +164,24 @@ mfa_dispatch_smtp(int sig, short event, void *p)
mr = imsg.data;
log_debug("mfa_dispatch_smtp: testing forward path");
ss.id = mr->id;
- ss.code = 250;
+ ss.code = 530;
ss.u.path = mr->path;
ss.ss = mr->ss;
+ ss.msg = mr->msg;
ss.flags = mr->flags;
- imsg_compose(env->sc_ibufs[PROC_LKA], IMSG_LKA_RCPT, 0,
- 0, -1, &ss, sizeof(ss));
+ if (! mfa_check_rcpt(env, &ss.u.path, &ss.ss) &&
+ ! (ss.flags & F_MESSAGE_AUTHENTICATED)) {
+ imsg_compose(env->sc_ibufs[PROC_SMTP], IMSG_MFA_RCPT, 0,
+ 0, -1, &ss, sizeof(ss));
+ }
+ else {
+ ss.code = 250;
+ imsg_compose(env->sc_ibufs[PROC_LKA], IMSG_LKA_RCPT, 0,
+ 0, -1, &ss, sizeof(ss));
+ }
+
break;
}
default:
@@ -352,4 +370,109 @@ msg_cmp(struct message *m1, struct message *m2)
return (0);
}
+int
+mfa_check_rcpt(struct smtpd *env, struct path *path, struct sockaddr_storage *ss)
+{
+ struct rule *r;
+ struct cond *cond;
+ struct map *map;
+ struct mapel *me;
+
+ TAILQ_FOREACH(r, env->sc_rules, r_entry) {
+ if (! mfa_check_source(env, r->r_sources, ss))
+ continue;
+
+ log_debug("client authorized");
+ TAILQ_FOREACH(cond, &r->r_conditions, c_entry) {
+ if (cond->c_type == C_ALL) {
+ path->rule = *r;
+ return 1;
+ }
+
+ if (cond->c_type == C_DOM) {
+ cond->c_match = map_find(env, cond->c_map);
+ if (cond->c_match == NULL)
+ fatal("mfa failed to lookup map.");
+
+ map = cond->c_match;
+ TAILQ_FOREACH(me, &map->m_contents, me_entry) {
+ if (strcasecmp(me->me_key.med_string,
+ path->domain) == 0) {
+ path->rule = *r;
+ return 1;
+ }
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+int
+mfa_check_source(struct smtpd *env, struct map *map, struct sockaddr_storage *ss)
+{
+ struct mapel *me;
+
+ if (ss == NULL) {
+ /* This happens when caller is part of an internal
+ * lookup (ie: alias resolved to a remote address)
+ */
+ return 1;
+ }
+
+ TAILQ_FOREACH(me, &map->m_contents, me_entry) {
+
+ if (ss->ss_family != me->me_key.med_addr.ss.ss_family)
+ continue;
+
+ if (ss->ss_len == me->me_key.med_addr.ss.ss_len)
+ continue;
+
+ if (mfa_match_mask(ss, &me->me_key.med_addr))
+ return 1;
+
+ }
+ return 0;
+}
+
+int
+mfa_match_mask(struct sockaddr_storage *ss, struct netaddr *ssmask)
+{
+ if (ss->ss_family == AF_INET) {
+ struct sockaddr_in *ssin = (struct sockaddr_in *)ss;
+ struct sockaddr_in *ssinmask = (struct sockaddr_in *)&ssmask->ss;
+
+ if ((ssin->sin_addr.s_addr & ssinmask->sin_addr.s_addr) ==
+ ssinmask->sin_addr.s_addr)
+ return (1);
+ return (0);
+ }
+
+ if (ss->ss_family == AF_INET6) {
+ struct in6_addr *in;
+ struct in6_addr *inmask;
+ struct in6_addr mask;
+ int i;
+
+ bzero(&mask, sizeof(mask));
+ for (i = 0; i < (128 - ssmask->masked) / 8; i++)
+ mask.s6_addr[i] = 0xff;
+ i = ssmask->masked % 8;
+ if (i)
+ mask.s6_addr[ssmask->masked / 8] = 0xff00 >> i;
+
+ in = &((struct sockaddr_in6 *)ss)->sin6_addr;
+ inmask = &((struct sockaddr_in6 *)&ssmask->ss)->sin6_addr;
+
+ for (i = 0; i < 16; i++) {
+ if ((in->s6_addr[i] & mask.s6_addr[i]) !=
+ inmask->s6_addr[i])
+ return (0);
+ }
+ return (1);
+ }
+
+ return (0);
+}
+
SPLAY_GENERATE(msgtree, message, nodes, msg_cmp);
diff --git a/usr.sbin/smtpd/queue.c b/usr.sbin/smtpd/queue.c
index 1ee80863d01..b8ef27480d6 100644
--- a/usr.sbin/smtpd/queue.c
+++ b/usr.sbin/smtpd/queue.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: queue.c,v 1.42 2009/01/02 22:08:02 jacekm Exp $ */
+/* $OpenBSD: queue.c,v 1.43 2009/01/04 00:58:59 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -178,55 +178,6 @@ queue_dispatch_smtp(int sig, short event, void *p)
queue_delete_incoming_message(messagep->message_id);
break;
}
- case IMSG_QUEUE_SUBMIT_ENVELOPE: {
- struct message *messagep;
- struct submit_status ss;
-
- messagep = imsg.data;
- messagep->id = queue_generate_id();
- ss.id = messagep->session_id;
- ss.code = 250;
- ss.u.path = messagep->recipient;
-
- if (IS_MAILBOX(messagep->recipient.rule.r_action) ||
- IS_EXT(messagep->recipient.rule.r_action))
- messagep->type = T_MDA_MESSAGE;
- else
- messagep->type = T_MTA_MESSAGE;
-
- /* Write to disk */
- if (! queue_record_incoming_envelope(messagep)) {
- ss.code = 421;
- imsg_compose(ibuf, IMSG_QUEUE_SUBMIT_ENVELOPE,
- 0, 0, -1, &ss, sizeof(ss));
- break;
- }
-
- imsg_compose(ibuf, IMSG_QUEUE_SUBMIT_ENVELOPE, 0, 0, -1,
- &ss, sizeof(ss));
-
- if (messagep->type & T_MTA_MESSAGE) {
- break;
- }
-
- if ((messagep->recipient.flags & (F_ALIAS|F_VIRTUAL)) == 0) {
- /* not an alias, perform ~/.forward resolution */
- imsg_compose(env->sc_ibufs[PROC_LKA],
- IMSG_LKA_FORWARD, 0, 0, -1, messagep,
- sizeof(struct message));
- break;
- }
-
- /* Recipient is an alias, proceed to resolving it.
- * ~/.forward will be handled by the IMSG_LKA_ALIAS
- * dispatch case.
- */
- imsg_compose(env->sc_ibufs[PROC_LKA],
- IMSG_LKA_ALIAS, 0, 0, -1, messagep,
- sizeof (struct message));
-
- break;
- }
case IMSG_QUEUE_COMMIT_MESSAGE: {
struct message *messagep;
struct submit_status ss;
@@ -420,36 +371,41 @@ queue_dispatch_lka(int sig, short event, void *p)
switch (imsg.hdr.type) {
- case IMSG_LKA_ALIAS: {
- struct message *messagep;
+ case IMSG_QUEUE_SUBMIT_ENVELOPE: {
+ struct message *messagep;
+ struct submit_status ss;
messagep = imsg.data;
messagep->id = queue_generate_id();
- messagep->batch_id = 0;
- queue_record_incoming_envelope(messagep);
+ ss.id = messagep->session_id;
- if (messagep->type & T_MDA_MESSAGE) {
- imsg_compose(ibuf, IMSG_LKA_FORWARD, 0, 0, -1,
- messagep, sizeof(struct message));
- }
- break;
- }
+ if (IS_MAILBOX(messagep->recipient.rule.r_action) ||
+ IS_EXT(messagep->recipient.rule.r_action))
+ messagep->type = T_MDA_MESSAGE;
+ else
+ messagep->type = T_MTA_MESSAGE;
- case IMSG_LKA_FORWARD: {
- struct message *messagep;
+ /* Write to disk */
+ if (! queue_record_incoming_envelope(messagep)) {
+ ss.code = 421;
+ imsg_compose(env->sc_ibufs[PROC_SMTP], IMSG_QUEUE_TEMPFAIL,
+ 0, 0, -1, &ss, sizeof(ss));
+ break;
+ }
- messagep = (struct message *)imsg.data;
- messagep->id = queue_generate_id();
- messagep->batch_id = 0;
- queue_record_incoming_envelope(messagep);
break;
}
- case IMSG_QUEUE_REMOVE_SUBMISSION: {
- struct message *messagep;
+ case IMSG_QUEUE_COMMIT_ENVELOPES: {
+ struct message *messagep;
+ struct submit_status ss;
- messagep = (struct message *)imsg.data;
- queue_remove_incoming_envelope(messagep);
+ messagep = imsg.data;
+ ss.id = messagep->session_id;
+ ss.code = 250;
+
+ imsg_compose(env->sc_ibufs[PROC_SMTP], IMSG_QUEUE_COMMIT_ENVELOPES,
+ 0, 0, -1, &ss, sizeof(ss));
break;
}
@@ -893,6 +849,7 @@ queue_update_envelope(struct message *messagep)
fatal("queue_update_envelope: open");
if (flock(fileno(fp), LOCK_EX) == -1)
fatal("queue_update_envelope: flock");
+
if (fwrite(messagep, sizeof(struct message), 1, fp) != 1) {
if (errno == ENOSPC)
return 0;
diff --git a/usr.sbin/smtpd/smtp.c b/usr.sbin/smtpd/smtp.c
index 80e24c3cce6..a9bff9a0a78 100644
--- a/usr.sbin/smtpd/smtp.c
+++ b/usr.sbin/smtpd/smtp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: smtp.c,v 1.14 2009/01/01 16:15:47 jacekm Exp $ */
+/* $OpenBSD: smtp.c,v 1.15 2009/01/04 00:58:59 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -410,7 +410,26 @@ smtp_dispatch_queue(int sig, short event, void *p)
break;
}
- case IMSG_QUEUE_SUBMIT_ENVELOPE:
+ case IMSG_QUEUE_TEMPFAIL: {
+ struct submit_status *ss;
+ struct session *s;
+ struct session key;
+
+ log_debug("smtp_dispatch_queue: queue acknownedged a temporary failure");
+ ss = imsg.data;
+ key.s_id = ss->id;
+ key.s_msg.id = ss->id;
+
+ s = SPLAY_FIND(sessiontree, &env->sc_sessions, &key);
+ if (s == NULL) {
+ /* Session was removed while we were waiting for the message */
+ break;
+ }
+ s->s_msg.status |= S_MESSAGE_TEMPFAILURE;
+ break;
+ }
+
+ case IMSG_QUEUE_COMMIT_ENVELOPES:
case IMSG_QUEUE_COMMIT_MESSAGE: {
struct submit_status *ss;
struct session *s;
diff --git a/usr.sbin/smtpd/smtp_session.c b/usr.sbin/smtpd/smtp_session.c
index e904961b471..da5a61dc90b 100644
--- a/usr.sbin/smtpd/smtp_session.c
+++ b/usr.sbin/smtpd/smtp_session.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: smtp_session.c,v 1.38 2009/01/01 16:15:47 jacekm Exp $ */
+/* $OpenBSD: smtp_session.c,v 1.39 2009/01/04 00:58:59 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -460,6 +460,7 @@ session_rfc5321_rcpt_handler(struct session *s, char *args)
mr.id = s->s_msg.id;
s->s_state = S_RCPTREQUEST;
mr.ss = s->s_ss;
+ mr.msg = s->s_msg;
if (s->s_flags & F_AUTHENTICATED) {
@@ -631,7 +632,8 @@ session_pickup(struct session *s, struct submit_status *ss)
bufferevent_enable(s->s_bev, EV_READ);
- if (ss != NULL && ss->code == 421)
+ if ((ss != NULL && ss->code == 421) ||
+ (s->s_msg.status & S_MESSAGE_TEMPFAILURE))
goto tempfail;
switch (s->s_state) {
@@ -689,14 +691,9 @@ session_pickup(struct session *s, struct submit_status *ss)
s->s_state = S_RCPT;
s->s_msg.rcptcount++;
s->s_msg.recipient = ss->u.path;
- imsg_compose(s->s_env->sc_ibufs[PROC_QUEUE],
- IMSG_QUEUE_SUBMIT_ENVELOPE, 0, 0, -1, &s->s_msg,
- sizeof(s->s_msg));
- bufferevent_disable(s->s_bev, EV_READ);
- break;
+ session_respond(s, "%d Recipient ok", ss->code);
case S_RCPT:
- session_respond(s, "%d Recipient ok", ss->code);
break;
case S_DATAREQUEST:
diff --git a/usr.sbin/smtpd/smtpd.h b/usr.sbin/smtpd/smtpd.h
index fadadadadce..c77de671eb2 100644
--- a/usr.sbin/smtpd/smtpd.h
+++ b/usr.sbin/smtpd/smtpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: smtpd.h,v 1.37 2008/12/27 17:36:37 jacekm Exp $ */
+/* $OpenBSD: smtpd.h,v 1.38 2009/01/04 00:58:59 gilles Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -174,8 +174,10 @@ enum imsg_type {
IMSG_QUEUE_CREATE_MESSAGE,
IMSG_QUEUE_SUBMIT_ENVELOPE,
+ IMSG_QUEUE_COMMIT_ENVELOPES,
IMSG_QUEUE_REMOVE_MESSAGE,
IMSG_QUEUE_COMMIT_MESSAGE,
+ IMSG_QUEUE_TEMPFAIL,
IMSG_QUEUE_REMOVE_SUBMISSION,
IMSG_QUEUE_MESSAGE_UPDATE,
@@ -191,6 +193,7 @@ enum imsg_type {
IMSG_PARENT_MAILBOX_RENAME,
IMSG_PARENT_AUTHENTICATE
+
};
#define IMSG_HEADER_SIZE sizeof(struct imsg_hdr)
@@ -332,7 +335,8 @@ enum path_flags {
F_VIRTUAL = 0x2,
F_EXPANDED = 0x4,
F_NOFORWARD = 0x8,
- F_FORWARDED = 0x10
+ F_FORWARDED = 0x10,
+ F_ACCOUNT = 0x20,
};
struct path {
@@ -614,6 +618,7 @@ struct submit_status {
} u;
enum message_flags flags;
struct sockaddr_storage ss;
+ struct message msg;
};
struct message_recipient {
@@ -621,6 +626,7 @@ struct message_recipient {
struct sockaddr_storage ss;
enum message_flags flags;
struct path path;
+ struct message msg;
};