Hello and good evening!

Please excuse the late replay.

Wietse Venema wrote in
 <4bzhbq2rngzj...@spike.porcupine.org>:
 |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

Reply via email to