]> andersk Git - gssapi-openssh.git/commitdiff
http://www.sxw.org.uk/computing/patches/openssh-4.3p2-gsskex-20060223.patch committed...
authorjbasney <jbasney>
Tue, 7 Mar 2006 16:39:34 +0000 (16:39 +0000)
committerjbasney <jbasney>
Tue, 7 Mar 2006 16:39:34 +0000 (16:39 +0000)
25 files changed:
openssh/Makefile.in
openssh/auth-krb5.c
openssh/auth.h
openssh/auth2-gss.c
openssh/auth2.c
openssh/configure.ac
openssh/gss-genr.c
openssh/gss-serv.c
openssh/kex.c
openssh/kex.h
openssh/key.c
openssh/key.h
openssh/monitor.c
openssh/monitor.h
openssh/monitor_wrap.c
openssh/monitor_wrap.h
openssh/readconf.c
openssh/readconf.h
openssh/servconf.c
openssh/servconf.h
openssh/ssh-gss.h
openssh/ssh_config.5
openssh/sshconnect2.c
openssh/sshd.c
openssh/sshd_config.5

index 15a165a8fd2a26f48404b7f51ecefe4e2e2aa3a5..221eb1a05c01019753160d747065e3a5f65e6563 100644 (file)
@@ -71,7 +71,7 @@ LIBSSH_OBJS=acss.o authfd.o authfile.o bufaux.o buffer.o \
        atomicio.o key.o dispatch.o kex.o mac.o uidswap.o uuencode.o misc.o \
        monitor_fdpass.o rijndael.o ssh-dss.o ssh-rsa.o dh.o kexdh.o \
        kexgex.o kexdhc.o kexgexc.o scard.o msg.o progressmeter.o dns.o \
-       entropy.o scard-opensc.o gss-genr.o
+       entropy.o scard-opensc.o gss-genr.o kexgssc.o
 
 SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \
        sshconnect.o sshconnect1.o sshconnect2.o
@@ -84,7 +84,7 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \
        auth2-none.o auth2-passwd.o auth2-pubkey.o \
        monitor_mm.o monitor.o monitor_wrap.o kexdhs.o kexgexs.o \
        auth-krb5.o \
-       auth2-gss.o gss-serv.o gss-serv-krb5.o \
+       auth2-gss.o gss-serv.o gss-serv-krb5.o kexgsss.o\
        loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \
        audit.o audit-bsm.o
 
index 64d613543db05d21ae648b71eee936727fd0c777..bc37675a2486879b5ffdbe6e78556cca0dff092d 100644 (file)
@@ -156,8 +156,13 @@ auth_krb5_password(Authctxt *authctxt, const char *password)
 
        len = strlen(authctxt->krb5_ticket_file) + 6;
        authctxt->krb5_ccname = xmalloc(len);
+#ifdef USE_CCAPI
+       snprintf(authctxt->krb5_ccname, len, "API:%s",
+           authctxt->krb5_ticket_file);
+#else
        snprintf(authctxt->krb5_ccname, len, "FILE:%s",
            authctxt->krb5_ticket_file);
+#endif
 
 #ifdef USE_PAM
        if (options.use_pam)
@@ -209,15 +214,22 @@ krb5_cleanup_proc(Authctxt *authctxt)
 #ifndef HEIMDAL
 krb5_error_code
 ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) {
-       int tmpfd, ret;
+       int ret;
        char ccname[40];
        mode_t old_umask;
+#ifdef USE_CCAPI
+       char cctemplate[] = "API:krb5cc_%d";
+#else
+       char cctemplate[] = "FILE:/tmp/krb5cc_%d_XXXXXXXXXX";
+       int tmpfd;
+#endif
 
        ret = snprintf(ccname, sizeof(ccname),
-           "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid());
+           cctemplate, geteuid());
        if (ret < 0 || (size_t)ret >= sizeof(ccname))
                return ENOMEM;
 
+#ifndef USE_CCAPI
        old_umask = umask(0177);
        tmpfd = mkstemp(ccname + strlen("FILE:"));
        umask(old_umask);
@@ -232,6 +244,7 @@ ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) {
                return errno;
        }
        close(tmpfd);
+#endif
 
        return (krb5_cc_resolve(ctx, ccname, ccache));
 }
index 8b814ba6a080fbcece3694078b600c6d68869ec1..456d28f3797d355e8c525248e75a52676bd31e36 100644 (file)
@@ -53,6 +53,7 @@ struct Authctxt {
        int              valid;         /* user exists and is allowed to login */
        int              attempt;
        int              failures;
+       int              server_caused_failure; 
        int              force_pwchange;
        char            *user;          /* username sent by the client */
        char            *service;
index 95844a05e5ba8d5350be05df87adfe0987b888d7..539654ee082ab61e92a9589027e121efee217ee7 100644 (file)
@@ -46,6 +46,39 @@ static void input_gssapi_mic(int type, u_int32_t plen, void *ctxt);
 static void input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt);
 static void input_gssapi_errtok(int, u_int32_t, void *);
 
+/* 
+ * The 'gssapi_keyex' userauth mechanism.
+ */
+static int
+userauth_gsskeyex(Authctxt *authctxt)
+{
+       int authenticated = 0;
+       Buffer b;
+       gss_buffer_desc mic, gssbuf;
+       u_int len;
+
+       mic.value = packet_get_string(&len);
+       mic.length = len;
+
+       packet_check_eom();
+
+       ssh_gssapi_buildmic(&b, authctxt->user, authctxt->service,
+           "gssapi-keyex");
+
+       gssbuf.value = buffer_ptr(&b);
+       gssbuf.length = buffer_len(&b);
+
+       /* gss_kex_context is NULL with privsep, so we can't check it here */
+       if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gss_kex_context, 
+           &gssbuf, &mic))))
+               authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
+       
+       buffer_free(&b);
+       xfree(mic.value);
+
+       return (authenticated);
+}
+
 /*
  * We only support those mechanisms that we know about (ie ones that we know
  * how to check local user kuserok and the like)
@@ -96,11 +129,13 @@ userauth_gssapi(Authctxt *authctxt)
 
        if (!present) {
                xfree(doid);
+               authctxt->server_caused_failure = 1;
                return (0);
        }
 
        if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, &goid)))) {
                xfree(doid);
+               authctxt->server_caused_failure = 1;
                return (0);
        }
 
@@ -284,6 +319,12 @@ input_gssapi_mic(int type, u_int32_t plen, void *ctxt)
        userauth_finish(authctxt, authenticated, "gssapi-with-mic");
 }
 
+Authmethod method_gsskeyex = {
+       "gssapi-keyex",
+       userauth_gsskeyex,
+       &options.gss_authentication
+};
+
 Authmethod method_gssapi = {
        "gssapi-with-mic",
        userauth_gssapi,
index d255242edb0716b18e91e49769bf6d8fd7c5c276..6e58797bd5c1525921733939c32a9024cb0825c1 100644 (file)
@@ -55,6 +55,7 @@ extern Authmethod method_passwd;
 extern Authmethod method_kbdint;
 extern Authmethod method_hostbased;
 #ifdef GSSAPI
+extern Authmethod method_gsskeyex;
 extern Authmethod method_gssapi;
 #endif
 
@@ -62,6 +63,7 @@ Authmethod *authmethods[] = {
        &method_none,
        &method_pubkey,
 #ifdef GSSAPI
+       &method_gsskeyex,
        &method_gssapi,
 #endif
        &method_passwd,
@@ -188,6 +190,7 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
 #endif
 
        authctxt->postponed = 0;
+       authctxt->server_caused_failure = 0;
 
        /* try to authenticate user */
        m = authmethod_lookup(method);
@@ -258,7 +261,9 @@ userauth_finish(Authctxt *authctxt, int authenticated, char *method)
                /* now we can break out */
                authctxt->success = 1;
        } else {
-               if (authctxt->failures++ > options.max_authtries) {
+               /* Dont count server configuration issues against the client */
+               if (!authctxt->server_caused_failure && 
+                   authctxt->failures++ > options.max_authtries) {
 #ifdef SSH_AUDIT_EVENTS
                        PRIVSEP(audit_event(SSH_LOGIN_EXCEED_MAXTRIES));
 #endif
index f2c86a53acd51ef4f3ccac87590ce32f591d7f0f..00a2d69bc68c1a8406fb04b5c255c90542b4011d 100644 (file)
@@ -231,6 +231,30 @@ main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16))
        AC_DEFINE(BROKEN_SETREGID)
        AC_DEFINE_UNQUOTED(BIND_8_COMPAT, 1,
                [Define if your resolver libs need this for getrrsetbyname])
+       AC_MSG_CHECKING(if we have the Security Authorization Session API)
+       AC_TRY_COMPILE([#include <Security/AuthSession.h>],
+               [SessionCreate(0, 0);],
+               [ac_cv_use_security_session_api="yes"
+                AC_DEFINE(USE_SECURITY_SESSION_API, 1, 
+                       [platform has the Security Authorization Session API])
+                LIBS="$LIBS -framework Security"
+                AC_MSG_RESULT(yes)],
+               [ac_cv_use_security_session_api="no"
+                AC_MSG_RESULT(no)])
+       AC_MSG_CHECKING(if we have an in-memory credentials cache)
+       AC_TRY_COMPILE(
+               [#include <Kerberos/Kerberos.h>],
+               [cc_context_t c;
+                (void) cc_initialize (&c, 0, NULL, NULL);],
+               [AC_DEFINE(USE_CCAPI, 1, 
+                       [platform uses an in-memory credentials cache])
+                LIBS="$LIBS -framework Security"
+                AC_MSG_RESULT(yes)
+                if test "x$ac_cv_use_security_session_api" = "xno"; then
+                       AC_MSG_ERROR(*** Need a security framework to use the credentials cache API ***)
+               fi],
+               [AC_MSG_RESULT(no)]
+       )
        ;;
 *-*-hpux*)
        # first we define all of the options common to all HP-UX releases
index c2b4f2dd84bb60019eb9f6177a0d4f13e4005dc2..dfaa708ea98fb17751232fc0349f577b79e43143 100644 (file)
@@ -1,7 +1,7 @@
 /*     $OpenBSD: gss-genr.c,v 1.6 2005/10/13 22:24:31 stevesk Exp $    */
 
 /*
- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
+ * Copyright (c) 2001-2005 Simon Wilkinson. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #include "bufaux.h"
 #include "log.h"
 #include "ssh2.h"
+#include <openssl/evp.h>
 
 #include "ssh-gss.h"
 
 extern u_char *session_id2;
 extern u_int session_id2_len;
 
+typedef struct {
+       char *encoded;
+       gss_OID oid;
+} ssh_gss_kex_mapping;
+
+/*
+ * XXX - It would be nice to find a more elegant way of handling the
+ * XXX   passing of the key exchange context to the userauth routines
+ */
+
+Gssctxt *gss_kex_context = NULL;
+
+static ssh_gss_kex_mapping *gss_enc2oid = NULL;
+
+int 
+ssh_gssapi_oid_table_ok() {
+       return (gss_enc2oid != NULL);
+}
+
+/*
+ * Return a list of the gss-group1-sha1 mechanisms supported by this program
+ *
+ * We test mechanisms to ensure that we can use them, to avoid starting
+ * a key exchange with a bad mechanism
+ */
+
+
+char *
+ssh_gssapi_client_mechanisms(const char *host) {
+       gss_OID_set gss_supported;
+       OM_uint32 min_status;
+
+       gss_indicate_mechs(&min_status, &gss_supported);
+
+       return(ssh_gssapi_kex_mechs(gss_supported, ssh_gssapi_check_mechanism,
+           (void *)host));
+}
+
+char *
+ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check,
+    void *data) {
+       Buffer buf;
+       int i, oidpos, enclen;
+       char *mechs, *encoded;
+       char digest[EVP_MAX_MD_SIZE];
+       char deroid[2];
+       const EVP_MD *evp_md = EVP_md5();
+       EVP_MD_CTX md;
+
+       if (gss_enc2oid != NULL) {
+               for (i=0;gss_enc2oid[i].encoded!=NULL;i++)
+                       xfree(gss_enc2oid[i].encoded);
+               xfree(gss_enc2oid);
+       }
+
+       gss_enc2oid = xmalloc(sizeof(ssh_gss_kex_mapping)*
+           (gss_supported->count+1));
+
+       buffer_init(&buf);
+
+       oidpos = 0;
+       for (i = 0;i < gss_supported->count;i++) {
+               if (gss_supported->elements[i].length < 128 &&
+                   (*check)(&(gss_supported->elements[i]), data)) {
+
+                       deroid[0] = SSH_GSS_OIDTYPE;
+                       deroid[1] = gss_supported->elements[i].length;
+
+                       EVP_DigestInit(&md, evp_md);
+                       EVP_DigestUpdate(&md, deroid, 2);
+                       EVP_DigestUpdate(&md,
+                           gss_supported->elements[i].elements,
+                           gss_supported->elements[i].length);
+                       EVP_DigestFinal(&md, digest, NULL);
+
+                       encoded = xmalloc(EVP_MD_size(evp_md)*2);
+                       enclen = __b64_ntop(digest, EVP_MD_size(evp_md),
+                           encoded, EVP_MD_size(evp_md)*2);
+
+                       if (oidpos != 0)
+                           buffer_put_char(&buf, ',');
+
+                       buffer_append(&buf, KEX_GSS_GEX_SHA1_ID,
+                           sizeof(KEX_GSS_GEX_SHA1_ID)-1);
+                       buffer_append(&buf, encoded, enclen);
+                       buffer_put_char(&buf,',');
+                       buffer_append(&buf, KEX_GSS_GRP1_SHA1_ID, 
+                           sizeof(KEX_GSS_GRP1_SHA1_ID)-1);
+                       buffer_append(&buf, encoded, enclen);
+
+                       gss_enc2oid[oidpos].oid = &(gss_supported->elements[i]);
+                       gss_enc2oid[oidpos].encoded = encoded;
+                       oidpos++;
+               }
+       }
+       gss_enc2oid[oidpos].oid = NULL;
+       gss_enc2oid[oidpos].encoded = NULL;
+
+       buffer_put_char(&buf, '\0');
+
+       mechs = xmalloc(buffer_len(&buf));
+       buffer_get(&buf, mechs, buffer_len(&buf));
+       buffer_free(&buf);
+
+       if (strlen(mechs) == 0) {
+               xfree(mechs);
+               mechs = NULL;
+       }
+       
+       return (mechs);
+}
+
+gss_OID
+ssh_gssapi_id_kex(Gssctxt *ctx, char *name, int *gex) {
+       int i = 0;
+
+       if (strncmp(name, KEX_GSS_GRP1_SHA1_ID,
+           sizeof(KEX_GSS_GRP1_SHA1_ID)-1) == 0) {
+               name+=sizeof(KEX_GSS_GRP1_SHA1_ID)-1;
+               *gex = 0;
+       } else if (strncmp(name, KEX_GSS_GEX_SHA1_ID,
+           sizeof(KEX_GSS_GEX_SHA1_ID)-1) == 0) {
+               name+=sizeof(KEX_GSS_GEX_SHA1_ID)-1;
+               *gex = 1;
+       } else {
+               return NULL;
+       }
+
+       while (gss_enc2oid[i].encoded != NULL &&
+           strcmp(name, gss_enc2oid[i].encoded) != 0) {
+               i++;
+       }
+
+       if (gss_enc2oid[i].oid != NULL && ctx != NULL)
+               ssh_gssapi_set_oid(ctx, gss_enc2oid[i].oid);
+
+       return gss_enc2oid[i].oid;
+}
+
 /* Check that the OID in a data stream matches that in the context */
 int
 ssh_gssapi_check_oid(Gssctxt *ctx, void *data, size_t len)
@@ -248,6 +388,9 @@ ssh_gssapi_acquire_cred(Gssctxt *ctx)
 OM_uint32
 ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash)
 {
+       if (ctx == NULL) 
+               return -1;
+
        if ((ctx->major = gss_get_mic(&ctx->minor, ctx->context,
            GSS_C_QOP_DEFAULT, buffer, hash)))
                ssh_gssapi_error(ctx);
@@ -255,6 +398,19 @@ ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash)
        return (ctx->major);
 }
 
+/* Priviledged when used by server */
+OM_uint32
+ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
+{
+       if (ctx == NULL)
+               return -1;
+
+       ctx->major = gss_verify_mic(&ctx->minor, ctx->context,
+           gssbuf, gssmic, NULL);
+
+       return (ctx->major);
+}
+
 void
 ssh_gssapi_buildmic(Buffer *b, const char *user, const char *service,
     const char *context)
@@ -277,4 +433,19 @@ ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID oid)
        return (ssh_gssapi_acquire_cred(*ctx));
 }
 
+int
+ssh_gssapi_check_mechanism(gss_OID oid, void *host) {
+       Gssctxt * ctx = NULL;
+       gss_buffer_desc token = GSS_C_EMPTY_BUFFER;
+       OM_uint32 major, minor;
+       
+       ssh_gssapi_build_ctx(&ctx);
+       ssh_gssapi_set_oid(ctx, oid);
+       ssh_gssapi_import_name(ctx, host);
+       major = ssh_gssapi_init_ctx(ctx, 0, GSS_C_NO_BUFFER, &token, NULL);
+       gss_release_buffer(&minor, &token);
+       ssh_gssapi_delete_ctx(&ctx);
+       return (!GSS_ERROR(major));
+}
+
 #endif /* GSSAPI */
index 26eec25bdc8137371d1e8affd751ed5b44a3ccb9..190f56fc0850ae0a1a384514527c9771861992ab 100644 (file)
@@ -36,6 +36,7 @@
 #include "servconf.h"
 #include "xmalloc.h"
 #include "getput.h"
+#include "monitor_wrap.h"
 
 #include "ssh-gss.h"
 
@@ -57,6 +58,28 @@ ssh_gssapi_mech* supported_mechs[]= {
        &gssapi_null_mech,
 };
 
+/* Unprivileged */
+char *
+ssh_gssapi_server_mechanisms() {
+       gss_OID_set     supported;
+
+       ssh_gssapi_supported_oids(&supported);
+       return (ssh_gssapi_kex_mechs(supported, &ssh_gssapi_server_check_mech,
+           NULL));
+}
+
+/* Unprivileged */
+int
+ssh_gssapi_server_check_mech(gss_OID oid, void *data) {
+       Gssctxt * ctx = NULL;
+       int res;
+       res = !GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctx, oid)));
+       ssh_gssapi_delete_ctx(&ctx);
+
+       return (res);
+}
+
 /* Unprivileged */
 void
 ssh_gssapi_supported_oids(gss_OID_set *oidset)
@@ -293,14 +316,4 @@ ssh_gssapi_userok(char *user)
        return (0);
 }
 
-/* Privileged */
-OM_uint32
-ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
-{
-       ctx->major = gss_verify_mic(&ctx->minor, ctx->context,
-           gssbuf, gssmic, NULL);
-
-       return (ctx->major);
-}
-
 #endif
index cd71be9ca778aeca26a3dff0e6bdf4f5b8ac9ff2..47983f8d9e93e804d9c766911c49d5aa20a03099 100644 (file)
@@ -42,6 +42,10 @@ RCSID("$OpenBSD: kex.c,v 1.65 2005/11/04 05:15:59 djm Exp $");
 #include "dispatch.h"
 #include "monitor.h"
 
+#ifdef GSSAPI
+#include "ssh-gss.h"
+#endif
+
 #define KEX_COOKIE_LEN 16
 
 /* prototype */
@@ -301,6 +305,16 @@ choose_kex(Kex *k, char *client, char *server)
        } else if (strcmp(k->name, KEX_DHGEX_SHA1) == 0) {
                k->kex_type = KEX_DH_GEX_SHA1;
                k->evp_md = EVP_sha1();
+#ifdef GSSAPI
+       } else if (strncmp(k->name, KEX_GSS_GEX_SHA1_ID,
+           sizeof(KEX_GSS_GEX_SHA1_ID)-1) == 0) {
+               k->kex_type = KEX_GSS_GEX_SHA1;
+               k->evp_md = EVP_sha1();
+       } else if (strncmp(k->name, KEX_GSS_GRP1_SHA1_ID,
+           sizeof(KEX_GSS_GRP1_SHA1_ID)-1) == 0) {
+               k->kex_type = KEX_GSS_GRP1_SHA1;
+               k->evp_md = EVP_sha1();
+#endif
        } else
                fatal("bad kex alg %s", k->name);
 }
index bbd931e049df7ad068f6ca77739a9ff34165ade2..1c4d1a7181fd036797a75622370eb37f19650282 100644 (file)
@@ -63,6 +63,8 @@ enum kex_exchange {
        KEX_DH_GRP1_SHA1,
        KEX_DH_GRP14_SHA1,
        KEX_DH_GEX_SHA1,
+       KEX_GSS_GRP1_SHA1,
+       KEX_GSS_GEX_SHA1,
        KEX_MAX
 };
 
@@ -115,6 +117,11 @@ struct Kex {
        int     done;
        int     flags;
        const EVP_MD *evp_md;
+#ifdef GSSAPI
+       int     gss_deleg_creds;
+       int     gss_trust_dns;
+       char    *gss_host;
+#endif
        char    *client_version_string;
        char    *server_version_string;
        int     (*verify_host_key)(Key *);
@@ -137,6 +144,11 @@ void        kexdh_server(Kex *);
 void    kexgex_client(Kex *);
 void    kexgex_server(Kex *);
 
+#ifdef GSSAPI
+void   kexgss_client(Kex *);
+void   kexgss_server(Kex *);
+#endif
+
 void
 kex_dh_hash(char *, char *, char *, int, char *, int, u_char *, int,
     BIGNUM *, BIGNUM *, BIGNUM *, u_char **, u_int *);
index 08c158b59c124b2305bbb2863823f5faa902c2d5..239a35919536d8234fbd98d03e056f5e99efc39a 100644 (file)
@@ -650,6 +650,8 @@ key_type_from_name(char *name)
                return KEY_RSA;
        } else if (strcmp(name, "ssh-dss") == 0) {
                return KEY_DSA;
+       } else if (strcmp(name, "null") == 0) {
+               return KEY_NULL;
        }
        debug2("key_type_from_name: unknown key type '%s'", name);
        return KEY_UNSPEC;
index 50df8500bb99a4f6b7ddd420654711d2e5966f7a..6358e955fc56829d7daace6c399475cc242ed5ff 100644 (file)
@@ -34,6 +34,7 @@ enum types {
        KEY_RSA1,
        KEY_RSA,
        KEY_DSA,
+       KEY_NULL,
        KEY_UNSPEC
 };
 enum fp_type {
index e6f648b0b0badbd3de433dad15458f9274721414..57d2c376c98fe22a9d350e483a0a0c94aa31f9ea 100644 (file)
@@ -141,6 +141,7 @@ int mm_answer_gss_setup_ctx(int, Buffer *);
 int mm_answer_gss_accept_ctx(int, Buffer *);
 int mm_answer_gss_userok(int, Buffer *);
 int mm_answer_gss_checkmic(int, Buffer *);
+int mm_answer_gss_sign(int, Buffer *);
 #endif
 
 #ifdef SSH_AUDIT_EVENTS
@@ -209,11 +210,17 @@ struct mon_table mon_dispatch_proto20[] = {
     {MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx},
     {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok},
     {MONITOR_REQ_GSSCHECKMIC, MON_ISAUTH, mm_answer_gss_checkmic},
+    {MONITOR_REQ_GSSSIGN, MON_ONCE, mm_answer_gss_sign},
 #endif
     {0, 0, NULL}
 };
 
 struct mon_table mon_dispatch_postauth20[] = {
+#ifdef GSSAPI
+    {MONITOR_REQ_GSSSETUP, 0, mm_answer_gss_setup_ctx},
+    {MONITOR_REQ_GSSSTEP, 0, mm_answer_gss_accept_ctx},
+    {MONITOR_REQ_GSSSIGN, 0, mm_answer_gss_sign},
+#endif
     {MONITOR_REQ_MODULI, 0, mm_answer_moduli},
     {MONITOR_REQ_SIGN, 0, mm_answer_sign},
     {MONITOR_REQ_PTY, 0, mm_answer_pty},
@@ -318,6 +325,10 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
                /* Permit requests for moduli and signatures */
                monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
                monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
+#ifdef GSSAPI
+               /* and for the GSSAPI key exchange */
+               monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1);
+#endif
        } else {
                mon_dispatch = mon_dispatch_proto15;
 
@@ -391,6 +402,10 @@ monitor_child_postauth(struct monitor *pmonitor)
                monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
                monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
                monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
+#ifdef GSSAPI
+               /* and for the GSSAPI key exchange */
+               monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1);
+#endif         
        } else {
                mon_dispatch = mon_dispatch_postauth15;
                monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
@@ -1621,6 +1636,10 @@ mm_get_kex(Buffer *m)
        kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
        kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server;
        kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
+#ifdef GSSAPI
+       kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server;
+       kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server;
+#endif
        kex->server = 1;
        kex->hostkey_type = buffer_get_int(m);
        kex->kex_type = buffer_get_int(m);
@@ -1863,6 +1882,7 @@ mm_answer_gss_accept_ctx(int sock, Buffer *m)
                monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0);
                monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1);
                monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1);
+               monitor_permit(mon_dispatch, MONITOR_REQ_GSSSIGN, 1);
        }
        return (0);
 }
@@ -1913,4 +1933,42 @@ mm_answer_gss_userok(int sock, Buffer *m)
        /* Monitor loop will terminate if authenticated */
        return (authenticated);
 }
+
+int 
+mm_answer_gss_sign(int socket, Buffer *m)
+{
+       gss_buffer_desc data;
+       gss_buffer_desc hash = GSS_C_EMPTY_BUFFER;
+       OM_uint32 major, minor;
+       u_int len;
+
+       data.value = buffer_get_string(m, &len);
+       data.length = len;
+       if (data.length != 20) 
+               fatal("%s: data length incorrect: %d", __func__, data.length);
+
+       /* Save the session ID on the first time around */
+       if (session_id2_len == 0) {
+               session_id2_len = data.length;
+               session_id2 = xmalloc(session_id2_len);
+               memcpy(session_id2, data.value, session_id2_len);
+       }
+       major = ssh_gssapi_sign(gsscontext, &data, &hash);
+
+       xfree(data.value);
+
+       buffer_clear(m);
+       buffer_put_int(m, major);
+       buffer_put_string(m, hash.value, hash.length);
+
+       mm_request_send(socket, MONITOR_ANS_GSSSIGN, m);
+
+       gss_release_buffer(&minor, &hash);
+
+       /* Turn on getpwnam permissions */
+       monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1);
+
+       return (0);
+}
+
 #endif /* GSSAPI */
index 13ce3e1ca3e593d70aa9c1dc5e76ed6ac98652b1..7b306b4af1bcc1dba2a53464e86a8f5528a70b26 100644 (file)
@@ -53,6 +53,7 @@ enum monitor_reqtype {
        MONITOR_REQ_GSSSTEP, MONITOR_ANS_GSSSTEP,
        MONITOR_REQ_GSSUSEROK, MONITOR_ANS_GSSUSEROK,
        MONITOR_REQ_GSSCHECKMIC, MONITOR_ANS_GSSCHECKMIC,
+       MONITOR_REQ_GSSSIGN, MONITOR_ANS_GSSSIGN,
        MONITOR_REQ_PAM_START,
        MONITOR_REQ_PAM_ACCOUNT, MONITOR_ANS_PAM_ACCOUNT,
        MONITOR_REQ_PAM_INIT_CTX, MONITOR_ANS_PAM_INIT_CTX,
index 3b50753de7f337a58d650354add00297d02e37c6..c94675c6fb93ca067f3e0923e996e36a6b49234a 100644 (file)
@@ -1215,4 +1215,27 @@ mm_ssh_gssapi_userok(char *user)
        debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not ");
        return (authenticated);
 }
+
+OM_uint32
+mm_ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_desc *data, gss_buffer_desc *hash)
+{
+       Buffer m;
+       OM_uint32 major;
+       u_int len;
+
+       buffer_init(&m);
+       buffer_put_string(&m, data->value, data->length);
+
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSIGN, &m);
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSIGN, &m);
+
+       major = buffer_get_int(&m);
+       hash->value = buffer_get_string(&m, &len);
+       hash->length = len;
+
+       buffer_free(&m);
+
+       return(major);
+}
+
 #endif /* GSSAPI */
index 310b425130c31ebe0c8787a5c9974cb2a9bde586..871eabb9d6409f8bbbff95886df21b273627f52d 100644 (file)
@@ -63,6 +63,7 @@ OM_uint32 mm_ssh_gssapi_accept_ctx(Gssctxt *,
    gss_buffer_desc *, gss_buffer_desc *, OM_uint32 *);
 int mm_ssh_gssapi_userok(char *user);
 OM_uint32 mm_ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);
+OM_uint32 mm_ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t);
 #endif
 
 #ifdef USE_PAM
index 1fbf597936d84e8b795889aeec733c92ba50eb90..355a41ccbcac0d1111e3b0e37225318990a35cf7 100644 (file)
@@ -109,6 +109,7 @@ typedef enum {
        oClearAllForwardings, oNoHostAuthenticationForLocalhost,
        oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
        oAddressFamily, oGssAuthentication, oGssDelegateCreds,
+       oGssTrustDns,
        oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
        oSendEnv, oControlPath, oControlMaster, oHashKnownHosts,
        oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
@@ -145,9 +146,11 @@ static struct {
 #if defined(GSSAPI)
        { "gssapiauthentication", oGssAuthentication },
        { "gssapidelegatecredentials", oGssDelegateCreds },
+       { "gssapitrustdns", oGssTrustDns },
 #else
        { "gssapiauthentication", oUnsupported },
        { "gssapidelegatecredentials", oUnsupported },
+       { "gssapitrustdns", oUnsupported },
 #endif
        { "fallbacktorsh", oDeprecated },
        { "usersh", oDeprecated },
@@ -420,6 +423,10 @@ parse_flag:
                intptr = &options->gss_deleg_creds;
                goto parse_flag;
 
+       case oGssTrustDns:
+               intptr = &options->gss_trust_dns;
+               goto parse_flag;
+
        case oBatchMode:
                intptr = &options->batch_mode;
                goto parse_flag;
@@ -971,6 +978,7 @@ initialize_options(Options * options)
        options->challenge_response_authentication = -1;
        options->gss_authentication = -1;
        options->gss_deleg_creds = -1;
+       options->gss_trust_dns = -1;
        options->password_authentication = -1;
        options->kbd_interactive_authentication = -1;
        options->kbd_interactive_devices = NULL;
@@ -1059,6 +1067,8 @@ fill_default_options(Options * options)
                options->gss_authentication = 0;
        if (options->gss_deleg_creds == -1)
                options->gss_deleg_creds = 0;
+       if (options->gss_trust_dns == -1)
+               options->gss_trust_dns = 0;
        if (options->password_authentication == -1)
                options->password_authentication = 1;
        if (options->kbd_interactive_authentication == -1)
index 4565b2c2cedabd42cc95334be089295a45368135..bb70e9373b7acce91ea1fea0b1bee6ad25e943b2 100644 (file)
@@ -46,6 +46,7 @@ typedef struct {
                                        /* Try S/Key or TIS, authentication. */
        int     gss_authentication;     /* Try GSS authentication */
        int     gss_deleg_creds;        /* Delegate GSS credentials */
+       int     gss_trust_dns;          /* Trust DNS for GSS canonicalization */
        int     password_authentication;        /* Try password
                                                 * authentication. */
        int     kbd_interactive_authentication; /* Try keyboard-interactive auth. */
index 81953bb80aac64f7082e690e55a936599c725e24..219a0300fdf96d60ce1a8570a575ed657e505eb3 100644 (file)
@@ -72,6 +72,7 @@ initialize_server_options(ServerOptions *options)
        options->kerberos_ticket_cleanup = -1;
        options->kerberos_get_afs_token = -1;
        options->gss_authentication=-1;
+       options->gss_keyex = -1;
        options->gss_cleanup_creds = -1;
        options->password_authentication = -1;
        options->kbd_interactive_authentication = -1;
@@ -187,6 +188,8 @@ fill_default_server_options(ServerOptions *options)
                options->kerberos_get_afs_token = 0;
        if (options->gss_authentication == -1)
                options->gss_authentication = 0;
+       if (options->gss_keyex == -1)
+               options->gss_keyex = 0;
        if (options->gss_cleanup_creds == -1)
                options->gss_cleanup_creds = 1;
        if (options->password_authentication == -1)
@@ -273,7 +276,8 @@ typedef enum {
        sBanner, sUseDNS, sHostbasedAuthentication,
        sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
        sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
-       sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel,
+       sGssAuthentication, sGssKeyEx, sGssCleanupCreds, 
+       sAcceptEnv, sPermitTunnel,
        sUsePrivilegeSeparation,
        sDeprecated, sUnsupported
 } ServerOpCodes;
@@ -327,9 +331,11 @@ static struct {
        { "afstokenpassing", sUnsupported },
 #ifdef GSSAPI
        { "gssapiauthentication", sGssAuthentication },
+       { "gssapikeyexchange", sGssKeyEx },
        { "gssapicleanupcredentials", sGssCleanupCreds },
 #else
        { "gssapiauthentication", sUnsupported },
+       { "gssapikeyexchange", sUnsupported },
        { "gssapicleanupcredentials", sUnsupported },
 #endif
        { "passwordauthentication", sPasswordAuthentication },
@@ -673,6 +679,10 @@ parse_flag:
                intptr = &options->gss_authentication;
                goto parse_flag;
 
+       case sGssKeyEx:
+               intptr = &options->gss_keyex;
+               goto parse_flag;
+
        case sGssCleanupCreds:
                intptr = &options->gss_cleanup_creds;
                goto parse_flag;
index ab82c8f57a683a9904ac107cc724a842f79269bd..0ef05bcd908c6b95aee9c8ad2d9a3ceafedc3ade 100644 (file)
@@ -88,6 +88,7 @@ typedef struct {
        int     kerberos_get_afs_token;         /* If true, try to get AFS token if
                                                 * authenticated with Kerberos. */
        int     gss_authentication;     /* If true, permit GSSAPI authentication */
+       int     gss_keyex;              /* If true, permit GSSAPI key exchange */
        int     gss_cleanup_creds;      /* If true, destroy cred cache on logout */
        int     password_authentication;        /* If true, permit password
                                                 * authentication. */
index 52fb49a6f3ea4beb31e30af28a1a0758771a5c54..213930103cecd2c4bc1fdd2ea7c152d58c59802c 100644 (file)
 
 #define SSH_GSS_OIDTYPE 0x06
 
+#define SSH2_MSG_KEXGSS_INIT                           30
+#define SSH2_MSG_KEXGSS_CONTINUE                       31
+#define SSH2_MSG_KEXGSS_COMPLETE                       32
+#define SSH2_MSG_KEXGSS_HOSTKEY                                33
+#define SSH2_MSG_KEXGSS_ERROR                          34
+#define SSH2_MSG_KEXGSS_GROUPREQ                       40
+#define SSH2_MSG_KEXGSS_GROUP                          41
+#define KEX_GSS_GRP1_SHA1_ID                           "gss-group1-sha1-"
+#define KEX_GSS_GEX_SHA1_ID                            "gss-gex-sha1-"
+
 typedef struct {
        char *filename;
        char *envvar;
@@ -99,6 +109,7 @@ typedef struct {
 } Gssctxt;
 
 extern ssh_gssapi_mech *supported_mechs[];
+extern Gssctxt *gss_kex_context;
 
 int  ssh_gssapi_check_oid(Gssctxt *, void *, size_t);
 void ssh_gssapi_set_oid_data(Gssctxt *, void *, size_t);
@@ -121,13 +132,20 @@ OM_uint32 ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t);
 OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID);
 void ssh_gssapi_buildmic(Buffer *, const char *, const char *, const char *);
 
-/* In the server */
+typedef int ssh_gssapi_check_fn(gss_OID, void *);
+char *ssh_gssapi_client_mechanisms(const char *host);
+char *ssh_gssapi_kex_mechs(gss_OID_set, ssh_gssapi_check_fn *, void *);
+int ssh_gssapi_check_mechanism(gss_OID, void *);
+gss_OID ssh_gssapi_id_kex(Gssctxt *, char *, int *);
+
+int ssh_gssapi_server_check_mech(gss_OID, void *);
 int ssh_gssapi_userok(char *name);
 OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);
 void ssh_gssapi_do_child(char ***, u_int *);
 void ssh_gssapi_cleanup_creds(void);
 void ssh_gssapi_storecreds(void);
-
+char * ssh_gssapi_server_mechanisms(void);
+int ssh_gssapi_oid_table_ok();
 #endif /* GSSAPI */
 
 #endif /* _SSH_GSS_H */
index 5c94ffc9cdb5fce69a2351dc01af0526f407796f..5c41189fa4fe2fadc0d2f385d60de4c9858b2a5e 100644 (file)
@@ -471,6 +471,16 @@ Forward (delegate) credentials to the server.
 The default is
 .Dq no .
 Note that this option applies to protocol version 2 only.
+.It Cm GSSAPITrustDns
+Set to 
+.Dq yes to indicate that the DNS is trusted to securely canonicalize
+the name of the host being connected to. If 
+.Dq no, the hostname entered on the
+command line will be passed untouched to the GSSAPI library.
+The default is
+.Dq no .
+This option only applies to protocol version 2 connections using GSSAPI 
+key exchange.
 .It Cm HashKnownHosts
 Indicates that
 .Nm ssh
index adf96728194483d5709cf552ad26583de6b97b89..1a69c6b2b11679f02a583c8b6ebf0a11ed757365 100644 (file)
@@ -84,9 +84,34 @@ ssh_kex2(char *host, struct sockaddr *hostaddr)
 {
        Kex *kex;
 
+#ifdef GSSAPI
+       char *orig, *gss;
+       int len;
+        char *gss_host;
+#endif
+
        xxx_host = host;
        xxx_hostaddr = hostaddr;
 
+#ifdef GSSAPI
+       /* Add the GSSAPI mechanisms currently supported on this client to
+        * the key exchange algorithm proposal */
+       orig = myproposal[PROPOSAL_KEX_ALGS];
+       if (options.gss_trust_dns)
+               gss_host = (char *)get_canonical_hostname(1);
+       else
+               gss_host = host;
+
+       gss = ssh_gssapi_client_mechanisms(gss_host);
+       if (gss) {
+               debug("Offering GSSAPI proposal: %s", gss);
+               len = strlen(orig) + strlen(gss) + 2;
+               myproposal[PROPOSAL_KEX_ALGS] = xmalloc(len);
+               snprintf(myproposal[PROPOSAL_KEX_ALGS], len, "%s,%s", gss, 
+                   orig);
+       }
+#endif
+
        if (options.ciphers == (char *)-1) {
                logit("No valid ciphers for protocol version 2 given, using defaults.");
                options.ciphers = NULL;
@@ -114,6 +139,18 @@ ssh_kex2(char *host, struct sockaddr *hostaddr)
                myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =
                    options.hostkeyalgorithms;
 
+#ifdef GSSAPI
+       /* If we've got GSSAPI algorithms, then we also support the
+        * 'null' hostkey, as a last resort */
+       if (gss) {
+               orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS];
+               len = strlen(orig) + sizeof(",null");
+               myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = xmalloc(len);
+               snprintf(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS], len, 
+                   "%s,null", orig);
+       }
+#endif
+
        if (options.rekey_limit)
                packet_set_rekey_limit(options.rekey_limit);
 
@@ -122,10 +159,20 @@ ssh_kex2(char *host, struct sockaddr *hostaddr)
        kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client;
        kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client;
        kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
+#ifdef GSSAPI
+       kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client;
+       kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client;
+#endif
        kex->client_version_string=client_version_string;
        kex->server_version_string=server_version_string;
        kex->verify_host_key=&verify_host_key_callback;
 
+#ifdef GSSAPI
+       kex->gss_deleg_creds = options.gss_deleg_creds;
+       kex->gss_trust_dns = options.gss_trust_dns;
+       kex->gss_host = gss_host;
+#endif
+
        xxx_kex = kex;
 
        dispatch_run(DISPATCH_BLOCK, &kex->done, kex);
@@ -208,6 +255,7 @@ void        input_gssapi_token(int type, u_int32_t, void *);
 void   input_gssapi_hash(int type, u_int32_t, void *);
 void   input_gssapi_error(int, u_int32_t, void *);
 void   input_gssapi_errtok(int, u_int32_t, void *);
+int    userauth_gsskeyex(Authctxt *authctxt);
 #endif
 
 void   userauth(Authctxt *, char *);
@@ -223,6 +271,10 @@ static char *authmethods_get(void);
 
 Authmethod authmethods[] = {
 #ifdef GSSAPI
+       {"gssapi-keyex",
+               userauth_gsskeyex,
+               &options.gss_authentication,
+               NULL},
        {"gssapi-with-mic",
                userauth_gssapi,
                &options.gss_authentication,
@@ -706,6 +758,48 @@ input_gssapi_error(int type, u_int32_t plen, void *ctxt)
        xfree(msg);
        xfree(lang);
 }
+
+int
+userauth_gsskeyex(Authctxt *authctxt)
+{
+       Buffer b;
+       gss_buffer_desc gssbuf;
+       gss_buffer_desc mic = GSS_C_EMPTY_BUFFER;
+       OM_uint32 ms;
+
+       static int attempt = 0;
+       if (attempt++ >= 1)
+               return (0);
+
+       if (gss_kex_context == NULL) {
+               debug("No valid Key exchange context"); 
+               return (0);
+       }
+
+       ssh_gssapi_buildmic(&b, authctxt->server_user, authctxt->service,
+           "gssapi-keyex");
+
+       gssbuf.value = buffer_ptr(&b);
+       gssbuf.length = buffer_len(&b);
+
+       if (GSS_ERROR(ssh_gssapi_sign(gss_kex_context, &gssbuf, &mic))) {
+               buffer_free(&b);
+               return (0);
+       }
+
+       packet_start(SSH2_MSG_USERAUTH_REQUEST);
+       packet_put_cstring(authctxt->server_user);
+       packet_put_cstring(authctxt->service);
+       packet_put_cstring(authctxt->method->name);
+       packet_put_string(mic.value, mic.length);
+       packet_send();
+
+       buffer_free(&b);
+       gss_release_buffer(&ms, &mic);
+
+       return (1);
+}
+
 #endif /* GSSAPI */
 
 int
index def90d827a2b34ef465f5db723e007ea979f464c..1eac327978784a8f547a2523c7d9af8672e6c19d 100644 (file)
@@ -86,6 +86,10 @@ RCSID("$OpenBSD: sshd.c,v 1.318 2005/12/24 02:27:41 djm Exp $");
 #include "monitor_wrap.h"
 #include "monitor_fdpass.h"
 
+#ifdef USE_SECURITY_SESSION_API
+#include <Security/AuthSession.h>
+#endif
+
 #ifdef LIBWRAP
 #include <tcpd.h>
 #include <syslog.h>
@@ -1123,10 +1127,13 @@ main(int ac, char **av)
                logit("Disabling protocol version 1. Could not load host key");
                options.protocol &= ~SSH_PROTO_1;
        }
+#ifndef GSSAPI
+       /* The GSSAPI key exchange can run without a host key */
        if ((options.protocol & SSH_PROTO_2) && !sensitive_data.have_ssh2_key) {
                logit("Disabling protocol version 2. Could not load host key");
                options.protocol &= ~SSH_PROTO_2;
        }
+#endif
        if (!(options.protocol & (SSH_PROTO_1|SSH_PROTO_2))) {
                logit("sshd: no hostkeys available -- exiting.");
                exit(1);
@@ -1674,6 +1681,60 @@ main(int ac, char **av)
        /* Log the connection. */
        verbose("Connection from %.500s port %d", remote_ip, remote_port);
 
+#ifdef USE_SECURITY_SESSION_API
+       /*
+        * Create a new security session for use by the new user login if
+        * the current session is the root session or we are not launched
+        * by inetd (eg: debugging mode or server mode).  We do not
+        * necessarily need to create a session if we are launched from
+        * inetd because Panther xinetd will create a session for us.
+        *
+        * The only case where this logic will fail is if there is an
+        * inetd running in a non-root session which is not creating
+        * new sessions for us.  Then all the users will end up in the
+        * same session (bad).
+        *
+        * When the client exits, the session will be destroyed for us
+        * automatically.
+        *
+        * We must create the session before any credentials are stored
+        * (including AFS pags, which happens a few lines below).
+        */
+       {
+               OSStatus err = 0;
+               SecuritySessionId sid = 0;
+               SessionAttributeBits sattrs = 0;
+
+               err = SessionGetInfo(callerSecuritySession, &sid, &sattrs);
+               if (err)
+                       error("SessionGetInfo() failed with error %.8X",
+                           (unsigned) err);
+               else
+                       debug("Current Session ID is %.8X / Session Attributes are %.8X",
+                           (unsigned) sid, (unsigned) sattrs);
+
+               if (inetd_flag && !(sattrs & sessionIsRoot))
+                       debug("Running in inetd mode in a non-root session... "
+                           "assuming inetd created the session for us.");
+               else {
+                       debug("Creating new security session...");
+                       err = SessionCreate(0, sessionHasTTY | sessionIsRemote);
+                       if (err)
+                               error("SessionCreate() failed with error %.8X",
+                                   (unsigned) err);
+
+                       err = SessionGetInfo(callerSecuritySession, &sid, 
+                           &sattrs);
+                       if (err)
+                               error("SessionGetInfo() failed with error %.8X",
+                                   (unsigned) err);
+                       else
+                               debug("New Session ID is %.8X / Session Attributes are %.8X",
+                                   (unsigned) sid, (unsigned) sattrs);
+               }
+       }
+#endif
+
        /*
         * We don't want to listen forever unless the other side
         * successfully authenticates itself.  So we set up an alarm which is
@@ -2028,13 +2089,63 @@ do_ssh2_kex(void)
        myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = list_hostkey_types();
 
        /* start key exchange */
-       kex = kex_setup(myproposal);
-       kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
+  
+#ifdef GSSAPI
+       {
+       char *orig;
+       char *gss = NULL;
+       char *newstr = NULL;
+       orig = myproposal[PROPOSAL_KEX_ALGS];
+
+       /* 
+        * If we don't have a host key, then there's no point advertising
+         * the other key exchange algorithms
+        */
+
+       if (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]) == 0)
+               orig = NULL;
+
+       if (options.gss_keyex)
+               gss = ssh_gssapi_server_mechanisms();
+       else
+               gss = NULL;
+
+       if (gss && orig) {
+               int len = strlen(orig) + strlen(gss) + 2;
+               newstr = xmalloc(len);
+               snprintf(newstr, len, "%s,%s", gss, orig);
+       } else if (gss) {
+               newstr = gss;
+       } else if (orig) {
+               newstr = orig;
+       }
+       /* 
+        * If we've got GSSAPI mechanisms, then we've got the 'null' host
+        * key alg, but we can't tell people about it unless its the only
+        * host key algorithm we support
+        */
+       if (gss && (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS])) == 0)
+               myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = "null";
+
+       if (newstr)
+               myproposal[PROPOSAL_KEX_ALGS] = newstr;
+       else
+               fatal("No supported key exchange algorithms");
+       }
+#endif
+
+       /* start key exchange */
+       kex = kex_setup(myproposal);
+       kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
        kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server;
        kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
-       kex->server = 1;
-       kex->client_version_string=client_version_string;
-       kex->server_version_string=server_version_string;
+#ifdef GSSAPI
+       kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server;
+       kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server;
+#endif
+       kex->server = 1;
+       kex->client_version_string=client_version_string;
+       kex->server_version_string=server_version_string;
        kex->load_host_key=&get_hostkey_by_type;
        kex->host_key_index=&get_hostkey_index;
 
index 71a293ffb223013ec92677038504eee27ac78241..841cb29d3af3b46417acb7109cf99e660338f09a 100644 (file)
@@ -277,6 +277,12 @@ Specifies whether user authentication based on GSSAPI is allowed.
 The default is
 .Dq no .
 Note that this option applies to protocol version 2 only.
+.It Cm GSSAPIKeyExchange
+Specifies whether key exchange based on GSSAPI is allowed. GSSAPI key exchange 
+doesn't rely on ssh keys to verify host identity.
+The default is
+.Dq no .
+Note that this option applies to protocol version 2 only.
 .It Cm GSSAPICleanupCredentials
 Specifies whether to automatically destroy the user's credentials cache
 on logout.
This page took 0.107922 seconds and 5 git commands to generate.