When the SSH protocol does and doesn't do user authentication

July 21, 2017

A while back, I was reading this lobste.rs posting and ran into what struck me as an interesting question from evaryont:

I haven’t taken a deep look at this, but doesn’t OpenSSH need frequent access to the [user] secret key material? [...]

My gut reaction was that it didn't, but gut reactions are dangerous in crytographic protocols so I decided to find out for sure. This turned out to be more involved than I expected, partly because the various RFCs describing the SSH protocol use somewhat confusing terminology.

SSH is composed of three protocols, which are nominally stacked on top of each other: the SSH transport protocol, the SSH user authentication protocol, and the SSH connection protocol. It is the connection protocol that actually gets things like interactive logins and port forwarding done; everything else is just there to support it. However these protocols are not nested in a direct sense; instead they are sort of sequenced, one after the other, and their actual operation all happens at the same level.

What flows over an SSH connection is a sequence of messages (in a binary packet format); each message has a type (a byte) and different protocols have different range of message types that they use for their various messages. When the SSH connection starts these packets are unencrypted, so the first job is to use the SSH transport protocol to work out session keys and switch on encryption (and in the process the client obtains the server's host key). Once the connection is encrypted the next thing the client must do is request a service, and in basically all situations the client is going to request (and the server is going to require) that this be the user authentication service.

The user authentication service (and protocol) has its own set of messages that are exchanged over the now-encrypted connection between client and server. User authentication is obviously where you initially need the user's secret key material (once challenged by the server). As part of requesting user authentication the client specifies a service name, which is the service to 'start' for the user after user authentication is complete. What starting the service really means is that the server and client will stop sending user authentication messages to each other and start sending connection protocol messages back and forth.

The SSH transport protocol has explicit provisions for re-keying the connection; since all of the SSH (sub)protocols are just sending messages in the overall message stream, this re-keying can happen at any time during another protocol's message flow. Server and client implementations will probably arrange to make it transparent to higher-level code that handles things like the connection protocol. By contrast, the SSH user authentication protocol has no provisions for re-authenticating you; in fact the protocol explicitly states that after user authentication is successful, all further authentication related messages received should be silently ignored. Once user authentication is complete, control is transferred to the SSH connection protocol and that's it.

So that brings us around to our answer: SSH only needs user secret key material once, at the start of your session. Once authenticated you can never be challenged to re-authenticate, and re-keying the overall encryption is a separate thing entirely (and doesn't use your secret keys, although the initial session keys can figure into the user authentication process).

Sidebar: The terminology confusion

I say that the SSH RFCs use confusing terminology because they often say things like that the SSH connection protocol 'run[s] on top of the SSH transport layer and user authentication protocols'. This is sort of true in a logical sense, but it is not true in a wire sense. SSH runs on top of TCP which runs on top of IP in a literal and wire sense, in that SSH data is inside TCP data which is inside IP data. But the various SSH protocols are all messages at the same level in the TCP stream and are not 'on top of' each other in that way. This is especially true of user authentication and the connection protocol, because what really happens is that first user authentication is done and then we shift over to the connection protocol.


Comments on this page:

It sounds like the three ssh protocols that you mentioned, transport, authentication, and connection are sibling protocols that all run multiplexed in the same parent TCP connection.

The lack of re-authentication makes sense and is supported by the fact that you can have long lived ssh connections authenticated by ssh keys loaded into an ssh-agent where the keys keys have a short lifetime (30 ~ 90 seconds) to prevent re-use.

Also, where does ssh's ability to multiplex connections come into play? Is that yet another parallel ssh connection protocol multiplexed in the TCP connection?

By cks at 2017-07-22 16:56:46:

SSH's multiplexing abilities are part of the connection protocol, which fundamentally supports multiple independent channels. Within a single ssh command these are used to support things like having your login session plus a port forwarding plus forwarding X11, but the underlying protocol (and server) can perfectly well have two login session channels running at the same time if you ask it to. This is how OpenSSH's connection sharing works; the new ssh connection asks the ControlMaster ssh to open up some new channels (and then they have to relay the actual traffic back and forth between the new and existing ssh processes).

Written on 21 July 2017.
« I'm cautiously optimistic about the new OmniOS Community Edition
Understanding a bit about the SSH connection protocol »

Page tools: View Source, View Normal.
Search:
Login: Password:

Last modified: Fri Jul 21 23:37:31 2017
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.