GSSAPI KEX#856
Conversation
This patch has been rejected upstream: "None of the OpenSSH developers are in favour of adding this, and this situation has not changed for several years. This is not a slight on Simon's patch, which is of fine quality, but just that a) we don't trust GSSAPI implementations that much and b) we don't like adding new KEX since they are pre-auth attack surface. This one is particularly scary, since it requires hooks out to typically root-owned system resources." However, quite a lot of people rely on this in Debian, and it's better to have it merged into the main openssh package rather than having separate -krb5 packages (as we used to have). It seems to have a generally good security history. Author: Simon Wilkinson <simon@sxw.org.uk> Author: Colin Watson <cjwatson@debian.org> Author: Jakub Jelen <jjelen@redhat.com> Origin: other, openssh-gsskex/openssh-gsskex#23 Bug: https://bugzilla.mindrot.org/show_bug.cgi?id=1242 Last-Updated: 2026-03-27 Patch-Name: gssapi.patch
There was a problem hiding this comment.
Pull request overview
This PR adds RFC 4462 GSSAPI-based key exchange (GSS KEX) support to OpenSSH portable, including a “null” hostkey algorithm to allow server authentication via GSSAPI without requiring traditional SSH host keys, plus the required configuration/options, monitor/privsep plumbing, and Windows/SSPI shim updates.
Changes:
- Implement GSSAPI key exchange (client + server) and wire it into kex negotiation, proposals, and rekey credential updates.
- Introduce a
nullhostkey algorithm (KEY_NULL) and adjust hostkey handling to support hostkey-less operation when GSS KEX is enabled. - Add client/server config options + manpage documentation, and update build systems (Makefile + Win32 .vcxproj) to compile the new sources.
Reviewed changes
Copilot reviewed 51 out of 51 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| sshkey.h | Add KEY_NULL key type for the “null” hostkey algorithm. |
| sshkey.c | Register sshkey_null_impl; hide null from key algorithm listings. |
| sshd.c | Allow starting sshd without hostkeys when GSSAPIKeyExchange is enabled. |
| sshd-session.c | Don’t fatal when no hostkeys exist (needed for hostkey-less GSS KEX). |
| sshd-auth.c | Server-side proposal/kex wiring for GSS KEX and null hostkey mode. |
| sshd_config.5 | Document GSSAPIKeyExchange, GSSAPIStoreCredentialsOnRekey, GSSAPIKexAlgorithms. |
| sshd_config | Add commented example lines for new GSS-related sshd options. |
| sshconnect2.c | Client-side proposal/kex wiring for GSS KEX and null hostkey fallback. |
| ssh.c | Add ssh -Q kex-gss query support. |
| ssh.1 | Document kex-gss query and new GSS-related ssh options in the option index. |
| ssh-null.c | Implement “null” sshkey backend for the null hostkey algorithm. |
| ssh-gss.h | Add GSS KEX constants, defaults, and new GSS helper prototypes/state. |
| ssh_config.5 | Document client-side GSSAPIKeyExchange and related options. |
| ssh_config | Add commented example lines for new GSS-related ssh client options. |
| session.c | Run Kerberos/GSS credential cleanup under the authenticated user’s UID. |
| servconf.h | Add server options: gss_keyex, gss_store_rekey, gss_kex_algorithms. |
| servconf.c | Parse/dump new server options and set defaults (incl. default GSS KEX list). |
| readconf.h | Add client options: gss_keyex, trust-dns, renewal-rekey, identities, kex alg list. |
| readconf.c | Parse/dump new client options and set defaults (incl. default GSS KEX list). |
| monitor.h | Add monitor request/answer IDs for GSS signing and credential update. |
| monitor.c | Permit and implement GSS signing + credential update requests across privsep. |
| monitor_wrap.h | Extend monitor wrapper APIs for GSS userok/sign/updatecreds. |
| monitor_wrap.c | Implement wrapper calls for GSS sign/updatecreds; extend gss userok args. |
| Makefile.in | Build/link new objects: ssh-null.o, kexgssc.o, kexgsss.o. |
| kexgsss.c | Add server-side GSS KEX implementations (DH/ECDH/C25519 + GEX variants). |
| kexgssc.c | Add client-side GSS KEX implementations (DH/ECDH/C25519 + GEX variants). |
| kexgen.c | Export kex_gen_hash() for reuse by GSS KEX implementations. |
| kexdh.c | Allow DH group selection for GSS KEX DH-based variants. |
| kex.h | Add GSS KEX enum values, kex->gss* fields, and new GSS kex helper prototypes. |
| kex.c | Free kex->gss_host during kex teardown. |
| kex-names.c | Add GSS KEX algorithm list + validation helpers and a kex_gss_alg_list() API. |
| gss-serv.c | Add server-side GSS KEX mechanism advertising/checking and rekey cred plumbing. |
| gss-serv-krb5.c | Add/update Kerberos ccache storage and implement credential update on rekey. |
| gss-genr.c | Add client mechanism enumeration/encoding for GSS KEX, OID mapping, renew detection. |
| contrib/win32/win32compat/inc/gssapi.h | Extend SSPI shim API surface for new GSS calls/types. |
| contrib/win32/win32compat/gss-sspi.c | Implement SSPI shims for name compare and cred inquiry; improve lifetime handling. |
| contrib/win32/openssh/sshd.vcxproj.filters | Adjust Win32 project filters (source list changes). |
| contrib/win32/openssh/sshd.vcxproj | Update Win32 sshd project compilation units (remove gss-serv sources here). |
| contrib/win32/openssh/sshd-session.vcxproj.filters | Add kexgsss.c to sshd-session project filters. |
| contrib/win32/openssh/sshd-session.vcxproj | Compile kexgsss.c in sshd-session Win32 project. |
| contrib/win32/openssh/sshd-auth.vcxproj.filters | Add kexgsss.c to sshd-auth project filters. |
| contrib/win32/openssh/sshd-auth.vcxproj | Compile kexgsss.c in sshd-auth Win32 project. |
| contrib/win32/openssh/libssh.vcxproj.filters | Add kexgssc.c and ssh-null.c to libssh project filters. |
| contrib/win32/openssh/libssh.vcxproj | Compile kexgssc.c and ssh-null.c in libssh Win32 project. |
| configure.ac | Add Apple Security Session / CCAPI detection (for credential cache handling). |
| clientloop.c | Force rekey when credentials renew (if configured) outside of active rekeying. |
| auth2.c | Register gssapi-keyex auth method on the server. |
| auth2-methods.c | Add gssapi-keyex method configuration wiring. |
| auth2-gss.c | Implement server-side gssapi-keyex userauth method and adjust gss userok calls. |
| auth.c | Permit root login via gssapi-keyex when configured similarly to other strong methods. |
| README.md | Add a GSS KEX-focused header section ahead of the upstream README content. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if (gss && (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS])) == 0) | ||
| myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = "null"; | ||
|
|
||
| if (newstr) | ||
| myproposal[PROPOSAL_KEX_ALGS] = newstr; | ||
| else | ||
| fatal("No supported key exchange algorithms"); |
| gss = ssh_gssapi_client_mechanisms(gss_host, | ||
| options.gss_client_identity, options.gss_kex_algorithms); | ||
| if (gss) { | ||
| debug("Offering GSSAPI proposal: %s", gss); | ||
| xasprintf(&myproposal[PROPOSAL_KEX_ALGS], | ||
| "%s,%s", gss, orig); | ||
|
|
||
| /* If we've got GSSAPI algorithms, then we also support the | ||
| * 'null' hostkey, as a last resort */ | ||
| orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]; | ||
| xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS], | ||
| "%s,null", orig); | ||
| } |
| case KEX_GSS_C25519_SHA256: | ||
| if (sshbuf_ptr(server_blob)[sshbuf_len(server_blob)] & 0x80) | ||
| fatal("The received key has MSB of last octet set!"); | ||
| r = kex_c25519_dec(kex, server_blob, &shared_secret); | ||
| break; |
There was a problem hiding this comment.
I saw this, but I am preparing a patch for upstream which we can then bring over to this repo. So, in short: this is not the correct place to fix this, it should be fixed upstream and then the pulled over.
| struct sshbuf *empty = sshbuf_new(); | ||
| int type = 0; | ||
| gss_OID oid; | ||
| char *mechs; | ||
| u_char hash[SSH_DIGEST_MAX_LENGTH]; | ||
| size_t hashlen; | ||
| int r; | ||
|
|
||
| /* Initialise GSSAPI */ |
| struct sshbuf *empty = sshbuf_new(); | ||
| int r; | ||
|
|
||
| /* Initialise GSSAPI */ |
| Controls whether the user's GSSAPI credentials should be updated following a | ||
| successful connection rekeying. This option can be used to accepted renewed | ||
| or updated credentials from a compatible client. The default is |
There was a problem hiding this comment.
Again, this is a minor suggestion to an upstream patch which should be fixed upstream.
|
@microsoft-github-policy-service agree company="The Old Chapel Technology, Ltd" |
The GSS Curve25519 client path checked sshbuf_ptr(server_blob)[sshbuf_len(server_blob)] when rejecting public keys with the high bit set. That indexes one byte past the end of the sshbuf payload. The byte after Q_S is the first byte of the following MIC string length, encoded in network byte order. With OpenSSH's packet size limit this byte is normally zero, so the bug usually made the intended high-bit rejection a no-op rather than causing random failures. A peer can send a high-bit-set Q_S, but it still has to produce the GSS MIC over the exchange hash for the exact values used. This does not appear to provide key compromise or authentication bypass; it is a correctness fix for the validation policy carried by the GSS KEX patch. Reject an empty server blob explicitly, then test the last payload byte at sshbuf_len(server_blob) - 1 before passing the blob to kex_c25519_dec().
PR Summary
Add GSSAPI KEX.
PR Context
In an environment which uses GSS, this patch will use GSS to authenticate the remote server which eliminates the need to use SSH host keys.
GSS KEX is defined by RFC 4462.
The base GSSAPI key exchange implementation comes from Simon Wilkinson's patch, carried and maintained by Debian for OpenSSH. We add the Windows build and SSPI shim adaptations needed.
Fixes 15..