Hi all,
I am still working on the table-procexec for opensmtpd
and while there, I was thinking of how to do authentication
using LDAP, which the current table-ldap from ports does not
support.
The primary reason for that, I believe, is that LDAP
authentication should be done by bind and not by returning
the userPassword and us doing the authentication with
crypt_checkpass. That kind of defeats one of the uses of LDAP.
Here I've added a patch which pushes the authentication step
to the table backend and it only returns the final AUTH/NOAUTH
kind of values.
While here, I also made another small change with mailaddrmap,
where instead of returning ALL possible aliases that a user
may use, we now pass the current mailaddr to the table, so
it can now return a smaller set of addresses.
It should not affect any workflow, so testing from others
would be appreciated.
Cheers,
Aisha
diff --git a/usr.sbin/smtpd/aliases.c b/usr.sbin/smtpd/aliases.c
index a473aeca189..8e3835f78a6 100644
--- a/usr.sbin/smtpd/aliases.c
+++ b/usr.sbin/smtpd/aliases.c
@@ -45,7 +45,7 @@ aliases_get(struct expand *expand, const char *username)
/* first, check if entry has a user-part tag */
pbuf = strchr(buf, *env->sc_subaddressing_delim);
if (pbuf) {
- ret = table_lookup(mapping, K_ALIAS, buf, &lk);
+ ret = table_lookup(mapping, K_ALIAS, buf, NULL, &lk);
if (ret < 0)
return (-1);
if (ret)
@@ -54,7 +54,7 @@ aliases_get(struct expand *expand, const char *username)
}
/* no user-part tag, try looking up user */
- ret = table_lookup(mapping, K_ALIAS, buf, &lk);
+ ret = table_lookup(mapping, K_ALIAS, buf, NULL, &lk);
if (ret <= 0)
return ret;
@@ -116,7 +116,7 @@ aliases_virtual_get(struct expand *expand, const struct
mailaddr *maddr)
if (!bsnprintf(buf, sizeof(buf), "%s%c%s@%s",
user, *env->sc_subaddressing_delim, tag, domain))
return 0;
- ret = table_lookup(mapping, K_ALIAS, buf, &lk);
+ ret = table_lookup(mapping, K_ALIAS, buf, NULL, &lk);
if (ret < 0)
return (-1);
if (ret)
@@ -126,7 +126,7 @@ aliases_virtual_get(struct expand *expand, const struct
mailaddr *maddr)
/* then, check if entry exists without user-part tag */
if (!bsnprintf(buf, sizeof(buf), "%s@%s", user, domain))
return 0;
- ret = table_lookup(mapping, K_ALIAS, buf, &lk);
+ ret = table_lookup(mapping, K_ALIAS, buf, NULL, &lk);
if (ret < 0)
return (-1);
if (ret)
@@ -137,7 +137,7 @@ aliases_virtual_get(struct expand *expand, const struct
mailaddr *maddr)
if (!bsnprintf(buf, sizeof(buf), "%s%c%s",
user, *env->sc_subaddressing_delim, tag))
return 0;
- ret = table_lookup(mapping, K_ALIAS, buf, &lk);
+ ret = table_lookup(mapping, K_ALIAS, buf, NULL, &lk);
if (ret < 0)
return (-1);
if (ret)
@@ -147,7 +147,7 @@ aliases_virtual_get(struct expand *expand, const struct
mailaddr *maddr)
/* Failed ? We lookup for username only */
if (!bsnprintf(buf, sizeof(buf), "%s", user))
return 0;
- ret = table_lookup(mapping, K_ALIAS, buf, &lk);
+ ret = table_lookup(mapping, K_ALIAS, buf, NULL, &lk);
if (ret < 0)
return (-1);
if (ret)
@@ -160,14 +160,14 @@ aliases_virtual_get(struct expand *expand, const struct
mailaddr *maddr)
if (!bsnprintf(buf, sizeof(buf), "@%s", domain))
return 0;
/* Failed ? We lookup for catch all for virtual domain */
- ret = table_lookup(mapping, K_ALIAS, buf, &lk);
+ ret = table_lookup(mapping, K_ALIAS, buf, NULL, &lk);
if (ret < 0)
return (-1);
if (ret)
goto expand;
/* Failed ? We lookup for a *global* catch all */
- ret = table_lookup(mapping, K_ALIAS, "@", &lk);
+ ret = table_lookup(mapping, K_ALIAS, "@", NULL, &lk);
if (ret <= 0)
return (ret);
diff --git a/usr.sbin/smtpd/lka.c b/usr.sbin/smtpd/lka.c
index 764130d6078..3354ccde7d7 100644
--- a/usr.sbin/smtpd/lka.c
+++ b/usr.sbin/smtpd/lka.c
@@ -268,7 +268,7 @@ lka_imsg(struct mproc *p, struct imsg *imsg)
if (domain == NULL)
ret = table_fetch(table, K_RELAYHOST, &lk);
else
- ret = table_lookup(table, K_RELAYHOST, domain,
&lk);
+ ret = table_lookup(table, K_RELAYHOST, domain,
NULL, &lk);
if (ret == -1)
m_add_int(p, LKA_TEMPFAIL);
@@ -729,7 +729,7 @@ lka_authenticate(const char *tablename, const char *user,
const char *password)
return (LKA_TEMPFAIL);
}
- switch (table_lookup(table, K_CREDENTIALS, user, &lk)) {
+ switch (table_lookup(table, K_AUTHENTICATE, user, password, &lk)) {
case -1:
log_warnx("warn: user credentials lookup fail for %s:%s",
tablename, user);
@@ -737,9 +737,7 @@ lka_authenticate(const char *tablename, const char *user,
const char *password)
case 0:
return (LKA_PERMFAIL);
default:
- if (crypt_checkpass(password, lk.creds.password) == 0)
- return (LKA_OK);
- return (LKA_PERMFAIL);
+ return (LKA_OK);
}
}
@@ -759,7 +757,7 @@ lka_credentials(const char *tablename, const char *label,
char *dst, size_t sz)
dst[0] = '\0';
- switch (table_lookup(table, K_CREDENTIALS, label, &lk)) {
+ switch (table_lookup(table, K_CREDENTIALS, label, NULL, &lk)) {
case -1:
log_warnx("warn: credentials lookup fail for %s:%s",
tablename, label);
@@ -800,7 +798,7 @@ lka_userinfo(const char *tablename, const char *username,
struct userinfo *res)
return (LKA_TEMPFAIL);
}
- switch (table_lookup(table, K_USERINFO, username, &lk)) {
+ switch (table_lookup(table, K_USERINFO, username, NULL, &lk)) {
case -1:
log_warnx("warn: failure during userinfo lookup %s:%s",
tablename, username);
@@ -830,7 +828,7 @@ lka_addrname(const char *tablename, const struct sockaddr
*sa,
return (LKA_TEMPFAIL);
}
- switch (table_lookup(table, K_ADDRNAME, source, &lk)) {
+ switch (table_lookup(table, K_ADDRNAME, source, NULL, &lk)) {
case -1:
log_warnx("warn: failure during helo lookup %s:%s",
tablename, source);
@@ -858,7 +856,7 @@ lka_mailaddrmap(const char *tablename, const char
*username, const struct mailad
return (LKA_TEMPFAIL);
}
- switch (table_lookup(table, K_MAILADDRMAP, username, &lk)) {
+ switch (table_lookup(table, K_MAILADDRMAP, username,
mailaddr_to_text(maddr), &lk)) {
case -1:
log_warnx("warn: failure during mailaddrmap lookup %s:%s",
tablename, username);
diff --git a/usr.sbin/smtpd/lka_session.c b/usr.sbin/smtpd/lka_session.c
index cac9108349e..6976c584c7d 100644
--- a/usr.sbin/smtpd/lka_session.c
+++ b/usr.sbin/smtpd/lka_session.c
@@ -383,7 +383,7 @@ lka_expand(struct lka_session *lks, struct rule *rule,
struct expandnode *xn)
}
userbase = table_find(env, dsp->u.local.table_userbase);
- r = table_lookup(userbase, K_USERINFO, xn->u.user, &lk);
+ r = table_lookup(userbase, K_USERINFO, xn->u.user, NULL, &lk);
if (r == -1) {
log_trace(TRACE_EXPAND, "expand: lka_expand: "
"backend error while searching user");
diff --git a/usr.sbin/smtpd/smtpd-api.h b/usr.sbin/smtpd/smtpd-api.h
index f83edd05854..f2841107a43 100644
--- a/usr.sbin/smtpd/smtpd-api.h
+++ b/usr.sbin/smtpd/smtpd-api.h
@@ -122,21 +122,22 @@ struct table_open_params {
};
enum table_service {
- K_NONE = 0x000,
- K_ALIAS = 0x001, /* returns struct expand */
- K_DOMAIN = 0x002, /* returns struct destination */
- K_CREDENTIALS = 0x004, /* returns struct credentials */
- K_NETADDR = 0x008, /* returns struct netaddr */
- K_USERINFO = 0x010, /* returns struct userinfo */
- K_SOURCE = 0x020, /* returns struct source */
- K_MAILADDR = 0x040, /* returns struct mailaddr */
- K_ADDRNAME = 0x080, /* returns struct addrname */
- K_MAILADDRMAP = 0x100, /* returns struct maddrmap */
- K_RELAYHOST = 0x200, /* returns struct relayhost */
- K_STRING = 0x400,
- K_REGEX = 0x800,
+ K_NONE = 0,
+ K_ALIAS = 1, /* returns struct expand */
+ K_DOMAIN = 2, /* returns struct destination */
+ K_AUTHENTICATE = 4, /* returns int authenticated */
+ K_CREDENTIALS = 8, /* returns struct credentials */
+ K_NETADDR = 16, /* returns struct netaddr */
+ K_USERINFO = 32, /* returns struct userinfo */
+ K_SOURCE = 64, /* returns struct source */
+ K_MAILADDR = 128, /* returns struct mailaddr */
+ K_ADDRNAME = 256, /* returns struct addrname */
+ K_MAILADDRMAP = 512, /* returns struct maddrmap */
+ K_RELAYHOST = 1024, /* returns struct relayhost */
+ K_STRING = 2048,
+ K_REGEX = 4096
};
-#define K_ANY 0xfff
+#define K_ANY 8191
enum {
PROC_TABLE_OK,
diff --git a/usr.sbin/smtpd/smtpd.h b/usr.sbin/smtpd/smtpd.h
index e6fc114d0a6..8dff20d8c3f 100644
--- a/usr.sbin/smtpd/smtpd.h
+++ b/usr.sbin/smtpd/smtpd.h
@@ -156,6 +156,7 @@ union lookup {
struct mailaddr mailaddr;
struct addrname addrname;
struct maddrmap *maddrmap;
+ int authenticated;
char relayhost[LINE_MAX];
};
@@ -372,7 +373,7 @@ struct table_backend {
int (*open)(struct table *);
int (*update)(struct table *);
void (*close)(struct table *);
- int (*lookup)(struct table *, enum table_service, const char *,
char **);
+ int (*lookup)(struct table *, enum table_service, const char *,
const char *, char **);
int (*fetch)(struct table *, enum table_service, char **);
};
@@ -1652,7 +1653,7 @@ int table_check_type(struct table *, uint32_t);
int table_check_service(struct table *, uint32_t);
int table_match(struct table *, enum table_service, const char *);
int table_lookup(struct table *, enum table_service, const char *,
- union lookup *);
+ const char *, union lookup *);
int table_fetch(struct table *, enum table_service, union lookup *);
void table_destroy(struct smtpd *, struct table *);
void table_add(struct table *, const char *, const char *);
diff --git a/usr.sbin/smtpd/table.c b/usr.sbin/smtpd/table.c
index 7328cf5df6e..631c17af6c2 100644
--- a/usr.sbin/smtpd/table.c
+++ b/usr.sbin/smtpd/table.c
@@ -39,7 +39,7 @@ extern struct table_backend table_backend_proc;
static const char * table_service_name(enum table_service);
static int table_parse_lookup(enum table_service, const char *, const char *,
- union lookup *);
+ const char *, union lookup *);
static int parse_sockaddr(struct sockaddr *, int, const char *);
static unsigned int last_table_id = 0;
@@ -74,6 +74,7 @@ table_service_name(enum table_service s)
case K_NONE: return "NONE";
case K_ALIAS: return "ALIAS";
case K_DOMAIN: return "DOMAIN";
+ case K_AUTHENTICATE: return "AUTHENTICATE";
case K_CREDENTIALS: return "CREDENTIALS";
case K_NETADDR: return "NETADDR";
case K_USERINFO: return "USERINFO";
@@ -97,12 +98,12 @@ table_find(struct smtpd *conf, const char *name)
int
table_match(struct table *table, enum table_service kind, const char *key)
{
- return table_lookup(table, kind, key, NULL);
+ return table_lookup(table, kind, key, NULL, NULL);
}
int
table_lookup(struct table *table, enum table_service kind, const char *key,
- union lookup *lk)
+ const char *data, union lookup *lk)
{
char lkey[1024], *buf = NULL;
int r;
@@ -115,7 +116,7 @@ table_lookup(struct table *table, enum table_service kind,
const char *key,
errno = EINVAL;
}
else
- r = table->t_backend->lookup(table, kind, lkey, lk ? &buf :
NULL);
+ r = table->t_backend->lookup(table, kind, lkey, data, lk ? &buf
: NULL);
if (r == 1) {
log_trace(TRACE_LOOKUP, "lookup: %s \"%s\" as %s in table %s:%s
-> %s%s%s",
@@ -128,7 +129,7 @@ table_lookup(struct table *table, enum table_service kind,
const char *key,
lk ? buf : "true",
lk ? "\"" : "");
if (buf)
- r = table_parse_lookup(kind, lkey, buf, lk);
+ r = table_parse_lookup(kind, lkey, buf, data, lk);
}
else
log_trace(TRACE_LOOKUP, "lookup: %s \"%s\" as %s in table %s:%s
-> %s%s",
@@ -163,7 +164,7 @@ table_fetch(struct table *table, enum table_service kind,
union lookup *lk)
table->t_backend->name,
table->t_name,
buf);
- r = table_parse_lookup(kind, NULL, buf, lk);
+ r = table_parse_lookup(kind, NULL, buf, NULL, lk);
}
else
log_trace(TRACE_LOOKUP, "lookup: fetch %s from table %s:%s ->
%s%s",
@@ -510,7 +511,7 @@ table_close_all(struct smtpd *conf)
static int
table_parse_lookup(enum table_service service, const char *key,
- const char *line, union lookup *lk)
+ const char *line, const char *data, union lookup *lk)
{
char buffer[LINE_MAX], *p;
size_t len;
@@ -534,6 +535,14 @@ table_parse_lookup(enum table_service service, const char
*key,
return (-1);
return (1);
+ case K_AUTHENTICATE:
+ if (strncmp(line, "AUTHENTICATED", 13) == 0){
+ lk->authenticated = 1;
+ return 1;
+ }
+ lk->authenticated = -1;
+ return -1;
+
case K_CREDENTIALS:
/* credentials are stored as user:password */
diff --git a/usr.sbin/smtpd/table_db.c b/usr.sbin/smtpd/table_db.c
index b4db8f7ccae..5977820948a 100644
--- a/usr.sbin/smtpd/table_db.c
+++ b/usr.sbin/smtpd/table_db.c
@@ -22,6 +22,7 @@
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include "smtpd.h"
#include "log.h"
@@ -31,7 +32,7 @@ static int table_db_config(struct table *);
static int table_db_update(struct table *);
static int table_db_open(struct table *);
static void *table_db_open2(struct table *);
-static int table_db_lookup(struct table *, enum table_service, const char *,
char **);
+static int table_db_lookup(struct table *, enum table_service, const char *,
const char *, char **);
static int table_db_fetch(struct table *, enum table_service, char **);
static void table_db_close(struct table *);
static void table_db_close2(void *);
@@ -153,7 +154,7 @@ table_db_close2(void *hdl)
static int
table_db_lookup(struct table *table, enum table_service service, const char
*key,
- char **dst)
+ const char *data, char **dst)
{
struct dbhandle *handle = table->t_handle;
char *line;
@@ -184,11 +185,28 @@ table_db_lookup(struct table *table, enum table_service
service, const char *key
return 0;
ret = 1;
- if (dst)
- *dst = line;
- else
- free(line);
-
+ switch(service) {
+ case K_AUTHENTICATE: {
+ char authy[] = "AUTHENTICATED";
+ char authn[] = "INCORRECT-AUTH";
+ if (crypt_checkpass(data, line) == 0){
+ *dst = strdup(authy);
+ ret = 1;
+ }
+ else{
+ *dst = strdup(authn);
+ ret = 0;
+ }
+ break;
+ }
+ default:
+ if (dst)
+ *dst = line;
+ else
+ free(line);
+ ret = 1;
+ break;
+ }
return ret;
}
diff --git a/usr.sbin/smtpd/table_getpwnam.c b/usr.sbin/smtpd/table_getpwnam.c
index d40f1920073..9d9086ae67c 100644
--- a/usr.sbin/smtpd/table_getpwnam.c
+++ b/usr.sbin/smtpd/table_getpwnam.c
@@ -26,7 +26,7 @@ static int table_getpwnam_config(struct table *);
static int table_getpwnam_update(struct table *);
static int table_getpwnam_open(struct table *);
static int table_getpwnam_lookup(struct table *, enum table_service, const
char *,
- char **);
+ const char *, char **);
static void table_getpwnam_close(struct table *);
struct table_backend table_backend_getpwnam = {
@@ -70,7 +70,7 @@ table_getpwnam_close(struct table *table)
static int
table_getpwnam_lookup(struct table *table, enum table_service kind, const char
*key,
- char **dst)
+ const char *data, char **dst)
{
struct passwd *pw;
diff --git a/usr.sbin/smtpd/table_proc.c b/usr.sbin/smtpd/table_proc.c
index 56893a0fb61..6d903492740 100644
--- a/usr.sbin/smtpd/table_proc.c
+++ b/usr.sbin/smtpd/table_proc.c
@@ -169,7 +169,7 @@ imsg_add_params(struct ibuf *buf)
}
static int
-table_proc_lookup(struct table *table, enum table_service s, const char *k,
char **dst)
+table_proc_lookup(struct table *table, enum table_service s, const char *k,
const char *data, char **dst)
{
struct table_proc_priv *priv = table->t_handle;
struct ibuf *buf;
diff --git a/usr.sbin/smtpd/table_static.c b/usr.sbin/smtpd/table_static.c
index af57038f231..c4f5f774ed5 100644
--- a/usr.sbin/smtpd/table_static.c
+++ b/usr.sbin/smtpd/table_static.c
@@ -21,6 +21,7 @@
#include <errno.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include "smtpd.h"
#include "log.h"
@@ -38,7 +39,7 @@ static void table_static_dump(struct table *);
static int table_static_update(struct table *);
static int table_static_open(struct table *);
static int table_static_lookup(struct table *, enum table_service, const char
*,
- char **);
+ const char *, char **);
static int table_static_fetch(struct table *, enum table_service, char **);
static void table_static_close(struct table *);
@@ -314,7 +315,7 @@ table_static_close(struct table *table)
static int
table_static_lookup(struct table *table, enum table_service service, const
char *key,
- char **dst)
+ const char *data, char **dst)
{
struct table_static_priv *priv = table->t_handle;
char *line;
@@ -355,11 +356,29 @@ table_static_lookup(struct table *table, enum
table_service service, const char
if (ret == 0)
return 0;
- *dst = strdup(line);
+ int ans;
+ switch(service) {
+ case K_AUTHENTICATE: {
+ char authy[] = "AUTHENTICATED";
+ char authn[] = "INCORRECT-AUTH";
+ if (crypt_checkpass(data, line) == 0){
+ *dst = strdup(authy);
+ ans = 1;
+ }
+ else{
+ *dst = strdup(authn);
+ ans = 0;
+ }
+ break;
+ }
+ default:
+ *dst = strdup(line);
+ ans = 1;
+ break;
+ }
if (*dst == NULL)
return -1;
-
- return 1;
+ return ans;
}
static int