Ticket #27250: 0001-GSS-key-exchange-patch.patch

File 0001-GSS-key-exchange-patch.patch, 90.0 KB (added by lassi.tuura@…, 13 years ago)

Patch regenerated in more clean format with git

  • new file ChangeLog.gssapi

    From 29169b27afb10a3743bfd272c990503f6559637b Mon Sep 17 00:00:00 2001
    From: Lassi Tuura <lat@cern.ch>
    Date: Wed, 21 Sep 2011 19:35:20 +0200
    Subject: [PATCH 1/2] GSS key exchange patch.
    
    ---
     ChangeLog.gssapi |  113 ++++++++++++++++++
     Makefile.in      |    3 +-
     auth-krb5.c      |   17 +++-
     auth2-gss.c      |   48 ++++++++-
     auth2.c          |    2 +
     clientloop.c     |   13 ++
     configure.ac     |   24 ++++
     gss-genr.c       |  276 ++++++++++++++++++++++++++++++++++++++++++++-
     gss-serv-krb5.c  |   84 +++++++++++++-
     gss-serv.c       |  220 +++++++++++++++++++++++++++++++-----
     kex.c            |   18 +++
     kex.h            |   14 +++
     kexgssc.c        |  334 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
     kexgsss.c        |  288 ++++++++++++++++++++++++++++++++++++++++++++++
     key.c            |    4 +
     key.h            |    1 +
     monitor.c        |  108 +++++++++++++++++-
     monitor.h        |    2 +
     monitor_wrap.c   |   47 ++++++++-
     monitor_wrap.h   |    4 +-
     readconf.c       |   42 +++++++
     readconf.h       |    5 +
     servconf.c       |   38 ++++++-
     servconf.h       |    3 +
     ssh-gss.h        |   39 ++++++-
     ssh_config       |    2 +
     ssh_config.5     |   34 ++++++-
     sshconnect2.c    |  124 +++++++++++++++++++-
     sshd.c           |  110 ++++++++++++++++++
     sshd_config      |    2 +
     sshd_config.5    |   28 +++++
     31 files changed, 1990 insertions(+), 57 deletions(-)
     create mode 100644 ChangeLog.gssapi
     create mode 100644 kexgssc.c
     create mode 100644 kexgsss.c
    
    diff --git a/ChangeLog.gssapi b/ChangeLog.gssapi
    new file mode 100644
    index 0000000..f117a33
    - +  
     120110101
     2  - Finally update for OpenSSH 5.6p1
     3  - Add GSSAPIServerIdentity option from Jim Basney
     4 
     520100308
     6  - [ Makefile.in, key.c, key.h ]
     7    Updates for OpenSSH 5.4p1
     8  - [ servconf.c ]
     9    Include GSSAPI options in the sshd -T configuration dump, and flag
     10    some older configuration options as being unsupported. Thanks to Colin
     11    Watson.
     12  -
     13
     1420100124
     15  - [ sshconnect2.c ]
     16    Adapt to deal with additional element in Authmethod structure. Thanks to
     17    Colin Watson
     18
     1920090615
     20  - [ gss-genr.c gss-serv.c kexgssc.c kexgsss.c monitor.c sshconnect2.c
     21      sshd.c ]
     22    Fix issues identified by Greg Hudson following a code review
     23        Check return value of gss_indicate_mechs
     24        Protect GSSAPI calls in monitor, so they can only be used if enabled
     25        Check return values of bignum functions in key exchange
     26        Use BN_clear_free to clear other side's DH value
     27        Make ssh_gssapi_id_kex more robust
     28        Only configure kex table pointers if GSSAPI is enabled
     29        Don't leak mechanism list, or gss mechanism list
     30        Cast data.length before printing
     31        If serverkey isn't provided, use an empty string, rather than NULL
     32
     3320090201
     34  - [ gss-genr.c gss-serv.c kex.h kexgssc.c readconf.c readconf.h ssh-gss.h
     35      ssh_config.5 sshconnet2.c ]
     36    Add support for the GSSAPIClientIdentity option, which allows the user
     37    to specify which GSSAPI identity to use to contact a given server
     38
     3920080404
     40  - [ gss-serv.c ]
     41    Add code to actually implement GSSAPIStrictAcceptCheck, which had somehow
     42    been omitted from a previous version of this patch. Reported by Borislav
     43    Stoichkov
     44
     4520070317
     46  - [ gss-serv-krb5.c ]
     47    Remove C99ism, where new_ccname was being declared in the middle of a
     48    function
     49
     5020061220
     51  - [ servconf.c ]
     52    Make default for GSSAPIStrictAcceptorCheck be Yes, to match previous, and
     53    documented, behaviour. Reported by Dan Watson.
     54
     5520060910
     56  - [ gss-genr.c kexgssc.c kexgsss.c kex.h monitor.c sshconnect2.c sshd.c
     57      ssh-gss.h ]
     58    add support for gss-group14-sha1 key exchange mechanisms
     59  - [ gss-serv.c servconf.c servconf.h sshd_config sshd_config.5 ]
     60    Add GSSAPIStrictAcceptorCheck option to allow the disabling of
     61    acceptor principal checking on multi-homed machines.
     62    <Bugzilla #928>
     63  - [ sshd_config ssh_config ]
     64    Add settings for GSSAPIKeyExchange and GSSAPITrustDNS to the sample
     65    configuration files
     66  - [ kexgss.c kegsss.c sshconnect2.c sshd.c ]
     67    Code cleanup. Replace strlen/xmalloc/snprintf sequences with xasprintf()
     68    Limit length of error messages displayed by client
     69
     7020060909
     71  - [ gss-genr.c gss-serv.c ]
     72    move ssh_gssapi_acquire_cred() and ssh_gssapi_server_ctx to be server
     73    only, where they belong
     74    <Bugzilla #1225>
     75
     7620060829
     77  - [ gss-serv-krb5.c ]
     78    Fix CCAPI credentials cache name when creating KRB5CCNAME environment
     79    variable
     80
     8120060828
     82  - [ gss-genr.c ]
     83    Avoid Heimdal context freeing problem
     84    <Fixed upstream 20060829>
     85
     8620060818
     87  - [ gss-genr.c ssh-gss.h sshconnect2.c ]
     88    Make sure that SPENGO is disabled
     89    <Bugzilla #1218 - Fixed upstream 20060818>
     90
     9120060421
     92  - [ gssgenr.c, sshconnect2.c ]
     93    a few type changes (signed versus unsigned, int versus size_t) to
     94    fix compiler errors/warnings
     95    (from jbasney AT ncsa.uiuc.edu)
     96  - [ kexgssc.c, sshconnect2.c ]
     97    fix uninitialized variable warnings
     98    (from jbasney AT ncsa.uiuc.edu)
     99  - [ gssgenr.c ]
     100    pass oid to gss_display_status (helpful when using GSSAPI mechglue)
     101    (from jbasney AT ncsa.uiuc.edu)
     102    <Bugzilla #1220 >
     103  - [ gss-serv-krb5.c ]
     104    #ifdef HAVE_GSSAPI_KRB5 should be #ifdef HAVE_GSSAPI_KRB5_H
     105    (from jbasney AT ncsa.uiuc.edu)
     106    <Fixed upstream 20060304>
     107  - [ readconf.c, readconf.h, ssh_config.5, sshconnect2.c
     108    add client-side GssapiKeyExchange option
     109    (from jbasney AT ncsa.uiuc.edu)
     110  - [ sshconnect2.c ]
     111    add support for GssapiTrustDns option for gssapi-with-mic
     112    (from jbasney AT ncsa.uiuc.edu)
     113    <gssapi-with-mic support is Bugzilla #1008>
  • Makefile.in

    diff --git a/Makefile.in b/Makefile.in
    index 3be3aa6..e479a44 100644
    a b LIBSSH_OBJS=acss.o authfd.o authfile.o bufaux.o bufbn.o buffer.o \ 
    7070        atomicio.o key.o dispatch.o kex.o mac.o uidswap.o uuencode.o misc.o \
    7171        monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o dh.o \
    7272        kexdh.o kexgex.o kexdhc.o kexgexc.o bufec.o kexecdh.o kexecdhc.o \
     73        kexgssc.o \
    7374        msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o jpake.o \
    7475        schnorr.o ssh-pkcs11.o
    7576
    SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \ 
    8687        auth2-none.o auth2-passwd.o auth2-pubkey.o auth2-jpake.o \
    8788        monitor_mm.o monitor.o monitor_wrap.o kexdhs.o kexgexs.o kexecdhs.o \
    8889        auth-krb5.o \
    89         auth2-gss.o gss-serv.o gss-serv-krb5.o \
     90        auth2-gss.o gss-serv.o gss-serv-krb5.o kexgsss.o\
    9091        loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \
    9192        sftp-server.o sftp-common.o \
    9293        roaming_common.o roaming_serv.o \
  • auth-krb5.c

    diff --git a/auth-krb5.c b/auth-krb5.c
    index d019fe2..8219133 100644
    a b auth_krb5_password(Authctxt *authctxt, const char *password) 
    170170
    171171        len = strlen(authctxt->krb5_ticket_file) + 6;
    172172        authctxt->krb5_ccname = xmalloc(len);
     173#ifdef USE_CCAPI
     174        snprintf(authctxt->krb5_ccname, len, "API:%s",
     175            authctxt->krb5_ticket_file);
     176#else
    173177        snprintf(authctxt->krb5_ccname, len, "FILE:%s",
    174178            authctxt->krb5_ticket_file);
     179#endif
    175180
    176181#ifdef USE_PAM
    177182        if (options.use_pam)
    krb5_cleanup_proc(Authctxt *authctxt) 
    226231#ifndef HEIMDAL
    227232krb5_error_code
    228233ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) {
    229         int tmpfd, ret;
     234        int ret;
    230235        char ccname[40];
    231236        mode_t old_umask;
     237#ifdef USE_CCAPI
     238        char cctemplate[] = "API:krb5cc_%d";
     239#else
     240        char cctemplate[] = "FILE:/tmp/krb5cc_%d_XXXXXXXXXX";
     241        int tmpfd;
     242#endif
    232243
    233244        ret = snprintf(ccname, sizeof(ccname),
    234             "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid());
     245            cctemplate, geteuid());
    235246        if (ret < 0 || (size_t)ret >= sizeof(ccname))
    236247                return ENOMEM;
    237248
     249#ifndef USE_CCAPI
    238250        old_umask = umask(0177);
    239251        tmpfd = mkstemp(ccname + strlen("FILE:"));
    240252        umask(old_umask);
    ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) { 
    249261                return errno;
    250262        }
    251263        close(tmpfd);
     264#endif
    252265
    253266        return (krb5_cc_resolve(ctx, ccname, ccache));
    254267}
  • auth2-gss.c

    diff --git a/auth2-gss.c b/auth2-gss.c
    index 0d59b21..7dc87db 100644
    a b  
    11/* $OpenBSD: auth2-gss.c,v 1.17 2011/03/10 02:52:57 djm Exp $ */
    22
    33/*
    4  * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
     4 * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved.
    55 *
    66 * Redistribution and use in source and binary forms, with or without
    77 * modification, are permitted provided that the following conditions
    static void input_gssapi_mic(int type, u_int32_t plen, void *ctxt); 
    5252static void input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt);
    5353static void input_gssapi_errtok(int, u_int32_t, void *);
    5454
     55/*
     56 * The 'gssapi_keyex' userauth mechanism.
     57 */
     58static int
     59userauth_gsskeyex(Authctxt *authctxt)
     60{
     61        int authenticated = 0;
     62        Buffer b;
     63        gss_buffer_desc mic, gssbuf;
     64        u_int len;
     65
     66        mic.value = packet_get_string(&len);
     67        mic.length = len;
     68
     69        packet_check_eom();
     70
     71        ssh_gssapi_buildmic(&b, authctxt->user, authctxt->service,
     72            "gssapi-keyex");
     73
     74        gssbuf.value = buffer_ptr(&b);
     75        gssbuf.length = buffer_len(&b);
     76
     77        /* gss_kex_context is NULL with privsep, so we can't check it here */
     78        if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gss_kex_context,
     79            &gssbuf, &mic))))
     80                authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user,
     81                    authctxt->pw));
     82       
     83        buffer_free(&b);
     84        xfree(mic.value);
     85
     86        return (authenticated);
     87}
     88
    5589/*
    5690 * We only support those mechanisms that we know about (ie ones that we know
    5791 * how to check local user kuserok and the like)
    input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt) 
    244278
    245279        packet_check_eom();
    246280
    247         authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
     281        authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user,
     282            authctxt->pw));
    248283
    249284        authctxt->postponed = 0;
    250285        dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
    input_gssapi_mic(int type, u_int32_t plen, void *ctxt) 
    279314        gssbuf.length = buffer_len(&b);
    280315
    281316        if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic))))
    282                 authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
     317                authenticated =
     318                    PRIVSEP(ssh_gssapi_userok(authctxt->user, authctxt->pw));
    283319        else
    284320                logit("GSSAPI MIC check failed");
    285321
    input_gssapi_mic(int type, u_int32_t plen, void *ctxt) 
    294330        userauth_finish(authctxt, authenticated, "gssapi-with-mic");
    295331}
    296332
     333Authmethod method_gsskeyex = {
     334        "gssapi-keyex",
     335        userauth_gsskeyex,
     336        &options.gss_authentication
     337};
     338
    297339Authmethod method_gssapi = {
    298340        "gssapi-with-mic",
    299341        userauth_gssapi,
  • auth2.c

    diff --git a/auth2.c b/auth2.c
    index c06c95f..f73ac18 100644
    a b extern Authmethod method_passwd; 
    6969extern Authmethod method_kbdint;
    7070extern Authmethod method_hostbased;
    7171#ifdef GSSAPI
     72extern Authmethod method_gsskeyex;
    7273extern Authmethod method_gssapi;
    7374#endif
    7475#ifdef JPAKE
    Authmethod *authmethods[] = { 
    7980        &method_none,
    8081        &method_pubkey,
    8182#ifdef GSSAPI
     83        &method_gsskeyex,
    8284        &method_gssapi,
    8385#endif
    8486#ifdef JPAKE
  • clientloop.c

    diff --git a/clientloop.c b/clientloop.c
    index c19b01f..17628ef 100644
    a b  
    111111#include "msg.h"
    112112#include "roaming.h"
    113113
     114#ifdef GSSAPI
     115#include "ssh-gss.h"
     116#endif
     117
    114118/* import options */
    115119extern Options options;
    116120
    client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) 
    15081512                /* Do channel operations unless rekeying in progress. */
    15091513                if (!rekeying) {
    15101514                        channel_after_select(readset, writeset);
     1515
     1516#ifdef GSSAPI
     1517                        if (options.gss_renewal_rekey &&
     1518                            ssh_gssapi_credentials_updated(GSS_C_NO_CONTEXT)) {
     1519                                debug("credentials updated - forcing rekey");
     1520                                need_rekeying = 1;
     1521                        }
     1522#endif
     1523
    15111524                        if (need_rekeying || packet_need_rekeying()) {
    15121525                                debug("need rekeying");
    15131526                                xxx_kex->done = 0;
  • configure.ac

    diff --git a/configure.ac b/configure.ac
    index 7a91527..8cc7ce9 100644
    a b main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16)) 
    515515            [Use tunnel device compatibility to OpenBSD])
    516516        AC_DEFINE([SSH_TUN_PREPEND_AF], [1],
    517517            [Prepend the address family to IP tunnel traffic])
     518        AC_MSG_CHECKING(if we have the Security Authorization Session API)
     519        AC_TRY_COMPILE([#include <Security/AuthSession.h>],
     520                [SessionCreate(0, 0);],
     521                [ac_cv_use_security_session_api="yes"
     522                 AC_DEFINE(USE_SECURITY_SESSION_API, 1,
     523                        [platform has the Security Authorization Session API])
     524                 LIBS="$LIBS -framework Security"
     525                 AC_MSG_RESULT(yes)],
     526                [ac_cv_use_security_session_api="no"
     527                 AC_MSG_RESULT(no)])
     528        AC_MSG_CHECKING(if we have an in-memory credentials cache)
     529        AC_TRY_COMPILE(
     530                [#include <Kerberos/Kerberos.h>],
     531                [cc_context_t c;
     532                 (void) cc_initialize (&c, 0, NULL, NULL);],
     533                [AC_DEFINE(USE_CCAPI, 1,
     534                        [platform uses an in-memory credentials cache])
     535                 LIBS="$LIBS -framework Security"
     536                 AC_MSG_RESULT(yes)
     537                 if test "x$ac_cv_use_security_session_api" = "xno"; then
     538                        AC_MSG_ERROR(*** Need a security framework to use the credentials cache API ***)
     539                fi],
     540                [AC_MSG_RESULT(no)]
     541        )
    518542        m4_pattern_allow([AU_IPv])
    519543        AC_CHECK_DECL([AU_IPv4], [],
    520544            AC_DEFINE([AU_IPv4], [0], [System only supports IPv4 audit records])
  • gss-genr.c

    diff --git a/gss-genr.c b/gss-genr.c
    index 842f385..f9b39cf 100644
    a b  
    11/* $OpenBSD: gss-genr.c,v 1.20 2009/06/22 05:39:28 dtucker Exp $ */
    22
    33/*
    4  * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved.
     4 * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved.
    55 *
    66 * Redistribution and use in source and binary forms, with or without
    77 * modification, are permitted provided that the following conditions
     
    3939#include "buffer.h"
    4040#include "log.h"
    4141#include "ssh2.h"
     42#include "cipher.h"
     43#include "key.h"
     44#include "kex.h"
     45#include <openssl/evp.h>
    4246
    4347#include "ssh-gss.h"
    4448
    4549extern u_char *session_id2;
    4650extern u_int session_id2_len;
    4751
     52typedef struct {
     53        char *encoded;
     54        gss_OID oid;
     55} ssh_gss_kex_mapping;
     56
     57/*
     58 * XXX - It would be nice to find a more elegant way of handling the
     59 * XXX   passing of the key exchange context to the userauth routines
     60 */
     61
     62Gssctxt *gss_kex_context = NULL;
     63
     64static ssh_gss_kex_mapping *gss_enc2oid = NULL;
     65
     66int
     67ssh_gssapi_oid_table_ok() {
     68        return (gss_enc2oid != NULL);
     69}
     70
     71/*
     72 * Return a list of the gss-group1-sha1 mechanisms supported by this program
     73 *
     74 * We test mechanisms to ensure that we can use them, to avoid starting
     75 * a key exchange with a bad mechanism
     76 */
     77
     78char *
     79ssh_gssapi_client_mechanisms(const char *host, const char *client) {
     80        gss_OID_set gss_supported;
     81        OM_uint32 min_status;
     82
     83        if (GSS_ERROR(gss_indicate_mechs(&min_status, &gss_supported)))
     84                return NULL;
     85
     86        return(ssh_gssapi_kex_mechs(gss_supported, ssh_gssapi_check_mechanism,
     87            host, client));
     88}
     89
     90char *
     91ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check,
     92    const char *host, const char *client) {
     93        Buffer buf;
     94        size_t i;
     95        int oidpos, enclen;
     96        char *mechs, *encoded;
     97        u_char digest[EVP_MAX_MD_SIZE];
     98        char deroid[2];
     99        const EVP_MD *evp_md = EVP_md5();
     100        EVP_MD_CTX md;
     101
     102        if (gss_enc2oid != NULL) {
     103                for (i = 0; gss_enc2oid[i].encoded != NULL; i++)
     104                        xfree(gss_enc2oid[i].encoded);
     105                xfree(gss_enc2oid);
     106        }
     107
     108        gss_enc2oid = xmalloc(sizeof(ssh_gss_kex_mapping) *
     109            (gss_supported->count + 1));
     110
     111        buffer_init(&buf);
     112
     113        oidpos = 0;
     114        for (i = 0; i < gss_supported->count; i++) {
     115                if (gss_supported->elements[i].length < 128 &&
     116                    (*check)(NULL, &(gss_supported->elements[i]), host, client)) {
     117
     118                        deroid[0] = SSH_GSS_OIDTYPE;
     119                        deroid[1] = gss_supported->elements[i].length;
     120
     121                        EVP_DigestInit(&md, evp_md);
     122                        EVP_DigestUpdate(&md, deroid, 2);
     123                        EVP_DigestUpdate(&md,
     124                            gss_supported->elements[i].elements,
     125                            gss_supported->elements[i].length);
     126                        EVP_DigestFinal(&md, digest, NULL);
     127
     128                        encoded = xmalloc(EVP_MD_size(evp_md) * 2);
     129                        enclen = __b64_ntop(digest, EVP_MD_size(evp_md),
     130                            encoded, EVP_MD_size(evp_md) * 2);
     131
     132                        if (oidpos != 0)
     133                                buffer_put_char(&buf, ',');
     134
     135                        buffer_append(&buf, KEX_GSS_GEX_SHA1_ID,
     136                            sizeof(KEX_GSS_GEX_SHA1_ID) - 1);
     137                        buffer_append(&buf, encoded, enclen);
     138                        buffer_put_char(&buf, ',');
     139                        buffer_append(&buf, KEX_GSS_GRP1_SHA1_ID,
     140                            sizeof(KEX_GSS_GRP1_SHA1_ID) - 1);
     141                        buffer_append(&buf, encoded, enclen);
     142                        buffer_put_char(&buf, ',');
     143                        buffer_append(&buf, KEX_GSS_GRP14_SHA1_ID,
     144                            sizeof(KEX_GSS_GRP14_SHA1_ID) - 1);
     145                        buffer_append(&buf, encoded, enclen);
     146
     147                        gss_enc2oid[oidpos].oid = &(gss_supported->elements[i]);
     148                        gss_enc2oid[oidpos].encoded = encoded;
     149                        oidpos++;
     150                }
     151        }
     152        gss_enc2oid[oidpos].oid = NULL;
     153        gss_enc2oid[oidpos].encoded = NULL;
     154
     155        buffer_put_char(&buf, '\0');
     156
     157        mechs = xmalloc(buffer_len(&buf));
     158        buffer_get(&buf, mechs, buffer_len(&buf));
     159        buffer_free(&buf);
     160
     161        if (strlen(mechs) == 0) {
     162                xfree(mechs);
     163                mechs = NULL;
     164        }
     165       
     166        return (mechs);
     167}
     168
     169gss_OID
     170ssh_gssapi_id_kex(Gssctxt *ctx, char *name, int kex_type) {
     171        int i = 0;
     172       
     173        switch (kex_type) {
     174        case KEX_GSS_GRP1_SHA1:
     175                if (strlen(name) < sizeof(KEX_GSS_GRP1_SHA1_ID))
     176                        return GSS_C_NO_OID;
     177                name += sizeof(KEX_GSS_GRP1_SHA1_ID) - 1;
     178                break;
     179        case KEX_GSS_GRP14_SHA1:
     180                if (strlen(name) < sizeof(KEX_GSS_GRP14_SHA1_ID))
     181                        return GSS_C_NO_OID;
     182                name += sizeof(KEX_GSS_GRP14_SHA1_ID) - 1;
     183                break;
     184        case KEX_GSS_GEX_SHA1:
     185                if (strlen(name) < sizeof(KEX_GSS_GEX_SHA1_ID))
     186                        return GSS_C_NO_OID;
     187                name += sizeof(KEX_GSS_GEX_SHA1_ID) - 1;
     188                break;
     189        default:
     190                return GSS_C_NO_OID;
     191        }
     192
     193        while (gss_enc2oid[i].encoded != NULL &&
     194            strcmp(name, gss_enc2oid[i].encoded) != 0)
     195                i++;
     196
     197        if (gss_enc2oid[i].oid != NULL && ctx != NULL)
     198                ssh_gssapi_set_oid(ctx, gss_enc2oid[i].oid);
     199
     200        return gss_enc2oid[i].oid;
     201}
     202
    48203/* Check that the OID in a data stream matches that in the context */
    49204int
    50205ssh_gssapi_check_oid(Gssctxt *ctx, void *data, size_t len)
    ssh_gssapi_init_ctx(Gssctxt *ctx, int deleg_creds, gss_buffer_desc *recv_tok, 
    197352        }
    198353
    199354        ctx->major = gss_init_sec_context(&ctx->minor,
    200             GSS_C_NO_CREDENTIAL, &ctx->context, ctx->name, ctx->oid,
     355            ctx->client_creds, &ctx->context, ctx->name, ctx->oid,
    201356            GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG | deleg_flag,
    202357            0, NULL, recv_tok, NULL, send_tok, flags, NULL);
    203358
    ssh_gssapi_import_name(Gssctxt *ctx, const char *host) 
    227382}
    228383
    229384OM_uint32
     385ssh_gssapi_client_identity(Gssctxt *ctx, const char *name)
     386{
     387        gss_buffer_desc gssbuf;
     388        gss_name_t gssname;
     389        OM_uint32 status;
     390        gss_OID_set oidset;
     391
     392        gssbuf.value = (void *) name;
     393        gssbuf.length = strlen(gssbuf.value);
     394
     395        gss_create_empty_oid_set(&status, &oidset);
     396        gss_add_oid_set_member(&status, ctx->oid, &oidset);
     397
     398        ctx->major = gss_import_name(&ctx->minor, &gssbuf,
     399            GSS_C_NT_USER_NAME, &gssname);
     400
     401        if (!ctx->major)
     402                ctx->major = gss_acquire_cred(&ctx->minor,
     403                    gssname, 0, oidset, GSS_C_INITIATE,
     404                    &ctx->client_creds, NULL, NULL);
     405
     406        gss_release_name(&status, &gssname);
     407        gss_release_oid_set(&status, &oidset);
     408
     409        if (ctx->major)
     410                ssh_gssapi_error(ctx);
     411
     412        return(ctx->major);
     413}
     414
     415OM_uint32
    230416ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash)
    231417{
     418        if (ctx == NULL)
     419                return -1;
     420
    232421        if ((ctx->major = gss_get_mic(&ctx->minor, ctx->context,
    233422            GSS_C_QOP_DEFAULT, buffer, hash)))
    234423                ssh_gssapi_error(ctx);
    ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash) 
    236425        return (ctx->major);
    237426}
    238427
     428/* Priviledged when used by server */
     429OM_uint32
     430ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
     431{
     432        if (ctx == NULL)
     433                return -1;
     434
     435        ctx->major = gss_verify_mic(&ctx->minor, ctx->context,
     436            gssbuf, gssmic, NULL);
     437
     438        return (ctx->major);
     439}
     440
    239441void
    240442ssh_gssapi_buildmic(Buffer *b, const char *user, const char *service,
    241443    const char *context)
    ssh_gssapi_buildmic(Buffer *b, const char *user, const char *service, 
    249451}
    250452
    251453int
    252 ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host)
     454ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host,
     455    const char *client)
    253456{
    254457        gss_buffer_desc token = GSS_C_EMPTY_BUFFER;
    255458        OM_uint32 major, minor;
    256459        gss_OID_desc spnego_oid = {6, (void *)"\x2B\x06\x01\x05\x05\x02"};
     460        Gssctxt *intctx = NULL;
     461
     462        if (ctx == NULL)
     463                ctx = &intctx;
    257464
    258465        /* RFC 4462 says we MUST NOT do SPNEGO */
    259466        if (oid->length == spnego_oid.length &&
    ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host) 
    263470        ssh_gssapi_build_ctx(ctx);
    264471        ssh_gssapi_set_oid(*ctx, oid);
    265472        major = ssh_gssapi_import_name(*ctx, host);
     473
     474        if (!GSS_ERROR(major) && client)
     475                major = ssh_gssapi_client_identity(*ctx, client);
     476
    266477        if (!GSS_ERROR(major)) {
    267478                major = ssh_gssapi_init_ctx(*ctx, 0, GSS_C_NO_BUFFER, &token,
    268479                    NULL);
    ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host) 
    272483                            GSS_C_NO_BUFFER);
    273484        }
    274485
    275         if (GSS_ERROR(major))
     486        if (GSS_ERROR(major) || intctx != NULL)
    276487                ssh_gssapi_delete_ctx(ctx);
    277488
    278489        return (!GSS_ERROR(major));
    279490}
    280491
     492int
     493ssh_gssapi_credentials_updated(Gssctxt *ctxt) {
     494        static gss_name_t saved_name = GSS_C_NO_NAME;
     495        static OM_uint32 saved_lifetime = 0;
     496        static gss_OID saved_mech = GSS_C_NO_OID;
     497        static gss_name_t name;
     498        static OM_uint32 last_call = 0;
     499        OM_uint32 lifetime, now, major, minor;
     500        int equal;
     501        gss_cred_usage_t usage = GSS_C_INITIATE;
     502       
     503        now = time(NULL);
     504
     505        if (ctxt) {
     506                debug("Rekey has happened - updating saved versions");
     507
     508                if (saved_name != GSS_C_NO_NAME)
     509                        gss_release_name(&minor, &saved_name);
     510
     511                major = gss_inquire_cred(&minor, GSS_C_NO_CREDENTIAL,
     512                    &saved_name, &saved_lifetime, NULL, NULL);
     513
     514                if (!GSS_ERROR(major)) {
     515                        saved_mech = ctxt->oid;
     516                        saved_lifetime+= now;
     517                } else {
     518                        /* Handle the error */
     519                }
     520                return 0;
     521        }
     522
     523        if (now - last_call < 10)
     524                return 0;
     525
     526        last_call = now;
     527
     528        if (saved_mech == GSS_C_NO_OID)
     529                return 0;
     530       
     531        major = gss_inquire_cred(&minor, GSS_C_NO_CREDENTIAL,
     532            &name, &lifetime, NULL, NULL);
     533        if (major == GSS_S_CREDENTIALS_EXPIRED)
     534                return 0;
     535        else if (GSS_ERROR(major))
     536                return 0;
     537
     538        major = gss_compare_name(&minor, saved_name, name, &equal);
     539        gss_release_name(&minor, &name);
     540        if (GSS_ERROR(major))
     541                return 0;
     542
     543        if (equal && (saved_lifetime < lifetime + now - 10))
     544                return 1;
     545
     546        return 0;
     547}
     548
    281549#endif /* GSSAPI */
  • gss-serv-krb5.c

    diff --git a/gss-serv-krb5.c b/gss-serv-krb5.c
    index 5a625ac..e7170ee 100644
    a b  
    11/* $OpenBSD: gss-serv-krb5.c,v 1.7 2006/08/03 03:34:42 deraadt Exp $ */
    22
    33/*
    4  * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
     4 * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved.
    55 *
    66 * Redistribution and use in source and binary forms, with or without
    77 * modification, are permitted provided that the following conditions
    ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) 
    120120        krb5_principal princ;
    121121        OM_uint32 maj_status, min_status;
    122122        int len;
     123        const char *new_ccname;
    123124
    124125        if (client->creds == NULL) {
    125126                debug("No credentials stored");
    ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) 
    168169                return;
    169170        }
    170171
    171         client->store.filename = xstrdup(krb5_cc_get_name(krb_context, ccache));
     172        new_ccname = krb5_cc_get_name(krb_context, ccache);
     173
    172174        client->store.envvar = "KRB5CCNAME";
    173         len = strlen(client->store.filename) + 6;
    174         client->store.envval = xmalloc(len);
    175         snprintf(client->store.envval, len, "FILE:%s", client->store.filename);
     175#ifdef USE_CCAPI
     176        xasprintf(&client->store.envval, "API:%s", new_ccname);
     177        client->store.filename = NULL;
     178#else
     179        xasprintf(&client->store.envval, "FILE:%s", new_ccname);
     180        client->store.filename = xstrdup(new_ccname);
     181#endif
    176182
    177183#ifdef USE_PAM
    178184        if (options.use_pam)
    ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) 
    184190        return;
    185191}
    186192
     193int
     194ssh_gssapi_krb5_updatecreds(ssh_gssapi_ccache *store,
     195    ssh_gssapi_client *client)
     196{
     197        krb5_ccache ccache = NULL;
     198        krb5_principal principal = NULL;
     199        char *name = NULL;
     200        krb5_error_code problem;
     201        OM_uint32 maj_status, min_status;
     202
     203        if ((problem = krb5_cc_resolve(krb_context, store->envval, &ccache))) {
     204                logit("krb5_cc_resolve(): %.100s",
     205                    krb5_get_err_text(krb_context, problem));
     206                return 0;
     207        }
     208       
     209        /* Find out who the principal in this cache is */
     210        if ((problem = krb5_cc_get_principal(krb_context, ccache,
     211            &principal))) {
     212                logit("krb5_cc_get_principal(): %.100s",
     213                    krb5_get_err_text(krb_context, problem));
     214                krb5_cc_close(krb_context, ccache);
     215                return 0;
     216        }
     217
     218        if ((problem = krb5_unparse_name(krb_context, principal, &name))) {
     219                logit("krb5_unparse_name(): %.100s",
     220                    krb5_get_err_text(krb_context, problem));
     221                krb5_free_principal(krb_context, principal);
     222                krb5_cc_close(krb_context, ccache);
     223                return 0;
     224        }
     225
     226
     227        if (strcmp(name,client->exportedname.value)!=0) {
     228                debug("Name in local credentials cache differs. Not storing");
     229                krb5_free_principal(krb_context, principal);
     230                krb5_cc_close(krb_context, ccache);
     231                krb5_free_unparsed_name(krb_context, name);
     232                return 0;
     233        }
     234        krb5_free_unparsed_name(krb_context, name);
     235
     236        /* Name matches, so lets get on with it! */
     237
     238        if ((problem = krb5_cc_initialize(krb_context, ccache, principal))) {
     239                logit("krb5_cc_initialize(): %.100s",
     240                    krb5_get_err_text(krb_context, problem));
     241                krb5_free_principal(krb_context, principal);
     242                krb5_cc_close(krb_context, ccache);
     243                return 0;
     244        }
     245
     246        krb5_free_principal(krb_context, principal);
     247
     248        if ((maj_status = gss_krb5_copy_ccache(&min_status, client->creds,
     249            ccache))) {
     250                logit("gss_krb5_copy_ccache() failed. Sorry!");
     251                krb5_cc_close(krb_context, ccache);
     252                return 0;
     253        }
     254
     255        return 1;
     256}
     257
    187258ssh_gssapi_mech gssapi_kerberos_mech = {
    188259        "toWM5Slw5Ew8Mqkay+al2g==",
    189260        "Kerberos",
    ssh_gssapi_mech gssapi_kerberos_mech = { 
    191262        NULL,
    192263        &ssh_gssapi_krb5_userok,
    193264        NULL,
    194         &ssh_gssapi_krb5_storecreds
     265        &ssh_gssapi_krb5_storecreds,
     266        &ssh_gssapi_krb5_updatecreds
    195267};
    196268
    197269#endif /* KRB5 */
  • gss-serv.c

    diff --git a/gss-serv.c b/gss-serv.c
    index c719c13..380895e 100644
    a b  
    11/* $OpenBSD: gss-serv.c,v 1.23 2011/08/01 19:18:15 markus Exp $ */
    22
    33/*
    4  * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
     4 * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved.
    55 *
    66 * Redistribution and use in source and binary forms, with or without
    77 * modification, are permitted provided that the following conditions
     
    4545#include "channels.h"
    4646#include "session.h"
    4747#include "misc.h"
     48#include "servconf.h"
     49#include "uidswap.h"
    4850
    4951#include "ssh-gss.h"
     52#include "monitor_wrap.h"
     53
     54extern ServerOptions options;
    5055
    5156static ssh_gssapi_client gssapi_client =
    5257    { GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER,
    53     GSS_C_NO_CREDENTIAL, NULL, {NULL, NULL, NULL}};
     58    GSS_C_NO_CREDENTIAL, GSS_C_NO_NAME,  NULL, {NULL, NULL, NULL}, 0, 0};
    5459
    5560ssh_gssapi_mech gssapi_null_mech =
    56     { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL};
     61    { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL, NULL};
    5762
    5863#ifdef KRB5
    5964extern ssh_gssapi_mech gssapi_kerberos_mech;
    ssh_gssapi_acquire_cred(Gssctxt *ctx) 
    8186        char lname[MAXHOSTNAMELEN];
    8287        gss_OID_set oidset;
    8388
    84         gss_create_empty_oid_set(&status, &oidset);
    85         gss_add_oid_set_member(&status, ctx->oid, &oidset);
     89        if (options.gss_strict_acceptor) {
     90                gss_create_empty_oid_set(&status, &oidset);
     91                gss_add_oid_set_member(&status, ctx->oid, &oidset);
    8692
    87         if (gethostname(lname, MAXHOSTNAMELEN)) {
    88                 gss_release_oid_set(&status, &oidset);
    89                 return (-1);
    90         }
     93                if (gethostname(lname, MAXHOSTNAMELEN)) {
     94                        gss_release_oid_set(&status, &oidset);
     95                        return (-1);
     96                }
     97
     98                if (GSS_ERROR(ssh_gssapi_import_name(ctx, lname))) {
     99                        gss_release_oid_set(&status, &oidset);
     100                        return (ctx->major);
     101                }
     102
     103                if ((ctx->major = gss_acquire_cred(&ctx->minor,
     104                    ctx->name, 0, oidset, GSS_C_ACCEPT, &ctx->creds,
     105                    NULL, NULL)))
     106                        ssh_gssapi_error(ctx);
    91107
    92         if (GSS_ERROR(ssh_gssapi_import_name(ctx, lname))) {
    93108                gss_release_oid_set(&status, &oidset);
    94109                return (ctx->major);
     110        } else {
     111                ctx->name = GSS_C_NO_NAME;
     112                ctx->creds = GSS_C_NO_CREDENTIAL;
    95113        }
    96 
    97         if ((ctx->major = gss_acquire_cred(&ctx->minor,
    98             ctx->name, 0, oidset, GSS_C_ACCEPT, &ctx->creds, NULL, NULL)))
    99                 ssh_gssapi_error(ctx);
    100 
    101         gss_release_oid_set(&status, &oidset);
    102         return (ctx->major);
     114        return GSS_S_COMPLETE;
    103115}
    104116
    105117/* Privileged */
    ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID oid) 
    114126}
    115127
    116128/* Unprivileged */
     129char *
     130ssh_gssapi_server_mechanisms() {
     131        gss_OID_set     supported;
     132
     133        ssh_gssapi_supported_oids(&supported);
     134        return (ssh_gssapi_kex_mechs(supported, &ssh_gssapi_server_check_mech,
     135            NULL, NULL));
     136}
     137
     138/* Unprivileged */
     139int
     140ssh_gssapi_server_check_mech(Gssctxt **dum, gss_OID oid, const char *data,
     141    const char *dummy) {
     142        Gssctxt *ctx = NULL;
     143        int res;
     144 
     145        res = !GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctx, oid)));
     146        ssh_gssapi_delete_ctx(&ctx);
     147
     148        return (res);
     149}
     150
     151/* Unprivileged */
    117152void
    118153ssh_gssapi_supported_oids(gss_OID_set *oidset)
    119154{
    ssh_gssapi_supported_oids(gss_OID_set *oidset) 
    123158        gss_OID_set supported;
    124159
    125160        gss_create_empty_oid_set(&min_status, oidset);
    126         gss_indicate_mechs(&min_status, &supported);
     161
     162        if (GSS_ERROR(gss_indicate_mechs(&min_status, &supported)))
     163                return;
    127164
    128165        while (supported_mechs[i]->name != NULL) {
    129166                if (GSS_ERROR(gss_test_oid_set_member(&min_status,
    OM_uint32 
    249286ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client)
    250287{
    251288        int i = 0;
     289        int equal = 0;
     290        gss_name_t new_name = GSS_C_NO_NAME;
     291        gss_buffer_desc ename = GSS_C_EMPTY_BUFFER;
     292
     293        if (options.gss_store_rekey && client->used && ctx->client_creds) {
     294                if (client->mech->oid.length != ctx->oid->length ||
     295                    (memcmp(client->mech->oid.elements,
     296                     ctx->oid->elements, ctx->oid->length) !=0)) {
     297                        debug("Rekeyed credentials have different mechanism");
     298                        return GSS_S_COMPLETE;
     299                }
     300
     301                if ((ctx->major = gss_inquire_cred_by_mech(&ctx->minor,
     302                    ctx->client_creds, ctx->oid, &new_name,
     303                    NULL, NULL, NULL))) {
     304                        ssh_gssapi_error(ctx);
     305                        return (ctx->major);
     306                }
     307
     308                ctx->major = gss_compare_name(&ctx->minor, client->name,
     309                    new_name, &equal);
    252310
    253         gss_buffer_desc ename;
     311                if (GSS_ERROR(ctx->major)) {
     312                        ssh_gssapi_error(ctx);
     313                        return (ctx->major);
     314                }
     315 
     316                if (!equal) {
     317                        debug("Rekeyed credentials have different name");
     318                        return GSS_S_COMPLETE;
     319                }
     320
     321                debug("Marking rekeyed credentials for export");
     322
     323                gss_release_name(&ctx->minor, &client->name);
     324                gss_release_cred(&ctx->minor, &client->creds);
     325                client->name = new_name;
     326                client->creds = ctx->client_creds;
     327                ctx->client_creds = GSS_C_NO_CREDENTIAL;
     328                client->updated = 1;
     329                return GSS_S_COMPLETE;
     330        }
    254331
    255332        client->mech = NULL;
    256333
    ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client) 
    265342        if (client->mech == NULL)
    266343                return GSS_S_FAILURE;
    267344
     345        if (ctx->client_creds &&
     346            (ctx->major = gss_inquire_cred_by_mech(&ctx->minor,
     347             ctx->client_creds, ctx->oid, &client->name, NULL, NULL, NULL))) {
     348                ssh_gssapi_error(ctx);
     349                return (ctx->major);
     350        }
     351
    268352        if ((ctx->major = gss_display_name(&ctx->minor, ctx->client,
    269353            &client->displayname, NULL))) {
    270354                ssh_gssapi_error(ctx);
    ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client) 
    282366                return (ctx->major);
    283367        }
    284368
     369        gss_release_buffer(&ctx->minor, &ename);
     370
    285371        /* We can't copy this structure, so we just move the pointer to it */
    286372        client->creds = ctx->client_creds;
    287373        ctx->client_creds = GSS_C_NO_CREDENTIAL;
    ssh_gssapi_do_child(char ***envp, u_int *envsizep) 
    329415
    330416/* Privileged */
    331417int
    332 ssh_gssapi_userok(char *user)
     418ssh_gssapi_userok(char *user, struct passwd *pw)
    333419{
    334420        OM_uint32 lmin;
    335421
    ssh_gssapi_userok(char *user) 
    339425                return 0;
    340426        }
    341427        if (gssapi_client.mech && gssapi_client.mech->userok)
    342                 if ((*gssapi_client.mech->userok)(&gssapi_client, user))
     428                if ((*gssapi_client.mech->userok)(&gssapi_client, user)) {
     429                        gssapi_client.used = 1;
     430                        gssapi_client.store.owner = pw;
    343431                        return 1;
    344                 else {
     432                } else {
    345433                        /* Destroy delegated credentials if userok fails */
    346434                        gss_release_buffer(&lmin, &gssapi_client.displayname);
    347435                        gss_release_buffer(&lmin, &gssapi_client.exportedname);
    ssh_gssapi_userok(char *user) 
    354442        return (0);
    355443}
    356444
    357 /* Privileged */
    358 OM_uint32
    359 ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
     445/* These bits are only used for rekeying. The unpriviledged child is running
     446 * as the user, the monitor is root.
     447 *
     448 * In the child, we want to :
     449 *    *) Ask the monitor to store our credentials into the store we specify
     450 *    *) If it succeeds, maybe do a PAM update
     451 */
     452
     453/* Stuff for PAM */
     454
     455#ifdef USE_PAM
     456static int ssh_gssapi_simple_conv(int n, const struct pam_message **msg,
     457    struct pam_response **resp, void *data)
    360458{
    361         ctx->major = gss_verify_mic(&ctx->minor, ctx->context,
    362             gssbuf, gssmic, NULL);
     459        return (PAM_CONV_ERR);
     460}
     461#endif
    363462
    364         return (ctx->major);
     463void
     464ssh_gssapi_rekey_creds() {
     465        int ok;
     466        int ret;
     467#ifdef USE_PAM
     468        pam_handle_t *pamh = NULL;
     469        struct pam_conv pamconv = {ssh_gssapi_simple_conv, NULL};
     470        char *envstr;
     471#endif
     472
     473        if (gssapi_client.store.filename == NULL &&
     474            gssapi_client.store.envval == NULL &&
     475            gssapi_client.store.envvar == NULL)
     476                return;
     477 
     478        ok = PRIVSEP(ssh_gssapi_update_creds(&gssapi_client.store));
     479
     480        if (!ok)
     481                return;
     482
     483        debug("Rekeyed credentials stored successfully");
     484
     485        /* Actually managing to play with the ssh pam stack from here will
     486         * be next to impossible. In any case, we may want different options
     487         * for rekeying. So, use our own :)
     488         */
     489#ifdef USE_PAM 
     490        if (!use_privsep) {
     491                debug("Not even going to try and do PAM with privsep disabled");
     492                return;
     493        }
     494
     495        ret = pam_start("sshd-rekey", gssapi_client.store.owner->pw_name,
     496            &pamconv, &pamh);
     497        if (ret)
     498                return;
     499
     500        xasprintf(&envstr, "%s=%s", gssapi_client.store.envvar,
     501            gssapi_client.store.envval);
     502
     503        ret = pam_putenv(pamh, envstr);
     504        if (!ret)
     505                pam_setcred(pamh, PAM_REINITIALIZE_CRED);
     506        pam_end(pamh, PAM_SUCCESS);
     507#endif
     508}
     509
     510int
     511ssh_gssapi_update_creds(ssh_gssapi_ccache *store) {
     512        int ok = 0;
     513
     514        /* Check we've got credentials to store */
     515        if (!gssapi_client.updated)
     516                return 0;
     517
     518        gssapi_client.updated = 0;
     519
     520        temporarily_use_uid(gssapi_client.store.owner);
     521        if (gssapi_client.mech && gssapi_client.mech->updatecreds)
     522                ok = (*gssapi_client.mech->updatecreds)(store, &gssapi_client);
     523        else
     524                debug("No update function for this mechanism");
     525
     526        restore_uid();
     527
     528        return ok;
    365529}
    366530
    367531#endif
  • kex.c

    diff --git a/kex.c b/kex.c
    index c65e28f..58349fc 100644
    a b  
    5050#include "monitor.h"
    5151#include "roaming.h"
    5252
     53#ifdef GSSAPI
     54#include "ssh-gss.h"
     55#endif
     56
    5357#if OPENSSL_VERSION_NUMBER >= 0x00907000L
    5458# if defined(HAVE_EVP_SHA256)
    5559# define evp_ssh_sha256 EVP_sha256
    choose_kex(Kex *k, char *client, char *server) 
    358362                k->kex_type = KEX_ECDH_SHA2;
    359363                k->evp_md = kex_ecdh_name_to_evpmd(k->name);
    360364#endif
     365#ifdef GSSAPI
     366        } else if (strncmp(k->name, KEX_GSS_GEX_SHA1_ID,
     367            sizeof(KEX_GSS_GEX_SHA1_ID) - 1) == 0) {
     368                k->kex_type = KEX_GSS_GEX_SHA1;
     369                k->evp_md = EVP_sha1();
     370        } else if (strncmp(k->name, KEX_GSS_GRP1_SHA1_ID,
     371            sizeof(KEX_GSS_GRP1_SHA1_ID) - 1) == 0) {
     372                k->kex_type = KEX_GSS_GRP1_SHA1;
     373                k->evp_md = EVP_sha1();
     374        } else if (strncmp(k->name, KEX_GSS_GRP14_SHA1_ID,
     375            sizeof(KEX_GSS_GRP14_SHA1_ID) - 1) == 0) {
     376                k->kex_type = KEX_GSS_GRP14_SHA1;
     377                k->evp_md = EVP_sha1();
     378#endif
    361379        } else
    362380                fatal("bad kex alg %s", k->name);
    363381}
  • kex.h

    diff --git a/kex.h b/kex.h
    index 7373d3c..fa50b2c 100644
    a b enum kex_exchange { 
    7373        KEX_DH_GEX_SHA1,
    7474        KEX_DH_GEX_SHA256,
    7575        KEX_ECDH_SHA2,
     76        KEX_GSS_GRP1_SHA1,
     77        KEX_GSS_GRP14_SHA1,
     78        KEX_GSS_GEX_SHA1,
    7679        KEX_MAX
    7780};
    7881
    struct Kex { 
    129132        sig_atomic_t done;
    130133        int     flags;
    131134        const EVP_MD *evp_md;
     135#ifdef GSSAPI
     136        int     gss_deleg_creds;
     137        int     gss_trust_dns;
     138        char    *gss_host;
     139        char    *gss_client;
     140#endif
    132141        char    *client_version_string;
    133142        char    *server_version_string;
    134143        int     (*verify_host_key)(Key *);
    void kexgex_server(Kex *); 
    156165void     kexecdh_client(Kex *);
    157166void     kexecdh_server(Kex *);
    158167
     168#ifdef GSSAPI
     169void    kexgss_client(Kex *);
     170void    kexgss_server(Kex *);
     171#endif
     172
    159173void
    160174kex_dh_hash(char *, char *, char *, int, char *, int, u_char *, int,
    161175    BIGNUM *, BIGNUM *, BIGNUM *, u_char **, u_int *);
  • new file kexgssc.c

    diff --git a/kexgssc.c b/kexgssc.c
    new file mode 100644
    index 0000000..39be405
    - +  
     1/*
     2 * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved.
     3 *
     4 * Redistribution and use in source and binary forms, with or without
     5 * modification, are permitted provided that the following conditions
     6 * are met:
     7 * 1. Redistributions of source code must retain the above copyright
     8 *    notice, this list of conditions and the following disclaimer.
     9 * 2. Redistributions in binary form must reproduce the above copyright
     10 *    notice, this list of conditions and the following disclaimer in the
     11 *    documentation and/or other materials provided with the distribution.
     12 *
     13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
     14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     23 */
     24
     25#include "includes.h"
     26
     27#ifdef GSSAPI
     28
     29#include "includes.h"
     30
     31#include <openssl/crypto.h>
     32#include <openssl/bn.h>
     33
     34#include <string.h>
     35
     36#include "xmalloc.h"
     37#include "buffer.h"
     38#include "ssh2.h"
     39#include "key.h"
     40#include "cipher.h"
     41#include "kex.h"
     42#include "log.h"
     43#include "packet.h"
     44#include "dh.h"
     45
     46#include "ssh-gss.h"
     47
     48void
     49kexgss_client(Kex *kex) {
     50        gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
     51        gss_buffer_desc recv_tok, gssbuf, msg_tok, *token_ptr;
     52        Gssctxt *ctxt;
     53        OM_uint32 maj_status, min_status, ret_flags;
     54        u_int klen, kout, slen = 0, hashlen, strlen;
     55        DH *dh;
     56        BIGNUM *dh_server_pub = NULL;
     57        BIGNUM *shared_secret = NULL;
     58        BIGNUM *p = NULL;
     59        BIGNUM *g = NULL;       
     60        u_char *kbuf, *hash;
     61        u_char *serverhostkey = NULL;
     62        u_char *empty = "";
     63        char *msg;
     64        char *lang;
     65        int type = 0;
     66        int first = 1;
     67        int nbits = 0, min = DH_GRP_MIN, max = DH_GRP_MAX;
     68
     69        /* Initialise our GSSAPI world */       
     70        ssh_gssapi_build_ctx(&ctxt);
     71        if (ssh_gssapi_id_kex(ctxt, kex->name, kex->kex_type)
     72            == GSS_C_NO_OID)
     73                fatal("Couldn't identify host exchange");
     74
     75        if (ssh_gssapi_import_name(ctxt, kex->gss_host))
     76                fatal("Couldn't import hostname");
     77
     78        if (kex->gss_client &&
     79            ssh_gssapi_client_identity(ctxt, kex->gss_client))
     80                fatal("Couldn't acquire client credentials");
     81
     82        switch (kex->kex_type) {
     83        case KEX_GSS_GRP1_SHA1:
     84                dh = dh_new_group1();
     85                break;
     86        case KEX_GSS_GRP14_SHA1:
     87                dh = dh_new_group14();
     88                break;
     89        case KEX_GSS_GEX_SHA1:
     90                debug("Doing group exchange\n");
     91                nbits = dh_estimate(kex->we_need * 8);
     92                packet_start(SSH2_MSG_KEXGSS_GROUPREQ);
     93                packet_put_int(min);
     94                packet_put_int(nbits);
     95                packet_put_int(max);
     96
     97                packet_send();
     98
     99                packet_read_expect(SSH2_MSG_KEXGSS_GROUP);
     100
     101                if ((p = BN_new()) == NULL)
     102                        fatal("BN_new() failed");
     103                packet_get_bignum2(p);
     104                if ((g = BN_new()) == NULL)
     105                        fatal("BN_new() failed");
     106                packet_get_bignum2(g);
     107                packet_check_eom();
     108
     109                if (BN_num_bits(p) < min || BN_num_bits(p) > max)
     110                        fatal("GSSGRP_GEX group out of range: %d !< %d !< %d",
     111                            min, BN_num_bits(p), max);
     112
     113                dh = dh_new_group(g, p);
     114                break;
     115        default:
     116                fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type);
     117        }
     118       
     119        /* Step 1 - e is dh->pub_key */
     120        dh_gen_key(dh, kex->we_need * 8);
     121
     122        /* This is f, we initialise it now to make life easier */
     123        dh_server_pub = BN_new();
     124        if (dh_server_pub == NULL)
     125                fatal("dh_server_pub == NULL");
     126
     127        token_ptr = GSS_C_NO_BUFFER;
     128                         
     129        do {
     130                debug("Calling gss_init_sec_context");
     131               
     132                maj_status = ssh_gssapi_init_ctx(ctxt,
     133                    kex->gss_deleg_creds, token_ptr, &send_tok,
     134                    &ret_flags);
     135
     136                if (GSS_ERROR(maj_status)) {
     137                        if (send_tok.length != 0) {
     138                                packet_start(SSH2_MSG_KEXGSS_CONTINUE);
     139                                packet_put_string(send_tok.value,
     140                                    send_tok.length);
     141                        }
     142                        fatal("gss_init_context failed");
     143                }
     144
     145                /* If we've got an old receive buffer get rid of it */
     146                if (token_ptr != GSS_C_NO_BUFFER)
     147                        xfree(recv_tok.value);
     148
     149                if (maj_status == GSS_S_COMPLETE) {
     150                        /* If mutual state flag is not true, kex fails */
     151                        if (!(ret_flags & GSS_C_MUTUAL_FLAG))
     152                                fatal("Mutual authentication failed");
     153
     154                        /* If integ avail flag is not true kex fails */
     155                        if (!(ret_flags & GSS_C_INTEG_FLAG))
     156                                fatal("Integrity check failed");
     157                }
     158
     159                /*
     160                 * If we have data to send, then the last message that we
     161                 * received cannot have been a 'complete'.
     162                 */
     163                if (send_tok.length != 0) {
     164                        if (first) {
     165                                packet_start(SSH2_MSG_KEXGSS_INIT);
     166                                packet_put_string(send_tok.value,
     167                                    send_tok.length);
     168                                packet_put_bignum2(dh->pub_key);
     169                                first = 0;
     170                        } else {
     171                                packet_start(SSH2_MSG_KEXGSS_CONTINUE);
     172                                packet_put_string(send_tok.value,
     173                                    send_tok.length);
     174                        }
     175                        packet_send();
     176                        gss_release_buffer(&min_status, &send_tok);
     177
     178                        /* If we've sent them data, they should reply */
     179                        do {   
     180                                type = packet_read();
     181                                if (type == SSH2_MSG_KEXGSS_HOSTKEY) {
     182                                        debug("Received KEXGSS_HOSTKEY");
     183                                        if (serverhostkey)
     184                                                fatal("Server host key received more than once");
     185                                        serverhostkey =
     186                                            packet_get_string(&slen);
     187                                }
     188                        } while (type == SSH2_MSG_KEXGSS_HOSTKEY);
     189
     190                        switch (type) {
     191                        case SSH2_MSG_KEXGSS_CONTINUE:
     192                                debug("Received GSSAPI_CONTINUE");
     193                                if (maj_status == GSS_S_COMPLETE)
     194                                        fatal("GSSAPI Continue received from server when complete");
     195                                recv_tok.value = packet_get_string(&strlen);
     196                                recv_tok.length = strlen;
     197                                break;
     198                        case SSH2_MSG_KEXGSS_COMPLETE:
     199                                debug("Received GSSAPI_COMPLETE");
     200                                packet_get_bignum2(dh_server_pub);
     201                                msg_tok.value =  packet_get_string(&strlen);
     202                                msg_tok.length = strlen;
     203
     204                                /* Is there a token included? */
     205                                if (packet_get_char()) {
     206                                        recv_tok.value=
     207                                            packet_get_string(&strlen);
     208                                        recv_tok.length = strlen;
     209                                        /* If we're already complete - protocol error */
     210                                        if (maj_status == GSS_S_COMPLETE)
     211                                                packet_disconnect("Protocol error: received token when complete");
     212                                        } else {
     213                                                /* No token included */
     214                                                if (maj_status != GSS_S_COMPLETE)
     215                                                        packet_disconnect("Protocol error: did not receive final token");
     216                                }
     217                                break;
     218                        case SSH2_MSG_KEXGSS_ERROR:
     219                                debug("Received Error");
     220                                maj_status = packet_get_int();
     221                                min_status = packet_get_int();
     222                                msg = packet_get_string(NULL);
     223                                lang = packet_get_string(NULL);
     224                                fatal("GSSAPI Error: \n%.400s",msg);
     225                        default:
     226                                packet_disconnect("Protocol error: didn't expect packet type %d",
     227                                type);
     228                        }
     229                        token_ptr = &recv_tok;
     230                } else {
     231                        /* No data, and not complete */
     232                        if (maj_status != GSS_S_COMPLETE)
     233                                fatal("Not complete, and no token output");
     234                }
     235        } while (maj_status & GSS_S_CONTINUE_NEEDED);
     236
     237        /*
     238         * We _must_ have received a COMPLETE message in reply from the
     239         * server, which will have set dh_server_pub and msg_tok
     240         */
     241
     242        if (type != SSH2_MSG_KEXGSS_COMPLETE)
     243                fatal("Didn't receive a SSH2_MSG_KEXGSS_COMPLETE when I expected it");
     244
     245        /* Check f in range [1, p-1] */
     246        if (!dh_pub_is_valid(dh, dh_server_pub))
     247                packet_disconnect("bad server public DH value");
     248
     249        /* compute K=f^x mod p */
     250        klen = DH_size(dh);
     251        kbuf = xmalloc(klen);
     252        kout = DH_compute_key(kbuf, dh_server_pub, dh);
     253        if (kout < 0)
     254                fatal("DH_compute_key: failed");
     255
     256        shared_secret = BN_new();
     257        if (shared_secret == NULL)
     258                fatal("kexgss_client: BN_new failed");
     259
     260        if (BN_bin2bn(kbuf, kout, shared_secret) == NULL)
     261                fatal("kexdh_client: BN_bin2bn failed");
     262
     263        memset(kbuf, 0, klen);
     264        xfree(kbuf);
     265
     266        switch (kex->kex_type) {
     267        case KEX_GSS_GRP1_SHA1:
     268        case KEX_GSS_GRP14_SHA1:
     269                kex_dh_hash( kex->client_version_string,
     270                    kex->server_version_string,
     271                    buffer_ptr(&kex->my), buffer_len(&kex->my),
     272                    buffer_ptr(&kex->peer), buffer_len(&kex->peer),
     273                    (serverhostkey ? serverhostkey : empty), slen,
     274                    dh->pub_key,        /* e */
     275                    dh_server_pub,      /* f */
     276                    shared_secret,      /* K */
     277                    &hash, &hashlen
     278                );
     279                break;
     280        case KEX_GSS_GEX_SHA1:
     281                kexgex_hash(
     282                    kex->evp_md,
     283                    kex->client_version_string,
     284                    kex->server_version_string,
     285                    buffer_ptr(&kex->my), buffer_len(&kex->my),
     286                    buffer_ptr(&kex->peer), buffer_len(&kex->peer),
     287                    (serverhostkey ? serverhostkey : empty), slen,
     288                    min, nbits, max,
     289                    dh->p, dh->g,
     290                    dh->pub_key,
     291                    dh_server_pub,
     292                    shared_secret,
     293                    &hash, &hashlen
     294                );
     295                break;
     296        default:
     297                fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type);
     298        }
     299
     300        gssbuf.value = hash;
     301        gssbuf.length = hashlen;
     302
     303        /* Verify that the hash matches the MIC we just got. */
     304        if (GSS_ERROR(ssh_gssapi_checkmic(ctxt, &gssbuf, &msg_tok)))
     305                packet_disconnect("Hash's MIC didn't verify");
     306
     307        xfree(msg_tok.value);
     308
     309        DH_free(dh);
     310        if (serverhostkey)
     311                xfree(serverhostkey);
     312        BN_clear_free(dh_server_pub);
     313
     314        /* save session id */
     315        if (kex->session_id == NULL) {
     316                kex->session_id_len = hashlen;
     317                kex->session_id = xmalloc(kex->session_id_len);
     318                memcpy(kex->session_id, hash, kex->session_id_len);
     319        }
     320
     321        if (kex->gss_deleg_creds)
     322                ssh_gssapi_credentials_updated(ctxt);
     323
     324        if (gss_kex_context == NULL)
     325                gss_kex_context = ctxt;
     326        else
     327                ssh_gssapi_delete_ctx(&ctxt);
     328
     329        kex_derive_keys(kex, hash, hashlen, shared_secret);
     330        BN_clear_free(shared_secret);
     331        kex_finish(kex);
     332}
     333
     334#endif /* GSSAPI */
  • new file kexgsss.c

    diff --git a/kexgsss.c b/kexgsss.c
    new file mode 100644
    index 0000000..0c3eeaa
    - +  
     1/*
     2 * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved.
     3 *
     4 * Redistribution and use in source and binary forms, with or without
     5 * modification, are permitted provided that the following conditions
     6 * are met:
     7 * 1. Redistributions of source code must retain the above copyright
     8 *    notice, this list of conditions and the following disclaimer.
     9 * 2. Redistributions in binary form must reproduce the above copyright
     10 *    notice, this list of conditions and the following disclaimer in the
     11 *    documentation and/or other materials provided with the distribution.
     12 *
     13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
     14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     23 */
     24
     25#include "includes.h"
     26
     27#ifdef GSSAPI
     28
     29#include <string.h>
     30
     31#include <openssl/crypto.h>
     32#include <openssl/bn.h>
     33
     34#include "xmalloc.h"
     35#include "buffer.h"
     36#include "ssh2.h"
     37#include "key.h"
     38#include "cipher.h"
     39#include "kex.h"
     40#include "log.h"
     41#include "packet.h"
     42#include "dh.h"
     43#include "ssh-gss.h"
     44#include "monitor_wrap.h"
     45#include "servconf.h"
     46
     47extern ServerOptions options;
     48
     49void
     50kexgss_server(Kex *kex)
     51{
     52        OM_uint32 maj_status, min_status;
     53       
     54        /*
     55         * Some GSSAPI implementations use the input value of ret_flags (an
     56         * output variable) as a means of triggering mechanism specific
     57         * features. Initializing it to zero avoids inadvertently
     58         * activating this non-standard behaviour.
     59         */
     60
     61        OM_uint32 ret_flags = 0;
     62        gss_buffer_desc gssbuf, recv_tok, msg_tok;
     63        gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
     64        Gssctxt *ctxt = NULL;
     65        u_int slen, klen, kout, hashlen;
     66        u_char *kbuf, *hash;
     67        DH *dh;
     68        int min = -1, max = -1, nbits = -1;
     69        BIGNUM *shared_secret = NULL;
     70        BIGNUM *dh_client_pub = NULL;
     71        int type = 0;
     72        gss_OID oid;
     73        char *mechs;
     74
     75        /* Initialise GSSAPI */
     76
     77        /* If we're rekeying, privsep means that some of the private structures
     78         * in the GSSAPI code are no longer available. This kludges them back
     79         * into life
     80         */
     81        if (!ssh_gssapi_oid_table_ok())
     82                if ((mechs = ssh_gssapi_server_mechanisms()))
     83                        xfree(mechs);
     84
     85        debug2("%s: Identifying %s", __func__, kex->name);
     86        oid = ssh_gssapi_id_kex(NULL, kex->name, kex->kex_type);
     87        if (oid == GSS_C_NO_OID)
     88           fatal("Unknown gssapi mechanism");
     89
     90        debug2("%s: Acquiring credentials", __func__);
     91
     92        if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, oid))))
     93                fatal("Unable to acquire credentials for the server");
     94
     95        switch (kex->kex_type) {
     96        case KEX_GSS_GRP1_SHA1:
     97                dh = dh_new_group1();
     98                break;
     99        case KEX_GSS_GRP14_SHA1:
     100                dh = dh_new_group14();
     101                break;
     102        case KEX_GSS_GEX_SHA1:
     103                debug("Doing group exchange");
     104                packet_read_expect(SSH2_MSG_KEXGSS_GROUPREQ);
     105                min = packet_get_int();
     106                nbits = packet_get_int();
     107                max = packet_get_int();
     108                min = MAX(DH_GRP_MIN, min);
     109                max = MIN(DH_GRP_MAX, max);
     110                packet_check_eom();
     111                if (max < min || nbits < min || max < nbits)
     112                        fatal("GSS_GEX, bad parameters: %d !< %d !< %d",
     113                            min, nbits, max);
     114                dh = PRIVSEP(choose_dh(min, nbits, max));
     115                if (dh == NULL)
     116                        packet_disconnect("Protocol error: no matching group found");
     117
     118                packet_start(SSH2_MSG_KEXGSS_GROUP);
     119                packet_put_bignum2(dh->p);
     120                packet_put_bignum2(dh->g);
     121                packet_send();
     122
     123                packet_write_wait();
     124                break;
     125        default:
     126                fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type);
     127        }
     128
     129        dh_gen_key(dh, kex->we_need * 8);
     130
     131        do {
     132                debug("Wait SSH2_MSG_GSSAPI_INIT");
     133                type = packet_read();
     134                switch(type) {
     135                case SSH2_MSG_KEXGSS_INIT:
     136                        if (dh_client_pub != NULL)
     137                                fatal("Received KEXGSS_INIT after initialising");
     138                        recv_tok.value = packet_get_string(&slen);
     139                        recv_tok.length = slen;
     140
     141                        if ((dh_client_pub = BN_new()) == NULL)
     142                                fatal("dh_client_pub == NULL");
     143
     144                        packet_get_bignum2(dh_client_pub);
     145
     146                        /* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */
     147                        break;
     148                case SSH2_MSG_KEXGSS_CONTINUE:
     149                        recv_tok.value = packet_get_string(&slen);
     150                        recv_tok.length = slen;
     151                        break;
     152                default:
     153                        packet_disconnect(
     154                            "Protocol error: didn't expect packet type %d",
     155                            type);
     156                }
     157
     158                maj_status = PRIVSEP(ssh_gssapi_accept_ctx(ctxt, &recv_tok,
     159                    &send_tok, &ret_flags));
     160
     161                xfree(recv_tok.value);
     162
     163                if (maj_status != GSS_S_COMPLETE && send_tok.length == 0)
     164                        fatal("Zero length token output when incomplete");
     165
     166                if (dh_client_pub == NULL)
     167                        fatal("No client public key");
     168               
     169                if (maj_status & GSS_S_CONTINUE_NEEDED) {
     170                        debug("Sending GSSAPI_CONTINUE");
     171                        packet_start(SSH2_MSG_KEXGSS_CONTINUE);
     172                        packet_put_string(send_tok.value, send_tok.length);
     173                        packet_send();
     174                        gss_release_buffer(&min_status, &send_tok);
     175                }
     176        } while (maj_status & GSS_S_CONTINUE_NEEDED);
     177
     178        if (GSS_ERROR(maj_status)) {
     179                if (send_tok.length > 0) {
     180                        packet_start(SSH2_MSG_KEXGSS_CONTINUE);
     181                        packet_put_string(send_tok.value, send_tok.length);
     182                        packet_send();
     183                }
     184                fatal("accept_ctx died");
     185        }
     186
     187        if (!(ret_flags & GSS_C_MUTUAL_FLAG))
     188                fatal("Mutual Authentication flag wasn't set");
     189
     190        if (!(ret_flags & GSS_C_INTEG_FLAG))
     191                fatal("Integrity flag wasn't set");
     192       
     193        if (!dh_pub_is_valid(dh, dh_client_pub))
     194                packet_disconnect("bad client public DH value");
     195
     196        klen = DH_size(dh);
     197        kbuf = xmalloc(klen);
     198        kout = DH_compute_key(kbuf, dh_client_pub, dh);
     199        if (kout < 0)
     200                fatal("DH_compute_key: failed");
     201
     202        shared_secret = BN_new();
     203        if (shared_secret == NULL)
     204                fatal("kexgss_server: BN_new failed");
     205
     206        if (BN_bin2bn(kbuf, kout, shared_secret) == NULL)
     207                fatal("kexgss_server: BN_bin2bn failed");
     208
     209        memset(kbuf, 0, klen);
     210        xfree(kbuf);
     211
     212        switch (kex->kex_type) {
     213        case KEX_GSS_GRP1_SHA1:
     214        case KEX_GSS_GRP14_SHA1:
     215                kex_dh_hash(
     216                    kex->client_version_string, kex->server_version_string,
     217                    buffer_ptr(&kex->peer), buffer_len(&kex->peer),
     218                    buffer_ptr(&kex->my), buffer_len(&kex->my),
     219                    NULL, 0, /* Change this if we start sending host keys */
     220                    dh_client_pub, dh->pub_key, shared_secret,
     221                    &hash, &hashlen
     222                );
     223                break;
     224        case KEX_GSS_GEX_SHA1:
     225                kexgex_hash(
     226                    kex->evp_md,
     227                    kex->client_version_string, kex->server_version_string,
     228                    buffer_ptr(&kex->peer), buffer_len(&kex->peer),
     229                    buffer_ptr(&kex->my), buffer_len(&kex->my),
     230                    NULL, 0,
     231                    min, nbits, max,
     232                    dh->p, dh->g,
     233                    dh_client_pub,
     234                    dh->pub_key,
     235                    shared_secret,
     236                    &hash, &hashlen
     237                );
     238                break;
     239        default:
     240                fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type);
     241        }
     242
     243        BN_clear_free(dh_client_pub);
     244
     245        if (kex->session_id == NULL) {
     246                kex->session_id_len = hashlen;
     247                kex->session_id = xmalloc(kex->session_id_len);
     248                memcpy(kex->session_id, hash, kex->session_id_len);
     249        }
     250
     251        gssbuf.value = hash;
     252        gssbuf.length = hashlen;
     253
     254        if (GSS_ERROR(PRIVSEP(ssh_gssapi_sign(ctxt,&gssbuf,&msg_tok))))
     255                fatal("Couldn't get MIC");
     256
     257        packet_start(SSH2_MSG_KEXGSS_COMPLETE);
     258        packet_put_bignum2(dh->pub_key);
     259        packet_put_string(msg_tok.value,msg_tok.length);
     260
     261        if (send_tok.length != 0) {
     262                packet_put_char(1); /* true */
     263                packet_put_string(send_tok.value, send_tok.length);
     264        } else {
     265                packet_put_char(0); /* false */
     266        }
     267        packet_send();
     268
     269        gss_release_buffer(&min_status, &send_tok);
     270        gss_release_buffer(&min_status, &msg_tok);
     271
     272        if (gss_kex_context == NULL)
     273                gss_kex_context = ctxt;
     274        else
     275                ssh_gssapi_delete_ctx(&ctxt);
     276
     277        DH_free(dh);
     278
     279        kex_derive_keys(kex, hash, hashlen, shared_secret);
     280        BN_clear_free(shared_secret);
     281        kex_finish(kex);
     282
     283        /* If this was a rekey, then save out any delegated credentials we
     284         * just exchanged.  */
     285        if (options.gss_store_rekey)
     286                ssh_gssapi_rekey_creds();
     287}
     288#endif /* GSSAPI */
  • key.c

    diff --git a/key.c b/key.c
    index 498cf5a..fc65c29 100644
    a b key_ssh_name_from_type_nid(int type, int nid) 
    971971                }
    972972                break;
    973973#endif /* OPENSSL_HAS_ECC */
     974        case KEY_NULL:
     975                return "null";
    974976        }
    975977        return "ssh-unknown";
    976978}
    key_type_from_name(char *name) 
    12761278            strcmp(name, "ecdsa-sha2-nistp521-cert-v01@openssh.com") == 0) {
    12771279                return KEY_ECDSA_CERT;
    12781280#endif
     1281        } else if (strcmp(name, "null") == 0) {
     1282                return KEY_NULL;
    12791283        }
    12801284
    12811285        debug2("key_type_from_name: unknown key type '%s'", name);
  • key.h

    diff --git a/key.h b/key.h
    index ec5ac5e..8b5c565 100644
    a b enum types { 
    4444        KEY_ECDSA_CERT,
    4545        KEY_RSA_CERT_V00,
    4646        KEY_DSA_CERT_V00,
     47        KEY_NULL,
    4748        KEY_UNSPEC
    4849};
    4950enum fp_type {
  • monitor.c

    diff --git a/monitor.c b/monitor.c
    index a166fed..2d46b7b 100644
    a b int mm_answer_gss_setup_ctx(int, Buffer *); 
    180180int mm_answer_gss_accept_ctx(int, Buffer *);
    181181int mm_answer_gss_userok(int, Buffer *);
    182182int mm_answer_gss_checkmic(int, Buffer *);
     183int mm_answer_gss_sign(int, Buffer *);
     184int mm_answer_gss_updatecreds(int, Buffer *);
    183185#endif
    184186
    185187#ifdef SSH_AUDIT_EVENTS
    struct mon_table mon_dispatch_proto20[] = { 
    251253    {MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx},
    252254    {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok},
    253255    {MONITOR_REQ_GSSCHECKMIC, MON_ISAUTH, mm_answer_gss_checkmic},
     256    {MONITOR_REQ_GSSSIGN, MON_ONCE, mm_answer_gss_sign},
    254257#endif
    255258#ifdef JPAKE
    256259    {MONITOR_REQ_JPAKE_GET_PWDATA, MON_ONCE, mm_answer_jpake_get_pwdata},
    struct mon_table mon_dispatch_proto20[] = { 
    263266};
    264267
    265268struct mon_table mon_dispatch_postauth20[] = {
     269#ifdef GSSAPI
     270    {MONITOR_REQ_GSSSETUP, 0, mm_answer_gss_setup_ctx},
     271    {MONITOR_REQ_GSSSTEP, 0, mm_answer_gss_accept_ctx},
     272    {MONITOR_REQ_GSSSIGN, 0, mm_answer_gss_sign},
     273    {MONITOR_REQ_GSSUPCREDS, 0, mm_answer_gss_updatecreds},
     274#endif
    266275    {MONITOR_REQ_MODULI, 0, mm_answer_moduli},
    267276    {MONITOR_REQ_SIGN, 0, mm_answer_sign},
    268277    {MONITOR_REQ_PTY, 0, mm_answer_pty},
    monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) 
    371380                /* Permit requests for moduli and signatures */
    372381                monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
    373382                monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
     383#ifdef GSSAPI
     384                /* and for the GSSAPI key exchange */
     385                monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1);
     386#endif
    374387        } else {
    375388                mon_dispatch = mon_dispatch_proto15;
    376389
    monitor_child_postauth(struct monitor *pmonitor) 
    468481                monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
    469482                monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
    470483                monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
     484#ifdef GSSAPI
     485                /* and for the GSSAPI key exchange */
     486                monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1);
     487#endif         
    471488        } else {
    472489                mon_dispatch = mon_dispatch_postauth15;
    473490                monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
    mm_get_kex(Buffer *m) 
    18021819        kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
    18031820        kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
    18041821        kex->kex[KEX_ECDH_SHA2] = kexecdh_server;
     1822#ifdef GSSAPI
     1823        if (options.gss_keyex) {
     1824                kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server;
     1825                kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server;
     1826                kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server;
     1827        }
     1828#endif
    18051829        kex->server = 1;
    18061830        kex->hostkey_type = buffer_get_int(m);
    18071831        kex->kex_type = buffer_get_int(m);
    mm_answer_gss_setup_ctx(int sock, Buffer *m) 
    20082032        OM_uint32 major;
    20092033        u_int len;
    20102034
     2035        if (!options.gss_authentication && !options.gss_keyex)
     2036                fatal("In GSSAPI monitor when GSSAPI is disabled");
     2037
    20112038        goid.elements = buffer_get_string(m, &len);
    20122039        goid.length = len;
    20132040
    mm_answer_gss_accept_ctx(int sock, Buffer *m) 
    20352062        OM_uint32 flags = 0; /* GSI needs this */
    20362063        u_int len;
    20372064
     2065        if (!options.gss_authentication && !options.gss_keyex)
     2066                fatal("In GSSAPI monitor when GSSAPI is disabled");
     2067
    20382068        in.value = buffer_get_string(m, &len);
    20392069        in.length = len;
    20402070        major = ssh_gssapi_accept_ctx(gsscontext, &in, &out, &flags);
    mm_answer_gss_accept_ctx(int sock, Buffer *m) 
    20522082                monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0);
    20532083                monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1);
    20542084                monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1);
     2085                monitor_permit(mon_dispatch, MONITOR_REQ_GSSSIGN, 1);
    20552086        }
    20562087        return (0);
    20572088}
    mm_answer_gss_checkmic(int sock, Buffer *m) 
    20632094        OM_uint32 ret;
    20642095        u_int len;
    20652096
     2097        if (!options.gss_authentication && !options.gss_keyex)
     2098                fatal("In GSSAPI monitor when GSSAPI is disabled");
     2099
    20662100        gssbuf.value = buffer_get_string(m, &len);
    20672101        gssbuf.length = len;
    20682102        mic.value = buffer_get_string(m, &len);
    mm_answer_gss_userok(int sock, Buffer *m) 
    20892123{
    20902124        int authenticated;
    20912125
    2092         authenticated = authctxt->valid && ssh_gssapi_userok(authctxt->user);
     2126        if (!options.gss_authentication && !options.gss_keyex)
     2127                fatal("In GSSAPI monitor when GSSAPI is disabled");
     2128
     2129        authenticated = authctxt->valid &&
     2130            ssh_gssapi_userok(authctxt->user, authctxt->pw);
    20932131
    20942132        buffer_clear(m);
    20952133        buffer_put_int(m, authenticated);
    mm_answer_gss_userok(int sock, Buffer *m) 
    21022140        /* Monitor loop will terminate if authenticated */
    21032141        return (authenticated);
    21042142}
     2143
     2144int
     2145mm_answer_gss_sign(int socket, Buffer *m)
     2146{
     2147        gss_buffer_desc data;
     2148        gss_buffer_desc hash = GSS_C_EMPTY_BUFFER;
     2149        OM_uint32 major, minor;
     2150        u_int len;
     2151
     2152        if (!options.gss_authentication && !options.gss_keyex)
     2153                fatal("In GSSAPI monitor when GSSAPI is disabled");
     2154
     2155        data.value = buffer_get_string(m, &len);
     2156        data.length = len;
     2157        if (data.length != 20)
     2158                fatal("%s: data length incorrect: %d", __func__,
     2159                    (int) data.length);
     2160
     2161        /* Save the session ID on the first time around */
     2162        if (session_id2_len == 0) {
     2163                session_id2_len = data.length;
     2164                session_id2 = xmalloc(session_id2_len);
     2165                memcpy(session_id2, data.value, session_id2_len);
     2166        }
     2167        major = ssh_gssapi_sign(gsscontext, &data, &hash);
     2168
     2169        xfree(data.value);
     2170
     2171        buffer_clear(m);
     2172        buffer_put_int(m, major);
     2173        buffer_put_string(m, hash.value, hash.length);
     2174
     2175        mm_request_send(socket, MONITOR_ANS_GSSSIGN, m);
     2176
     2177        gss_release_buffer(&minor, &hash);
     2178
     2179        /* Turn on getpwnam permissions */
     2180        monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1);
     2181       
     2182        /* And credential updating, for when rekeying */
     2183        monitor_permit(mon_dispatch, MONITOR_REQ_GSSUPCREDS, 1);
     2184
     2185        return (0);
     2186}
     2187
     2188int
     2189mm_answer_gss_updatecreds(int socket, Buffer *m) {
     2190        ssh_gssapi_ccache store;
     2191        int ok;
     2192
     2193        store.filename = buffer_get_string(m, NULL);
     2194        store.envvar   = buffer_get_string(m, NULL);
     2195        store.envval   = buffer_get_string(m, NULL);
     2196
     2197        ok = ssh_gssapi_update_creds(&store);
     2198
     2199        xfree(store.filename);
     2200        xfree(store.envvar);
     2201        xfree(store.envval);
     2202
     2203        buffer_clear(m);
     2204        buffer_put_int(m, ok);
     2205
     2206        mm_request_send(socket, MONITOR_ANS_GSSUPCREDS, m);
     2207
     2208        return(0);
     2209}
     2210
    21052211#endif /* GSSAPI */
    21062212
    21072213#ifdef JPAKE
  • monitor.h

    diff --git a/monitor.h b/monitor.h
    index 5e7d552..db0443f 100644
    a b enum monitor_reqtype { 
    5353        MONITOR_REQ_GSSSTEP, MONITOR_ANS_GSSSTEP,
    5454        MONITOR_REQ_GSSUSEROK, MONITOR_ANS_GSSUSEROK,
    5555        MONITOR_REQ_GSSCHECKMIC, MONITOR_ANS_GSSCHECKMIC,
     56        MONITOR_REQ_GSSSIGN, MONITOR_ANS_GSSSIGN,
     57        MONITOR_REQ_GSSUPCREDS, MONITOR_ANS_GSSUPCREDS,
    5658        MONITOR_REQ_PAM_START,
    5759        MONITOR_REQ_PAM_ACCOUNT, MONITOR_ANS_PAM_ACCOUNT,
    5860        MONITOR_REQ_PAM_INIT_CTX, MONITOR_ANS_PAM_INIT_CTX,
  • monitor_wrap.c

    diff --git a/monitor_wrap.c b/monitor_wrap.c
    index 1f60658..fc6bbcd 100644
    a b mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) 
    12701270}
    12711271
    12721272int
    1273 mm_ssh_gssapi_userok(char *user)
     1273mm_ssh_gssapi_userok(char *user, struct passwd *pw)
    12741274{
    12751275        Buffer m;
    12761276        int authenticated = 0;
    mm_ssh_gssapi_userok(char *user) 
    12871287        debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not ");
    12881288        return (authenticated);
    12891289}
     1290
     1291OM_uint32
     1292mm_ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_desc *data, gss_buffer_desc *hash)
     1293{
     1294        Buffer m;
     1295        OM_uint32 major;
     1296        u_int len;
     1297
     1298        buffer_init(&m);
     1299        buffer_put_string(&m, data->value, data->length);
     1300
     1301        mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSIGN, &m);
     1302        mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSIGN, &m);
     1303
     1304        major = buffer_get_int(&m);
     1305        hash->value = buffer_get_string(&m, &len);
     1306        hash->length = len;
     1307
     1308        buffer_free(&m);
     1309
     1310        return(major);
     1311}
     1312
     1313int
     1314mm_ssh_gssapi_update_creds(ssh_gssapi_ccache *store)
     1315{
     1316        Buffer m;
     1317        int ok;
     1318
     1319        buffer_init(&m);
     1320
     1321        buffer_put_cstring(&m, store->filename ? store->filename : "");
     1322        buffer_put_cstring(&m, store->envvar ? store->envvar : "");
     1323        buffer_put_cstring(&m, store->envval ? store->envval : "");
     1324       
     1325        mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUPCREDS, &m);
     1326        mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSUPCREDS, &m);
     1327
     1328        ok = buffer_get_int(&m);
     1329
     1330        buffer_free(&m);
     1331       
     1332        return (ok);
     1333}
     1334
    12901335#endif /* GSSAPI */
    12911336
    12921337#ifdef JPAKE
  • monitor_wrap.h

    diff --git a/monitor_wrap.h b/monitor_wrap.h
    index 0c7f2e3..ec9b9b1 100644
    a b BIGNUM *mm_auth_rsa_generate_challenge(Key *); 
    5858OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **, gss_OID);
    5959OM_uint32 mm_ssh_gssapi_accept_ctx(Gssctxt *,
    6060   gss_buffer_desc *, gss_buffer_desc *, OM_uint32 *);
    61 int mm_ssh_gssapi_userok(char *user);
     61int mm_ssh_gssapi_userok(char *user, struct passwd *);
    6262OM_uint32 mm_ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);
     63OM_uint32 mm_ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t);
     64int mm_ssh_gssapi_update_creds(ssh_gssapi_ccache *);
    6365#endif
    6466
    6567#ifdef USE_PAM
  • readconf.c

    diff --git a/readconf.c b/readconf.c
    index 91dfa56..60befde 100644
    a b typedef enum { 
    129129        oClearAllForwardings, oNoHostAuthenticationForLocalhost,
    130130        oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
    131131        oAddressFamily, oGssAuthentication, oGssDelegateCreds,
     132        oGssTrustDns, oGssKeyEx, oGssClientIdentity, oGssRenewalRekey,
     133        oGssServerIdentity,
    132134        oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
    133135        oSendEnv, oControlPath, oControlMaster, oControlPersist,
    134136        oHashKnownHosts,
    static struct { 
    169171        { "afstokenpassing", oUnsupported },
    170172#if defined(GSSAPI)
    171173        { "gssapiauthentication", oGssAuthentication },
     174        { "gssapikeyexchange", oGssKeyEx },
    172175        { "gssapidelegatecredentials", oGssDelegateCreds },
     176        { "gssapitrustdns", oGssTrustDns },
     177        { "gssapiclientidentity", oGssClientIdentity },
     178        { "gssapiserveridentity", oGssServerIdentity },
     179        { "gssapirenewalforcesrekey", oGssRenewalRekey },
    173180#else
    174181        { "gssapiauthentication", oUnsupported },
     182        { "gssapikeyexchange", oUnsupported },
    175183        { "gssapidelegatecredentials", oUnsupported },
     184        { "gssapitrustdns", oUnsupported },
     185        { "gssapiclientidentity", oUnsupported },
     186        { "gssapirenewalforcesrekey", oUnsupported },
    176187#endif
    177188        { "fallbacktorsh", oDeprecated },
    178189        { "usersh", oDeprecated },
    parse_flag: 
    482493                intptr = &options->gss_authentication;
    483494                goto parse_flag;
    484495
     496        case oGssKeyEx:
     497                intptr = &options->gss_keyex;
     498                goto parse_flag;
     499
    485500        case oGssDelegateCreds:
    486501                intptr = &options->gss_deleg_creds;
    487502                goto parse_flag;
    488503
     504        case oGssTrustDns:
     505                intptr = &options->gss_trust_dns;
     506                goto parse_flag;
     507
     508        case oGssClientIdentity:
     509                charptr = &options->gss_client_identity;
     510                goto parse_string;
     511
     512        case oGssServerIdentity:
     513                charptr = &options->gss_server_identity;
     514                goto parse_string;
     515
     516        case oGssRenewalRekey:
     517                intptr = &options->gss_renewal_rekey;
     518                goto parse_flag;
     519
    489520        case oBatchMode:
    490521                intptr = &options->batch_mode;
    491522                goto parse_flag;
    initialize_options(Options * options) 
    11381169        options->pubkey_authentication = -1;
    11391170        options->challenge_response_authentication = -1;
    11401171        options->gss_authentication = -1;
     1172        options->gss_keyex = -1;
    11411173        options->gss_deleg_creds = -1;
     1174        options->gss_trust_dns = -1;
     1175        options->gss_renewal_rekey = -1;
     1176        options->gss_client_identity = NULL;
     1177        options->gss_server_identity = NULL;
    11421178        options->password_authentication = -1;
    11431179        options->kbd_interactive_authentication = -1;
    11441180        options->kbd_interactive_devices = NULL;
    fill_default_options(Options * options) 
    12381274                options->challenge_response_authentication = 1;
    12391275        if (options->gss_authentication == -1)
    12401276                options->gss_authentication = 0;
     1277        if (options->gss_keyex == -1)
     1278                options->gss_keyex = 0;
    12411279        if (options->gss_deleg_creds == -1)
    12421280                options->gss_deleg_creds = 0;
     1281        if (options->gss_trust_dns == -1)
     1282                options->gss_trust_dns = 0;
     1283        if (options->gss_renewal_rekey == -1)
     1284                options->gss_renewal_rekey = 0;
    12431285        if (options->password_authentication == -1)
    12441286                options->password_authentication = 1;
    12451287        if (options->kbd_interactive_authentication == -1)
  • readconf.h

    diff --git a/readconf.h b/readconf.h
    index 5944cff..617686f 100644
    a b typedef struct { 
    4747        int     challenge_response_authentication;
    4848                                        /* Try S/Key or TIS, authentication. */
    4949        int     gss_authentication;     /* Try GSS authentication */
     50        int     gss_keyex;              /* Try GSS key exchange */
    5051        int     gss_deleg_creds;        /* Delegate GSS credentials */
     52        int     gss_trust_dns;          /* Trust DNS for GSS canonicalization */
     53        int     gss_renewal_rekey;      /* Credential renewal forces rekey */
     54        char    *gss_client_identity;   /* Principal to initiate GSSAPI with */
     55        char    *gss_server_identity;   /* GSSAPI target principal */
    5156        int     password_authentication;        /* Try password
    5257                                                 * authentication. */
    5358        int     kbd_interactive_authentication; /* Try keyboard-interactive auth. */
  • servconf.c

    diff --git a/servconf.c b/servconf.c
    index 91986e5..756a3a2 100644
    a b initialize_server_options(ServerOptions *options) 
    9797        options->kerberos_ticket_cleanup = -1;
    9898        options->kerberos_get_afs_token = -1;
    9999        options->gss_authentication=-1;
     100        options->gss_keyex = -1;
    100101        options->gss_cleanup_creds = -1;
     102        options->gss_strict_acceptor = -1;
     103        options->gss_store_rekey = -1;
    101104        options->password_authentication = -1;
    102105        options->kbd_interactive_authentication = -1;
    103106        options->challenge_response_authentication = -1;
    fill_default_server_options(ServerOptions *options) 
    225228                options->kerberos_get_afs_token = 0;
    226229        if (options->gss_authentication == -1)
    227230                options->gss_authentication = 0;
     231        if (options->gss_keyex == -1)
     232                options->gss_keyex = 0;
    228233        if (options->gss_cleanup_creds == -1)
    229234                options->gss_cleanup_creds = 1;
     235        if (options->gss_strict_acceptor == -1)
     236                options->gss_strict_acceptor = 1;
     237        if (options->gss_store_rekey == -1)
     238                options->gss_store_rekey = 0;
    230239        if (options->password_authentication == -1)
    231240                options->password_authentication = 1;
    232241        if (options->kbd_interactive_authentication == -1)
    typedef enum { 
    318327        sBanner, sUseDNS, sHostbasedAuthentication,
    319328        sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
    320329        sClientAliveCountMax, sAuthorizedKeysFile,
    321         sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel,
     330        sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor,
     331        sGssKeyEx, sGssStoreRekey,
     332        sAcceptEnv, sPermitTunnel,
    322333        sMatch, sPermitOpen, sForceCommand, sChrootDirectory,
    323334        sUsePrivilegeSeparation, sAllowAgentForwarding,
    324335        sZeroKnowledgePasswordAuthentication, sHostCertificate,
    static struct { 
    382393#ifdef GSSAPI
    383394        { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL },
    384395        { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL },
     396        { "gssapicleanupcreds", sGssCleanupCreds, SSHCFG_GLOBAL },
     397        { "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL },
     398        { "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL },
     399        { "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL },
    385400#else
    386401        { "gssapiauthentication", sUnsupported, SSHCFG_ALL },
    387402        { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
     403        { "gssapicleanupcreds", sUnsupported, SSHCFG_GLOBAL },
     404        { "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL },
     405        { "gssapikeyexchange", sUnsupported, SSHCFG_GLOBAL },
     406        { "gssapistorecredentialsonrekey", sUnsupported, SSHCFG_GLOBAL },
    388407#endif
     408        { "gssusesessionccache", sUnsupported, SSHCFG_GLOBAL },
     409        { "gssapiusesessioncredcache", sUnsupported, SSHCFG_GLOBAL },
    389410        { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL },
    390411        { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL },
    391412        { "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL },
    process_server_config_line(ServerOptions *options, char *line, 
    962983                intptr = &options->gss_authentication;
    963984                goto parse_flag;
    964985
     986        case sGssKeyEx:
     987                intptr = &options->gss_keyex;
     988                goto parse_flag;
     989
    965990        case sGssCleanupCreds:
    966991                intptr = &options->gss_cleanup_creds;
    967992                goto parse_flag;
    968993
     994        case sGssStrictAcceptor:
     995                intptr = &options->gss_strict_acceptor;
     996                goto parse_flag;
     997
     998        case sGssStoreRekey:
     999                intptr = &options->gss_store_rekey;
     1000                goto parse_flag;
     1001
    9691002        case sPasswordAuthentication:
    9701003                intptr = &options->password_authentication;
    9711004                goto parse_flag;
    dump_config(ServerOptions *o) 
    17201753#endif
    17211754#ifdef GSSAPI
    17221755        dump_cfg_fmtint(sGssAuthentication, o->gss_authentication);
     1756        dump_cfg_fmtint(sGssKeyEx, o->gss_keyex);
    17231757        dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds);
     1758        dump_cfg_fmtint(sGssStrictAcceptor, o->gss_strict_acceptor);
     1759        dump_cfg_fmtint(sGssStoreRekey, o->gss_store_rekey);
    17241760#endif
    17251761#ifdef JPAKE
    17261762        dump_cfg_fmtint(sZeroKnowledgePasswordAuthentication,
  • servconf.h

    diff --git a/servconf.h b/servconf.h
    index 89f38e2..a434c6f 100644
    a b typedef struct { 
    103103        int     kerberos_get_afs_token;         /* If true, try to get AFS token if
    104104                                                 * authenticated with Kerberos. */
    105105        int     gss_authentication;     /* If true, permit GSSAPI authentication */
     106        int     gss_keyex;              /* If true, permit GSSAPI key exchange */
    106107        int     gss_cleanup_creds;      /* If true, destroy cred cache on logout */
     108        int     gss_strict_acceptor;    /* If true, restrict the GSSAPI acceptor name */
     109        int     gss_store_rekey;
    107110        int     password_authentication;        /* If true, permit password
    108111                                                 * authentication. */
    109112        int     kbd_interactive_authentication; /* If true, permit */
  • ssh-gss.h

    diff --git a/ssh-gss.h b/ssh-gss.h
    index c29a1b7..31d5a08 100644
    a b  
    11/* $OpenBSD: ssh-gss.h,v 1.10 2007/06/12 08:20:00 djm Exp $ */
    22/*
    3  * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
     3 * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved.
    44 *
    55 * Redistribution and use in source and binary forms, with or without
    66 * modification, are permitted provided that the following conditions
     
    6060
    6161#define SSH_GSS_OIDTYPE 0x06
    6262
     63#define SSH2_MSG_KEXGSS_INIT                            30
     64#define SSH2_MSG_KEXGSS_CONTINUE                        31
     65#define SSH2_MSG_KEXGSS_COMPLETE                        32
     66#define SSH2_MSG_KEXGSS_HOSTKEY                         33
     67#define SSH2_MSG_KEXGSS_ERROR                           34
     68#define SSH2_MSG_KEXGSS_GROUPREQ                        40
     69#define SSH2_MSG_KEXGSS_GROUP                           41
     70#define KEX_GSS_GRP1_SHA1_ID                            "gss-group1-sha1-"
     71#define KEX_GSS_GRP14_SHA1_ID                           "gss-group14-sha1-"
     72#define KEX_GSS_GEX_SHA1_ID                             "gss-gex-sha1-"
     73
    6374typedef struct {
    6475        char *filename;
    6576        char *envvar;
    6677        char *envval;
     78        struct passwd *owner;
    6779        void *data;
    6880} ssh_gssapi_ccache;
    6981
    typedef struct { 
    7183        gss_buffer_desc displayname;
    7284        gss_buffer_desc exportedname;
    7385        gss_cred_id_t creds;
     86        gss_name_t name;
    7487        struct ssh_gssapi_mech_struct *mech;
    7588        ssh_gssapi_ccache store;
     89        int used;
     90        int updated;
    7691} ssh_gssapi_client;
    7792
    7893typedef struct ssh_gssapi_mech_struct {
    typedef struct ssh_gssapi_mech_struct { 
    8398        int (*userok) (ssh_gssapi_client *, char *);
    8499        int (*localname) (ssh_gssapi_client *, char **);
    85100        void (*storecreds) (ssh_gssapi_client *);
     101        int (*updatecreds) (ssh_gssapi_ccache *, ssh_gssapi_client *);
    86102} ssh_gssapi_mech;
    87103
    88104typedef struct {
    typedef struct { 
    93109        gss_OID         oid; /* client */
    94110        gss_cred_id_t   creds; /* server */
    95111        gss_name_t      client; /* server */
    96         gss_cred_id_t   client_creds; /* server */
     112        gss_cred_id_t   client_creds; /* both */
    97113} Gssctxt;
    98114
    99115extern ssh_gssapi_mech *supported_mechs[];
     116extern Gssctxt *gss_kex_context;
    100117
    101118int  ssh_gssapi_check_oid(Gssctxt *, void *, size_t);
    102119void ssh_gssapi_set_oid_data(Gssctxt *, void *, size_t);
    void ssh_gssapi_build_ctx(Gssctxt **); 
    116133void ssh_gssapi_delete_ctx(Gssctxt **);
    117134OM_uint32 ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t);
    118135void ssh_gssapi_buildmic(Buffer *, const char *, const char *, const char *);
    119 int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *);
     136int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *, const char *);
     137OM_uint32 ssh_gssapi_client_identity(Gssctxt *, const char *);
     138int ssh_gssapi_credentials_updated(Gssctxt *);
    120139
    121140/* In the server */
     141typedef int ssh_gssapi_check_fn(Gssctxt **, gss_OID, const char *,
     142    const char *);
     143char *ssh_gssapi_client_mechanisms(const char *, const char *);
     144char *ssh_gssapi_kex_mechs(gss_OID_set, ssh_gssapi_check_fn *, const char *,
     145    const char *);
     146gss_OID ssh_gssapi_id_kex(Gssctxt *, char *, int);
     147int ssh_gssapi_server_check_mech(Gssctxt **,gss_OID, const char *,
     148    const char *);
    122149OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID);
    123 int ssh_gssapi_userok(char *name);
     150int ssh_gssapi_userok(char *name, struct passwd *);
    124151OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);
    125152void ssh_gssapi_do_child(char ***, u_int *);
    126153void ssh_gssapi_cleanup_creds(void);
    127154void ssh_gssapi_storecreds(void);
    128155
     156char *ssh_gssapi_server_mechanisms(void);
     157int ssh_gssapi_oid_table_ok();
     158
     159int ssh_gssapi_update_creds(ssh_gssapi_ccache *store);
    129160#endif /* GSSAPI */
    130161
    131162#endif /* _SSH_GSS_H */
  • ssh_config

    diff --git a/ssh_config b/ssh_config
    index 1893674..2c06ba7 100644
    a b  
    2626#   HostbasedAuthentication no
    2727#   GSSAPIAuthentication no
    2828#   GSSAPIDelegateCredentials no
     29#   GSSAPIKeyExchange no
     30#   GSSAPITrustDNS no
    2931#   BatchMode no
    3032#   CheckHostIP yes
    3133#   AddressFamily any
  • ssh_config.5

    diff --git a/ssh_config.5 b/ssh_config.5
    index a782d6f..9e1e9a6 100644
    a b Specifies whether user authentication based on GSSAPI is allowed. 
    527527The default is
    528528.Dq no .
    529529Note that this option applies to protocol version 2 only.
     530.It Cm GSSAPIKeyExchange
     531Specifies whether key exchange based on GSSAPI may be used. When using
     532GSSAPI key exchange the server need not have a host key.
     533The default is
     534.Dq no .
     535Note that this option applies to protocol version 2 only.
     536.It Cm GSSAPIClientIdentity
     537If set, specifies the GSSAPI client identity that ssh should use when
     538connecting to the server. The default is unset, which means that the default
     539identity will be used.
     540.It Cm GSSAPIServerIdentity
     541If set, specifies the GSSAPI server identity that ssh should expect when
     542connecting to the server. The default is unset, which means that the
     543expected GSSAPI server identity will be determined from the target
     544hostname.
    530545.It Cm GSSAPIDelegateCredentials
    531546Forward (delegate) credentials to the server.
    532547The default is
    533548.Dq no .
    534 Note that this option applies to protocol version 2 only.
     549Note that this option applies to protocol version 2 connections using GSSAPI.
     550.It Cm GSSAPIRenewalForcesRekey
     551If set to
     552.Dq yes
     553then renewal of the client's GSSAPI credentials will force the rekeying of the
     554ssh connection. With a compatible server, this can delegate the renewed
     555credentials to a session on the server.
     556The default is
     557.Dq no .
     558.It Cm GSSAPITrustDns
     559Set to
     560.Dq yes to indicate that the DNS is trusted to securely canonicalize
     561the name of the host being connected to. If
     562.Dq no, the hostname entered on the
     563command line will be passed untouched to the GSSAPI library.
     564The default is
     565.Dq no .
     566This option only applies to protocol version 2 connections using GSSAPI.
    535567.It Cm HashKnownHosts
    536568Indicates that
    537569.Xr ssh 1
  • sshconnect2.c

    diff --git a/sshconnect2.c b/sshconnect2.c
    index c24b202..3ddef32 100644
    a b ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) 
    160160{
    161161        Kex *kex;
    162162
     163#ifdef GSSAPI
     164        char *orig = NULL, *gss = NULL;
     165        char *gss_host = NULL;
     166#endif
     167
    163168        xxx_host = host;
    164169        xxx_hostaddr = hostaddr;
    165170
     171#ifdef GSSAPI
     172        if (options.gss_keyex) {
     173                /* Add the GSSAPI mechanisms currently supported on this
     174                 * client to the key exchange algorithm proposal */
     175                orig = myproposal[PROPOSAL_KEX_ALGS];
     176
     177                if (options.gss_trust_dns)
     178                        gss_host = (char *)get_canonical_hostname(1);
     179                else
     180                        gss_host = host;
     181
     182                gss = ssh_gssapi_client_mechanisms(gss_host, options.gss_client_identity);
     183                if (gss) {
     184                        debug("Offering GSSAPI proposal: %s", gss);
     185                        xasprintf(&myproposal[PROPOSAL_KEX_ALGS],
     186                            "%s,%s", gss, orig);
     187                }
     188        }
     189#endif
     190
    166191        if (options.ciphers == (char *)-1) {
    167192                logit("No valid ciphers for protocol version 2 given, using defaults.");
    168193                options.ciphers = NULL;
    ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) 
    197222        if (options.kex_algorithms != NULL)
    198223                myproposal[PROPOSAL_KEX_ALGS] = options.kex_algorithms;
    199224
     225#ifdef GSSAPI
     226        /* If we've got GSSAPI algorithms, then we also support the
     227         * 'null' hostkey, as a last resort */
     228        if (options.gss_keyex && gss) {
     229                orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS];
     230                xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS],
     231                    "%s,null", orig);
     232                xfree(gss);
     233        }
     234#endif
     235
    200236        if (options.rekey_limit)
    201237                packet_set_rekey_limit((u_int32_t)options.rekey_limit);
    202238
    ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) 
    207243        kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
    208244        kex->kex[KEX_DH_GEX_SHA256] = kexgex_client;
    209245        kex->kex[KEX_ECDH_SHA2] = kexecdh_client;
     246#ifdef GSSAPI
     247        if (options.gss_keyex) {
     248                kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client;
     249                kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_client;
     250                kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client;
     251        }
     252#endif
    210253        kex->client_version_string=client_version_string;
    211254        kex->server_version_string=server_version_string;
    212255        kex->verify_host_key=&verify_host_key_callback;
    213256
     257#ifdef GSSAPI
     258        if (options.gss_keyex) {
     259                kex->gss_deleg_creds = options.gss_deleg_creds;
     260                kex->gss_trust_dns = options.gss_trust_dns;
     261                kex->gss_client = options.gss_client_identity;
     262                if (options.gss_server_identity) {
     263                        kex->gss_host = options.gss_server_identity;
     264                } else {
     265                        kex->gss_host = gss_host;
     266        }
     267        }
     268#endif
     269
    214270        xxx_kex = kex;
    215271
    216272        dispatch_run(DISPATCH_BLOCK, &kex->done, kex);
    void input_gssapi_token(int type, u_int32_t, void *); 
    305361void    input_gssapi_hash(int type, u_int32_t, void *);
    306362void    input_gssapi_error(int, u_int32_t, void *);
    307363void    input_gssapi_errtok(int, u_int32_t, void *);
     364int     userauth_gsskeyex(Authctxt *authctxt);
    308365#endif
    309366
    310367void    userauth(Authctxt *, char *);
    static char *authmethods_get(void); 
    320377
    321378Authmethod authmethods[] = {
    322379#ifdef GSSAPI
     380        {"gssapi-keyex",
     381                userauth_gsskeyex,
     382                NULL,
     383                &options.gss_authentication,
     384                NULL},
    323385        {"gssapi-with-mic",
    324386                userauth_gssapi,
    325387                NULL,
    userauth_gssapi(Authctxt *authctxt) 
    626688        static u_int mech = 0;
    627689        OM_uint32 min;
    628690        int ok = 0;
     691        const char *gss_host;
     692
     693        if (options.gss_server_identity)
     694                gss_host = options.gss_server_identity;
     695        else if (options.gss_trust_dns)
     696                gss_host = get_canonical_hostname(1);
     697        else
     698                gss_host = authctxt->host;
    629699
    630700        /* Try one GSSAPI method at a time, rather than sending them all at
    631701         * once. */
    632702
    633703        if (gss_supported == NULL)
    634                 gss_indicate_mechs(&min, &gss_supported);
     704                if (GSS_ERROR(gss_indicate_mechs(&min, &gss_supported))) {
     705                        gss_supported = NULL;
     706                        return 0;
     707                }
    635708
    636709        /* Check to see if the mechanism is usable before we offer it */
    637710        while (mech < gss_supported->count && !ok) {
    638711                /* My DER encoding requires length<128 */
    639712                if (gss_supported->elements[mech].length < 128 &&
    640713                    ssh_gssapi_check_mechanism(&gssctxt,
    641                     &gss_supported->elements[mech], authctxt->host)) {
     714                    &gss_supported->elements[mech], gss_host,
     715                    options.gss_client_identity)) {
    642716                        ok = 1; /* Mechanism works */
    643717                } else {
    644718                        mech++;
    input_gssapi_response(int type, u_int32_t plen, void *ctxt) 
    735809{
    736810        Authctxt *authctxt = ctxt;
    737811        Gssctxt *gssctxt;
    738         int oidlen;
    739         char *oidv;
     812        u_int oidlen;
     813        u_char *oidv;
    740814
    741815        if (authctxt == NULL)
    742816                fatal("input_gssapi_response: no authentication context");
    input_gssapi_error(int type, u_int32_t plen, void *ctxt) 
    846920        xfree(msg);
    847921        xfree(lang);
    848922}
     923
     924int
     925userauth_gsskeyex(Authctxt *authctxt)
     926{
     927        Buffer b;
     928        gss_buffer_desc gssbuf;
     929        gss_buffer_desc mic = GSS_C_EMPTY_BUFFER;
     930        OM_uint32 ms;
     931
     932        static int attempt = 0;
     933        if (attempt++ >= 1)
     934                return (0);
     935
     936        if (gss_kex_context == NULL) {
     937                debug("No valid Key exchange context");
     938                return (0);
     939        }
     940
     941        ssh_gssapi_buildmic(&b, authctxt->server_user, authctxt->service,
     942            "gssapi-keyex");
     943
     944        gssbuf.value = buffer_ptr(&b);
     945        gssbuf.length = buffer_len(&b);
     946
     947        if (GSS_ERROR(ssh_gssapi_sign(gss_kex_context, &gssbuf, &mic))) {
     948                buffer_free(&b);
     949                return (0);
     950        }
     951
     952        packet_start(SSH2_MSG_USERAUTH_REQUEST);
     953        packet_put_cstring(authctxt->server_user);
     954        packet_put_cstring(authctxt->service);
     955        packet_put_cstring(authctxt->method->name);
     956        packet_put_string(mic.value, mic.length);
     957        packet_send();
     958
     959        buffer_free(&b);
     960        gss_release_buffer(&ms, &mic);
     961
     962        return (1);
     963}
     964
    849965#endif /* GSSAPI */
    850966
    851967int
  • sshd.c

    diff --git a/sshd.c b/sshd.c
    index cc10395..112a5f9 100644
    a b  
    121121#include "ssh-sandbox.h"
    122122#include "version.h"
    123123
     124#ifdef USE_SECURITY_SESSION_API
     125#include <Security/AuthSession.h>
     126#endif
     127
    124128#ifdef LIBWRAP
    125129#include <tcpd.h>
    126130#include <syslog.h>
    main(int ac, char **av) 
    16121616                logit("Disabling protocol version 1. Could not load host key");
    16131617                options.protocol &= ~SSH_PROTO_1;
    16141618        }
     1619#ifndef GSSAPI
     1620        /* The GSSAPI key exchange can run without a host key */
    16151621        if ((options.protocol & SSH_PROTO_2) && !sensitive_data.have_ssh2_key) {
    16161622                logit("Disabling protocol version 2. Could not load host key");
    16171623                options.protocol &= ~SSH_PROTO_2;
    16181624        }
     1625#endif
    16191626        if (!(options.protocol & (SSH_PROTO_1|SSH_PROTO_2))) {
    16201627                logit("sshd: no hostkeys available -- exiting.");
    16211628                exit(1);
    main(int ac, char **av) 
    19441951        /* Log the connection. */
    19451952        verbose("Connection from %.500s port %d", remote_ip, remote_port);
    19461953
     1954#ifdef USE_SECURITY_SESSION_API
     1955        /*
     1956         * Create a new security session for use by the new user login if
     1957         * the current session is the root session or we are not launched
     1958         * by inetd (eg: debugging mode or server mode).  We do not
     1959         * necessarily need to create a session if we are launched from
     1960         * inetd because Panther xinetd will create a session for us.
     1961         *
     1962         * The only case where this logic will fail is if there is an
     1963         * inetd running in a non-root session which is not creating
     1964         * new sessions for us.  Then all the users will end up in the
     1965         * same session (bad).
     1966         *
     1967         * When the client exits, the session will be destroyed for us
     1968         * automatically.
     1969         *
     1970         * We must create the session before any credentials are stored
     1971         * (including AFS pags, which happens a few lines below).
     1972         */
     1973        {
     1974                OSStatus err = 0;
     1975                SecuritySessionId sid = 0;
     1976                SessionAttributeBits sattrs = 0;
     1977
     1978                err = SessionGetInfo(callerSecuritySession, &sid, &sattrs);
     1979                if (err)
     1980                        error("SessionGetInfo() failed with error %.8X",
     1981                            (unsigned) err);
     1982                else
     1983                        debug("Current Session ID is %.8X / Session Attributes are %.8X",
     1984                            (unsigned) sid, (unsigned) sattrs);
     1985
     1986                if (inetd_flag && !(sattrs & sessionIsRoot))
     1987                        debug("Running in inetd mode in a non-root session... "
     1988                            "assuming inetd created the session for us.");
     1989                else {
     1990                        debug("Creating new security session...");
     1991                        err = SessionCreate(0, sessionHasTTY | sessionIsRemote);
     1992                        if (err)
     1993                                error("SessionCreate() failed with error %.8X",
     1994                                    (unsigned) err);
     1995
     1996                        err = SessionGetInfo(callerSecuritySession, &sid,
     1997                            &sattrs);
     1998                        if (err)
     1999                                error("SessionGetInfo() failed with error %.8X",
     2000                                    (unsigned) err);
     2001                        else
     2002                                debug("New Session ID is %.8X / Session Attributes are %.8X",
     2003                                    (unsigned) sid, (unsigned) sattrs);
     2004                }
     2005        }
     2006#endif
     2007
    19472008        /*
    19482009         * We don't want to listen forever unless the other side
    19492010         * successfully authenticates itself.  So we set up an alarm which is
    do_ssh2_kex(void) 
    23252386
    23262387        myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = list_hostkey_types();
    23272388
     2389#ifdef GSSAPI
     2390        {
     2391        char *orig;
     2392        char *gss = NULL;
     2393        char *newstr = NULL;
     2394        orig = myproposal[PROPOSAL_KEX_ALGS];
     2395
     2396        /*
     2397         * If we don't have a host key, then there's no point advertising
     2398         * the other key exchange algorithms
     2399         */
     2400
     2401        if (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]) == 0)
     2402                orig = NULL;
     2403
     2404        if (options.gss_keyex)
     2405                gss = ssh_gssapi_server_mechanisms();
     2406        else
     2407                gss = NULL;
     2408
     2409        if (gss && orig)
     2410                xasprintf(&newstr, "%s,%s", gss, orig);
     2411        else if (gss)
     2412                newstr = gss;
     2413        else if (orig)
     2414                newstr = orig;
     2415
     2416        /*
     2417         * If we've got GSSAPI mechanisms, then we've got the 'null' host
     2418         * key alg, but we can't tell people about it unless its the only
     2419         * host key algorithm we support
     2420         */
     2421        if (gss && (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS])) == 0)
     2422                myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = "null";
     2423
     2424        if (newstr)
     2425                myproposal[PROPOSAL_KEX_ALGS] = newstr;
     2426        else
     2427                fatal("No supported key exchange algorithms");
     2428        }
     2429#endif
     2430
    23282431        /* start key exchange */
    23292432        kex = kex_setup(myproposal);
    23302433        kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
    do_ssh2_kex(void) 
    23322435        kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
    23332436        kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
    23342437        kex->kex[KEX_ECDH_SHA2] = kexecdh_server;
     2438#ifdef GSSAPI
     2439        if (options.gss_keyex) {
     2440                kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server;
     2441                kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server;
     2442                kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server;
     2443        }
     2444#endif
    23352445        kex->server = 1;
    23362446        kex->client_version_string=client_version_string;
    23372447        kex->server_version_string=server_version_string;
  • sshd_config

    diff --git a/sshd_config b/sshd_config
    index 473e866..d02d7a7 100644
    a b AuthorizedKeysFile .ssh/authorized_keys 
    7575# GSSAPI options
    7676#GSSAPIAuthentication no
    7777#GSSAPICleanupCredentials yes
     78#GSSAPIStrictAcceptorCheck yes
     79#GSSAPIKeyExchange no
    7880
    7981# Set this to 'yes' to enable PAM authentication, account processing,
    8082# and session processing. If this is enabled, PAM authentication will
  • sshd_config.5

    diff --git a/sshd_config.5 b/sshd_config.5
    index a6c3787..76c95aa 100644
    a b Specifies whether user authentication based on GSSAPI is allowed. 
    424424The default is
    425425.Dq no .
    426426Note that this option applies to protocol version 2 only.
     427.It Cm GSSAPIKeyExchange
     428Specifies whether key exchange based on GSSAPI is allowed. GSSAPI key exchange
     429doesn't rely on ssh keys to verify host identity.
     430The default is
     431.Dq no .
     432Note that this option applies to protocol version 2 only.
    427433.It Cm GSSAPICleanupCredentials
    428434Specifies whether to automatically destroy the user's credentials cache
    429435on logout.
    430436The default is
    431437.Dq yes .
    432438Note that this option applies to protocol version 2 only.
     439.It Cm GSSAPIStrictAcceptorCheck
     440Determines whether to be strict about the identity of the GSSAPI acceptor
     441a client authenticates against. If
     442.Dq yes
     443then the client must authenticate against the
     444.Pa host
     445service on the current hostname. If
     446.Dq no
     447then the client may authenticate against any service key stored in the
     448machine's default store. This facility is provided to assist with operation
     449on multi homed machines.
     450The default is
     451.Dq yes .
     452Note that this option applies only to protocol version 2 GSSAPI connections,
     453and setting it to
     454.Dq no
     455may only work with recent Kerberos GSSAPI libraries.
     456.It Cm GSSAPIStoreCredentialsOnRekey
     457Controls whether the user's GSSAPI credentials should be updated following a
     458successful connection rekeying. This option can be used to accepted renewed
     459or updated credentials from a compatible client. The default is
     460.Dq no .
    433461.It Cm HostbasedAuthentication
    434462Specifies whether rhosts or /etc/hosts.equiv authentication together
    435463with successful public key client host authentication is allowed