]> andersk Git - gssapi-openssh.git/commitdiff
merging OPENSSH_5_2P1_SIMON_20090726_HPN13V6 to trunk:
authorbasney <basney>
Mon, 31 Aug 2009 18:45:53 +0000 (18:45 +0000)
committerbasney <basney>
Mon, 31 Aug 2009 18:45:53 +0000 (18:45 +0000)
http://www.psc.edu/networking/projects/hpn-ssh/openssh-5.2p1-hpn13v6.diff.gz
http://www.sxw.org.uk/computing/patches/openssh-5.2p1-gsskex-all-20090726.patch

30 files changed:
openssh/ChangeLog.gssapi
openssh/Makefile.in
openssh/auth2-gss.c
openssh/auth2.c
openssh/channels.c
openssh/cipher-ctr-mt.c
openssh/clientloop.c
openssh/compat.h
openssh/configure.ac
openssh/gss-genr.c
openssh/gss-serv-gsi.c
openssh/gss-serv-krb5.c
openssh/gss-serv.c
openssh/kex.h
openssh/kexgssc.c
openssh/kexgsss.c
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
openssh/version.h

index 010612c4ce67143db7c161dc55ace337f824dbc9..927b98bc9e6dc054d29bf6947d376b0fc6262433 100644 (file)
@@ -1,3 +1,29 @@
+20090615
+  - [ gss-genr.c gss-serv.c kexgssc.c kexgsss.c monitor.c sshconnect2.c
+      sshd.c ]
+    Fix issues identified by Greg Hudson following a code review
+       Check return value of gss_indicate_mechs
+       Protect GSSAPI calls in monitor, so they can only be used if enabled
+       Check return values of bignum functions in key exchange
+       Use BN_clear_free to clear other side's DH value
+       Make ssh_gssapi_id_kex more robust
+       Only configure kex table pointers if GSSAPI is enabled
+       Don't leak mechanism list, or gss mechanism list
+       Cast data.length before printing
+       If serverkey isn't provided, use an empty string, rather than NULL
+
+20090201
+  - [ gss-genr.c gss-serv.c kex.h kexgssc.c readconf.c readconf.h ssh-gss.h
+      ssh_config.5 sshconnet2.c ]
+    Add support for the GSSAPIClientIdentity option, which allows the user
+    to specify which GSSAPI identity to use to contact a given server
+
+20080404
+  - [ gss-serv.c ]
+    Add code to actually implement GSSAPIStrictAcceptCheck, which had somehow
+    been omitted from a previous version of this patch. Reported by Borislav
+    Stoichkov
+
 20070317
   - [ gss-serv-krb5.c ]
     Remove C99ism, where new_ccname was being declared in the middle of a 
index d448c7550bfd1b78aa269a90c8acc567524824a1..3d10d92c73eafdb232253f87ac07aeab5b022ccc 100644 (file)
@@ -72,8 +72,8 @@ LIBSSH_OBJS=acss.o authfd.o authfile.o bufaux.o bufbn.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 \
-       kexgssc.o \
-       entropy.o scard-opensc.o gss-genr.o umac.o jpake.o schnorr.o
+       entropy.o scard-opensc.o gss-genr.o umac.o jpake.o schnorr.o \
+       kexgssc.o
 
 SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \
        sshconnect.o sshconnect1.o sshconnect2.o mux.o
@@ -86,8 +86,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 auth2-jpake.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 \
-       kexgsss.o \
+       auth2-gss.o gss-serv.o gss-serv-krb5.o kexgsss.o\
        gss-serv-gsi.o \
        loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \
        audit.o audit-bsm.o platform.o sftp-server.o sftp-common.o
index 2cf692945ecb2b2500980b144f94bc5bb7b08684..1db62c438bad6e035735e5522ccb8ae31ce9ed82 100644 (file)
@@ -1,7 +1,7 @@
 /* $OpenBSD: auth2-gss.c,v 1.16 2007/10/29 00:52:45 dtucker Exp $ */
 
 /*
- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
+ * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -62,7 +62,7 @@ userauth_external(Authctxt *authctxt)
         packet_check_eom();
 
        if (authctxt->valid && authctxt->user && authctxt->user[0]) {
-               return(PRIVSEP(ssh_gssapi_userok(authctxt->user)));
+               return(PRIVSEP(ssh_gssapi_userok(authctxt->user, authctxt->pw)));
        }
        return 0;
 }
@@ -102,7 +102,8 @@ userauth_gsskeyex(Authctxt *authctxt)
            !GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gss_kex_context, 
                                                   &gssbuf2, &mic)))) {
            if (authctxt->valid && authctxt->user && authctxt->user[0]) {
-               authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
+            authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user,
+                                                      authctxt->pw));
            }
        }
        
@@ -341,7 +342,8 @@ input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt)
 
        /* user should be set if valid but we double-check here */
        if (authctxt->valid && authctxt->user && authctxt->user[0]) {
-           authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
+           authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user,
+                                                  authctxt->pw));
        } else {
            authenticated = 0;
        }
@@ -397,9 +399,10 @@ input_gssapi_mic(int type, u_int32_t plen, void *ctxt)
 
        if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic))))
            if (authctxt->valid && authctxt->user && authctxt->user[0]) {
-               authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
+            authenticated =
+                PRIVSEP(ssh_gssapi_userok(authctxt->user, authctxt->pw));
            } else {
-               authenticated = 0;
+            authenticated = 0;
            }
        else
                logit("GSSAPI MIC check failed");
index 2e466384fcdf55636a290b23b114e705abda30ad..1cd3e10364ee7df583ae46718936e226999d6112 100644 (file)
@@ -411,7 +411,7 @@ userauth_finish(Authctxt *authctxt, int authenticated, char *method)
                /* Dont count server configuration issues against the client */
                /* Allow initial try of "none" auth without failure penalty */
                if (!authctxt->server_caused_failure &&
-            (authctxt->attempt > 1 || strcmp(method, "none") != 0))
+                   (authctxt->attempt > 1 || strcmp(method, "none") != 0))
                        authctxt->failures++;
                if (authctxt->failures >= options.max_authtries) {
 #ifdef SSH_AUDIT_EVENTS
index 6996bde2b451412b43ab103340030470d6c5ddb5..79c7696cebec97bf6590a5525cb063291e2246e6 100644 (file)
@@ -2662,10 +2662,10 @@ channel_setup_fwd_listener(int type, const char *listen_addr,
                c = channel_new("port listener", type, sock, sock, -1,
                    CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
                    0, "port listener", 1);
-               else
-                       c = channel_new("port listener", type, sock, sock, -1,
-                         hpn_buffer_size, CHAN_TCP_PACKET_DEFAULT,
-                         0, "port listener", 1); 
+               else
+                       c = channel_new("port listener", type, sock, sock, -1,
+                         hpn_buffer_size, CHAN_TCP_PACKET_DEFAULT,
+                         0, "port listener", 1); 
                c->path = xstrdup(host);
                c->host_port = port_to_connect;
                c->listening_port = listen_port;
index fd30499e0a1c6b1e743ad0102df4e99f264573a1..93fb444c971f207a5957177253e38fe9a05aa86b 100644 (file)
 
 /* Processor cacheline length */
 #define CACHELINE_LEN  64
+
+/* Collect thread stats and print at cancellation when in debug mode */
+/* #define CIPHER_THREAD_STATS */
+
+/* Use single-byte XOR instead of 8-byte XOR */
+/* #define CIPHER_BYTE_XOR */
 /*-------------------- END TUNABLES --------------------*/
 
 
 const EVP_CIPHER *evp_aes_ctr_mt(void);
 
+#ifdef CIPHER_THREAD_STATS
+/*
+ * Struct to collect thread stats
+ */
+struct thread_stats {
+       u_int   fills;
+       u_int   skips;
+       u_int   waits;
+       u_int   drains;
+};
+
+/*
+ * Debug print the thread stats
+ * Use with pthread_cleanup_push for displaying at thread cancellation
+ */
+static void
+thread_loop_stats(void *x)
+{
+       struct thread_stats *s = x;
+
+       debug("tid %lu - %u fills, %u skips, %u waits", pthread_self(),
+                       s->fills, s->skips, s->waits);
+}
+
+ #define STATS_STRUCT(s)       struct thread_stats s
+ #define STATS_INIT(s)         { memset(&s, 0, sizeof(s)); }
+ #define STATS_FILL(s)         { s.fills++; }
+ #define STATS_SKIP(s)         { s.skips++; }
+ #define STATS_WAIT(s)         { s.waits++; }
+ #define STATS_DRAIN(s)                { s.drains++; }
+#else
+ #define STATS_STRUCT(s)
+ #define STATS_INIT(s)
+ #define STATS_FILL(s)
+ #define STATS_SKIP(s)
+ #define STATS_WAIT(s)
+ #define STATS_DRAIN(s)
+#endif
+
 /* Keystream Queue state */
 enum {
        KQINIT,
@@ -82,6 +127,7 @@ struct ssh_aes_ctr_ctx
 {
        struct kq       q[NUMKQ];
        AES_KEY         aes_ctx;
+       STATS_STRUCT(stats);
        u_char          aes_counter[AES_BLOCK_SIZE];
        pthread_t       tid[CIPHER_THREADS];
        int             state;
@@ -139,11 +185,18 @@ static void *
 thread_loop(void *x)
 {
        AES_KEY key;
+       STATS_STRUCT(stats);
        struct ssh_aes_ctr_ctx *c = x;
        struct kq *q;
        int i;
        int qidx;
 
+       /* Threads stats on cancellation */
+       STATS_INIT(stats);
+#ifdef CIPHER_THREAD_STATS
+       pthread_cleanup_push(thread_loop_stats, &stats);
+#endif
+
        /* Thread local copy of AES key */
        memcpy(&key, &c->aes_ctx, sizeof(key));
 
@@ -161,10 +214,13 @@ thread_loop(void *x)
                        }
                        ssh_ctr_add(q->ctr, KQLEN * (NUMKQ - 1), AES_BLOCK_SIZE);
                        q->qstate = KQDRAINING;
+                       STATS_FILL(stats);
                        pthread_cond_broadcast(&q->cond);
                }
                pthread_mutex_unlock(&q->lock);
        }
+       else 
+               STATS_SKIP(stats);
 
        /*
         * Normal case is to find empty queues and fill them, skipping over
@@ -184,6 +240,7 @@ thread_loop(void *x)
                pthread_mutex_lock(&q->lock);
                pthread_cleanup_push(thread_loop_cleanup, &q->lock);
                while (q->qstate == KQDRAINING || q->qstate == KQINIT) {
+                       STATS_WAIT(stats);
                        pthread_cond_wait(&q->cond, &q->lock);
                }
                pthread_cleanup_pop(0);
@@ -191,6 +248,7 @@ thread_loop(void *x)
                /* If filling or full, somebody else got it, skip */
                if (q->qstate != KQEMPTY) {
                        pthread_mutex_unlock(&q->lock);
+                       STATS_SKIP(stats);
                        continue;
                }
 
@@ -210,10 +268,16 @@ thread_loop(void *x)
                pthread_mutex_lock(&q->lock);
                ssh_ctr_add(q->ctr, KQLEN * (NUMKQ - 1), AES_BLOCK_SIZE);
                q->qstate = KQFULL;
+               STATS_FILL(stats);
                pthread_cond_signal(&q->cond);
                pthread_mutex_unlock(&q->lock);
        }
 
+#ifdef CIPHER_THREAD_STATS
+       /* Stats */
+       pthread_cleanup_pop(1);
+#endif
+
        return NULL;
 }
 
@@ -275,6 +339,7 @@ ssh_aes_ctr(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src,
                        q = &c->q[c->qidx];
                        pthread_mutex_lock(&q->lock);
                        while (q->qstate != KQFULL) {
+                               STATS_WAIT(c->stats);
                                pthread_cond_wait(&q->cond, &q->lock);
                        }
                        q->qstate = KQDRAINING;
@@ -283,6 +348,7 @@ ssh_aes_ctr(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src,
                        /* Mark consumed queue empty and signal producers */
                        pthread_mutex_lock(&oldq->lock);
                        oldq->qstate = KQEMPTY;
+                       STATS_DRAIN(c->stats);
                        pthread_cond_broadcast(&oldq->cond);
                        pthread_mutex_unlock(&oldq->lock);
                }
@@ -310,6 +376,8 @@ ssh_aes_ctr_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
                        pthread_cond_init(&c->q[i].cond, NULL);
                }
 
+               STATS_INIT(c->stats);
+               
                EVP_CIPHER_CTX_set_app_data(ctx, c);
        }
 
@@ -366,6 +434,10 @@ ssh_aes_ctr_cleanup(EVP_CIPHER_CTX *ctx)
        int i;
 
        if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
+#ifdef CIPHER_THREAD_STATS
+               debug("main thread: %u drains, %u waits", c->stats.drains,
+                               c->stats.waits);
+#endif
                /* Cancel pregen threads */
                for (i = 0; i < CIPHER_THREADS; i++)
                        pthread_cancel(c->tid[i]);
index 38028d549f1ccf46b3d6fbcf39a64078c964a51a..c516e76a491617cec61e1cc0fe1a6508dd994eb2 100644 (file)
 #include "match.h"
 #include "msg.h"
 
+#ifdef GSSAPI
+#include "ssh-gss.h"
+#endif
+
 /* import options */
 extern Options options;
 
@@ -1429,6 +1433,13 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
                /* Do channel operations unless rekeying in progress. */
                if (!rekeying) {
                        channel_after_select(readset, writeset);
+
+                       if (options.gss_renewal_rekey &&
+                           ssh_gssapi_credentials_updated(GSS_C_NO_CONTEXT)) {
+                               debug("credentials updated - forcing rekey");
+                               need_rekeying = 1;
+                       }
+
                        if (need_rekeying || packet_need_rekeying()) {
                                debug("need rekeying");
                                xxx_kex->done = 0;
index e303d3354139a25e5e4e452786f401959a9f7458..6feaa6b296cedba97cc6c767dde0a54e46d84c65 100644 (file)
@@ -58,7 +58,7 @@
 #define SSH_OLD_FORWARD_ADDR   0x01000000
 #define SSH_BUG_RFWD_ADDR      0x02000000
 #define SSH_NEW_OPENSSH                0x04000000
-#define SSH_BUG_LARGEWINDOW 0x08000000
+#define SSH_BUG_LARGEWINDOW     0x08000000
 
 void     enable_compat13(void);
 void     enable_compat20(void);
index 63029230ece767268e9014a618b0d6e7f0b678d3..afc39b4814d8f307179399a38abe9a54d544feec 100644 (file)
@@ -574,13 +574,6 @@ int main(void) { exit(0); }
            [Use tunnel device compatibility to OpenBSD])
        AC_DEFINE(SSH_TUN_PREPEND_AF, 1,
            [Prepend the address family to IP tunnel traffic])
-       m4_pattern_allow(AU_IPv)
-       AC_CHECK_DECL(AU_IPv4, [], 
-           AC_DEFINE(AU_IPv4, 0, [System only supports IPv4 audit records])
-           [#include <bsm/audit.h>]
-       AC_DEFINE(LASTLOG_WRITE_PUTUTXLINE, 1,
-           [Define if pututxline updates lastlog too])
-       )
        AC_MSG_CHECKING(if we have the Security Authorization Session API)
        AC_TRY_COMPILE([#include <Security/AuthSession.h>],
                [SessionCreate(0, 0);],
@@ -605,6 +598,13 @@ int main(void) { exit(0); }
                fi],
                [AC_MSG_RESULT(no)]
        )
+       m4_pattern_allow(AU_IPv)
+       AC_CHECK_DECL(AU_IPv4, [], 
+           AC_DEFINE(AU_IPv4, 0, [System only supports IPv4 audit records])
+           [#include <bsm/audit.h>]
+       AC_DEFINE(LASTLOG_WRITE_PUTUTXLINE, 1,
+           [Define if pututxline updates lastlog too])
+       )
        ;;
 *-*-dragonfly*)
        SSHDLIBS="$SSHDLIBS -lcrypt"
index 92cd09ad08a45c0d7e38336b4ae8346d186e259e..a8255c3e2c72a193d66efa47a520f0815d6da3ba 100644 (file)
@@ -1,7 +1,7 @@
 /* $OpenBSD: gss-genr.c,v 1.19 2007/06/12 11:56:15 dtucker Exp $ */
 
 /*
- * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved.
+ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -77,19 +77,20 @@ ssh_gssapi_oid_table_ok() {
  */
 
 char *
-ssh_gssapi_client_mechanisms(const char *host) {
+ssh_gssapi_client_mechanisms(const char *host, const char *client) {
        gss_OID_set gss_supported;
        OM_uint32 min_status;
 
-       gss_indicate_mechs(&min_status, &gss_supported);
+       if (GSS_ERROR(gss_indicate_mechs(&min_status, &gss_supported)))
+               return NULL;
 
        return(ssh_gssapi_kex_mechs(gss_supported, ssh_gssapi_check_mechanism,
-           host));
+           host, client));
 }
 
 char *
 ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check,
-    const char *data) {
+    const char *host, const char *client) {
        Buffer buf;
        size_t i;
        int oidpos, enclen;
@@ -113,7 +114,7 @@ ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check,
        oidpos = 0;
        for (i = 0; i < gss_supported->count; i++) {
                if (gss_supported->elements[i].length < 128 &&
-                   (*check)(NULL, &(gss_supported->elements[i]), data)) {
+                   (*check)(NULL, &(gss_supported->elements[i]), host, client)) {
 
                        deroid[0] = SSH_GSS_OIDTYPE;
                        deroid[1] = gss_supported->elements[i].length;
@@ -172,12 +173,18 @@ ssh_gssapi_id_kex(Gssctxt *ctx, char *name, int kex_type) {
        
        switch (kex_type) {
        case KEX_GSS_GRP1_SHA1:
+               if (strlen(name) < sizeof(KEX_GSS_GRP1_SHA1_ID))
+                       return GSS_C_NO_OID;
                name += sizeof(KEX_GSS_GRP1_SHA1_ID) - 1;
                break;
        case KEX_GSS_GRP14_SHA1:
+               if (strlen(name) < sizeof(KEX_GSS_GRP14_SHA1_ID))
+                       return GSS_C_NO_OID;
                name += sizeof(KEX_GSS_GRP14_SHA1_ID) - 1;
                break;
        case KEX_GSS_GEX_SHA1:
+               if (strlen(name) < sizeof(KEX_GSS_GEX_SHA1_ID))
+                       return GSS_C_NO_OID;
                name += sizeof(KEX_GSS_GEX_SHA1_ID) - 1;
                break;
        default:
@@ -350,7 +357,7 @@ ssh_gssapi_init_ctx(Gssctxt *ctx, int deleg_creds, gss_buffer_desc *recv_tok,
        }
 
        ctx->major = gss_init_sec_context(&ctx->minor,
-           GSS_C_NO_CREDENTIAL, &ctx->context, ctx->name, ctx->oid,
+           ctx->client_creds, &ctx->context, ctx->name, ctx->oid,
            GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG | deleg_flag,
            0, NULL, recv_tok, NULL, send_tok, flags, NULL);
 
@@ -389,9 +396,43 @@ ssh_gssapi_import_name(Gssctxt *ctx, const char *host)
        return (ctx->major);
 }
 
+OM_uint32
+ssh_gssapi_client_identity(Gssctxt *ctx, const char *name)
+{
+       gss_buffer_desc gssbuf;
+       gss_name_t gssname;
+       OM_uint32 status;
+       gss_OID_set oidset;
+
+       gssbuf.value = (void *) name;
+       gssbuf.length = strlen(gssbuf.value);
+
+       gss_create_empty_oid_set(&status, &oidset);
+       gss_add_oid_set_member(&status, ctx->oid, &oidset);
+
+       ctx->major = gss_import_name(&ctx->minor, &gssbuf,
+           GSS_C_NT_USER_NAME, &gssname);
+
+       if (!ctx->major)
+               ctx->major = gss_acquire_cred(&ctx->minor, 
+                   gssname, 0, oidset, GSS_C_INITIATE, 
+                   &ctx->client_creds, NULL, NULL);
+
+       gss_release_name(&status, &gssname);
+       gss_release_oid_set(&status, &oidset);
+
+       if (ctx->major)
+               ssh_gssapi_error(ctx);
+
+       return(ctx->major);
+}
+
 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);
@@ -400,17 +441,16 @@ ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash)
 }
 
 /* Priviledged when used by server */
-/* Moved here from gss-serv.c because called by kexgss_client(). */
 OM_uint32
 ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
 {
-       if (ctx == NULL)
-               return -1;
+       if (ctx == NULL)
+               return -1;
 
-       ctx->major = gss_verify_mic(&ctx->minor, ctx->context,
-           gssbuf, gssmic, NULL);
+       ctx->major = gss_verify_mic(&ctx->minor, ctx->context,
+           gssbuf, gssmic, NULL);
 
-       return (ctx->major);
+       return (ctx->major);
 }
 
 void
@@ -426,7 +466,8 @@ ssh_gssapi_buildmic(Buffer *b, const char *user, const char *service,
 }
 
 int
-ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host)
+ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host, 
+    const char *client)
 {
        gss_buffer_desc token = GSS_C_EMPTY_BUFFER;
        OM_uint32 major, minor;
@@ -444,6 +485,10 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host)
        ssh_gssapi_build_ctx(ctx);
        ssh_gssapi_set_oid(*ctx, oid);
        major = ssh_gssapi_import_name(*ctx, host);
+
+       if (!GSS_ERROR(major) && client)
+               major = ssh_gssapi_client_identity(*ctx, client);
+
        if (!GSS_ERROR(major)) {
                major = ssh_gssapi_init_ctx(*ctx, 0, GSS_C_NO_BUFFER, &token, 
                    NULL);
@@ -459,4 +504,61 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host)
        return (!GSS_ERROR(major));
 }
 
+int
+ssh_gssapi_credentials_updated(Gssctxt *ctxt) {
+       static gss_name_t saved_name = GSS_C_NO_NAME;
+       static OM_uint32 saved_lifetime = 0;
+       static gss_OID saved_mech = GSS_C_NO_OID;
+       static gss_name_t name;
+       static OM_uint32 last_call = 0;
+       OM_uint32 lifetime, now, major, minor;
+       int equal;
+       gss_cred_usage_t usage = GSS_C_INITIATE;
+       
+       now = time(NULL);
+
+       if (ctxt) {
+               debug("Rekey has happened - updating saved versions");
+
+               if (saved_name != GSS_C_NO_NAME)
+                       gss_release_name(&minor, &saved_name);
+
+               major = gss_inquire_cred(&minor, GSS_C_NO_CREDENTIAL,
+                   &saved_name, &saved_lifetime, NULL, NULL);
+
+               if (!GSS_ERROR(major)) {
+                       saved_mech = ctxt->oid;
+                       saved_lifetime+= now;
+               } else {
+                       /* Handle the error */
+               }
+               return 0;
+       }
+
+       if (now - last_call < 10)
+               return 0;
+
+       last_call = now;
+
+       if (saved_mech == GSS_C_NO_OID)
+               return 0;
+       
+       major = gss_inquire_cred(&minor, GSS_C_NO_CREDENTIAL, 
+           &name, &lifetime, NULL, NULL);
+       if (major == GSS_S_CREDENTIALS_EXPIRED)
+               return 0;
+       else if (GSS_ERROR(major))
+               return 0;
+
+       major = gss_compare_name(&minor, saved_name, name, &equal);
+       gss_release_name(&minor, &name);
+       if (GSS_ERROR(major))
+               return 0;
+
+       if (equal && (saved_lifetime < lifetime + now - 10))
+               return 1;
+
+       return 0;
+}
+
 #endif /* GSSAPI */
index e31d70cda30d5bfa036800219ac148cc66db96c1..e77db62b1c343cdec87517727b3ca1cc23c8b87b 100644 (file)
@@ -57,7 +57,8 @@ ssh_gssapi_mech gssapi_gsi_mech = {
        NULL,
        &ssh_gssapi_gsi_userok,
        &ssh_gssapi_gsi_localname,
-       &ssh_gssapi_gsi_storecreds
+       &ssh_gssapi_gsi_storecreds,
+    NULL
 };
 
 /*
index bea0eaebd25acc85797a42bc3e5b187edd47761c..a439393756bb988782a808b907f40ba1292d2c3f 100644 (file)
@@ -1,7 +1,7 @@
 /* $OpenBSD: gss-serv-krb5.c,v 1.7 2006/08/03 03:34:42 deraadt Exp $ */
 
 /*
- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
+ * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -69,7 +69,8 @@ ssh_gssapi_mech gssapi_kerberos_mech = {
        NULL,
        &ssh_gssapi_krb5_userok,
        &ssh_gssapi_krb5_localname,
-       &ssh_gssapi_krb5_storecreds
+       &ssh_gssapi_krb5_storecreds,
+       &ssh_gssapi_krb5_updatecreds
 };
 
 /* Initialise the krb5 library, for the stuff that GSSAPI won't do */
@@ -242,6 +243,71 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client)
        return;
 }
 
+int
+ssh_gssapi_krb5_updatecreds(ssh_gssapi_ccache *store, 
+    ssh_gssapi_client *client)
+{
+       krb5_ccache ccache = NULL;
+       krb5_principal principal = NULL;
+       char *name = NULL;
+       krb5_error_code problem;
+       OM_uint32 maj_status, min_status;
+
+       if ((problem = krb5_cc_resolve(krb_context, store->envval, &ccache))) {
+                logit("krb5_cc_resolve(): %.100s",
+                    krb5_get_err_text(krb_context, problem));
+                return 0;
+               }
+       
+       /* Find out who the principal in this cache is */
+       if ((problem = krb5_cc_get_principal(krb_context, ccache, 
+           &principal))) {
+               logit("krb5_cc_get_principal(): %.100s",
+                   krb5_get_err_text(krb_context, problem));
+               krb5_cc_close(krb_context, ccache);
+               return 0;
+       }
+
+       if ((problem = krb5_unparse_name(krb_context, principal, &name))) {
+               logit("krb5_unparse_name(): %.100s",
+                   krb5_get_err_text(krb_context, problem));
+               krb5_free_principal(krb_context, principal);
+               krb5_cc_close(krb_context, ccache);
+               return 0;
+       }
+
+
+       if (strcmp(name,client->exportedname.value)!=0) {
+               debug("Name in local credentials cache differs. Not storing");
+               krb5_free_principal(krb_context, principal);
+               krb5_cc_close(krb_context, ccache);
+               krb5_free_unparsed_name(krb_context, name);
+               return 0;
+       }
+       krb5_free_unparsed_name(krb_context, name);
+
+       /* Name matches, so lets get on with it! */
+
+       if ((problem = krb5_cc_initialize(krb_context, ccache, principal))) {
+               logit("krb5_cc_initialize(): %.100s",
+                   krb5_get_err_text(krb_context, problem));
+               krb5_free_principal(krb_context, principal);
+               krb5_cc_close(krb_context, ccache);
+               return 0;
+       }
+
+       krb5_free_principal(krb_context, principal);
+
+       if ((maj_status = gss_krb5_copy_ccache(&min_status, client->creds,
+           ccache))) {
+               logit("gss_krb5_copy_ccache() failed. Sorry!");
+               krb5_cc_close(krb_context, ccache);
+               return 0;
+       }
+
+       return 1;
+}
+
 #endif /* KRB5 */
 
 #endif /* GSSAPI */
index bf88d719278638e9a374cb7c96239c8fa39e156b..e1b2b433150f1476909c56221ac04c681dd7afa7 100644 (file)
@@ -1,7 +1,7 @@
 /* $OpenBSD: gss-serv.c,v 1.22 2008/05/08 12:02:23 djm Exp $ */
 
 /*
- * Copyright (c) 2001-2006 Simon Wilkinson. All rights reserved.
+ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -46,6 +46,7 @@
 #include "session.h"
 #include "misc.h"
 #include "servconf.h"
+#include "uidswap.h"
 
 #include "xmalloc.h"
 #include "ssh-gss.h"
@@ -56,10 +57,10 @@ extern Authctxt *the_authctxt;
 
 static ssh_gssapi_client gssapi_client =
     { GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER,
-    GSS_C_NO_CREDENTIAL, NULL, {NULL, NULL, NULL}};
+    GSS_C_NO_CREDENTIAL, GSS_C_NO_NAME,  NULL, {NULL, NULL, NULL}, 0, 0};
 
 ssh_gssapi_mech gssapi_null_mech =
-    { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL};
+    { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL, NULL};
 
 #ifdef KRB5
 extern ssh_gssapi_mech gssapi_kerberos_mech;
@@ -82,28 +83,6 @@ ssh_gssapi_mech* supported_mechs[]= {
 static int limited = 0;
 #endif
 
-/* 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(Gssctxt **dum, gss_OID oid, const char *data) {
-       Gssctxt *ctx = NULL;
-       int res;
-       res = !GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctx, oid)));
-       ssh_gssapi_delete_ctx(&ctx);
-
-       return (res);
-}
-
 /*
  * Acquire credentials for a server running on the current host.
  * Requires that the context structure contains a valid OID
@@ -146,7 +125,6 @@ ssh_gssapi_acquire_cred(Gssctxt *ctx)
        return GSS_S_COMPLETE;
 }
 
-
 /* Privileged */
 OM_uint32
 ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID oid)
@@ -158,6 +136,29 @@ ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID oid)
        return (ssh_gssapi_acquire_cred(*ctx));
 }
 
+/* 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, NULL));
+}
+
+/* Unprivileged */
+int
+ssh_gssapi_server_check_mech(Gssctxt **dum, gss_OID oid, const char *data,
+    const char *dummy) {
+       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)
@@ -168,8 +169,10 @@ ssh_gssapi_supported_oids(gss_OID_set *oidset)
        gss_OID_set supported;
 
        gss_create_empty_oid_set(&min_status, oidset);
-       /* Ask priviledged process what mechanisms it supports. */
-       PRIVSEP(gss_indicate_mechs(&min_status, &supported));
+
+       /* Ask privileged process what mechanisms it supports. */
+       if (GSS_ERROR(PRIVSEP(gss_indicate_mechs(&min_status, &supported))))
+               return;
 
        while (supported_mechs[i]->name != NULL) {
                if (GSS_ERROR(gss_test_oid_set_member(&min_status,
@@ -308,8 +311,51 @@ OM_uint32
 ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client)
 {
        int i = 0;
+       int equal = 0;
+       gss_name_t new_name = GSS_C_NO_NAME;
+       gss_buffer_desc ename = GSS_C_EMPTY_BUFFER;
+
+       if (options.gss_store_rekey && client->used && ctx->client_creds) {
+               if (client->mech->oid.length != ctx->oid->length ||
+                   (memcmp(client->mech->oid.elements,
+                    ctx->oid->elements, ctx->oid->length) !=0)) {
+                       debug("Rekeyed credentials have different mechanism");
+                       return GSS_S_COMPLETE;
+               }
+
+        /* Call gss_inquire_cred rather than gss_inquire_cred_by_mech
+           because GSI doesn't support the latter. -jbasney */
+
+               if ((ctx->major = gss_inquire_cred(&ctx->minor, 
+                   ctx->client_creds, &new_name, 
+                   NULL, NULL, NULL))) {
+                       ssh_gssapi_error(ctx);
+                       return (ctx->major);
+               }
 
-       gss_buffer_desc ename;
+               ctx->major = gss_compare_name(&ctx->minor, client->name, 
+                   new_name, &equal);
+
+               if (GSS_ERROR(ctx->major)) {
+                       ssh_gssapi_error(ctx);
+                       return (ctx->major);
+               }
+               if (!equal) {
+                       debug("Rekeyed credentials have different name");
+                       return GSS_S_COMPLETE;
+               }
+
+               debug("Marking rekeyed credentials for export");
+
+               gss_release_name(&ctx->minor, &client->name);
+               gss_release_cred(&ctx->minor, &client->creds);
+               client->name = new_name;
+               client->creds = ctx->client_creds;
+               ctx->client_creds = GSS_C_NO_CREDENTIAL;
+               client->updated = 1;
+               return GSS_S_COMPLETE;
+       }
 
        client->mech = NULL;
 
@@ -324,6 +370,16 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client)
        if (client->mech == NULL)
                return GSS_S_FAILURE;
 
+    /* Call gss_inquire_cred rather than gss_inquire_cred_by_mech
+       because GSI doesn't support the latter. -jbasney */
+
+       if (ctx->client_creds &&
+           (ctx->major = gss_inquire_cred(&ctx->minor,
+            ctx->client_creds, &client->name, NULL, NULL, NULL))) {
+               ssh_gssapi_error(ctx);
+               return (ctx->major);
+       }
+
        if ((ctx->major = gss_display_name(&ctx->minor, ctx->client,
            &client->displayname, NULL))) {
                ssh_gssapi_error(ctx);
@@ -341,6 +397,8 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client)
                return (ctx->major);
        }
 
+       gss_release_buffer(&ctx->minor, &ename);
+
        /* We can't copy this structure, so we just move the pointer to it */
        client->creds = ctx->client_creds;
        ctx->client_creds = GSS_C_NO_CREDENTIAL;
@@ -397,7 +455,7 @@ ssh_gssapi_do_child(char ***envp, u_int *envsizep)
 
 /* Privileged */
 int
-ssh_gssapi_userok(char *user)
+ssh_gssapi_userok(char *user, struct passwd *pw)
 {
        OM_uint32 lmin;
 
@@ -413,9 +471,11 @@ ssh_gssapi_userok(char *user)
        }
 #endif
        if (gssapi_client.mech && gssapi_client.mech->userok)
-               if ((*gssapi_client.mech->userok)(&gssapi_client, user))
+               if ((*gssapi_client.mech->userok)(&gssapi_client, user)) {
+                       gssapi_client.used = 1;
+                       gssapi_client.store.owner = pw;
                        return 1;
-               else {
+               else {
                        /* Destroy delegated credentials if userok fails */
                        gss_release_buffer(&lmin, &gssapi_client.displayname);
                        gss_release_buffer(&lmin, &gssapi_client.exportedname);
@@ -449,4 +509,90 @@ ssh_gssapi_localname(char **user)
        return(0);
 }
 
+/* These bits are only used for rekeying. The unpriviledged child is running 
+ * as the user, the monitor is root.
+ *
+ * In the child, we want to :
+ *    *) Ask the monitor to store our credentials into the store we specify
+ *    *) If it succeeds, maybe do a PAM update
+ */
+
+/* Stuff for PAM */
+
+#ifdef USE_PAM
+static int ssh_gssapi_simple_conv(int n, const struct pam_message **msg, 
+    struct pam_response **resp, void *data)
+{
+       return (PAM_CONV_ERR);
+}
+#endif
+
+void
+ssh_gssapi_rekey_creds() {
+       int ok;
+       int ret;
+#ifdef USE_PAM
+       pam_handle_t *pamh = NULL;
+       struct pam_conv pamconv = {ssh_gssapi_simple_conv, NULL};
+       char *envstr;
+#endif
+
+       if (gssapi_client.store.filename == NULL && 
+           gssapi_client.store.envval == NULL &&
+           gssapi_client.store.envvar == NULL)
+               return;
+       ok = PRIVSEP(ssh_gssapi_update_creds(&gssapi_client.store));
+
+       if (!ok)
+               return;
+
+       debug("Rekeyed credentials stored successfully");
+
+       /* Actually managing to play with the ssh pam stack from here will
+        * be next to impossible. In any case, we may want different options
+        * for rekeying. So, use our own :)
+        */
+#ifdef USE_PAM 
+       if (!use_privsep) {
+               debug("Not even going to try and do PAM with privsep disabled");
+               return;
+       }
+
+       ret = pam_start("sshd-rekey", gssapi_client.store.owner->pw_name,
+           &pamconv, &pamh);
+       if (ret)
+               return;
+
+       xasprintf(&envstr, "%s=%s", gssapi_client.store.envvar, 
+           gssapi_client.store.envval);
+
+       ret = pam_putenv(pamh, envstr);
+       if (!ret)
+               pam_setcred(pamh, PAM_REINITIALIZE_CRED);
+       pam_end(pamh, PAM_SUCCESS);
+#endif
+}
+
+int 
+ssh_gssapi_update_creds(ssh_gssapi_ccache *store) {
+       int ok = 0;
+
+       /* Check we've got credentials to store */
+       if (!gssapi_client.updated)
+               return 0;
+
+       gssapi_client.updated = 0;
+
+       temporarily_use_uid(gssapi_client.store.owner);
+       if (gssapi_client.mech && gssapi_client.mech->updatecreds)
+               ok = (*gssapi_client.mech->updatecreds)(store, &gssapi_client);
+       else
+               debug("No update function for this mechanism");
+
+       restore_uid();
+
+       return ok;
+}
+
 #endif
index 39c28c8c38e039467eaf94d0bfe28ad25d00767d..6100df8d86b2fe8918044d7a72d6793c6f54536c 100644 (file)
@@ -127,6 +127,7 @@ struct Kex {
        int     gss_deleg_creds;
        int     gss_trust_dns;
        char    *gss_host;
+       char    *gss_client;
 #endif
        char    *client_version_string;
        char    *server_version_string;
index 1cadb2a2904900464f6a82af59e18d43a69a147d..39be405310ce41ea2430d89f571759d348e614c2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001-2006 Simon Wilkinson. All rights reserved.
+ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -26,6 +26,8 @@
 
 #ifdef GSSAPI
 
+#include "includes.h"
+
 #include <openssl/crypto.h>
 #include <openssl/bn.h>
 
@@ -57,6 +59,7 @@ kexgss_client(Kex *kex) {
        BIGNUM *g = NULL;       
        u_char *kbuf, *hash;
        u_char *serverhostkey = NULL;
+       u_char *empty = "";
        char *msg;
        char *lang;
        int type = 0;
@@ -71,7 +74,11 @@ kexgss_client(Kex *kex) {
 
        if (ssh_gssapi_import_name(ctxt, kex->gss_host))
                fatal("Couldn't import hostname");
-       
+
+       if (kex->gss_client && 
+           ssh_gssapi_client_identity(ctxt, kex->gss_client))
+               fatal("Couldn't acquire client credentials");
+
        switch (kex->kex_type) {
        case KEX_GSS_GRP1_SHA1:
                dh = dh_new_group1();
@@ -243,9 +250,16 @@ kexgss_client(Kex *kex) {
        klen = DH_size(dh);
        kbuf = xmalloc(klen);
        kout = DH_compute_key(kbuf, dh_server_pub, dh);
+       if (kout < 0)
+               fatal("DH_compute_key: failed");
 
        shared_secret = BN_new();
-       BN_bin2bn(kbuf,kout, shared_secret);
+       if (shared_secret == NULL)
+               fatal("kexgss_client: BN_new failed");
+
+       if (BN_bin2bn(kbuf, kout, shared_secret) == NULL)
+               fatal("kexdh_client: BN_bin2bn failed");
+
        memset(kbuf, 0, klen);
        xfree(kbuf);
 
@@ -256,7 +270,7 @@ kexgss_client(Kex *kex) {
                    kex->server_version_string,
                    buffer_ptr(&kex->my), buffer_len(&kex->my),
                    buffer_ptr(&kex->peer), buffer_len(&kex->peer),
-                   serverhostkey, slen, /* server host key */
+                   (serverhostkey ? serverhostkey : empty), slen,
                    dh->pub_key,        /* e */
                    dh_server_pub,      /* f */
                    shared_secret,      /* K */
@@ -270,7 +284,7 @@ kexgss_client(Kex *kex) {
                    kex->server_version_string,
                    buffer_ptr(&kex->my), buffer_len(&kex->my),
                    buffer_ptr(&kex->peer), buffer_len(&kex->peer),
-                   serverhostkey, slen,
+                   (serverhostkey ? serverhostkey : empty), slen,
                    min, nbits, max,
                    dh->p, dh->g,
                    dh->pub_key,
@@ -304,6 +318,9 @@ kexgss_client(Kex *kex) {
                memcpy(kex->session_id, hash, kex->session_id_len);
        }
 
+       if (kex->gss_deleg_creds)
+               ssh_gssapi_credentials_updated(ctxt);
+
        if (gss_kex_context == NULL)
                gss_kex_context = ctxt;
        else
index ae58cacb722f92b38cd7bb6a178628b038033aa3..3e5205c43505c0f61ccab36684461d5bcf4ac944 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001-2006 Simon Wilkinson. All rights reserved.
+ * Copyright (c) 2001-2009 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 "dh.h"
 #include "ssh-gss.h"
 #include "monitor_wrap.h"
+#include "servconf.h"
 
 static void kex_gss_send_error(Gssctxt *ctxt);
+extern ServerOptions options;
 
 void
 kexgss_server(Kex *kex)
@@ -69,6 +71,7 @@ kexgss_server(Kex *kex)
        BIGNUM *dh_client_pub = NULL;
        int type = 0;
        gss_OID oid;
+       char *mechs;
 
        /* Initialise GSSAPI */
 
@@ -77,7 +80,8 @@ kexgss_server(Kex *kex)
         * into life
         */
        if (!ssh_gssapi_oid_table_ok()) 
-               ssh_gssapi_server_mechanisms();
+               if ((mechs = ssh_gssapi_server_mechanisms()))
+                       xfree(mechs);
 
        debug2("%s: Identifying %s", __func__, kex->name);
        oid = ssh_gssapi_id_kex(NULL, kex->name, kex->kex_type);
@@ -168,7 +172,7 @@ kexgss_server(Kex *kex)
                if (maj_status & GSS_S_CONTINUE_NEEDED) {
                        debug("Sending GSSAPI_CONTINUE");
                        packet_start(SSH2_MSG_KEXGSS_CONTINUE);
-                       packet_put_string(send_tok.value, send_tok.length);
+                       packet_put_string((char *)send_tok.value, send_tok.length);
                        packet_send();
                        gss_release_buffer(&min_status, &send_tok);
                }
@@ -178,7 +182,7 @@ kexgss_server(Kex *kex)
                kex_gss_send_error(ctxt);
                if (send_tok.length > 0) {
                        packet_start(SSH2_MSG_KEXGSS_CONTINUE);
-                       packet_put_string(send_tok.value, send_tok.length);
+                       packet_put_string((char *)send_tok.value, send_tok.length);
                        packet_send();
                }
                packet_disconnect("GSSAPI Key Exchange handshake failed");
@@ -196,9 +200,16 @@ kexgss_server(Kex *kex)
        klen = DH_size(dh);
        kbuf = xmalloc(klen); 
        kout = DH_compute_key(kbuf, dh_client_pub, dh);
+       if (kout < 0)
+               fatal("DH_compute_key: failed");
 
        shared_secret = BN_new();
-       BN_bin2bn(kbuf, kout, shared_secret);
+       if (shared_secret == NULL)
+               fatal("kexgss_server: BN_new failed");
+
+       if (BN_bin2bn(kbuf, kout, shared_secret) == NULL)
+               fatal("kexgss_server: BN_bin2bn failed");
+
        memset(kbuf, 0, klen);
        xfree(kbuf);
 
@@ -233,7 +244,7 @@ kexgss_server(Kex *kex)
                fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type);
        }
 
-       BN_free(dh_client_pub);
+       BN_clear_free(dh_client_pub);
 
        if (kex->session_id == NULL) {
                kex->session_id_len = hashlen;
@@ -272,6 +283,11 @@ kexgss_server(Kex *kex)
        kex_derive_keys(kex, hash, hashlen, shared_secret);
        BN_clear_free(shared_secret);
        kex_finish(kex);
+
+       /* If this was a rekey, then save out any delegated credentials we
+        * just exchanged.  */
+       if (options.gss_store_rekey)
+               ssh_gssapi_rekey_creds();
 }
 
 static void 
index bc018a4802c5f2b36a5d1e1e65eb90258b1d2614..e0434d5bcf506f732da2fb2212953acdd1a8464d 100644 (file)
@@ -174,6 +174,7 @@ int mm_answer_gss_sign(int, Buffer *);
 int mm_answer_gss_error(int, Buffer *);
 int mm_answer_gss_indicate_mechs(int, Buffer *);
 int mm_answer_gss_localname(int, Buffer *);
+int mm_answer_gss_updatecreds(int, Buffer *);
 #endif
 
 #ifdef SSH_AUDIT_EVENTS
@@ -265,6 +266,7 @@ struct mon_table mon_dispatch_postauth20[] = {
     {MONITOR_REQ_GSSSIGN, 0, mm_answer_gss_sign},
     {MONITOR_REQ_GSSERR, 0, mm_answer_gss_error},
     {MONITOR_REQ_GSSMECHS, 0, mm_answer_gss_indicate_mechs},
+    {MONITOR_REQ_GSSUPCREDS, 0, mm_answer_gss_updatecreds},
 #endif
     {MONITOR_REQ_MODULI, 0, mm_answer_moduli},
     {MONITOR_REQ_SIGN, 0, mm_answer_sign},
@@ -1737,9 +1739,11 @@ mm_get_kex(Buffer *m)
        kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
        kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
 #ifdef GSSAPI
-       kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server;
-       kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server;
-       kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server;
+       if (options.gss_keyex) {
+               kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server;
+               kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server;
+               kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server;
+       }
 #endif
        kex->server = 1;
        kex->hostkey_type = buffer_get_int(m);
@@ -1940,6 +1944,9 @@ mm_answer_gss_setup_ctx(int sock, Buffer *m)
        OM_uint32 major;
        u_int len;
 
+       if (!options.gss_authentication && !options.gss_keyex)
+               fatal("In GSSAPI monitor when GSSAPI is disabled");
+
        goid.elements = buffer_get_string(m, &len);
        goid.length = len;
 
@@ -1967,6 +1974,9 @@ mm_answer_gss_accept_ctx(int sock, Buffer *m)
        OM_uint32 flags = 0; /* GSI needs this */
        u_int len;
 
+       if (!options.gss_authentication && !options.gss_keyex)
+               fatal("In GSSAPI monitor when GSSAPI is disabled");
+
        in.value = buffer_get_string(m, &len);
        in.length = len;
        major = ssh_gssapi_accept_ctx(gsscontext, &in, &out, &flags);
@@ -1997,6 +2007,9 @@ mm_answer_gss_checkmic(int sock, Buffer *m)
        OM_uint32 ret;
        u_int len;
 
+       if (!options.gss_authentication && !options.gss_keyex)
+               fatal("In GSSAPI monitor when GSSAPI is disabled");
+
        gssbuf.value = buffer_get_string(m, &len);
        gssbuf.length = len;
        mic.value = buffer_get_string(m, &len);
@@ -2023,7 +2036,11 @@ mm_answer_gss_userok(int sock, Buffer *m)
 {
        int authenticated;
 
-       authenticated = authctxt->valid && ssh_gssapi_userok(authctxt->user);
+       if (!options.gss_authentication && !options.gss_keyex)
+               fatal("In GSSAPI monitor when GSSAPI is disabled");
+
+       authenticated = authctxt->valid && 
+           ssh_gssapi_userok(authctxt->user, authctxt->pw);
 
        buffer_clear(m);
        buffer_put_int(m, authenticated);
@@ -2037,43 +2054,6 @@ mm_answer_gss_userok(int sock, Buffer *m)
        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__, (int)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);
-}
-
 int
 mm_answer_gss_error(int socket, Buffer *m) {
         OM_uint32 major,minor;
@@ -2137,6 +2117,74 @@ mm_answer_gss_localname(int socket, Buffer *m) {
 
         return(0);
 }
+
+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;
+
+       if (!options.gss_authentication && !options.gss_keyex)
+               fatal("In GSSAPI monitor when GSSAPI is disabled");
+
+       data.value = buffer_get_string(m, &len);
+       data.length = len;
+       if (data.length != 20) 
+               fatal("%s: data length incorrect: %d", __func__, 
+                   (int) 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);
+       
+       /* And credential updating, for when rekeying */
+       monitor_permit(mon_dispatch, MONITOR_REQ_GSSUPCREDS, 1);
+
+       return (0);
+}
+
+int
+mm_answer_gss_updatecreds(int socket, Buffer *m) {
+       ssh_gssapi_ccache store;
+       int ok;
+
+       store.filename = buffer_get_string(m, NULL);
+       store.envvar   = buffer_get_string(m, NULL);
+       store.envval   = buffer_get_string(m, NULL);
+
+       ok = ssh_gssapi_update_creds(&store);
+
+       xfree(store.filename);
+       xfree(store.envvar);
+       xfree(store.envval);
+
+       buffer_clear(m);
+       buffer_put_int(m, ok);
+
+       mm_request_send(socket, MONITOR_ANS_GSSUPCREDS, m);
+
+       return(0);
+}
+
 #endif /* GSSAPI */
 
 #ifdef JPAKE
index 3b40f13210a2e3eb65219d52be0eb9359df8f9cf..9219f4ad6a428a68fd329eb4e8e218c01430eca9 100644 (file)
@@ -57,6 +57,7 @@ enum monitor_reqtype {
        MONITOR_REQ_GSSERR, MONITOR_ANS_GSSERR,
        MONITOR_REQ_GSSCHECKMIC, MONITOR_ANS_GSSCHECKMIC,
        MONITOR_REQ_GSSSIGN, MONITOR_ANS_GSSSIGN,
+       MONITOR_REQ_GSSUPCREDS, MONITOR_ANS_GSSUPCREDS,
        MONITOR_REQ_PAM_START,
        MONITOR_REQ_PAM_ACCOUNT, MONITOR_ANS_PAM_ACCOUNT,
        MONITOR_REQ_PAM_INIT_CTX, MONITOR_ANS_PAM_INIT_CTX,
index 368738f63be05cc9cdd85ee12a97430fac01acd2..a2bc3a6b348740b1198125a5ab8df29532815601 100644 (file)
@@ -1239,7 +1239,7 @@ mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
 }
 
 int
-mm_ssh_gssapi_userok(char *user)
+mm_ssh_gssapi_userok(char *user, struct passwd *pw)
 {
        Buffer m;
        int authenticated = 0;
@@ -1257,28 +1257,6 @@ mm_ssh_gssapi_userok(char *user)
        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);
-}
-
 char *
 mm_ssh_gssapi_last_error(Gssctxt *ctx, OM_uint32 *major, OM_uint32 *minor) {
        Buffer m;
@@ -1356,6 +1334,50 @@ mm_ssh_gssapi_localname(char **lname)
         return(0);
 }      
 
+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);
+}
+
+int
+mm_ssh_gssapi_update_creds(ssh_gssapi_ccache *store)
+{
+       Buffer m;
+       int ok;
+
+       buffer_init(&m);
+
+       buffer_put_cstring(&m, store->filename ? store->filename : "");
+       buffer_put_cstring(&m, store->envvar ? store->envvar : "");
+       buffer_put_cstring(&m, store->envval ? store->envval : "");
+       
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUPCREDS, &m);
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSUPCREDS, &m);
+
+       ok = buffer_get_int(&m);
+
+       buffer_free(&m);
+       
+       return (ok);
+}
+
 #endif /* GSSAPI */
 
 #ifdef JPAKE
index a190a26f6012deff172eb68560a385a58c312101..e4a3d485810f827511453ffac5cae870fbbe2759 100644 (file)
@@ -57,13 +57,14 @@ BIGNUM *mm_auth_rsa_generate_challenge(Key *);
 OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **, gss_OID);
 OM_uint32 mm_ssh_gssapi_accept_ctx(Gssctxt *,
    gss_buffer_desc *, gss_buffer_desc *, OM_uint32 *);
-int mm_ssh_gssapi_userok(char *user);
+int mm_ssh_gssapi_userok(char *user, struct passwd *);
 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);
 int mm_ssh_gssapi_localname(char **user);
 OM_uint32 mm_gss_indicate_mechs(OM_uint32 *minor_status,
                                gss_OID_set *mech_set);
 char *mm_ssh_gssapi_last_error(Gssctxt *ctxt, OM_uint32 *maj, OM_uint32 *min);
+int mm_ssh_gssapi_update_creds(ssh_gssapi_ccache *);
 #endif
 
 #ifdef USE_PAM
index 6d05b4ee92c85e72deeb6804d9bc8afe16a7c1ce..0f29417f3b0440764909eb27a3b7dfcee5639e21 100644 (file)
@@ -127,8 +127,7 @@ typedef enum {
        oClearAllForwardings, oNoHostAuthenticationForLocalhost,
        oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
        oAddressFamily, oGssAuthentication, oGssDelegateCreds,
-       oGssKeyEx,
-       oGssTrustDns,
+       oGssTrustDns, oGssKeyEx, oGssClientIdentity, oGssRenewalRekey,
        oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
        oSendEnv, oControlPath, oControlMaster, oHashKnownHosts,
        oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
@@ -171,11 +170,15 @@ static struct {
        { "gssapikeyexchange", oGssKeyEx },
        { "gssapidelegatecredentials", oGssDelegateCreds },
        { "gssapitrustdns", oGssTrustDns },
+       { "gssapiclientidentity", oGssClientIdentity },
+       { "gssapirenewalforcesrekey", oGssRenewalRekey },
 #else
        { "gssapiauthentication", oUnsupported },
        { "gssapikeyexchange", oUnsupported },
        { "gssapidelegatecredentials", oUnsupported },
        { "gssapitrustdns", oUnsupported },
+       { "gssapiclientidentity", oUnsupported },
+       { "gssapirenewalforcesrekey", oUnsupported },
 #endif
        { "fallbacktorsh", oDeprecated },
        { "usersh", oDeprecated },
@@ -235,25 +238,19 @@ static struct {
        { "tunneldevice", oTunnelDevice },
        { "localcommand", oLocalCommand },
        { "permitlocalcommand", oPermitLocalCommand },
-        { "noneenabled", oNoneEnabled },
-        { "tcprcvbufpoll", oTcpRcvBufPoll },
-        { "tcprcvbuf", oTcpRcvBuf },
-        { "noneswitch", oNoneSwitch },
-       { "hpndisabled", oHPNDisabled },
-       { "hpnbuffersize", oHPNBufferSize },
        { "visualhostkey", oVisualHostKey },
-       { "noneenabled", oNoneEnabled },
-       { "tcprcvbufpoll", oTcpRcvBufPoll },
-       { "tcprcvbuf", oTcpRcvBuf },
-       { "noneswitch", oNoneSwitch },
-       { "hpndisabled", oHPNDisabled },
-       { "hpnbuffersize", oHPNBufferSize },
 #ifdef JPAKE
        { "zeroknowledgepasswordauthentication",
            oZeroKnowledgePasswordAuthentication },
 #else
        { "zeroknowledgepasswordauthentication", oUnsupported },
 #endif
+       { "noneenabled", oNoneEnabled },
+       { "tcprcvbufpoll", oTcpRcvBufPoll },
+       { "tcprcvbuf", oTcpRcvBuf },
+       { "noneswitch", oNoneSwitch },
+       { "hpndisabled", oHPNDisabled },
+       { "hpnbuffersize", oHPNBufferSize },
        { NULL, oBadOption }
 };
 
@@ -473,7 +470,7 @@ parse_flag:
                goto parse_flag;
 
        case oGssKeyEx:
-               intptr = &options->gss_keyex;
+               intptr = &options->gss_keyex;
                goto parse_flag;
 
        case oGssDelegateCreds:
@@ -484,6 +481,14 @@ parse_flag:
                intptr = &options->gss_trust_dns;
                goto parse_flag;
 
+       case oGssClientIdentity:
+               charptr = &options->gss_client_identity;
+               goto parse_string;
+
+       case oGssRenewalRekey:
+               intptr = &options->gss_renewal_rekey;
+               goto parse_flag;
+
        case oBatchMode:
                intptr = &options->batch_mode;
                goto parse_flag;
@@ -1073,6 +1078,8 @@ initialize_options(Options * options)
        options->gss_keyex = -1;
        options->gss_deleg_creds = -1;
        options->gss_trust_dns = -1;
+       options->gss_renewal_rekey = -1;
+       options->gss_client_identity = NULL;
        options->password_authentication = -1;
        options->kbd_interactive_authentication = -1;
        options->kbd_interactive_devices = NULL;
@@ -1141,6 +1148,12 @@ initialize_options(Options * options)
        options->tcp_rcv_buf_poll = -1;
        options->tcp_rcv_buf = -1;
        options->zero_knowledge_password_authentication = -1;
+       options->none_switch = -1;
+       options->none_enabled = -1;
+       options->hpn_disabled = -1;
+       options->hpn_buffer_size = -1;
+       options->tcp_rcv_buf_poll = -1;
+       options->tcp_rcv_buf = -1;
 }
 
 /*
@@ -1181,6 +1194,8 @@ fill_default_options(Options * options)
                options->gss_deleg_creds = 1;
        if (options->gss_trust_dns == -1)
                options->gss_trust_dns = 1;
+       if (options->gss_renewal_rekey == -1)
+               options->gss_renewal_rekey = 0;
        if (options->password_authentication == -1)
                options->password_authentication = 1;
        if (options->kbd_interactive_authentication == -1)
index 9396f177cf674808151144ba58a234464447cf85..12477c05681b36dbfa5323ef5c142683a3749c80 100644 (file)
@@ -44,9 +44,11 @@ typedef struct {
        int     challenge_response_authentication;
                                        /* Try S/Key or TIS, authentication. */
        int     gss_authentication;     /* Try GSS authentication */
-       int     gss_keyex;              /* Try GSS key exchange */
+       int     gss_keyex;              /* Try GSS key exchange */
        int     gss_deleg_creds;        /* Delegate GSS credentials */
        int     gss_trust_dns;          /* Trust DNS for GSS canonicalization */
+       int     gss_renewal_rekey;      /* Credential renewal forces rekey */
+       char    *gss_client_identity;   /* Principal to initiate GSSAPI with */
        int     password_authentication;        /* Try password
                                                 * authentication. */
        int     kbd_interactive_authentication; /* Try keyboard-interactive auth. */
index 90c0eb7cc7edc6402e38a16a133c1ebf3b7a1bda..96a27f3ab196b3b7605ca356cdbafa58b607a181 100644 (file)
@@ -103,6 +103,7 @@ initialize_server_options(ServerOptions *options)
        options->gss_cleanup_creds = -1;
        options->gss_strict_acceptor = -1;
        options->gsi_allow_limited_proxy = -1;
+       options->gss_store_rekey = -1;
        options->password_authentication = -1;
        options->kbd_interactive_authentication = -1;
        options->challenge_response_authentication = -1;
@@ -137,11 +138,11 @@ initialize_server_options(ServerOptions *options)
        options->num_permitted_opens = -1;
        options->adm_forced_command = NULL;
        options->chroot_directory = NULL;
+       options->zero_knowledge_password_authentication = -1;
        options->none_enabled = -1;
        options->tcp_rcv_buf_poll = -1;
        options->hpn_disabled = -1;
        options->hpn_buffer_size = -1;
-       options->zero_knowledge_password_authentication = -1;
 }
 
 void
@@ -241,6 +242,8 @@ fill_default_server_options(ServerOptions *options)
                options->gss_strict_acceptor = 1;
        if (options->gsi_allow_limited_proxy == -1)
                options->gsi_allow_limited_proxy = 0;
+       if (options->gss_store_rekey == -1)
+               options->gss_store_rekey = 0;
        if (options->password_authentication == -1)
                options->password_authentication = 1;
        if (options->kbd_interactive_authentication == -1)
@@ -370,17 +373,16 @@ typedef enum {
        sBanner, sUseDNS, sHostbasedAuthentication,
        sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
        sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
-       sGssAuthentication, sGssCleanupCreds,
     sGssDelegateCreds,
-    sGssStrictAcceptor,
-       sGssKeyEx, 
     sGssCredsPath,
        sGsiAllowLimitedProxy,
-    sAcceptEnv, sPermitTunnel,
+       sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor,
+       sGssKeyEx, sGssStoreRekey,
+       sAcceptEnv, sPermitTunnel,
        sMatch, sPermitOpen, sForceCommand, sChrootDirectory,
        sUsePrivilegeSeparation, sAllowAgentForwarding,
-       sNoneEnabled, sTcpRcvBufPoll, sHPNDisabled, sHPNBufferSize,
        sZeroKnowledgePasswordAuthentication,
+       sNoneEnabled, sTcpRcvBufPoll, sHPNDisabled, sHPNBufferSize,
        sDeprecated, sUnsupported
 } ServerOpCodes;
 
@@ -442,22 +444,24 @@ static struct {
        { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL },
        { "gssapidelegatecredentials", sGssDelegateCreds, SSHCFG_ALL },
        { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL },
-       { "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL },
        { "gssapicredentialspath", sGssCredsPath, SSHCFG_GLOBAL },
-       { "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL },
 #ifdef GSI
        { "gsiallowlimitedproxy", sGsiAllowLimitedProxy, SSHCFG_GLOBAL },
 #endif
+       { "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL },
+       { "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL },
+       { "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL },
 #else
        { "gssapiauthentication", sUnsupported, SSHCFG_ALL },
        { "gssapidelegatecredentials", sUnsupported, SSHCFG_ALL },
        { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
-       { "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL },
        { "gssapicredentialspath", sUnsupported, SSHCFG_GLOBAL },
-       { "gssapikeyexchange", sUnsupported, SSHCFG_GLOBAL },
 #ifdef GSI
        { "gsiallowlimitedproxy", sUnsupported, SSHCFG_GLOBAL },
 #endif
+       { "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL },
+       { "gssapikeyexchange", sUnsupported, SSHCFG_GLOBAL },
+       { "gssapistorecredentialsonrekey", sUnsupported, SSHCFG_GLOBAL },
 #endif
 #ifdef SESSION_HOOKS
     { "allowsessionhooks", sAllowSessionHooks, SSHCFG_GLOBAL },
@@ -1024,17 +1028,23 @@ process_server_config_line(ServerOptions *options, char *line,
                intptr = &options->gss_cleanup_creds;
                goto parse_flag;
 
+       case sGssCredsPath:
+               charptr = &options->gss_creds_path;
+               goto parse_filename;
+
        case sGssStrictAcceptor:
                intptr = &options->gss_strict_acceptor;
                goto parse_flag;
 
-       case sGssCredsPath:
-               charptr = &options->gss_creds_path;
-               goto parse_filename;
+       case sGssStoreRekey:
+               intptr = &options->gss_store_rekey;
+               goto parse_flag;
 
+#ifdef GSI
        case sGsiAllowLimitedProxy:
                intptr = &options->gsi_allow_limited_proxy;
                goto parse_flag;
+#endif
 
 #ifdef SESSION_HOOKS
         case sAllowSessionHooks:
index fd8b90975c7d5331b477e8a12817c183d3b181e0..2c9f00e5a47192b47228b9ccb113b45b4eaca563 100644 (file)
@@ -95,13 +95,14 @@ typedef struct {
 #endif
        int     kerberos_get_afs_token;         /* If true, try to get AFS token if
                                                 * authenticated with Kerberos. */
+       int     gsi_allow_limited_proxy;        /* If true, accept limited proxies */
        int     gss_authentication;     /* If true, permit GSSAPI authentication */
        int     gss_deleg_creds;        /* If true, store delegated GSSAPI credentials*/
-       int     gss_keyex;              /* If true, permit GSSAPI key exchange */
+       int     gss_keyex;              /* If true, permit GSSAPI key exchange */
        int     gss_cleanup_creds;      /* If true, destroy cred cache on logout */
-       int     gss_strict_acceptor;    /* If true, restrict the GSSAPI acceptor name */
        char*   gss_creds_path; /* If true, destroy cred cache on logout */
-       int     gsi_allow_limited_proxy;        /* If true, accept limited proxies */
+       int     gss_strict_acceptor;    /* If true, restrict the GSSAPI acceptor name */
+       int     gss_store_rekey;
        int     password_authentication;        /* If true, permit password
                                                 * authentication. */
        int     kbd_interactive_authentication; /* If true, permit */
index 794e670f1c4528356cfde93221ff4278db810bde..dcb9bca4cfe5bd9e5c7eb76bd8460f09274ef39e 100644 (file)
@@ -1,6 +1,6 @@
 /* $OpenBSD: ssh-gss.h,v 1.10 2007/06/12 08:20:00 djm Exp $ */
 /*
- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
+ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -77,6 +77,7 @@ typedef struct {
        char *filename;
        char *envvar;
        char *envval;
+       struct passwd *owner;
        void *data;
 } ssh_gssapi_ccache;
 
@@ -84,9 +85,12 @@ typedef struct {
        gss_buffer_desc displayname;
        gss_buffer_desc exportedname;
        gss_cred_id_t creds;
+       gss_name_t name;
        struct ssh_gssapi_mech_struct *mech;
        ssh_gssapi_ccache store;
     gss_ctx_id_t context;
+       int used;
+       int updated;
 } ssh_gssapi_client;
 
 typedef struct ssh_gssapi_mech_struct {
@@ -97,6 +101,7 @@ typedef struct ssh_gssapi_mech_struct {
        int (*userok) (ssh_gssapi_client *, char *);
        int (*localname) (ssh_gssapi_client *, char **);
        void (*storecreds) (ssh_gssapi_client *);
+       int (*updatecreds) (ssh_gssapi_ccache *, ssh_gssapi_client *);
 } ssh_gssapi_mech;
 
 typedef struct {
@@ -107,7 +112,7 @@ typedef struct {
        gss_OID         oid; /* both */
        gss_cred_id_t   creds; /* server */
        gss_name_t      client; /* server */
-       gss_cred_id_t   client_creds; /* server */
+       gss_cred_id_t   client_creds; /* both */
 } Gssctxt;
 
 extern ssh_gssapi_mech *supported_mechs[];
@@ -131,24 +136,27 @@ void ssh_gssapi_build_ctx(Gssctxt **);
 void ssh_gssapi_delete_ctx(Gssctxt **);
 OM_uint32 ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t);
 void ssh_gssapi_buildmic(Buffer *, const char *, const char *, const char *);
-int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *);
+int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *, const char *);
+OM_uint32 ssh_gssapi_client_identity(Gssctxt *, const char *);
+int ssh_gssapi_credentials_updated(Gssctxt *);
 
 int ssh_gssapi_localname(char **name);
 
 /* In the server */
-typedef int ssh_gssapi_check_fn(Gssctxt **, gss_OID, const char *);
-char *ssh_gssapi_client_mechanisms(const char *host);
-char *ssh_gssapi_kex_mechs(gss_OID_set, ssh_gssapi_check_fn *, const char *);
+typedef int ssh_gssapi_check_fn(Gssctxt **, gss_OID, const char *, 
+    const char *);
+char *ssh_gssapi_client_mechanisms(const char *, const char *);
+char *ssh_gssapi_kex_mechs(gss_OID_set, ssh_gssapi_check_fn *, const char *,
+    const char *);
 gss_OID ssh_gssapi_id_kex(Gssctxt *, char *, int);
-int ssh_gssapi_server_check_mech(Gssctxt **,gss_OID, const char *);
+int ssh_gssapi_server_check_mech(Gssctxt **,gss_OID, const char *, 
+    const char *);
 OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID);
-int ssh_gssapi_userok(char *name);
+int ssh_gssapi_userok(char *name, struct passwd *);
 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();
 
 #ifdef MECHGLUE
 gss_cred_id_t __gss_get_mechanism_cred
@@ -157,6 +165,10 @@ gss_cred_id_t __gss_get_mechanism_cred
    );
 #endif
 
+char *ssh_gssapi_server_mechanisms(void);
+int ssh_gssapi_oid_table_ok();
+
+int ssh_gssapi_update_creds(ssh_gssapi_ccache *store);
 #endif /* GSSAPI */
 
 #endif /* _SSH_GSS_H */
index 073d038cc372dc8b86520db91ac270f23ec6b80d..a72a35b2114b8328746577bfa439a3dee0283cc9 100644 (file)
@@ -490,18 +490,28 @@ GSSAPI key exchange the server need not have a host key.
 The default is
 .Dq yes .
 Note that this option applies to protocol version 2 only.
+.It Cm GSSAPIClientIdentity
+If set, specifies the GSSAPI client identity that ssh should use when 
+connecting to the server. The default is unset, which means that the default 
+identity will be used.
 .It Cm GSSAPIDelegateCredentials
 Forward (delegate) credentials to the server.
 The default is
 .Dq yes .
-Note that this option applies to protocol version 2 only.
+Note that this option applies to protocol version 2 connections using GSSAPI.
+.It Cm GSSAPIRenewalForcesRekey
+If set to 
+.Dq yes
+then renewal of the client's GSSAPI credentials will force the rekeying of the
+ssh connection. With a compatible server, this can delegate the renewed 
+credentials to a session on the server.
+The default is
+.Dq yes .
 .It Cm GSSAPITrustDns
 Set to 
-.Dq yes 
-to indicate that the DNS is trusted to securely canonicalize
+.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
+.Dq no, the hostname entered on the
 command line will be passed untouched to the GSSAPI library.
 The default is
 .Dq yes .
index 4696f344dbcf618aeb0dfb154cb4d2b99276d73e..c7aadb4a9526c5433d685ee0b1c9c07d0e720c06 100644 (file)
 extern char *client_version_string;
 extern char *server_version_string;
 extern Options options;
+extern Kex *xxx_kex;
+
+/* tty_flag is set in ssh.c. use this in ssh_userauth2 */
+/* if it is set then prevent the switch to the null cipher */
+
+extern int tty_flag;
 
 /* tty_flag is set in ssh.c. use this in ssh_userauth2 */
 /* if it is set then prevent the switch to the null cipher */
@@ -133,7 +139,7 @@ ssh_kex2(char *host, struct sockaddr *hostaddr)
                else
                        gss_host = host;
 
-               gss = ssh_gssapi_client_mechanisms(gss_host);
+               gss = ssh_gssapi_client_mechanisms(gss_host, options.gss_client_identity);
                if (gss) {
                        debug("Offering GSSAPI proposal: %s", gss);
                        xasprintf(&myproposal[PROPOSAL_KEX_ALGS],
@@ -176,6 +182,7 @@ ssh_kex2(char *host, struct sockaddr *hostaddr)
                orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS];
                xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS], 
                    "%s,null", orig);
+               xfree(gss);
        }
 #endif
 
@@ -189,18 +196,23 @@ ssh_kex2(char *host, struct sockaddr *hostaddr)
        kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
        kex->kex[KEX_DH_GEX_SHA256] = kexgex_client;
 #ifdef GSSAPI
-       kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client;
-       kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_client;
-       kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client;
+       if (options.gss_keyex) {
+               kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client;
+               kex->kex[KEX_GSS_GRP14_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;
+       if (options.gss_keyex) {
+               kex->gss_deleg_creds = options.gss_deleg_creds;
+               kex->gss_trust_dns = options.gss_trust_dns;
+               kex->gss_client = options.gss_client_identity;
+               kex->gss_host = gss_host;
+       }
 #endif
 
        xxx_kex = kex;
@@ -654,14 +666,18 @@ userauth_gssapi(Authctxt *authctxt)
         * once. */
 
        if (gss_supported == NULL)
-               gss_indicate_mechs(&min, &gss_supported);
+               if (GSS_ERROR(gss_indicate_mechs(&min, &gss_supported))) {
+                       gss_supported = NULL;
+                       return 0;
+               }
 
        /* Check to see if the mechanism is usable before we offer it */
        while (mech < gss_supported->count && !ok) {
                /* My DER encoding requires length<128 */
                if (gss_supported->elements[mech].length < 128 &&
                    ssh_gssapi_check_mechanism(&gssctxt, 
-                   &gss_supported->elements[mech], gss_host)) {
+                   &gss_supported->elements[mech], gss_host, 
+                    options.gss_client_identity)) {
                        ok = 1; /* Mechanism works */
                } else {
                        mech++;
@@ -883,10 +899,10 @@ const gss_OID_desc * const              gss_mech_globus_gssapi_openssl;
 int
 userauth_external(Authctxt *authctxt)
 {
-        static int attempt = 0;
+    static int attempt = 0;
         
-        if (attempt++ >= 1)
-               return 0;
+    if (attempt++ >= 1)
+        return 0;
                                 
        /* The client MUST NOT try this method if initial key exchange
           was not performed using a GSSAPI-based key exchange
@@ -896,22 +912,22 @@ userauth_external(Authctxt *authctxt)
                return 0;
        }
 
-        debug2("userauth_external");
-        packet_start(SSH2_MSG_USERAUTH_REQUEST);
+    debug2("userauth_external");
+    packet_start(SSH2_MSG_USERAUTH_REQUEST);
 #ifdef GSI
-        if (options.implicit && is_gsi_oid(gss_kex_context->oid)) {
-       packet_put_cstring("");
+    if (options.implicit && is_gsi_oid(gss_kex_context->oid)) {
+        packet_put_cstring("");
        } else {
 #endif
-       packet_put_cstring(authctxt->server_user);
+    packet_put_cstring(authctxt->server_user);
 #ifdef GSI
        }
 #endif
-        packet_put_cstring(authctxt->service);
-        packet_put_cstring(authctxt->method->name);
-        packet_send();
-        packet_write_wait();
-        return 1;
+    packet_put_cstring(authctxt->service);
+    packet_put_cstring(authctxt->method->name);
+    packet_send();
+    packet_write_wait();
+    return 1;
 }                                                                                                
 int
 userauth_gsskeyex(Authctxt *authctxt)
@@ -931,12 +947,12 @@ userauth_gsskeyex(Authctxt *authctxt)
        }
 
 #ifdef GSI
-        if (options.implicit && is_gsi_oid(gss_kex_context->oid)) {
-       ssh_gssapi_buildmic(&b, "", authctxt->service, "gssapi-keyex");
+    if (options.implicit && is_gsi_oid(gss_kex_context->oid)) {
+        ssh_gssapi_buildmic(&b, "", authctxt->service, "gssapi-keyex");
        } else {
 #endif
-       ssh_gssapi_buildmic(&b, authctxt->server_user, authctxt->service,
-           "gssapi-keyex");
+        ssh_gssapi_buildmic(&b, authctxt->server_user, authctxt->service,
+                            "gssapi-keyex");
 #ifdef GSI
        }
 #endif
@@ -951,8 +967,8 @@ userauth_gsskeyex(Authctxt *authctxt)
 
        packet_start(SSH2_MSG_USERAUTH_REQUEST);
 #ifdef GSI
-        if (options.implicit && is_gsi_oid(gss_kex_context->oid)) {
-       packet_put_cstring("");
+    if (options.implicit && is_gsi_oid(gss_kex_context->oid)) {
+        packet_put_cstring("");
        } else {
 #endif
        packet_put_cstring(authctxt->server_user);
index 5db24fdd9336c11d0e1a38ffe6cdfb2b0f93403f..1805bdef230295bcedabcb860195b8a26602a83f 100644 (file)
@@ -1800,6 +1800,9 @@ main(int ac, char **av)
                cleanup_exit(255);
        }
 
+       /* set the HPN options for the child */
+       channel_set_hpn(options.hpn_disabled, options.hpn_buffer_size);
+
        /*
         * We use get_canonical_hostname with usedns = 0 instead of
         * get_remote_ipaddr here so IP options will be checked.
@@ -1891,9 +1894,6 @@ main(int ac, char **av)
        }
 #endif
 
-       /* set the HPN options for the child */
-       channel_set_hpn(options.hpn_disabled, options.hpn_buffer_size);
-
        /*
         * We don't want to listen forever unless the other side
         * successfully authenticates itself.  So we set up an alarm which is
@@ -2326,7 +2326,6 @@ do_ssh2_kex(void)
        }
 #endif
 
-       /* start key exchange */
        /* start key exchange */
        kex = kex_setup(myproposal);
        kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
@@ -2334,9 +2333,11 @@ do_ssh2_kex(void)
        kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
        kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
 #ifdef GSSAPI
-       kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server;
-       kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server;
-       kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server;
+       if (options.gss_keyex) {
+               kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server;
+               kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server;
+               kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server;
+       }
 #endif
        kex->server = 1;
        kex->client_version_string=client_version_string;
index 414be2458674427f39da00a692afab994890bd8e..060249535a9a604f5aa9a5a4995602b8bc08209a 100644 (file)
@@ -390,6 +390,22 @@ on logout.
 The default is
 .Dq yes .
 Note that this option applies to protocol version 2 only.
+.It Cm GSSAPICredentialsPath
+If specified, the delegated GSSAPI credential is stored in the
+given path, overwriting any existing credentials.  
+Paths can be specified with syntax similar to the AuthorizedKeysFile 
+option (i.e., accepting %h and %u tokens).  
+When using this option,
+setting 'GssapiCleanupCredentials no' is recommended,
+so logging out of one session
+doesn't remove the credentials in use by another session of
+the same user.
+Currently only implemented for the GSI mechanism.
+.It Cm GSIAllowLimitedProxy
+Specifies whether to accept limited proxy credentials for
+authentication.
+The default is
+.Dq no .
 .It Cm GSSAPIStrictAcceptorCheck
 Determines whether to be strict about the identity of the GSSAPI acceptor 
 a client authenticates against. If
@@ -407,21 +423,10 @@ Note that this option applies only to protocol version 2 GSSAPI connections,
 and setting it to 
 .Dq no
 may only work with recent Kerberos GSSAPI libraries.
-.It Cm GSSAPICredentialsPath
-If specified, the delegated GSSAPI credential is stored in the
-given path, overwriting any existing credentials.  
-Paths can be specified with syntax similar to the AuthorizedKeysFile 
-option (i.e., accepting %h and %u tokens).  
-When using this option,
-setting 'GssapiCleanupCredentials no' is recommended,
-so logging out of one session
-doesn't remove the credentials in use by another session of
-the same user.
-Currently only implemented for the GSI mechanism.
-.It Cm GSIAllowLimitedProxy
-Specifies whether to accept limited proxy credentials for
-authentication.
-The default is
+.It Cm GSSAPIStoreCredentialsOnRekey
+Controls whether the user's GSSAPI credentials should be updated following a 
+successful connection rekeying. This option can be used to accepted renewed 
+or updated credentials from a compatible client. The default is
 .Dq no .
 .It Cm HostbasedAuthentication
 Specifies whether rhosts or /etc/hosts.equiv authentication together
index bf3a36846988f68cd8e32451c13ca0a02c6ea2c5..1c416ad9ef8971e3fd5440988027455774aabeeb 100644 (file)
@@ -23,6 +23,6 @@
 #define SSH_VERSION    "OpenSSH_5.2"
 
 #define SSH_PORTABLE   "p1"
-#define SSH_HPN         "-hpn13v5"
+#define SSH_HPN         "-hpn13v6"
 #define SSH_RELEASE    SSH_VERSION SSH_PORTABLE SSH_HPN \
             NCSA_VERSION GSI_VERSION KRB5_VERSION MGLUE_VERSION
This page took 6.47851 seconds and 5 git commands to generate.