Go to:
Gentoo Home
Documentation
Forums
Lists
Bugs
Planet
Store
Wiki
Get Gentoo!
Gentoo's Bugzilla – Attachment 87921 Details for
Bug 134973
Please incorporate gssapi-keyex patch into Gentoo openssh patchset
Home
|
New
–
[Ex]
|
Browse
|
Search
|
Privacy Policy
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
openssh-4.3p2-gsskex-20060223.patch
openssh-4.3p2-gsskex-20060223.patch (text/plain), 58.81 KB, created by
Bryan Jacobs
on 2006-05-30 16:22:31 UTC
(
hide
)
Description:
openssh-4.3p2-gsskex-20060223.patch
Filename:
MIME Type:
Creator:
Bryan Jacobs
Created:
2006-05-30 16:22:31 UTC
Size:
58.81 KB
patch
obsolete
>diff -urN openssh-4.3p2/auth2.c openssh-4.3p2+kex/auth2.c >--- openssh-4.3p2/auth2.c 2005-09-24 03:43:51.000000000 +0100 >+++ openssh-4.3p2+kex/auth2.c 2006-02-23 18:27:56.000000000 +0000 >@@ -55,6 +55,7 @@ > extern Authmethod method_kbdint; > extern Authmethod method_hostbased; > #ifdef GSSAPI >+extern Authmethod method_gsskeyex; > extern Authmethod method_gssapi; > #endif > >@@ -62,6 +63,7 @@ > &method_none, > &method_pubkey, > #ifdef GSSAPI >+ &method_gsskeyex, > &method_gssapi, > #endif > &method_passwd, >@@ -188,6 +190,7 @@ > #endif > > authctxt->postponed = 0; >+ authctxt->server_caused_failure = 0; > > /* try to authenticate user */ > m = authmethod_lookup(method); >@@ -258,7 +261,9 @@ > /* 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 >diff -urN openssh-4.3p2/auth2-gss.c openssh-4.3p2+kex/auth2-gss.c >--- openssh-4.3p2/auth2-gss.c 2005-11-05 04:07:05.000000000 +0000 >+++ openssh-4.3p2+kex/auth2-gss.c 2006-02-23 18:27:56.000000000 +0000 >@@ -46,6 +46,39 @@ > 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 @@ > > 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 @@ > 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, >diff -urN openssh-4.3p2/auth.h openssh-4.3p2+kex/auth.h >--- openssh-4.3p2/auth.h 2005-07-07 02:50:20.000000000 +0100 >+++ openssh-4.3p2+kex/auth.h 2006-02-23 18:27:56.000000000 +0000 >@@ -53,6 +53,7 @@ > 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; >diff -urN openssh-4.3p2/auth-krb5.c openssh-4.3p2+kex/auth-krb5.c >--- openssh-4.3p2/auth-krb5.c 2005-11-22 08:42:42.000000000 +0000 >+++ openssh-4.3p2+kex/auth-krb5.c 2006-02-23 18:27:56.000000000 +0000 >@@ -156,8 +156,13 @@ > > 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 @@ > #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 @@ > return errno; > } > close(tmpfd); >+#endif > > return (krb5_cc_resolve(ctx, ccname, ccache)); > } >diff -urN openssh-4.3p2/config.h.in openssh-4.3p2+kex/config.h.in >--- openssh-4.3p2/config.h.in 2006-02-11 00:07:35.000000000 +0000 >+++ openssh-4.3p2+kex/config.h.in 2006-02-23 18:27:56.000000000 +0000 >@@ -1213,6 +1213,9 @@ > /* Use btmp to log bad logins */ > #undef USE_BTMP > >+/* platform uses an in-memory credentials cache */ >+#undef USE_CCAPI >+ > /* Use libedit for sftp */ > #undef USE_LIBEDIT > >@@ -1228,6 +1231,9 @@ > /* Define if you want smartcard support using sectok */ > #undef USE_SECTOK > >+/* platform has the Security Authorization Session API */ >+#undef USE_SECURITY_SESSION_API >+ > /* Define if you shouldn't strip 'tty' from your ttyname in [uw]tmp */ > #undef WITH_ABBREV_NO_TTY > >diff -urN openssh-4.3p2/configure openssh-4.3p2+kex/configure >--- openssh-4.3p2/configure 2006-02-11 00:07:37.000000000 +0000 >+++ openssh-4.3p2+kex/configure 2006-02-23 18:27:56.000000000 +0000 >@@ -5285,6 +5285,125 @@ > #define BIND_8_COMPAT 1 > _ACEOF > >+ echo "$as_me:$LINENO: checking if we have the Security Authorization Session API" >&5 >+echo $ECHO_N "checking if we have the Security Authorization Session API... $ECHO_C" >&6 >+ cat >conftest.$ac_ext <<_ACEOF >+/* confdefs.h. */ >+_ACEOF >+cat confdefs.h >>conftest.$ac_ext >+cat >>conftest.$ac_ext <<_ACEOF >+/* end confdefs.h. */ >+#include <Security/AuthSession.h> >+int >+main () >+{ >+SessionCreate(0, 0); >+ ; >+ return 0; >+} >+_ACEOF >+rm -f conftest.$ac_objext >+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 >+ (eval $ac_compile) 2>conftest.er1 >+ ac_status=$? >+ grep -v '^ *+' conftest.er1 >conftest.err >+ rm -f conftest.er1 >+ cat conftest.err >&5 >+ echo "$as_me:$LINENO: \$? = $ac_status" >&5 >+ (exit $ac_status); } && >+ { ac_try='test -z "$ac_c_werror_flag" >+ || test ! -s conftest.err' >+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 >+ (eval $ac_try) 2>&5 >+ ac_status=$? >+ echo "$as_me:$LINENO: \$? = $ac_status" >&5 >+ (exit $ac_status); }; } && >+ { ac_try='test -s conftest.$ac_objext' >+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 >+ (eval $ac_try) 2>&5 >+ ac_status=$? >+ echo "$as_me:$LINENO: \$? = $ac_status" >&5 >+ (exit $ac_status); }; }; then >+ ac_cv_use_security_session_api="yes" >+ >+cat >>confdefs.h <<\_ACEOF >+#define USE_SECURITY_SESSION_API 1 >+_ACEOF >+ >+ LIBS="$LIBS -framework Security" >+ echo "$as_me:$LINENO: result: yes" >&5 >+echo "${ECHO_T}yes" >&6 >+else >+ echo "$as_me: failed program was:" >&5 >+sed 's/^/| /' conftest.$ac_ext >&5 >+ >+ac_cv_use_security_session_api="no" >+ echo "$as_me:$LINENO: result: no" >&5 >+echo "${ECHO_T}no" >&6 >+fi >+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext >+ echo "$as_me:$LINENO: checking if we have an in-memory credentials cache" >&5 >+echo $ECHO_N "checking if we have an in-memory credentials cache... $ECHO_C" >&6 >+ cat >conftest.$ac_ext <<_ACEOF >+/* confdefs.h. */ >+_ACEOF >+cat confdefs.h >>conftest.$ac_ext >+cat >>conftest.$ac_ext <<_ACEOF >+/* end confdefs.h. */ >+#include <Kerberos/Kerberos.h> >+int >+main () >+{ >+cc_context_t c; >+ (void) cc_initialize (&c, 0, NULL, NULL); >+ ; >+ return 0; >+} >+_ACEOF >+rm -f conftest.$ac_objext >+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 >+ (eval $ac_compile) 2>conftest.er1 >+ ac_status=$? >+ grep -v '^ *+' conftest.er1 >conftest.err >+ rm -f conftest.er1 >+ cat conftest.err >&5 >+ echo "$as_me:$LINENO: \$? = $ac_status" >&5 >+ (exit $ac_status); } && >+ { ac_try='test -z "$ac_c_werror_flag" >+ || test ! -s conftest.err' >+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 >+ (eval $ac_try) 2>&5 >+ ac_status=$? >+ echo "$as_me:$LINENO: \$? = $ac_status" >&5 >+ (exit $ac_status); }; } && >+ { ac_try='test -s conftest.$ac_objext' >+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 >+ (eval $ac_try) 2>&5 >+ ac_status=$? >+ echo "$as_me:$LINENO: \$? = $ac_status" >&5 >+ (exit $ac_status); }; }; then >+ >+cat >>confdefs.h <<\_ACEOF >+#define USE_CCAPI 1 >+_ACEOF >+ >+ LIBS="$LIBS -framework Security" >+ echo "$as_me:$LINENO: result: yes" >&5 >+echo "${ECHO_T}yes" >&6 >+ if test "x$ac_cv_use_security_session_api" = "xno"; then >+ { { echo "$as_me:$LINENO: error: *** Need a security framework to use the credentials cache API ***" >&5 >+echo "$as_me: error: *** Need a security framework to use the credentials cache API ***" >&2;} >+ { (exit 1); exit 1; }; } >+ fi >+else >+ echo "$as_me: failed program was:" >&5 >+sed 's/^/| /' conftest.$ac_ext >&5 >+ >+echo "$as_me:$LINENO: result: no" >&5 >+echo "${ECHO_T}no" >&6 >+ >+fi >+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext > ;; > *-*-hpux*) > # first we define all of the options common to all HP-UX releases >@@ -27224,9 +27343,9 @@ > exec 5>>config.log > { > echo >- sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<BOXI_EOF >+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX > ## Running $as_me. ## >-BOXI_EOF >+_ASBOX > } >&5 > cat >&5 <<_CSEOF > >diff -urN openssh-4.3p2/configure.ac openssh-4.3p2+kex/configure.ac >--- openssh-4.3p2/configure.ac 2006-02-08 11:11:06.000000000 +0000 >+++ openssh-4.3p2+kex/configure.ac 2006-02-23 18:27:56.000000000 +0000 >@@ -231,6 +231,30 @@ > 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 >diff -urN openssh-4.3p2/gss-genr.c openssh-4.3p2+kex/gss-genr.c >--- openssh-4.3p2/gss-genr.c 2005-11-05 04:07:05.000000000 +0000 >+++ openssh-4.3p2+kex/gss-genr.c 2006-02-23 18:27:56.000000000 +0000 >@@ -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 >@@ -32,12 +32,152 @@ > #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 @@ > 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 @@ > 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 @@ > 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 */ >diff -urN openssh-4.3p2/gss-serv.c openssh-4.3p2+kex/gss-serv.c >--- openssh-4.3p2/gss-serv.c 2005-11-05 04:07:05.000000000 +0000 >+++ openssh-4.3p2+kex/gss-serv.c 2006-02-23 18:27:56.000000000 +0000 >@@ -36,6 +36,7 @@ > #include "servconf.h" > #include "xmalloc.h" > #include "getput.h" >+#include "monitor_wrap.h" > > #include "ssh-gss.h" > >@@ -58,6 +59,28 @@ > }; > > /* 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 @@ > 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 >diff -urN openssh-4.3p2/kex.c openssh-4.3p2+kex/kex.c >--- openssh-4.3p2/kex.c 2005-11-05 04:19:36.000000000 +0000 >+++ openssh-4.3p2+kex/kex.c 2006-02-23 18:27:56.000000000 +0000 >@@ -42,6 +42,10 @@ > #include "dispatch.h" > #include "monitor.h" > >+#ifdef GSSAPI >+#include "ssh-gss.h" >+#endif >+ > #define KEX_COOKIE_LEN 16 > > /* prototype */ >@@ -301,6 +305,16 @@ > } 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); > } >diff -urN openssh-4.3p2/kexgssc.c openssh-4.3p2+kex/kexgssc.c >--- openssh-4.3p2/kexgssc.c 1970-01-01 01:00:00.000000000 +0100 >+++ openssh-4.3p2+kex/kexgssc.c 2006-02-23 18:27:56.000000000 +0000 >@@ -0,0 +1,303 @@ >+/* >+ * 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 >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR >+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES >+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. >+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, >+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT >+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, >+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY >+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF >+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#include "includes.h" >+ >+#ifdef GSSAPI >+ >+#include <openssl/crypto.h> >+#include <openssl/bn.h> >+ >+#include "xmalloc.h" >+#include "buffer.h" >+#include "bufaux.h" >+#include "kex.h" >+#include "log.h" >+#include "packet.h" >+#include "dh.h" >+#include "canohost.h" >+#include "ssh2.h" >+#include "ssh-gss.h" >+ >+void >+kexgss_client(Kex *kex) { >+ gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; >+ gss_buffer_desc recv_tok, gssbuf, msg_tok, *token_ptr; >+ Gssctxt *ctxt; >+ OM_uint32 maj_status, min_status, ret_flags; >+ u_int klen, kout, slen = 0, hashlen, strlen; >+ DH *dh; >+ BIGNUM *dh_server_pub = NULL; >+ BIGNUM *shared_secret = NULL; >+ BIGNUM *p = NULL; >+ BIGNUM *g = NULL; >+ u_char *kbuf, *hash; >+ u_char *serverhostkey = NULL; >+ char *msg; >+ char *lang; >+ int type = 0; >+ int first = 1; >+ int gex = 0; >+ int nbits, min, max; >+ >+ /* Initialise our GSSAPI world */ >+ ssh_gssapi_build_ctx(&ctxt); >+ if (ssh_gssapi_id_kex(ctxt, kex->name, &gex) == NULL) >+ fatal("Couldn't identify host exchange"); >+ >+ if (ssh_gssapi_import_name(ctxt, kex->gss_host)) >+ fatal("Couldn't import hostname"); >+ >+ if (gex) { >+ debug("Doing group exchange\n"); >+ nbits = dh_estimate(kex->we_need * 8); >+ min = DH_GRP_MIN; >+ max = DH_GRP_MAX; >+ packet_start(SSH2_MSG_KEXGSS_GROUPREQ); >+ packet_put_int(min); >+ packet_put_int(nbits); >+ packet_put_int(max); >+ >+ packet_send(); >+ >+ packet_read_expect(SSH2_MSG_KEXGSS_GROUP); >+ >+ if ((p = BN_new()) == NULL) >+ fatal("BN_new() failed"); >+ packet_get_bignum2(p); >+ if ((g = BN_new()) == NULL) >+ fatal("BN_new() failed"); >+ packet_get_bignum2(g); >+ packet_check_eom(); >+ >+ if (BN_num_bits(p) < min || BN_num_bits(p) > max) >+ fatal("GSSGRP_GEX group out of range: %d !< %d !< %d", >+ min, BN_num_bits(p), max); >+ >+ dh = dh_new_group(g, p); >+ } else { >+ dh = dh_new_group1(); >+ } >+ >+ /* Step 1 - e is dh->pub_key */ >+ dh_gen_key(dh, kex->we_need * 8); >+ >+ /* This is f, we initialise it now to make life easier */ >+ dh_server_pub = BN_new(); >+ if (dh_server_pub == NULL) >+ fatal("dh_server_pub == NULL"); >+ >+ token_ptr = GSS_C_NO_BUFFER; >+ >+ do { >+ debug("Calling gss_init_sec_context"); >+ >+ maj_status = ssh_gssapi_init_ctx(ctxt, >+ kex->gss_deleg_creds, token_ptr, &send_tok, >+ &ret_flags); >+ >+ if (GSS_ERROR(maj_status)) { >+ if (send_tok.length != 0) { >+ packet_start(SSH2_MSG_KEXGSS_CONTINUE); >+ packet_put_string(send_tok.value, >+ send_tok.length); >+ } >+ fatal("gss_init_context failed"); >+ } >+ >+ /* If we've got an old receive buffer get rid of it */ >+ if (token_ptr != GSS_C_NO_BUFFER) >+ xfree(recv_tok.value); >+ >+ if (maj_status == GSS_S_COMPLETE) { >+ /* If mutual state flag is not true, kex fails */ >+ if (!(ret_flags & GSS_C_MUTUAL_FLAG)) >+ fatal("Mutual authentication failed"); >+ >+ /* If integ avail flag is not true kex fails */ >+ if (!(ret_flags & GSS_C_INTEG_FLAG)) >+ fatal("Integrity check failed"); >+ } >+ >+ /* >+ * If we have data to send, then the last message that we >+ * received cannot have been a 'complete'. >+ */ >+ if (send_tok.length != 0) { >+ if (first) { >+ packet_start(SSH2_MSG_KEXGSS_INIT); >+ packet_put_string(send_tok.value, >+ send_tok.length); >+ packet_put_bignum2(dh->pub_key); >+ first = 0; >+ } else { >+ packet_start(SSH2_MSG_KEXGSS_CONTINUE); >+ packet_put_string(send_tok.value, >+ send_tok.length); >+ } >+ packet_send(); >+ gss_release_buffer(&min_status, &send_tok); >+ >+ /* If we've sent them data, they should reply */ >+ do { >+ type = packet_read(); >+ if (type == SSH2_MSG_KEXGSS_HOSTKEY) { >+ debug("Received KEXGSS_HOSTKEY"); >+ if (serverhostkey) >+ fatal("Server host key received more than once"); >+ serverhostkey = >+ packet_get_string(&slen); >+ } >+ } while (type == SSH2_MSG_KEXGSS_HOSTKEY); >+ >+ switch (type) { >+ case SSH2_MSG_KEXGSS_CONTINUE: >+ debug("Received GSSAPI_CONTINUE"); >+ if (maj_status == GSS_S_COMPLETE) >+ fatal("GSSAPI Continue received from server when complete"); >+ recv_tok.value = packet_get_string(&strlen); >+ recv_tok.length = strlen; >+ break; >+ case SSH2_MSG_KEXGSS_COMPLETE: >+ debug("Received GSSAPI_COMPLETE"); >+ packet_get_bignum2(dh_server_pub); >+ msg_tok.value = packet_get_string(&strlen); >+ msg_tok.length = strlen; >+ >+ /* Is there a token included? */ >+ if (packet_get_char()) { >+ recv_tok.value= >+ packet_get_string(&strlen); >+ recv_tok.length = strlen; >+ /* If we're already complete - protocol error */ >+ if (maj_status == GSS_S_COMPLETE) >+ packet_disconnect("Protocol error: received token when complete"); >+ } else { >+ /* No token included */ >+ if (maj_status != GSS_S_COMPLETE) >+ packet_disconnect("Protocol error: did not receive final token"); >+ } >+ break; >+ case SSH2_MSG_KEXGSS_ERROR: >+ debug("Received Error"); >+ maj_status = packet_get_int(); >+ min_status = packet_get_int(); >+ msg = packet_get_string(NULL); >+ lang = packet_get_string(NULL); >+ fatal("GSSAPI Error: \n%s",msg); >+ default: >+ packet_disconnect("Protocol error: didn't expect packet type %d", >+ type); >+ } >+ token_ptr = &recv_tok; >+ } else { >+ /* No data, and not complete */ >+ if (maj_status != GSS_S_COMPLETE) >+ fatal("Not complete, and no token output"); >+ } >+ } while (maj_status & GSS_S_CONTINUE_NEEDED); >+ >+ /* >+ * We _must_ have received a COMPLETE message in reply from the >+ * server, which will have set dh_server_pub and msg_tok >+ */ >+ >+ if (type != SSH2_MSG_KEXGSS_COMPLETE) >+ fatal("Didn't receive a SSH2_MSG_KEXGSS_COMPLETE when I expected it"); >+ >+ /* Check f in range [1, p-1] */ >+ if (!dh_pub_is_valid(dh, dh_server_pub)) >+ packet_disconnect("bad server public DH value"); >+ >+ /* compute K=f^x mod p */ >+ klen = DH_size(dh); >+ kbuf = xmalloc(klen); >+ kout = DH_compute_key(kbuf, dh_server_pub, dh); >+ >+ shared_secret = BN_new(); >+ BN_bin2bn(kbuf,kout, shared_secret); >+ memset(kbuf, 0, klen); >+ xfree(kbuf); >+ >+ if (gex) { >+ kexgex_hash( >+ kex->evp_md, >+ kex->client_version_string, >+ kex->server_version_string, >+ buffer_ptr(&kex->my), buffer_len(&kex->my), >+ buffer_ptr(&kex->peer), buffer_len(&kex->peer), >+ serverhostkey, slen, >+ min, nbits, max, >+ dh->p, dh->g, >+ dh->pub_key, >+ dh_server_pub, >+ shared_secret, >+ &hash, &hashlen >+ ); >+ } else { >+ /* The GSS hash is identical to the DH one */ >+ kex_dh_hash( kex->client_version_string, >+ 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 */ >+ dh->pub_key, /* e */ >+ dh_server_pub, /* f */ >+ shared_secret, /* K */ >+ &hash, &hashlen >+ ); >+ } >+ >+ gssbuf.value = hash; >+ gssbuf.length = hashlen; >+ >+ /* Verify that the hash matches the MIC we just got. */ >+ if (GSS_ERROR(ssh_gssapi_checkmic(ctxt, &gssbuf, &msg_tok))) >+ packet_disconnect("Hash's MIC didn't verify"); >+ >+ xfree(msg_tok.value); >+ >+ DH_free(dh); >+ if (serverhostkey) >+ xfree(serverhostkey); >+ BN_clear_free(dh_server_pub); >+ >+ /* save session id */ >+ if (kex->session_id == NULL) { >+ kex->session_id_len = hashlen; >+ kex->session_id = xmalloc(kex->session_id_len); >+ memcpy(kex->session_id, hash, kex->session_id_len); >+ } >+ >+ if (gss_kex_context == NULL) >+ gss_kex_context = ctxt; >+ else >+ ssh_gssapi_delete_ctx(&ctxt); >+ >+ kex_derive_keys(kex, hash, hashlen, shared_secret); >+ BN_clear_free(shared_secret); >+ kex_finish(kex); >+} >+ >+#endif /* GSSAPI */ >diff -urN openssh-4.3p2/kexgsss.c openssh-4.3p2+kex/kexgsss.c >--- openssh-4.3p2/kexgsss.c 1970-01-01 01:00:00.000000000 +0100 >+++ openssh-4.3p2+kex/kexgsss.c 2006-02-23 18:27:56.000000000 +0000 >@@ -0,0 +1,256 @@ >+/* >+ * 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 >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR >+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES >+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. >+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, >+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT >+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, >+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY >+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF >+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#include "includes.h" >+ >+#ifdef GSSAPI >+ >+#include <openssl/crypto.h> >+#include <openssl/bn.h> >+ >+#include "xmalloc.h" >+#include "buffer.h" >+#include "bufaux.h" >+#include "kex.h" >+#include "log.h" >+#include "packet.h" >+#include "dh.h" >+#include "ssh2.h" >+#include "ssh-gss.h" >+#include "monitor_wrap.h" >+ >+void >+kexgss_server(Kex *kex) >+{ >+ OM_uint32 maj_status, min_status; >+ >+ /* >+ * Some GSSAPI implementations use the input value of ret_flags (an >+ * output variable) as a means of triggering mechanism specific >+ * features. Initializing it to zero avoids inadvertently >+ * activating this non-standard behaviour. >+ */ >+ >+ OM_uint32 ret_flags = 0; >+ gss_buffer_desc gssbuf, recv_tok, msg_tok; >+ gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; >+ Gssctxt *ctxt = NULL; >+ u_int slen, klen, kout, hashlen; >+ u_char *kbuf, *hash; >+ DH *dh; >+ int min = -1, max = -1, nbits = -1; >+ BIGNUM *shared_secret = NULL; >+ BIGNUM *dh_client_pub = NULL; >+ int type = 0; >+ int gex; >+ gss_OID oid; >+ >+ /* Initialise GSSAPI */ >+ >+ /* If we're rekeying, privsep means that some of the private structures >+ * in the GSSAPI code are no longer available. This kludges them back >+ * into life >+ */ >+ if (!ssh_gssapi_oid_table_ok()) >+ ssh_gssapi_server_mechanisms(); >+ >+ debug2("%s: Identifying %s", __func__, kex->name); >+ oid = ssh_gssapi_id_kex(NULL, kex->name, &gex); >+ if (oid == NULL) >+ fatal("Unknown gssapi mechanism"); >+ >+ debug2("%s: Acquiring credentials", __func__); >+ >+ if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, oid)))) >+ fatal("Unable to acquire credentials for the server"); >+ >+ if (gex) { >+ debug("Doing group exchange"); >+ packet_read_expect(SSH2_MSG_KEXGSS_GROUPREQ); >+ min = packet_get_int(); >+ nbits = packet_get_int(); >+ max = packet_get_int(); >+ min = MAX(DH_GRP_MIN, min); >+ max = MIN(DH_GRP_MAX, max); >+ packet_check_eom(); >+ if (max < min || nbits < min || max < nbits) >+ fatal("GSS_GEX, bad parameters: %d !< %d !< %d", >+ min, nbits, max); >+ dh = PRIVSEP(choose_dh(min, nbits, max)); >+ if (dh == NULL) >+ packet_disconnect("Protocol error: no matching group found"); >+ >+ packet_start(SSH2_MSG_KEXGSS_GROUP); >+ packet_put_bignum2(dh->p); >+ packet_put_bignum2(dh->g); >+ packet_send(); >+ >+ packet_write_wait(); >+ >+ } else { >+ dh = dh_new_group1(); >+ } >+ dh_gen_key(dh, kex->we_need * 8); >+ >+ do { >+ debug("Wait SSH2_MSG_GSSAPI_INIT"); >+ type = packet_read(); >+ switch(type) { >+ case SSH2_MSG_KEXGSS_INIT: >+ if (dh_client_pub != NULL) >+ fatal("Received KEXGSS_INIT after initialising"); >+ recv_tok.value = packet_get_string(&slen); >+ recv_tok.length = slen; >+ >+ if ((dh_client_pub = BN_new()) == NULL) >+ fatal("dh_client_pub == NULL"); >+ >+ packet_get_bignum2(dh_client_pub); >+ >+ /* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */ >+ break; >+ case SSH2_MSG_KEXGSS_CONTINUE: >+ recv_tok.value = packet_get_string(&slen); >+ recv_tok.length = slen; >+ break; >+ default: >+ packet_disconnect( >+ "Protocol error: didn't expect packet type %d", >+ type); >+ } >+ >+ maj_status = PRIVSEP(ssh_gssapi_accept_ctx(ctxt, &recv_tok, >+ &send_tok, &ret_flags)); >+ >+ xfree(recv_tok.value); >+ >+ if (maj_status != GSS_S_COMPLETE && send_tok.length == 0) >+ fatal("Zero length token output when incomplete"); >+ >+ if (dh_client_pub == NULL) >+ fatal("No client public key"); >+ >+ 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_send(); >+ gss_release_buffer(&min_status, &send_tok); >+ } >+ } while (maj_status & GSS_S_CONTINUE_NEEDED); >+ >+ if (GSS_ERROR(maj_status)) { >+ if (send_tok.length > 0) { >+ packet_start(SSH2_MSG_KEXGSS_CONTINUE); >+ packet_put_string(send_tok.value, send_tok.length); >+ packet_send(); >+ } >+ fatal("accept_ctx died"); >+ } >+ >+ if (!(ret_flags & GSS_C_MUTUAL_FLAG)) >+ fatal("Mutual Authentication flag wasn't set"); >+ >+ if (!(ret_flags & GSS_C_INTEG_FLAG)) >+ fatal("Integrity flag wasn't set"); >+ >+ if (!dh_pub_is_valid(dh, dh_client_pub)) >+ packet_disconnect("bad client public DH value"); >+ >+ klen = DH_size(dh); >+ kbuf = xmalloc(klen); >+ kout = DH_compute_key(kbuf, dh_client_pub, dh); >+ >+ shared_secret = BN_new(); >+ BN_bin2bn(kbuf, kout, shared_secret); >+ memset(kbuf, 0, klen); >+ xfree(kbuf); >+ >+ if (gex) { >+ kexgex_hash( >+ kex->evp_md, >+ kex->client_version_string, kex->server_version_string, >+ buffer_ptr(&kex->peer), buffer_len(&kex->peer), >+ buffer_ptr(&kex->my), buffer_len(&kex->my), >+ NULL, 0, >+ min, nbits, max, >+ dh->p, dh->g, >+ dh_client_pub, >+ dh->pub_key, >+ shared_secret, >+ &hash, &hashlen >+ ); >+ } >+ else { >+ /* The GSSAPI hash is identical to the Diffie Helman one */ >+ kex_dh_hash( >+ kex->client_version_string, kex->server_version_string, >+ buffer_ptr(&kex->peer), buffer_len(&kex->peer), >+ buffer_ptr(&kex->my), buffer_len(&kex->my), >+ NULL, 0, /* Change this if we start sending host keys */ >+ dh_client_pub, dh->pub_key, shared_secret, >+ &hash, &hashlen >+ ); >+ } >+ BN_free(dh_client_pub); >+ >+ if (kex->session_id == NULL) { >+ kex->session_id_len = hashlen; >+ kex->session_id = xmalloc(kex->session_id_len); >+ memcpy(kex->session_id, hash, kex->session_id_len); >+ } >+ >+ gssbuf.value = hash; >+ gssbuf.length = hashlen; >+ >+ if (GSS_ERROR(PRIVSEP(ssh_gssapi_sign(ctxt,&gssbuf,&msg_tok)))) >+ fatal("Couldn't get MIC"); >+ >+ packet_start(SSH2_MSG_KEXGSS_COMPLETE); >+ packet_put_bignum2(dh->pub_key); >+ packet_put_string((char *)msg_tok.value,msg_tok.length); >+ >+ if (send_tok.length != 0) { >+ packet_put_char(1); /* true */ >+ packet_put_string((char *)send_tok.value, send_tok.length); >+ } else { >+ packet_put_char(0); /* false */ >+ } >+ packet_send(); >+ >+ gss_release_buffer(&min_status, &send_tok); >+ gss_release_buffer(&min_status, &msg_tok); >+ >+ if (gss_kex_context == NULL) >+ gss_kex_context = ctxt; >+ else >+ ssh_gssapi_delete_ctx(&ctxt); >+ >+ DH_free(dh); >+ >+ kex_derive_keys(kex, hash, hashlen, shared_secret); >+ BN_clear_free(shared_secret); >+ kex_finish(kex); >+} >+#endif /* GSSAPI */ >diff -urN openssh-4.3p2/kex.h openssh-4.3p2+kex/kex.h >--- openssh-4.3p2/kex.h 2005-11-05 04:19:36.000000000 +0000 >+++ openssh-4.3p2+kex/kex.h 2006-02-23 18:27:56.000000000 +0000 >@@ -63,6 +63,8 @@ > 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 @@ > 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 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 *); >diff -urN openssh-4.3p2/key.c openssh-4.3p2+kex/key.c >--- openssh-4.3p2/key.c 2005-06-17 03:59:35.000000000 +0100 >+++ openssh-4.3p2+kex/key.c 2006-02-23 18:27:56.000000000 +0000 >@@ -650,6 +650,8 @@ > 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; >diff -urN openssh-4.3p2/key.h openssh-4.3p2+kex/key.h >--- openssh-4.3p2/key.h 2003-11-17 10:18:23.000000000 +0000 >+++ openssh-4.3p2+kex/key.h 2006-02-23 18:27:56.000000000 +0000 >@@ -34,6 +34,7 @@ > KEY_RSA1, > KEY_RSA, > KEY_DSA, >+ KEY_NULL, > KEY_UNSPEC > }; > enum fp_type { >diff -urN openssh-4.3p2/Makefile.in openssh-4.3p2+kex/Makefile.in >--- openssh-4.3p2/Makefile.in 2006-01-01 08:47:05.000000000 +0000 >+++ openssh-4.3p2+kex/Makefile.in 2006-02-23 18:27:56.000000000 +0000 >@@ -71,7 +71,7 @@ > 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 @@ > 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 > >diff -urN openssh-4.3p2/monitor.c openssh-4.3p2+kex/monitor.c >--- openssh-4.3p2/monitor.c 2005-11-05 04:07:05.000000000 +0000 >+++ openssh-4.3p2+kex/monitor.c 2006-02-23 18:27:56.000000000 +0000 >@@ -141,6 +141,7 @@ > 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 @@ > {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 @@ > /* 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_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 @@ > 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 @@ > 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 @@ > /* 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 */ >diff -urN openssh-4.3p2/monitor.h openssh-4.3p2+kex/monitor.h >--- openssh-4.3p2/monitor.h 2005-02-02 13:20:53.000000000 +0000 >+++ openssh-4.3p2+kex/monitor.h 2006-02-23 18:27:56.000000000 +0000 >@@ -53,6 +53,7 @@ > 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, >diff -urN openssh-4.3p2/monitor_wrap.c openssh-4.3p2+kex/monitor_wrap.c >--- openssh-4.3p2/monitor_wrap.c 2005-09-29 13:01:10.000000000 +0100 >+++ openssh-4.3p2+kex/monitor_wrap.c 2006-02-23 18:27:56.000000000 +0000 >@@ -1215,4 +1215,27 @@ > 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 */ >diff -urN openssh-4.3p2/monitor_wrap.h openssh-4.3p2+kex/monitor_wrap.h >--- openssh-4.3p2/monitor_wrap.h 2005-02-08 10:52:48.000000000 +0000 >+++ openssh-4.3p2+kex/monitor_wrap.h 2006-02-23 18:27:56.000000000 +0000 >@@ -63,6 +63,7 @@ > 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 >diff -urN openssh-4.3p2/readconf.c openssh-4.3p2+kex/readconf.c >--- openssh-4.3p2/readconf.c 2005-12-13 08:33:20.000000000 +0000 >+++ openssh-4.3p2+kex/readconf.c 2006-02-23 18:27:56.000000000 +0000 >@@ -109,6 +109,7 @@ > 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 @@ > #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 @@ > 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 @@ > 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 @@ > 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) >diff -urN openssh-4.3p2/readconf.h openssh-4.3p2+kex/readconf.h >--- openssh-4.3p2/readconf.h 2005-12-13 08:29:02.000000000 +0000 >+++ openssh-4.3p2+kex/readconf.h 2006-02-23 18:27:56.000000000 +0000 >@@ -46,6 +46,7 @@ > /* 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. */ >diff -urN openssh-4.3p2/servconf.c openssh-4.3p2+kex/servconf.c >--- openssh-4.3p2/servconf.c 2005-12-13 08:33:20.000000000 +0000 >+++ openssh-4.3p2+kex/servconf.c 2006-02-23 18:27:56.000000000 +0000 >@@ -72,6 +72,7 @@ > 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 @@ > 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 @@ > 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 @@ > { "afstokenpassing", sUnsupported }, > #ifdef GSSAPI > { "gssapiauthentication", sGssAuthentication }, >+ { "gssapikeyexchange", sGssKeyEx }, > { "gssapicleanupcredentials", sGssCleanupCreds }, > #else > { "gssapiauthentication", sUnsupported }, >+ { "gssapikeyexchange", sUnsupported }, > { "gssapicleanupcredentials", sUnsupported }, > #endif > { "passwordauthentication", sPasswordAuthentication }, >@@ -673,6 +679,10 @@ > 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; >diff -urN openssh-4.3p2/servconf.h openssh-4.3p2+kex/servconf.h >--- openssh-4.3p2/servconf.h 2005-12-13 08:29:03.000000000 +0000 >+++ openssh-4.3p2+kex/servconf.h 2006-02-23 18:27:56.000000000 +0000 >@@ -88,6 +88,7 @@ > 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. */ >diff -urN openssh-4.3p2/ssh_config.5 openssh-4.3p2+kex/ssh_config.5 >--- openssh-4.3p2/ssh_config.5 2006-01-31 10:39:03.000000000 +0000 >+++ openssh-4.3p2+kex/ssh_config.5 2006-02-23 18:27:56.000000000 +0000 >@@ -471,6 +471,16 @@ > 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 >diff -urN openssh-4.3p2/sshconnect2.c openssh-4.3p2+kex/sshconnect2.c >--- openssh-4.3p2/sshconnect2.c 2005-11-05 04:07:33.000000000 +0000 >+++ openssh-4.3p2+kex/sshconnect2.c 2006-02-23 18:27:56.000000000 +0000 >@@ -84,9 +84,34 @@ > { > 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 @@ > 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 @@ > 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_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 @@ > > Authmethod authmethods[] = { > #ifdef GSSAPI >+ {"gssapi-keyex", >+ userauth_gsskeyex, >+ &options.gss_authentication, >+ NULL}, > {"gssapi-with-mic", > userauth_gssapi, > &options.gss_authentication, >@@ -706,6 +758,48 @@ > 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 >diff -urN openssh-4.3p2/sshd.c openssh-4.3p2+kex/sshd.c >--- openssh-4.3p2/sshd.c 2005-12-24 03:59:12.000000000 +0000 >+++ openssh-4.3p2+kex/sshd.c 2006-02-23 18:27:56.000000000 +0000 >@@ -86,6 +86,10 @@ > #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 @@ > 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 @@ > /* 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 @@ > 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; > >diff -urN openssh-4.3p2/sshd_config.5 openssh-4.3p2+kex/sshd_config.5 >--- openssh-4.3p2/sshd_config.5 2006-01-03 07:47:31.000000000 +0000 >+++ openssh-4.3p2+kex/sshd_config.5 2006-02-23 18:27:56.000000000 +0000 >@@ -277,6 +277,12 @@ > 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. >diff -urN openssh-4.3p2/ssh-gss.h openssh-4.3p2+kex/ssh-gss.h >--- openssh-4.3p2/ssh-gss.h 2004-06-22 03:56:02.000000000 +0100 >+++ openssh-4.3p2+kex/ssh-gss.h 2006-02-23 18:27:56.000000000 +0000 >@@ -62,6 +62,16 @@ > > #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 @@ > } 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_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 */
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 134973
: 87921