Hello and good evening!
Please excuse the late replay.
Wietse Venema wrote in
<[email protected]>:
|Viktor Dukhovni:
|> On Sun, Aug 23, 2020 at 02:36:51AM +0200, Steffen Nurpmeso wrote:
...
|Annd if you must pass additional information to the Dovecot auth
|server, the proper way is to extend the xsasl_server_create() API,
|not adding ad-hoc arguments here and there to poke data through the
|abstraction layers.
So i have rewritten the patch, and extended
XSASL_SERVER_CREATE_ARGS instead, it makes things much easier!
I also adjusted the documentation in xsasl_server.c accordingly,
i had not seen that on Saturday.
I can successfully authentificate with the EXTERNAL SASL mechanism.
Ciao from Germany,
--steffen
|
|Der Kragenbaer, The moon bear,
|der holt sich munter he cheerfully and one by one
|einen nach dem anderen runter wa.ks himself off
|(By Robert Gernhardt)
diff --git a/src/smtpd/smtpd_sasl_glue.c b/src/smtpd/smtpd_sasl_glue.c
index 020c830..830d5c9 100644
--- a/src/smtpd/smtpd_sasl_glue.c
+++ b/src/smtpd/smtpd_sasl_glue.c
@@ -185,9 +185,9 @@ void smtpd_sasl_initialize(void)
void smtpd_sasl_activate(SMTPD_STATE *state, const char *sasl_opts_name,
const char *sasl_opts_val)
{
- const char *mechanism_list;
+ const char *tls_cert_username, *mechanism_list;
XSASL_SERVER_CREATE_ARGS create_args;
- int tls_flag;
+ int tls_flags;
/*
* Sanity check.
@@ -207,10 +207,16 @@ void smtpd_sasl_activate(SMTPD_STATE *state, const char *sasl_opts_name,
/*
* Set up a new server context for this connection.
*/
+ tls_cert_username = 0;
#ifdef USE_TLS
- tls_flag = state->tls_context != 0;
+ tls_flags = (state->tls_context != 0) ? XSASL_TLS_SECURED : 0;
+ if (tls_flags && TLS_CERT_IS_PRESENT(state->tls_context)) {
+ tls_flags |= XSASL_TLS_CLIENT_CERT;
+ tls_cert_username = state->tls_context->peer_CN;
+ }
+
#else
- tls_flag = 0;
+ tls_flags = 0;
#endif
#define ADDR_OR_EMPTY(addr, unknown) (strcmp(addr, unknown) ? addr : "")
#define REALM_OR_NULL(realm) (*(realm) ? (realm) : (char *) 0)
@@ -228,9 +234,10 @@ void smtpd_sasl_activate(SMTPD_STATE *state, const char *sasl_opts_name,
client_port = ADDR_OR_EMPTY(state->port,
CLIENT_PORT_UNKNOWN),
service = var_smtpd_sasl_service,
- user_realm = REALM_OR_NULL(var_smtpd_sasl_realm),
+ user_realm = REALM_OR_NULL(var_smtpd_sasl_realm),
security_options = sasl_opts_val,
- tls_flag = tls_flag)) == 0)
+ tls_flags = tls_flags,
+ tls_cert_username = tls_cert_username)) == 0)
msg_fatal("SASL per-connection initialization failed");
/*
diff --git a/src/xsasl/xsasl.h b/src/xsasl/xsasl.h
index b494d7e..2cbff64 100644
--- a/src/xsasl/xsasl.h
+++ b/src/xsasl/xsasl.h
@@ -54,7 +54,8 @@ typedef struct XSASL_SERVER_CREATE_ARGS {
const char *service;
const char *user_realm;
const char *security_options;
- int tls_flag;
+ int tls_flags;
+ const char *tls_cert_username; /* (Or 0; only used if tls_flags!=0!) */
} XSASL_SERVER_CREATE_ARGS;
typedef struct XSASL_SERVER_IMPL {
@@ -65,12 +66,15 @@ typedef struct XSASL_SERVER_IMPL {
extern XSASL_SERVER_IMPL *xsasl_server_init(const char *, const char *);
extern ARGV *xsasl_server_types(void);
+#define XSASL_TLS_SECURED (1<<0) /* (In fact: .tls_flags not 0) */
+#define XSASL_TLS_CLIENT_CERT (1<<1)
+
#define xsasl_server_create(impl, args) \
(impl)->create((impl), (args))
-#define XSASL_SERVER_CREATE(impl, args, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) \
+#define XSASL_SERVER_CREATE(impl, args, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) \
xsasl_server_create((impl), (((args)->a1), ((args)->a2), ((args)->a3), \
((args)->a4), ((args)->a5), ((args)->a6), ((args)->a7), ((args)->a8), \
- ((args)->a9), ((args)->a10), (args)))
+ ((args)->a9), ((args)->a10), ((args)->a11), (args)))
#define xsasl_server_done(impl) (impl)->done((impl));
/*
diff --git a/src/xsasl/xsasl_dovecot_server.c b/src/xsasl/xsasl_dovecot_server.c
index 601f787..9b849b4 100644
--- a/src/xsasl/xsasl_dovecot_server.c
+++ b/src/xsasl/xsasl_dovecot_server.c
@@ -166,7 +166,8 @@ typedef struct {
char *username; /* authenticated user */
VSTRING *sasl_line;
unsigned int sec_props; /* Postfix mechanism filter */
- int tls_flag; /* TLS enabled in this session */
+ int tls_flags; /* TLS flags of this session */
+ char *tls_cert_username; /* If .tls_flags, maybe commonName */
char *mechanism_list; /* filtered mechanism list */
ARGV *mechanism_argv; /* ditto */
char *client_addr; /* remote IP address */
@@ -450,7 +451,9 @@ static XSASL_SERVER *xsasl_dovecot_server_create(XSASL_SERVER_IMPL *impl,
server->last_request_id = 0;
server->mechanism_list = 0;
server->mechanism_argv = 0;
- server->tls_flag = args->tls_flag;
+ server->tls_flags = args->tls_flags;
+ server->tls_cert_username = (args->tls_flags && args->tls_cert_username)
+ ? mystrdup(args->tls_cert_username) : 0;
server->sec_props =
name_mask_opt(myname, xsasl_dovecot_conf_sec_props,
args->security_options,
@@ -502,6 +505,8 @@ static void xsasl_dovecot_server_free(XSASL_SERVER *xp)
vstring_free(server->sasl_line);
if (server->username)
myfree(server->username);
+ if (server->tls_cert_username)
+ myfree(server->tls_cert_username);
if (server->mechanism_list) {
myfree(server->mechanism_list);
argv_free(server->mechanism_argv);
@@ -680,9 +685,20 @@ int xsasl_dovecot_server_first(XSASL_SERVER *xp, const char *sasl_method,
server->last_request_id, sasl_method,
server->service, server->server_addr,
server->client_addr);
- if (server->tls_flag)
+ if (server->tls_flags) {
/* XXX Encapsulate for logging. */
vstream_fputs("\tsecured", server->impl->sasl_stream);
+ if (server->tls_flags & XSASL_TLS_CLIENT_CERT) {
+ /* XXX Encapsulate for logging. */
+ vstream_fputs("\tvalid-client-cert",
+ server->impl->sasl_stream);
+ if (server->tls_cert_username)
+ /* XXX Encapsulate for logging. */
+ vstream_fprintf(server->impl->sasl_stream,
+ "\tcert_username=%s",
+ server->tls_cert_username);
+ }
+ }
if (init_response) {
/*
diff --git a/src/xsasl/xsasl_server.c b/src/xsasl/xsasl_server.c
index e8d7e16..dfdde0c 100644
--- a/src/xsasl/xsasl_server.c
+++ b/src/xsasl/xsasl_server.c
@@ -18,12 +18,16 @@
/* .in +4
/* typedef struct XSASL_SERVER_CREATE_ARGS {
/* VSTREAM *stream;
+/* int addr_family;
/* const char *server_addr;
+/* const char *server_port;
/* const char *client_addr;
+/* const char *client_port;
/* const char *service;
/* const char *user_realm;
/* const char *security_options;
-/* int tls_flag;
+/* int tls_flags;
+/* const char *tls_cert_username;
/* } XSASL_SERVER_CREATE_ARGS;
/* .in -4
/*
@@ -34,7 +38,7 @@
/* XSASL_SERVER *XSASL_SERVER_CREATE(implementation, args,
/* stream = stream_value,
/* ...,
-/* tls_flag = tls_flag_value)
+/* tls_cert_username = tls_cert_username_value)
/* XSASL_SERVER_IMPL *implementation;
/* XSASL_SERVER_CREATE_ARGS *args;
/*
@@ -169,6 +173,16 @@
/* The connection between client and server. When SASL
/* encryption is negotiated, the plug-in will transparently
/* intercept the socket read/write operations.
+/* .IP tls_flags
+/* 0 or with XSASL_TLS_SECURED bit set if the connection is over
+/* secured transport.
+/* If the XSASL_TLS_CLIENT_CERT bit is also set then the client
+/* presented a valid client certificate.
+/* .IP tls_cert_username
+/* Only inspected during session authentication if
+/* XSASL_TLS_CLIENT_CERT is set in tls_flags, this is the
+/* commonName presented by the client certificate.
+/* The storage must be duplicated.
/* .IP user_realm
/* Authentication domain or null pointer.
/* SECURITY