Subject: Re: [ietf-smtp] ALPN: implementation / behaviour

From: Claus Assmann <[email-masked]>
Date: Sat, 10 Jul 2021 10:23:16 +0200

On Thu, Jul 08, 2021, Jeremy Harris wrote:

> In client MTA mode I'd expect the coding to make an ALPN request to
> be similarly simple. Administrative controls for non-use/offer/require-acceptance
> would probably be more work than just the library interface.

It seems there are the following possible cases to handle:
1. the other side did not offer/specify ALPN.
2. the other side did offer/specify ALPN and there is
  2.1  a match
  2.2  no match

but there is no way to determine case 1 for the client.  At least
that's what I found out when I implemented it in my MTA.

The ALPACA authors have this recommendation:
  ALPN for Clients
  We also recommend that the client aborts the handshake if the server
  acknowledges the ALPN extension, but does not select a protocol
  from the client list.

AFAICT it's no possible to implement this with ALPN. I suggested a
possible solution on the ietf-tls list but there was no interest
in it.

Hopefully someone who understand this topic better can explain
what needs to be done?

-- 
Address is valid for this mailing list only, please do not reply
to it direcly, but to the list.

---

From: Jeremy Harris <[email-masked]>
Date: Sat, 10 Jul 2021 14:54:53 +0100

On 10/07/2021 09:23, Claus Assmann wrote:
> but there is no way to determine case 1 for the client.

SSL_get0_alpn_selected() -
"data is set to NULL ... if no protocol has been selected".

gnutls_alpn_get_selected_protocol()
"On success, GNUTLS_E_SUCCESS (0) is returned,
otherwise a negative error code is returned."

... look as though they'll combine 1. and 2.2

Under GnuTLS you can hook into the handshake operations:
   gnutls_handshake_set_hook_function(state->session,
             GNUTLS_HANDSHAKE_ANY, GNUTLS_HOOK_POST, tls_server_hook_cb);

in the callback, spot an htype GNUTLS_HANDSHAKE_SERVER_HELLO
split by extension:
   gnutls_ext_raw_parse(NULL, tls_server_serverhello_ext, msg,
                            GNUTLS_EXT_RAW_FLAG_TLS_CLIENT_HELLO);
and then if the tls_id 16 is seen [1] the client did receive
an ALPN extension from the server, distinguishing the above
cases.

[I've not tried this, client-side.  Server side works fine.]

OpenSSL doesn't seem to give that level of observability.
-- 
Cheers,
   Jeremy

[1] https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml

---

From: Claus Assmann <[email-masked]>
Date: Sat, 10 Jul 2021 21:45:44 +0200

> Under GnuTLS you can hook into the handshake operations:

Same can be done in OpenSSL: quoting my notes:

For the client we would have to go through all the extensions:
SSL_set_tlsext_debug_callback(con, tlsext_cb);
void tlsext_cb(SSL *s, int client_server, int type,
               const unsigned char *data, int len, void *arg)
and set a flag there:
    if (TLSEXT_TYPE_application_layer_protocol_negotiation == type) {
        set flag ...

But that does not work: the extension is only returned if the
server selected a protocol.

> [I've not tried this, client-side.  Server side works fine.]

I added the code to the client side and observed the problem mentioned
above.