Hello.

Wietse Venema wrote in
 <4bbwrb5qbbzj...@spike.porcupine.org>:
 |What is the trust model: can anyone send email as long as they have
 |a valid certificate that is signed by one of hundreds of CAs, and

I am a political person and can only response to this politically.
Other than that i do not know, Wietse Venema.

Twenty years ago i was an angry young man because the new German
passports did not include S/MIME++ certificates and PGP keys,
signed by the German government.  In the meantime the
"Bundesdruckerei" (which has become more or less private until
then, what a mess, in my opinion) actually acts as a certificate
authority.

The IETF pushes per-DNS-zone authorities.  DNS can now go over
encrypted transport, and the content itself is also (though
differently, unfortunately) cryptographically verifiable, if the
zone does that.

The Internet of Things produces devices which want to call home
and take part in the internet.  If you buy a light bulb today it
may want to contact home when you use it first in five years from
now on.

The past has shown passports are important, i also say this in
particular as a German (others could chime in of course), people
even kill for passports eventually.  I do not see a particular
difference in between digital and paper passports.

I know for sure however that with client certificates there is
a little bit of security and affirmation where otherwise there is
nothing.  My MUA for example was treated as a lesser secure
application by a big free mail provider, because it does not use
OAuth.  Even though my password is in an encrypted .netrc file,
and that in turn exists on an encrypted partition on an
unencrypted block device (and also that will change in the
future).  The partition is unmounted on lid close.  The data
transport is secured via TLS.  Why is this lesser secure?

Especially since XOAUTH2 / OAUTHBEARER is not lesser secure.
But in how far is that different than just offering the
possibility to specify per-application passwords, for example.
I.e., diversify that, do not use the account master password for
logins via SMTP / POP3 / IMAP?

And then i have to go over HTTPS to refresh my temporary password.
Why is that necessary, the XOAUTH2 / OAUTHBEARER JSON hashmasp
used during login could very well be used to update refresh tokens
on the fly, too.  Maybe in the future there will be advertisements
when updating the token, i do not know.
I cannot time out this token, different to Kerberos/GSSAPI, where
my local kdestroy(1) program can be used to disable the ticket.

With client certificates people are, or could be, responsible
themselves.  We have programs like GPG agent and ssh-agent, there
are USB sticks like yubikey and such, which help in storing their
private counterparts securely (unless the scene is getting real
tough, at least, but this cannot be helped anyhow, i would say).
Their content is standardized, the algorithms are standardized and
well-tested, and open for any mathematician / cryptographer who is
dedicated enough to go for it.  This is as good as it can get.

 |as long as their certificate contains an email address that matches
 |smtpd_sender_login_maps?

Oh, sorry, i am not an administrator.  I have read the postfix
documentation once in 2015, to setup my server VM.  Until then
only externally managed accounts.  And the server does not support
any login mechanism at all, the message enters the postfix there
via ssh and sendmail.  That is enough for me.  (It even drives
mailing lists, but that via aliases.)

But in the meantime i have become conscious that this login-test
setup is totally broken, i am already reading the documentation
anew in another window.

Thank you!

By the way, there is a little improvement in the patch:

   diff --git a/src/xsasl/xsasl_dovecot_server.c 
b/src/xsasl/xsasl_dovecot_server.c
  -index 601f787..9b849b4 100644
  +index 601f787..780fd91 100644
   --- a/src/xsasl/xsasl_dovecot_server.c
   +++ b/src/xsasl/xsasl_dovecot_server.c
   @@ -166,7 +166,8 @@ typedef struct {
  @@ -98,8 +97,8 @@ index 601f787..9b849b4 100644
        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->tls_cert_username = ((args->tls_flags & XSASL_TLS_CLIENT_CERT)
  ++      && args->tls_cert_username) ? mystrdup(args->tls_cert_username) : 0;

It does not really fix a bug, but is more explicit.  (I have not
compiled this, i only recognized it would be more explicit like
this.)  I will attach this version, ok?

 | Wietse
 --End of <4bbwrb5qbbzj...@spike.porcupine.org>

Ciao, Mr. Venema,

--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..8a4f1fd 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,14 @@ void    smtpd_sasl_activate(SMTPD_STATE *state, const char *sasl_opts_name,
     /*
      * Set up a new server context for this connection.
      */
+    tls_flags = 0;
+    tls_cert_username = 0;
 #ifdef USE_TLS
-    tls_flag = state->tls_context != 0;
-#else
-    tls_flag = 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;
+    }
 #endif
 #define ADDR_OR_EMPTY(addr, unknown) (strcmp(addr, unknown) ? addr : "")
 #define REALM_OR_NULL(realm) (*(realm) ? (realm) : (char *) 0)
@@ -228,9 +232,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..780fd91 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 & XSASL_TLS_CLIENT_CERT)
+	&& 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