I often forget the exact steps, and when i'm debugging a TLS connection (e.g. with tools like
gnutls-cli) i need to poke a remote peer into being ready for a TLS handshake. So i'm noting the different mechanisms here. lines starting with C: are from the client, lines starting with S: are from the server.
many of these are (roughly) built into openssl s_client, using the -starttls option. Sometimes this doesn't work because the handshake needs tuning for a given server; other times you want to do this with a different TLS library. To use the techniques below with gnutls-cli from the gnutls-bin package, just provide the --starttls argument (and the appropriate --port XXX argument), and then hit Ctrl+D when you think it's ok to start the TLS negotiation.
C: EHLO myhostname.example S: [...] S: 250-STARTTLS S: [...] S: 250 [somefeature] C: STARTTLS S: 220 2.0.0 Ready to start TLS <Client can begin TLS handshake>
S: OK [CAPABILITY IMAP4rev1 [...] STARTTLS [...]] [...] C: A STARTTLS S: A OK Begin TLS negotiation now <Client can begin TLS handshake>
S: +OK POP3 ready C: STLS S: +OK Begin TLS <Client can begin TLS handshake>
C: <?xml version="1.0"?><stream:stream to="example.net" C: xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams" version="1.0"> S: <?xml version='1.0'?> S: <stream:stream S: xmlns:db='jabber:server:dialback' S: xmlns:stream='http://etherx.jabber.org/streams' S: version='1.0' S: from='example.net' S: id='d34edc7c-22bd-44b3-9dba-8162da5b5e72' S: xml:lang='en' S: xmlns='jabber:server'> S: <stream:features> S: <dialback xmlns='urn:xmpp:features:dialback'/> S: <starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/> S: </stream:features> C: <starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls" id="1"/> S: <proceed xmlns='urn:ietf:params:xml:ns:xmpp-tls'/> <Client can begin TLS handshake>
C: CAPABILITIES S: [...] S: STARTTLS S: [...] S: . C: STARTTLS S: 382 Continue with TLS negotiation <Client can begin TLS handshake>
The client starts by sending these eight octets:
0x00 0x00 0x00 0x08 0x04 0xD2 0x16 0x2Fand the server replies with 'S' for secure or 'N' for not. If the reply is S, TLS negotiation follows.
The message represents int32(8) specifying that there are 8 octets and int16(1234),int16(5678). All sent in network order.
(The non-TLS case starts with a similar message with int16(3),int16(0) for protocol version 3.0. Starttls is essentially pg protocol version 1234.5678.)
I don't know (but would like to) how to do:
Other interesting notes: RFC 2817, a not-widely-supported mechanism for upgrading to TLS in the middle of a normal HTTP session.