From 3fdf10cdb481bce274f68f9b0fb389e5104e7b9f Mon Sep 17 00:00:00 2001 From: "Jan F. Chadima" Date: Mon, 3 May 2010 13:32:38 +0000 Subject: [PATCH] - Create separate ldap package - Tweak the ldap patch - Rename stderr patch properly --- openssh-5.5p1-fips.patch | 4 +- openssh-5.5p1-gsskex.patch | 2933 +++++++++++++++++ ...ldap.patch => openssh-5.5p1-pka-ldap.patch | 553 +++- openssh-5.5p1-stderr.patch | 157 + openssh.spec | 49 +- 5 files changed, 3557 insertions(+), 139 deletions(-) create mode 100644 openssh-5.5p1-gsskex.patch rename openssh-5.5p1-ldap.patch => openssh-5.5p1-pka-ldap.patch (83%) create mode 100644 openssh-5.5p1-stderr.patch diff --git a/openssh-5.5p1-fips.patch b/openssh-5.5p1-fips.patch index e098978..2f6db6f 100644 --- a/openssh-5.5p1-fips.patch +++ b/openssh-5.5p1-fips.patch @@ -222,7 +222,7 @@ diff -up openssh-5.5p1/mac.c.fips openssh-5.5p1/mac.c diff -up openssh-5.5p1/Makefile.in.fips openssh-5.5p1/Makefile.in --- openssh-5.5p1/Makefile.in.fips 2010-03-13 22:41:34.000000000 +0100 +++ openssh-5.5p1/Makefile.in 2010-04-16 09:48:16.000000000 +0200 -@@ -139,31 +139,31 @@ libssh.a: $(LIBSSH_OBJS) +@@ -141,25 +141,25 @@ $(RANLIB) $@ ssh$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHOBJS) @@ -254,6 +254,8 @@ diff -up openssh-5.5p1/Makefile.in.fips openssh-5.5p1/Makefile.in ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-pkcs11-helper.o ssh-pkcs11.o $(LD) -o $@ ssh-pkcs11-helper.o ssh-pkcs11.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) +@@ -168,7 +168,7 @@ + $(LD) -o $@ ldapconf.o ldapbody.o ldapmisc.o ldap-helper.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o roaming_dummy.o - $(LD) -o $@ ssh-keyscan.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) diff --git a/openssh-5.5p1-gsskex.patch b/openssh-5.5p1-gsskex.patch new file mode 100644 index 0000000..3ffaf85 --- /dev/null +++ b/openssh-5.5p1-gsskex.patch @@ -0,0 +1,2933 @@ +diff -up openssh-5.4p1/auth2.c.gsskex openssh-5.4p1/auth2.c +--- openssh-5.4p1/auth2.c.gsskex 2010-03-01 18:14:24.000000000 +0100 ++++ openssh-5.4p1/auth2.c 2010-03-01 18:14:28.000000000 +0100 +@@ -69,6 +69,7 @@ extern Authmethod method_passwd; + extern Authmethod method_kbdint; + extern Authmethod method_hostbased; + #ifdef GSSAPI ++extern Authmethod method_gsskeyex; + extern Authmethod method_gssapi; + #endif + #ifdef JPAKE +@@ -79,6 +80,7 @@ Authmethod *authmethods[] = { + &method_none, + &method_pubkey, + #ifdef GSSAPI ++ &method_gsskeyex, + &method_gssapi, + #endif + #ifdef JPAKE +@@ -289,6 +291,7 @@ input_userauth_request(int type, u_int32 + #endif + + authctxt->postponed = 0; ++ authctxt->server_caused_failure = 0; + + /* try to authenticate user */ + m = authmethod_lookup(method); +@@ -361,7 +364,8 @@ userauth_finish(Authctxt *authctxt, int + } else { + + /* Allow initial try of "none" auth without failure penalty */ +- if (authctxt->attempt > 1 || strcmp(method, "none") != 0) ++ if (!authctxt->server_caused_failure && ++ (authctxt->attempt > 1 || strcmp(method, "none") != 0)) + authctxt->failures++; + if (authctxt->failures >= options.max_authtries) { + #ifdef SSH_AUDIT_EVENTS +diff -up openssh-5.4p1/auth2-gss.c.gsskex openssh-5.4p1/auth2-gss.c +--- openssh-5.4p1/auth2-gss.c.gsskex 2010-03-01 18:14:24.000000000 +0100 ++++ openssh-5.4p1/auth2-gss.c 2010-03-01 18:14:28.000000000 +0100 +@@ -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 +@@ -52,6 +52,40 @@ static void input_gssapi_mic(int type, u + 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, ++ authctxt->pw)); ++ ++ 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) +@@ -102,6 +136,7 @@ userauth_gssapi(Authctxt *authctxt) + + if (!present) { + xfree(doid); ++ authctxt->server_caused_failure = 1; + return (0); + } + +@@ -109,6 +144,7 @@ userauth_gssapi(Authctxt *authctxt) + if (ctxt != NULL) + ssh_gssapi_delete_ctx(&ctxt); + xfree(doid); ++ authctxt->server_caused_failure = 1; + return (0); + } + +@@ -242,7 +278,8 @@ input_gssapi_exchange_complete(int type, + + packet_check_eom(); + +- authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user)); ++ authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user, ++ authctxt->pw)); + + authctxt->postponed = 0; + dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); +@@ -284,7 +321,8 @@ input_gssapi_mic(int type, u_int32_t ple + gssbuf.length = buffer_len(&b); + + if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic)))) +- authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user)); ++ authenticated = ++ PRIVSEP(ssh_gssapi_userok(authctxt->user, authctxt->pw)); + else + logit("GSSAPI MIC check failed"); + +@@ -301,6 +339,12 @@ input_gssapi_mic(int type, u_int32_t ple + 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 -up openssh-5.4p1/auth.h.gsskex openssh-5.4p1/auth.h +--- openssh-5.4p1/auth.h.gsskex 2010-03-01 18:14:25.000000000 +0100 ++++ openssh-5.4p1/auth.h 2010-03-01 18:14:28.000000000 +0100 +@@ -53,6 +53,7 @@ struct Authctxt { + int valid; /* user exists and is allowed to login */ + int attempt; + int failures; ++ int server_caused_failure; + int force_pwchange; + char *user; /* username sent by the client */ + char *service; +diff -up openssh-5.4p1/auth-krb5.c.gsskex openssh-5.4p1/auth-krb5.c +--- openssh-5.4p1/auth-krb5.c.gsskex 2009-12-21 00:49:22.000000000 +0100 ++++ openssh-5.4p1/auth-krb5.c 2010-03-01 18:14:28.000000000 +0100 +@@ -170,8 +170,13 @@ auth_krb5_password(Authctxt *authctxt, c + + 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) +@@ -226,15 +231,22 @@ krb5_cleanup_proc(Authctxt *authctxt) + #ifndef HEIMDAL + krb5_error_code + ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) { +- int tmpfd, ret; ++ int ret; + char ccname[40]; + mode_t old_umask; ++#ifdef USE_CCAPI ++ char cctemplate[] = "API:krb5cc_%d"; ++#else ++ char cctemplate[] = "FILE:/tmp/krb5cc_%d_XXXXXXXXXX"; ++ int tmpfd; ++#endif + + ret = snprintf(ccname, sizeof(ccname), +- "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid()); ++ cctemplate, geteuid()); + if (ret < 0 || (size_t)ret >= sizeof(ccname)) + return ENOMEM; + ++#ifndef USE_CCAPI + old_umask = umask(0177); + tmpfd = mkstemp(ccname + strlen("FILE:")); + umask(old_umask); +@@ -249,6 +261,7 @@ ssh_krb5_cc_gen(krb5_context ctx, krb5_c + return errno; + } + close(tmpfd); ++#endif + + return (krb5_cc_resolve(ctx, ccname, ccache)); + } +diff -up openssh-5.4p1/ChangeLog.gssapi.gsskex openssh-5.4p1/ChangeLog.gssapi +--- openssh-5.4p1/ChangeLog.gssapi.gsskex 2010-03-01 18:14:28.000000000 +0100 ++++ openssh-5.4p1/ChangeLog.gssapi 2010-03-01 18:14:28.000000000 +0100 +@@ -0,0 +1,95 @@ ++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 ++ function ++ ++20061220 ++ - [ servconf.c ] ++ Make default for GSSAPIStrictAcceptorCheck be Yes, to match previous, and ++ documented, behaviour. Reported by Dan Watson. ++ ++20060910 ++ - [ gss-genr.c kexgssc.c kexgsss.c kex.h monitor.c sshconnect2.c sshd.c ++ ssh-gss.h ] ++ add support for gss-group14-sha1 key exchange mechanisms ++ - [ gss-serv.c servconf.c servconf.h sshd_config sshd_config.5 ] ++ Add GSSAPIStrictAcceptorCheck option to allow the disabling of ++ acceptor principal checking on multi-homed machines. ++ ++ - [ sshd_config ssh_config ] ++ Add settings for GSSAPIKeyExchange and GSSAPITrustDNS to the sample ++ configuration files ++ - [ kexgss.c kegsss.c sshconnect2.c sshd.c ] ++ Code cleanup. Replace strlen/xmalloc/snprintf sequences with xasprintf() ++ Limit length of error messages displayed by client ++ ++20060909 ++ - [ gss-genr.c gss-serv.c ] ++ move ssh_gssapi_acquire_cred() and ssh_gssapi_server_ctx to be server ++ only, where they belong ++ ++ ++20060829 ++ - [ gss-serv-krb5.c ] ++ Fix CCAPI credentials cache name when creating KRB5CCNAME environment ++ variable ++ ++20060828 ++ - [ gss-genr.c ] ++ Avoid Heimdal context freeing problem ++ ++ ++20060818 ++ - [ gss-genr.c ssh-gss.h sshconnect2.c ] ++ Make sure that SPENGO is disabled ++ ++ ++20060421 ++ - [ gssgenr.c, sshconnect2.c ] ++ a few type changes (signed versus unsigned, int versus size_t) to ++ fix compiler errors/warnings ++ (from jbasney AT ncsa.uiuc.edu) ++ - [ kexgssc.c, sshconnect2.c ] ++ fix uninitialized variable warnings ++ (from jbasney AT ncsa.uiuc.edu) ++ - [ gssgenr.c ] ++ pass oid to gss_display_status (helpful when using GSSAPI mechglue) ++ (from jbasney AT ncsa.uiuc.edu) ++ ++ - [ gss-serv-krb5.c ] ++ #ifdef HAVE_GSSAPI_KRB5 should be #ifdef HAVE_GSSAPI_KRB5_H ++ (from jbasney AT ncsa.uiuc.edu) ++ ++ - [ readconf.c, readconf.h, ssh_config.5, sshconnect2.c ++ add client-side GssapiKeyExchange option ++ (from jbasney AT ncsa.uiuc.edu) ++ - [ sshconnect2.c ] ++ add support for GssapiTrustDns option for gssapi-with-mic ++ (from jbasney AT ncsa.uiuc.edu) ++ +diff -up openssh-5.4p1/clientloop.c.gsskex openssh-5.4p1/clientloop.c +--- openssh-5.4p1/clientloop.c.gsskex 2010-01-30 07:28:35.000000000 +0100 ++++ openssh-5.4p1/clientloop.c 2010-03-01 18:14:28.000000000 +0100 +@@ -111,6 +111,10 @@ + #include "msg.h" + #include "roaming.h" + ++#ifdef GSSAPI ++#include "ssh-gss.h" ++#endif ++ + /* import options */ + extern Options options; + +@@ -1431,6 +1435,13 @@ client_loop(int have_pty, int escape_cha + /* 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; +diff -up openssh-5.4p1/configure.ac.gsskex openssh-5.4p1/configure.ac +--- openssh-5.4p1/configure.ac.gsskex 2010-03-01 18:14:27.000000000 +0100 ++++ openssh-5.4p1/configure.ac 2010-03-01 18:14:28.000000000 +0100 +@@ -477,6 +477,30 @@ main() { if (NSVersionOfRunTimeLibrary(" + [Use tunnel device compatibility to OpenBSD]) + AC_DEFINE(SSH_TUN_PREPEND_AF, 1, + [Prepend the address family to IP tunnel traffic]) ++ AC_MSG_CHECKING(if we have the Security Authorization Session API) ++ AC_TRY_COMPILE([#include ], ++ [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 ], ++ [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)] ++ ) + m4_pattern_allow(AU_IPv) + AC_CHECK_DECL(AU_IPv4, [], + AC_DEFINE(AU_IPv4, 0, [System only supports IPv4 audit records]) +diff -up openssh-5.4p1/gss-genr.c.gsskex openssh-5.4p1/gss-genr.c +--- openssh-5.4p1/gss-genr.c.gsskex 2009-06-22 08:11:07.000000000 +0200 ++++ openssh-5.4p1/gss-genr.c 2010-03-01 18:14:28.000000000 +0100 +@@ -39,12 +39,167 @@ + #include "buffer.h" + #include "log.h" + #include "ssh2.h" ++#include "cipher.h" ++#include "key.h" ++#include "kex.h" ++#include + + #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, const char *client) { ++ gss_OID_set gss_supported; ++ OM_uint32 min_status; ++ ++ if (GSS_ERROR(gss_indicate_mechs(&min_status, &gss_supported))) ++ return NULL; ++ ++ return(ssh_gssapi_kex_mechs(gss_supported, ssh_gssapi_check_mechanism, ++ host, client)); ++} ++ ++char * ++ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check, ++ const char *host, const char *client) { ++ Buffer buf; ++ size_t i; ++ int oidpos, enclen; ++ char *mechs, *encoded; ++ u_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)(NULL, &(gss_supported->elements[i]), host, client)) { ++ ++ 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); ++ buffer_put_char(&buf, ','); ++ buffer_append(&buf, KEX_GSS_GRP14_SHA1_ID, ++ sizeof(KEX_GSS_GRP14_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 kex_type) { ++ int i = 0; ++ ++ 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: ++ return GSS_C_NO_OID; ++ } ++ ++ 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) +@@ -197,7 +352,7 @@ ssh_gssapi_init_ctx(Gssctxt *ctx, int de + } + + 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); + +@@ -227,8 +382,42 @@ ssh_gssapi_import_name(Gssctxt *ctx, con + } + + 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); +@@ -236,6 +425,19 @@ ssh_gssapi_sign(Gssctxt *ctx, gss_buffer + 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) +@@ -249,11 +451,16 @@ ssh_gssapi_buildmic(Buffer *b, const cha + } + + 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; + gss_OID_desc spnego_oid = {6, (void *)"\x2B\x06\x01\x05\x05\x02"}; ++ Gssctxt *intctx = NULL; ++ ++ if (ctx == NULL) ++ ctx = &intctx; + + /* RFC 4462 says we MUST NOT do SPNEGO */ + if (oid->length == spnego_oid.length && +@@ -263,6 +470,10 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx + 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); +@@ -272,10 +483,67 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx + GSS_C_NO_BUFFER); + } + +- if (GSS_ERROR(major)) ++ if (GSS_ERROR(major) || intctx != NULL) + ssh_gssapi_delete_ctx(ctx); + + 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 */ +diff -up openssh-5.4p1/gss-serv.c.gsskex openssh-5.4p1/gss-serv.c +--- openssh-5.4p1/gss-serv.c.gsskex 2008-05-19 07:05:07.000000000 +0200 ++++ openssh-5.4p1/gss-serv.c 2010-03-01 18:14:28.000000000 +0100 +@@ -1,7 +1,7 @@ + /* $OpenBSD: gss-serv.c,v 1.22 2008/05/08 12:02:23 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 +@@ -45,15 +45,20 @@ + #include "channels.h" + #include "session.h" + #include "misc.h" ++#include "servconf.h" ++#include "uidswap.h" + + #include "ssh-gss.h" ++#include "monitor_wrap.h" ++ ++extern ServerOptions options; + + 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; +@@ -81,25 +86,32 @@ ssh_gssapi_acquire_cred(Gssctxt *ctx) + char lname[MAXHOSTNAMELEN]; + gss_OID_set oidset; + +- gss_create_empty_oid_set(&status, &oidset); +- gss_add_oid_set_member(&status, ctx->oid, &oidset); ++ if (options.gss_strict_acceptor) { ++ gss_create_empty_oid_set(&status, &oidset); ++ gss_add_oid_set_member(&status, ctx->oid, &oidset); ++ ++ if (gethostname(lname, MAXHOSTNAMELEN)) { ++ gss_release_oid_set(&status, &oidset); ++ return (-1); ++ } + +- if (gethostname(lname, MAXHOSTNAMELEN)) { +- gss_release_oid_set(&status, &oidset); +- return (-1); +- } ++ if (GSS_ERROR(ssh_gssapi_import_name(ctx, lname))) { ++ gss_release_oid_set(&status, &oidset); ++ return (ctx->major); ++ } ++ ++ if ((ctx->major = gss_acquire_cred(&ctx->minor, ++ ctx->name, 0, oidset, GSS_C_ACCEPT, &ctx->creds, ++ NULL, NULL))) ++ ssh_gssapi_error(ctx); + +- if (GSS_ERROR(ssh_gssapi_import_name(ctx, lname))) { + gss_release_oid_set(&status, &oidset); + return (ctx->major); ++ } else { ++ ctx->name = GSS_C_NO_NAME; ++ ctx->creds = GSS_C_NO_CREDENTIAL; + } +- +- if ((ctx->major = gss_acquire_cred(&ctx->minor, +- ctx->name, 0, oidset, GSS_C_ACCEPT, &ctx->creds, NULL, NULL))) +- ssh_gssapi_error(ctx); +- +- gss_release_oid_set(&status, &oidset); +- return (ctx->major); ++ return GSS_S_COMPLETE; + } + + /* Privileged */ +@@ -114,6 +126,29 @@ ssh_gssapi_server_ctx(Gssctxt **ctx, gss + } + + /* 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) + { +@@ -123,7 +158,9 @@ ssh_gssapi_supported_oids(gss_OID_set *o + gss_OID_set supported; + + gss_create_empty_oid_set(&min_status, oidset); +- gss_indicate_mechs(&min_status, &supported); ++ ++ if (GSS_ERROR(gss_indicate_mechs(&min_status, &supported))) ++ return; + + while (supported_mechs[i]->name != NULL) { + if (GSS_ERROR(gss_test_oid_set_member(&min_status, +@@ -247,8 +284,48 @@ 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; ++ } ++ ++ if ((ctx->major = gss_inquire_cred_by_mech(&ctx->minor, ++ ctx->client_creds, ctx->oid, &new_name, ++ NULL, NULL, NULL))) { ++ ssh_gssapi_error(ctx); ++ return (ctx->major); ++ } ++ ++ ctx->major = gss_compare_name(&ctx->minor, client->name, ++ new_name, &equal); + +- gss_buffer_desc ename; ++ 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; + +@@ -263,6 +340,13 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_g + if (client->mech == NULL) + return GSS_S_FAILURE; + ++ if (ctx->client_creds && ++ (ctx->major = gss_inquire_cred_by_mech(&ctx->minor, ++ ctx->client_creds, ctx->oid, &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); +@@ -280,6 +364,8 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_g + 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; +@@ -327,7 +413,7 @@ ssh_gssapi_do_child(char ***envp, u_int + + /* Privileged */ + int +-ssh_gssapi_userok(char *user) ++ssh_gssapi_userok(char *user, struct passwd *pw) + { + OM_uint32 lmin; + +@@ -337,9 +423,11 @@ ssh_gssapi_userok(char *user) + return 0; + } + 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); +@@ -352,14 +440,90 @@ ssh_gssapi_userok(char *user) + return (0); + } + +-/* Privileged */ +-OM_uint32 +-ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) ++/* 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) + { +- ctx->major = gss_verify_mic(&ctx->minor, ctx->context, +- gssbuf, gssmic, NULL); ++ return (PAM_CONV_ERR); ++} ++#endif + +- return (ctx->major); ++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 +diff -up openssh-5.4p1/gss-serv-krb5.c.gsskex openssh-5.4p1/gss-serv-krb5.c +--- openssh-5.4p1/gss-serv-krb5.c.gsskex 2006-09-01 07:38:36.000000000 +0200 ++++ openssh-5.4p1/gss-serv-krb5.c 2010-03-01 18:14:28.000000000 +0100 +@@ -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 +@@ -120,6 +120,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl + krb5_principal princ; + OM_uint32 maj_status, min_status; + int len; ++ const char *new_ccname; + + if (client->creds == NULL) { + debug("No credentials stored"); +@@ -168,11 +169,16 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl + return; + } + +- client->store.filename = xstrdup(krb5_cc_get_name(krb_context, ccache)); ++ new_ccname = krb5_cc_get_name(krb_context, ccache); ++ + client->store.envvar = "KRB5CCNAME"; +- len = strlen(client->store.filename) + 6; +- client->store.envval = xmalloc(len); +- snprintf(client->store.envval, len, "FILE:%s", client->store.filename); ++#ifdef USE_CCAPI ++ xasprintf(&client->store.envval, "API:%s", new_ccname); ++ client->store.filename = NULL; ++#else ++ xasprintf(&client->store.envval, "FILE:%s", new_ccname); ++ client->store.filename = xstrdup(new_ccname); ++#endif + + #ifdef USE_PAM + if (options.use_pam) +@@ -184,6 +190,71 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl + 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; ++} ++ + ssh_gssapi_mech gssapi_kerberos_mech = { + "toWM5Slw5Ew8Mqkay+al2g==", + "Kerberos", +@@ -191,7 +262,8 @@ ssh_gssapi_mech gssapi_kerberos_mech = { + NULL, + &ssh_gssapi_krb5_userok, + NULL, +- &ssh_gssapi_krb5_storecreds ++ &ssh_gssapi_krb5_storecreds, ++ &ssh_gssapi_krb5_updatecreds + }; + + #endif /* KRB5 */ +diff -up openssh-5.4p1/kex.c.gsskex openssh-5.4p1/kex.c +--- openssh-5.4p1/kex.c.gsskex 2010-01-08 06:50:41.000000000 +0100 ++++ openssh-5.4p1/kex.c 2010-03-01 18:18:42.000000000 +0100 +@@ -50,6 +50,10 @@ + #include "monitor.h" + #include "roaming.h" + ++#ifdef GSSAPI ++#include "ssh-gss.h" ++#endif ++ + #if OPENSSL_VERSION_NUMBER >= 0x00907000L + # if defined(HAVE_EVP_SHA256) + # define evp_ssh_sha256 EVP_sha256 +@@ -326,6 +330,20 @@ choose_kex(Kex *k, char *client, char *s + k->kex_type = KEX_DH_GEX_SHA256; + k->evp_md = evp_ssh_sha256(); + #endif ++#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(); ++ } else if (strncmp(k->name, KEX_GSS_GRP14_SHA1_ID, ++ sizeof(KEX_GSS_GRP14_SHA1_ID) - 1) == 0) { ++ k->kex_type = KEX_GSS_GRP14_SHA1; ++ k->evp_md = EVP_sha1(); ++#endif + } else + fatal("bad kex alg %s", k->name); + } +diff -up openssh-5.4p1/kexgssc.c.gsskex openssh-5.4p1/kexgssc.c +--- openssh-5.4p1/kexgssc.c.gsskex 2010-03-01 18:14:28.000000000 +0100 ++++ openssh-5.4p1/kexgssc.c 2010-03-01 18:14:28.000000000 +0100 +@@ -0,0 +1,334 @@ ++/* ++ * 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 ++ * 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 "includes.h" ++ ++#include ++#include ++ ++#include ++ ++#include "xmalloc.h" ++#include "buffer.h" ++#include "ssh2.h" ++#include "key.h" ++#include "cipher.h" ++#include "kex.h" ++#include "log.h" ++#include "packet.h" ++#include "dh.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; ++ u_char *empty = ""; ++ char *msg; ++ char *lang; ++ int type = 0; ++ int first = 1; ++ int nbits = 0, min = DH_GRP_MIN, max = DH_GRP_MAX; ++ ++ /* Initialise our GSSAPI world */ ++ ssh_gssapi_build_ctx(&ctxt); ++ if (ssh_gssapi_id_kex(ctxt, kex->name, kex->kex_type) ++ == GSS_C_NO_OID) ++ fatal("Couldn't identify host exchange"); ++ ++ 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(); ++ break; ++ case KEX_GSS_GRP14_SHA1: ++ dh = dh_new_group14(); ++ break; ++ case KEX_GSS_GEX_SHA1: ++ debug("Doing group exchange\n"); ++ nbits = dh_estimate(kex->we_need * 8); ++ 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); ++ break; ++ default: ++ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); ++ } ++ ++ /* 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%.400s",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); ++ if (kout < 0) ++ fatal("DH_compute_key: failed"); ++ ++ shared_secret = BN_new(); ++ 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); ++ ++ switch (kex->kex_type) { ++ case KEX_GSS_GRP1_SHA1: ++ case KEX_GSS_GRP14_SHA1: ++ 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 ? serverhostkey : empty), slen, ++ dh->pub_key, /* e */ ++ dh_server_pub, /* f */ ++ shared_secret, /* K */ ++ &hash, &hashlen ++ ); ++ break; ++ case KEX_GSS_GEX_SHA1: ++ 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 ? serverhostkey : empty), slen, ++ min, nbits, max, ++ dh->p, dh->g, ++ dh->pub_key, ++ dh_server_pub, ++ shared_secret, ++ &hash, &hashlen ++ ); ++ break; ++ default: ++ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); ++ } ++ ++ 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 (kex->gss_deleg_creds) ++ ssh_gssapi_credentials_updated(ctxt); ++ ++ 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 -up openssh-5.4p1/kexgsss.c.gsskex openssh-5.4p1/kexgsss.c +--- openssh-5.4p1/kexgsss.c.gsskex 2010-03-01 18:14:28.000000000 +0100 ++++ openssh-5.4p1/kexgsss.c 2010-03-01 18:14:28.000000000 +0100 +@@ -0,0 +1,288 @@ ++/* ++ * 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 ++ * 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 ++ ++#include ++#include ++ ++#include "xmalloc.h" ++#include "buffer.h" ++#include "ssh2.h" ++#include "key.h" ++#include "cipher.h" ++#include "kex.h" ++#include "log.h" ++#include "packet.h" ++#include "dh.h" ++#include "ssh-gss.h" ++#include "monitor_wrap.h" ++#include "servconf.h" ++ ++extern ServerOptions options; ++ ++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; ++ gss_OID oid; ++ char *mechs; ++ ++ /* 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()) ++ 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); ++ if (oid == GSS_C_NO_OID) ++ 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"); ++ ++ switch (kex->kex_type) { ++ case KEX_GSS_GRP1_SHA1: ++ dh = dh_new_group1(); ++ break; ++ case KEX_GSS_GRP14_SHA1: ++ dh = dh_new_group14(); ++ break; ++ case KEX_GSS_GEX_SHA1: ++ 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(); ++ break; ++ default: ++ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); ++ } ++ ++ 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); ++ if (kout < 0) ++ fatal("DH_compute_key: failed"); ++ ++ shared_secret = BN_new(); ++ 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); ++ ++ switch (kex->kex_type) { ++ case KEX_GSS_GRP1_SHA1: ++ case KEX_GSS_GRP14_SHA1: ++ 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 ++ ); ++ break; ++ case KEX_GSS_GEX_SHA1: ++ 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 ++ ); ++ break; ++ default: ++ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); ++ } ++ ++ BN_clear_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(msg_tok.value,msg_tok.length); ++ ++ if (send_tok.length != 0) { ++ packet_put_char(1); /* true */ ++ packet_put_string(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); ++ ++ /* If this was a rekey, then save out any delegated credentials we ++ * just exchanged. */ ++ if (options.gss_store_rekey) ++ ssh_gssapi_rekey_creds(); ++} ++#endif /* GSSAPI */ +diff -up openssh-5.4p1/kex.h.gsskex openssh-5.4p1/kex.h +--- openssh-5.4p1/kex.h.gsskex 2010-02-26 21:55:05.000000000 +0100 ++++ openssh-5.4p1/kex.h 2010-03-01 18:14:28.000000000 +0100 +@@ -67,6 +67,9 @@ enum kex_exchange { + KEX_DH_GRP14_SHA1, + KEX_DH_GEX_SHA1, + KEX_DH_GEX_SHA256, ++ KEX_GSS_GRP1_SHA1, ++ KEX_GSS_GRP14_SHA1, ++ KEX_GSS_GEX_SHA1, + KEX_MAX + }; + +@@ -123,6 +126,12 @@ struct Kex { + sig_atomic_t done; + int flags; + const EVP_MD *evp_md; ++#ifdef GSSAPI ++ int gss_deleg_creds; ++ int gss_trust_dns; ++ char *gss_host; ++ char *gss_client; ++#endif + char *client_version_string; + char *server_version_string; + int (*verify_host_key)(Key *); +@@ -146,6 +155,11 @@ void kexdh_server(Kex *); + void kexgex_client(Kex *); + void kexgex_server(Kex *); + ++#ifdef GSSAPI ++void kexgss_client(Kex *); ++void kexgss_server(Kex *); ++#endif ++ + void + kex_dh_hash(char *, char *, char *, int, char *, int, u_char *, int, + BIGNUM *, BIGNUM *, BIGNUM *, u_char **, u_int *); +diff -up openssh-5.4p1/key.c.gsskex openssh-5.4p1/key.c +--- openssh-5.4p1/key.c.gsskex 2010-02-26 21:55:05.000000000 +0100 ++++ openssh-5.4p1/key.c 2010-03-01 18:20:43.000000000 +0100 +@@ -969,6 +969,8 @@ key_type_from_name(char *name) + return KEY_RSA_CERT; + } else if (strcmp(name, "ssh-dss-cert-v00@openssh.com") == 0) { + return KEY_DSA_CERT; ++ } else if (strcmp(name, "null") == 0) { ++ return KEY_NULL; + } + debug2("key_type_from_name: unknown key type '%s'", name); + return KEY_UNSPEC; +diff -up openssh-5.4p1/key.h.gsskex openssh-5.4p1/key.h +--- openssh-5.4p1/key.h.gsskex 2010-02-26 21:55:05.000000000 +0100 ++++ openssh-5.4p1/key.h 2010-03-01 18:21:22.000000000 +0100 +@@ -37,6 +37,7 @@ enum types { + KEY_DSA, + KEY_RSA_CERT, + KEY_DSA_CERT, ++ KEY_NULL, + KEY_UNSPEC + }; + enum fp_type { +diff -up openssh-5.4p1/Makefile.in.gsskex openssh-5.4p1/Makefile.in +--- openssh-5.4p1/Makefile.in.gsskex 2010-03-01 18:14:27.000000000 +0100 ++++ openssh-5.4p1/Makefile.in 2010-03-01 18:23:31.000000000 +0100 +@@ -76,11 +76,11 @@ + monitor_fdpass.o rijndael.o ssh-dss.o ssh-rsa.o dh.o kexdh.o \ + kexgex.o kexdhc.o kexgexc.o msg.o progressmeter.o dns.o \ + entropy.o gss-genr.o umac.o jpake.o schnorr.o \ +- ssh-pkcs11.o ++ ssh-pkcs11.o kexgssc.o + + SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \ + sshconnect.o sshconnect1.o sshconnect2.o mux.o \ +- roaming_common.o roaming_client.o ++ roaming_common.o roaming_client.o kexgssc.o + + SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \ + sshpty.o sshlogin.o servconf.o serverloop.o \ +@@ -93,7 +93,7 @@ + auth2-gss.o gss-serv.o gss-serv-krb5.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 \ +- roaming_common.o roaming_serv.o ++ roaming_common.o roaming_serv.o kexgsss.o + + MANPAGES = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-rand-helper.8.out ssh-keysign.8.out ssh-pkcs11-helper.8.out ssh-ldap-helper.8.out sshd_config.5.out ssh_config.5.out + MANPAGES_IN = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-rand-helper.8 ssh-keysign.8 ssh-pkcs11-helper.8 ssh-ldap-helper.8 sshd_config.5 ssh_config.5 +diff -up openssh-5.4p1/monitor.c.gsskex openssh-5.4p1/monitor.c +--- openssh-5.4p1/monitor.c.gsskex 2010-03-01 18:14:25.000000000 +0100 ++++ openssh-5.4p1/monitor.c 2010-03-01 18:14:29.000000000 +0100 +@@ -175,6 +175,8 @@ int mm_answer_gss_setup_ctx(int, Buffer + int mm_answer_gss_accept_ctx(int, Buffer *); + int mm_answer_gss_userok(int, Buffer *); + int mm_answer_gss_checkmic(int, Buffer *); ++int mm_answer_gss_sign(int, Buffer *); ++int mm_answer_gss_updatecreds(int, Buffer *); + #endif + + #ifdef SSH_AUDIT_EVENTS +@@ -247,6 +249,7 @@ struct mon_table mon_dispatch_proto20[] + {MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx}, + {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok}, + {MONITOR_REQ_GSSCHECKMIC, MON_ISAUTH, mm_answer_gss_checkmic}, ++ {MONITOR_REQ_GSSSIGN, MON_ONCE, mm_answer_gss_sign}, + #endif + #ifdef JPAKE + {MONITOR_REQ_JPAKE_GET_PWDATA, MON_ONCE, mm_answer_jpake_get_pwdata}, +@@ -259,6 +262,12 @@ struct mon_table mon_dispatch_proto20[] + }; + + 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}, ++ {MONITOR_REQ_GSSUPCREDS, 0, mm_answer_gss_updatecreds}, ++#endif + {MONITOR_REQ_MODULI, 0, mm_answer_moduli}, + {MONITOR_REQ_SIGN, 0, mm_answer_sign}, + {MONITOR_REQ_PTY, 0, mm_answer_pty}, +@@ -363,6 +372,10 @@ monitor_child_preauth(Authctxt *_authctx + /* 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; + +@@ -449,6 +462,10 @@ monitor_child_postauth(struct monitor *p + 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); +@@ -1738,6 +1755,13 @@ mm_get_kex(Buffer *m) + kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; + kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; + kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; ++#ifdef GSSAPI ++ 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); + kex->kex_type = buffer_get_int(m); +@@ -1944,6 +1968,9 @@ mm_answer_gss_setup_ctx(int sock, Buffer + 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; + +@@ -1971,6 +1998,9 @@ mm_answer_gss_accept_ctx(int sock, Buffe + 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); +@@ -1988,6 +2018,7 @@ mm_answer_gss_accept_ctx(int sock, Buffe + 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); + } +@@ -1999,6 +2030,9 @@ mm_answer_gss_checkmic(int sock, Buffer + 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); +@@ -2025,7 +2059,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); +@@ -2038,6 +2076,74 @@ mm_answer_gss_userok(int sock, Buffer *m + /* Monitor loop will terminate if authenticated */ + return (authenticated); + } ++ ++int ++mm_answer_gss_sign(int socket, Buffer *m) ++{ ++ gss_buffer_desc data; ++ gss_buffer_desc hash = GSS_C_EMPTY_BUFFER; ++ OM_uint32 major, minor; ++ u_int len; ++ ++ 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 +diff -up openssh-5.4p1/monitor.h.gsskex openssh-5.4p1/monitor.h +--- openssh-5.4p1/monitor.h.gsskex 2010-03-01 18:14:25.000000000 +0100 ++++ openssh-5.4p1/monitor.h 2010-03-01 18:14:29.000000000 +0100 +@@ -56,6 +56,8 @@ enum monitor_reqtype { + MONITOR_REQ_GSSSTEP, MONITOR_ANS_GSSSTEP, + MONITOR_REQ_GSSUSEROK, MONITOR_ANS_GSSUSEROK, + MONITOR_REQ_GSSCHECKMIC, MONITOR_ANS_GSSCHECKMIC, ++ MONITOR_REQ_GSSSIGN, MONITOR_ANS_GSSSIGN, ++ MONITOR_REQ_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, +diff -up openssh-5.4p1/monitor_wrap.c.gsskex openssh-5.4p1/monitor_wrap.c +--- openssh-5.4p1/monitor_wrap.c.gsskex 2010-03-01 18:14:25.000000000 +0100 ++++ openssh-5.4p1/monitor_wrap.c 2010-03-01 18:14:29.000000000 +0100 +@@ -1267,7 +1267,7 @@ mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss + } + + int +-mm_ssh_gssapi_userok(char *user) ++mm_ssh_gssapi_userok(char *user, struct passwd *pw) + { + Buffer m; + int authenticated = 0; +@@ -1284,6 +1284,51 @@ mm_ssh_gssapi_userok(char *user) + debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not "); + return (authenticated); + } ++ ++OM_uint32 ++mm_ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_desc *data, gss_buffer_desc *hash) ++{ ++ Buffer m; ++ OM_uint32 major; ++ u_int len; ++ ++ buffer_init(&m); ++ buffer_put_string(&m, data->value, data->length); ++ ++ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSIGN, &m); ++ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSIGN, &m); ++ ++ major = buffer_get_int(&m); ++ hash->value = buffer_get_string(&m, &len); ++ hash->length = len; ++ ++ buffer_free(&m); ++ ++ return(major); ++} ++ ++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 +diff -up openssh-5.4p1/monitor_wrap.h.gsskex openssh-5.4p1/monitor_wrap.h +--- openssh-5.4p1/monitor_wrap.h.gsskex 2010-03-01 18:14:25.000000000 +0100 ++++ openssh-5.4p1/monitor_wrap.h 2010-03-01 18:14:29.000000000 +0100 +@@ -60,8 +60,10 @@ BIGNUM *mm_auth_rsa_generate_challenge(K + 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_update_creds(ssh_gssapi_ccache *); + #endif + + #ifdef USE_PAM +diff -up openssh-5.4p1/readconf.c.gsskex openssh-5.4p1/readconf.c +--- openssh-5.4p1/readconf.c.gsskex 2010-02-11 23:21:03.000000000 +0100 ++++ openssh-5.4p1/readconf.c 2010-03-01 18:14:29.000000000 +0100 +@@ -127,6 +127,7 @@ typedef enum { + oClearAllForwardings, oNoHostAuthenticationForLocalhost, + oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, + oAddressFamily, oGssAuthentication, oGssDelegateCreds, ++ oGssTrustDns, oGssKeyEx, oGssClientIdentity, oGssRenewalRekey, + oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, + oSendEnv, oControlPath, oControlMaster, oHashKnownHosts, + oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand, +@@ -164,10 +165,18 @@ static struct { + { "afstokenpassing", oUnsupported }, + #if defined(GSSAPI) + { "gssapiauthentication", oGssAuthentication }, ++ { "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 }, +@@ -456,10 +465,26 @@ parse_flag: + intptr = &options->gss_authentication; + goto parse_flag; + ++ case oGssKeyEx: ++ intptr = &options->gss_keyex; ++ goto parse_flag; ++ + case oGssDelegateCreds: + intptr = &options->gss_deleg_creds; + goto parse_flag; + ++ case oGssTrustDns: ++ 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; +@@ -1015,7 +1040,11 @@ initialize_options(Options * options) + options->pubkey_authentication = -1; + options->challenge_response_authentication = -1; + options->gss_authentication = -1; ++ 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; +@@ -1107,8 +1136,14 @@ fill_default_options(Options * options) + options->challenge_response_authentication = 1; + if (options->gss_authentication == -1) + options->gss_authentication = 0; ++ if (options->gss_keyex == -1) ++ options->gss_keyex = 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->gss_renewal_rekey == -1) ++ options->gss_renewal_rekey = 0; + if (options->password_authentication == -1) + options->password_authentication = 1; + if (options->kbd_interactive_authentication == -1) +diff -up openssh-5.4p1/readconf.h.gsskex openssh-5.4p1/readconf.h +--- openssh-5.4p1/readconf.h.gsskex 2010-02-11 23:21:03.000000000 +0100 ++++ openssh-5.4p1/readconf.h 2010-03-01 18:14:29.000000000 +0100 +@@ -44,7 +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_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. */ +diff -up openssh-5.4p1/servconf.c.gsskex openssh-5.4p1/servconf.c +--- openssh-5.4p1/servconf.c.gsskex 2010-03-01 18:14:28.000000000 +0100 ++++ openssh-5.4p1/servconf.c 2010-03-01 18:25:32.000000000 +0100 +@@ -93,7 +93,10 @@ initialize_server_options(ServerOptions + 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->gss_strict_acceptor = -1; ++ options->gss_store_rekey = -1; + options->password_authentication = -1; + options->kbd_interactive_authentication = -1; + options->challenge_response_authentication = -1; +@@ -215,8 +218,14 @@ fill_default_server_options(ServerOption + 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->gss_strict_acceptor == -1) ++ options->gss_strict_acceptor = 1; ++ 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) +@@ -310,7 +319,9 @@ typedef enum { + sBanner, sShowPatchLevel, sUseDNS, sHostbasedAuthentication, + sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, + sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2, +- sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel, ++ sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor, ++ sGssKeyEx, sGssStoreRekey, ++ sAcceptEnv, sPermitTunnel, + sMatch, sPermitOpen, sForceCommand, sChrootDirectory, + sUsePrivilegeSeparation, sAllowAgentForwarding, + sZeroKnowledgePasswordAuthentication, sHostCertificate, +@@ -373,9 +384,15 @@ static struct { + #ifdef GSSAPI + { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL }, + { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL }, ++ { "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL }, ++ { "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL }, ++ { "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL }, + #else + { "gssapiauthentication", sUnsupported, SSHCFG_ALL }, + { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL }, ++ { "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL }, ++ { "gssapikeyexchange", sUnsupported, SSHCFG_GLOBAL }, ++ { "gssapistorecredentialsonrekey", sUnsupported, SSHCFG_GLOBAL }, + #endif + { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL }, + { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, +@@ -935,10 +952,22 @@ process_server_config_line(ServerOptions + 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; + ++ case sGssStrictAcceptor: ++ intptr = &options->gss_strict_acceptor; ++ goto parse_flag; ++ ++ case sGssStoreRekey: ++ intptr = &options->gss_store_rekey; ++ goto parse_flag; ++ + case sPasswordAuthentication: + intptr = &options->password_authentication; + goto parse_flag; +diff -up openssh-5.4p1/servconf.h.gsskex openssh-5.4p1/servconf.h +--- openssh-5.4p1/servconf.h.gsskex 2010-03-01 18:14:28.000000000 +0100 ++++ openssh-5.4p1/servconf.h 2010-03-01 18:14:29.000000000 +0100 +@@ -94,7 +94,10 @@ typedef struct { + int kerberos_get_afs_token; /* If true, try to get AFS token if + * authenticated with Kerberos. */ + int gss_authentication; /* If true, permit GSSAPI authentication */ ++ int gss_keyex; /* If true, permit GSSAPI key exchange */ + int gss_cleanup_creds; /* If true, destroy cred cache on logout */ ++ int 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 */ +diff -up openssh-5.4p1/ssh_config.5.gsskex openssh-5.4p1/ssh_config.5 +--- openssh-5.4p1/ssh_config.5.gsskex 2010-02-11 23:26:02.000000000 +0100 ++++ openssh-5.4p1/ssh_config.5 2010-03-01 18:14:29.000000000 +0100 +@@ -478,11 +478,38 @@ Specifies whether user authentication ba + 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 may be used. When using ++GSSAPI key exchange the server need not have a host key. ++The default is ++.Dq no . ++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 no . +-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 no . ++.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. + .It Cm HashKnownHosts + Indicates that + .Xr ssh 1 +diff -up openssh-5.4p1/ssh_config.gsskex openssh-5.4p1/ssh_config +--- openssh-5.4p1/ssh_config.gsskex 2010-03-01 18:14:24.000000000 +0100 ++++ openssh-5.4p1/ssh_config 2010-03-01 18:14:29.000000000 +0100 +@@ -26,6 +26,8 @@ + # HostbasedAuthentication no + # GSSAPIAuthentication no + # GSSAPIDelegateCredentials no ++# GSSAPIKeyExchange no ++# GSSAPITrustDNS no + # BatchMode no + # CheckHostIP yes + # AddressFamily any +diff -up openssh-5.4p1/sshconnect2.c.gsskex openssh-5.4p1/sshconnect2.c +--- openssh-5.4p1/sshconnect2.c.gsskex 2010-03-01 18:14:27.000000000 +0100 ++++ openssh-5.4p1/sshconnect2.c 2010-03-01 18:14:29.000000000 +0100 +@@ -108,9 +108,34 @@ ssh_kex2(char *host, struct sockaddr *ho + { + Kex *kex; + ++#ifdef GSSAPI ++ char *orig = NULL, *gss = NULL; ++ char *gss_host = NULL; ++#endif ++ + xxx_host = host; + xxx_hostaddr = hostaddr; + ++#ifdef GSSAPI ++ if (options.gss_keyex) { ++ /* 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, options.gss_client_identity); ++ if (gss) { ++ debug("Offering GSSAPI proposal: %s", gss); ++ xasprintf(&myproposal[PROPOSAL_KEX_ALGS], ++ "%s,%s", gss, orig); ++ } ++ } ++#endif ++ + if (options.ciphers == (char *)-1) { + logit("No valid ciphers for protocol version 2 given, using defaults."); + options.ciphers = NULL; +@@ -146,6 +171,17 @@ ssh_kex2(char *host, struct sockaddr *ho + 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 (options.gss_keyex && gss) { ++ orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]; ++ xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS], ++ "%s,null", orig); ++ xfree(gss); ++ } ++#endif ++ + if (options.rekey_limit) + packet_set_rekey_limit((u_int32_t)options.rekey_limit); + +@@ -155,10 +191,26 @@ ssh_kex2(char *host, struct sockaddr *ho + kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client; + kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; + kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; ++#ifdef GSSAPI ++ 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 ++ 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; + + dispatch_run(DISPATCH_BLOCK, &kex->done, kex); +@@ -253,6 +305,7 @@ void input_gssapi_token(int type, u_int3 + 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 *); +@@ -268,6 +321,10 @@ static char *authmethods_get(void); + + Authmethod authmethods[] = { + #ifdef GSSAPI ++ {"gssapi-keyex", ++ userauth_gsskeyex, ++ &options.gss_authentication, ++ NULL}, + {"gssapi-with-mic", + userauth_gssapi, + NULL, +@@ -576,23 +633,35 @@ userauth_gssapi(Authctxt *authctxt) + int ok = 0; + char* remotehost = NULL; + const char* canonicalhost = get_canonical_hostname(1); ++ const char *gss_host; ++ + if ( strcmp( canonicalhost, "UNKNOWN" ) == 0 ) + remotehost = authctxt->host; + else + remotehost = canonicalhost; + ++ if (options.gss_trust_dns) ++// gss_host = get_canonical_hostname(1); ++ gss_host = remotehost; ++ else ++ gss_host = authctxt->host; ++ + /* Try one GSSAPI method at a time, rather than sending them all at + * 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], remotehost)) { ++ &gss_supported->elements[mech], gss_host, ++ options.gss_client_identity)) { + ok = 1; /* Mechanism works */ + } else { + mech++; +@@ -689,8 +758,8 @@ input_gssapi_response(int type, u_int32_ + { + Authctxt *authctxt = ctxt; + Gssctxt *gssctxt; +- int oidlen; +- char *oidv; ++ u_int oidlen; ++ u_char *oidv; + + if (authctxt == NULL) + fatal("input_gssapi_response: no authentication context"); +@@ -800,6 +869,48 @@ input_gssapi_error(int type, u_int32_t p + 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 -up openssh-5.4p1/sshd.c.gsskex openssh-5.4p1/sshd.c +--- openssh-5.4p1/sshd.c.gsskex 2010-03-01 18:14:27.000000000 +0100 ++++ openssh-5.4p1/sshd.c 2010-03-01 18:14:29.000000000 +0100 +@@ -129,6 +129,10 @@ int allow_severity; + int deny_severity; + #endif /* LIBWRAP */ + ++#ifdef USE_SECURITY_SESSION_API ++#include ++#endif ++ + #ifndef O_NOCTTY + #define O_NOCTTY 0 + #endif +@@ -1592,10 +1596,13 @@ main(int ac, char **av) + logit("Disabling protocol version 1. Could not load host key"); + options.protocol &= ~SSH_PROTO_1; + } ++#ifndef GSSAPI ++ /* The GSSAPI key exchange can run without a host key */ + if ((options.protocol & SSH_PROTO_2) && !sensitive_data.have_ssh2_key) { + logit("Disabling protocol version 2. Could not load host key"); + options.protocol &= ~SSH_PROTO_2; + } ++#endif + if (!(options.protocol & (SSH_PROTO_1|SSH_PROTO_2))) { + logit("sshd: no hostkeys available -- exiting."); + exit(1); +@@ -1928,6 +1935,60 @@ main(int ac, char **av) + /* Log the connection. */ + verbose("Connection from %.500s port %d", remote_ip, remote_port); + ++#ifdef USE_SECURITY_SESSION_API ++ /* ++ * Create a new security session for use by the new user login if ++ * the current session is the root session or we are not launched ++ * by inetd (eg: debugging mode or server mode). We do not ++ * necessarily need to create a session if we are launched from ++ * inetd because Panther xinetd will create a session for us. ++ * ++ * The only case where this logic will fail is if there is an ++ * inetd running in a non-root session which is not creating ++ * new sessions for us. Then all the users will end up in the ++ * same session (bad). ++ * ++ * When the client exits, the session will be destroyed for us ++ * automatically. ++ * ++ * We must create the session before any credentials are stored ++ * (including AFS pags, which happens a few lines below). ++ */ ++ { ++ OSStatus err = 0; ++ SecuritySessionId sid = 0; ++ SessionAttributeBits sattrs = 0; ++ ++ err = SessionGetInfo(callerSecuritySession, &sid, &sattrs); ++ if (err) ++ error("SessionGetInfo() failed with error %.8X", ++ (unsigned) err); ++ else ++ debug("Current Session ID is %.8X / Session Attributes are %.8X", ++ (unsigned) sid, (unsigned) sattrs); ++ ++ if (inetd_flag && !(sattrs & sessionIsRoot)) ++ debug("Running in inetd mode in a non-root session... " ++ "assuming inetd created the session for us."); ++ else { ++ debug("Creating new security session..."); ++ err = SessionCreate(0, sessionHasTTY | sessionIsRemote); ++ if (err) ++ error("SessionCreate() failed with error %.8X", ++ (unsigned) err); ++ ++ err = SessionGetInfo(callerSecuritySession, &sid, ++ &sattrs); ++ if (err) ++ error("SessionGetInfo() failed with error %.8X", ++ (unsigned) err); ++ else ++ debug("New Session ID is %.8X / Session Attributes are %.8X", ++ (unsigned) sid, (unsigned) sattrs); ++ } ++ } ++#endif ++ + /* + * We don't want to listen forever unless the other side + * successfully authenticates itself. So we set up an alarm which is +@@ -2314,12 +2375,61 @@ do_ssh2_kex(void) + + myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = list_hostkey_types(); + ++#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) ++ xasprintf(&newstr, "%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->kex[KEX_DH_GEX_SHA256] = kexgex_server; ++#ifdef GSSAPI ++ 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; + kex->server_version_string=server_version_string; +diff -up openssh-5.4p1/sshd_config.5.gsskex openssh-5.4p1/sshd_config.5 +--- openssh-5.4p1/sshd_config.5.gsskex 2010-03-01 18:14:28.000000000 +0100 ++++ openssh-5.4p1/sshd_config.5 2010-03-01 18:14:29.000000000 +0100 +@@ -379,12 +379,40 @@ Specifies whether user authentication ba + 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. + The default is + .Dq yes . + Note that this option applies to protocol version 2 only. ++.It Cm GSSAPIStrictAcceptorCheck ++Determines whether to be strict about the identity of the GSSAPI acceptor ++a client authenticates against. If ++.Dq yes ++then the client must authenticate against the ++.Pa host ++service on the current hostname. If ++.Dq no ++then the client may authenticate against any service key stored in the ++machine's default store. This facility is provided to assist with operation ++on multi homed machines. ++The default is ++.Dq yes . ++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 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 + with successful public key client host authentication is allowed +diff -up openssh-5.4p1/sshd_config.gsskex openssh-5.4p1/sshd_config +--- openssh-5.4p1/sshd_config.gsskex 2010-03-01 18:14:28.000000000 +0100 ++++ openssh-5.4p1/sshd_config 2010-03-01 18:14:29.000000000 +0100 +@@ -78,6 +78,8 @@ ChallengeResponseAuthentication no + GSSAPIAuthentication yes + #GSSAPICleanupCredentials yes + GSSAPICleanupCredentials yes ++#GSSAPIStrictAcceptorCheck yes ++#GSSAPIKeyExchange no + + # Set this to 'yes' to enable PAM authentication, account processing, + # and session processing. If this is enabled, PAM authentication will +diff -up openssh-5.4p1/ssh-gss.h.gsskex openssh-5.4p1/ssh-gss.h +--- openssh-5.4p1/ssh-gss.h.gsskex 2007-06-12 15:40:39.000000000 +0200 ++++ openssh-5.4p1/ssh-gss.h 2010-03-01 18:14:30.000000000 +0100 +@@ -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 +@@ -60,10 +60,22 @@ + + #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_GRP14_SHA1_ID "gss-group14-sha1-" ++#define KEX_GSS_GEX_SHA1_ID "gss-gex-sha1-" ++ + typedef struct { + char *filename; + char *envvar; + char *envval; ++ struct passwd *owner; + void *data; + } ssh_gssapi_ccache; + +@@ -71,8 +83,11 @@ 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; ++ int used; ++ int updated; + } ssh_gssapi_client; + + typedef struct ssh_gssapi_mech_struct { +@@ -83,6 +98,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 { +@@ -93,10 +109,11 @@ typedef struct { + gss_OID oid; /* client */ + 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[]; ++extern Gssctxt *gss_kex_context; + + int ssh_gssapi_check_oid(Gssctxt *, void *, size_t); + void ssh_gssapi_set_oid_data(Gssctxt *, void *, size_t); +@@ -116,16 +133,30 @@ 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 *); + + /* In the server */ ++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 *, ++ 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(); ++ ++int ssh_gssapi_update_creds(ssh_gssapi_ccache *store); + #endif /* GSSAPI */ + + #endif /* _SSH_GSS_H */ diff --git a/openssh-5.5p1-ldap.patch b/openssh-5.5p1-pka-ldap.patch similarity index 83% rename from openssh-5.5p1-ldap.patch rename to openssh-5.5p1-pka-ldap.patch index 591ff23..123a889 100644 --- a/openssh-5.5p1-ldap.patch +++ b/openssh-5.5p1-pka-ldap.patch @@ -1,6 +1,202 @@ -diff -up openssh-5.5p1/config.h.in.ldap openssh-5.5p1/config.h.in ---- openssh-5.5p1/config.h.in.ldap 2010-04-16 02:17:09.000000000 +0200 -+++ openssh-5.5p1/config.h.in 2010-04-28 11:34:13.000000000 +0200 +diff -up openssh-5.5p1/auth2-pubkey.c.pka openssh-5.5p1/auth2-pubkey.c +--- openssh-5.5p1/auth2-pubkey.c.pka 2010-03-21 19:51:21.000000000 +0100 ++++ openssh-5.5p1/auth2-pubkey.c 2010-04-29 11:08:25.000000000 +0200 +@@ -178,27 +178,15 @@ done: + + /* return 1 if user allows given key */ + static int +-user_key_allowed2(struct passwd *pw, Key *key, char *file) ++user_search_key_in_file(FILE *f, char *file, Key* key, struct passwd *pw) + { + char line[SSH_MAX_PUBKEY_BYTES]; + const char *reason; + int found_key = 0; +- FILE *f; + u_long linenum = 0; + Key *found; + char *fp; + +- /* Temporarily use the user's uid. */ +- temporarily_use_uid(pw); +- +- debug("trying public key file %s", file); +- f = auth_openkeyfile(file, pw, options.strict_modes); +- +- if (!f) { +- restore_uid(); +- return 0; +- } +- + found_key = 0; + found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type); + +@@ -273,8 +261,6 @@ user_key_allowed2(struct passwd *pw, Key + break; + } + } +- restore_uid(); +- fclose(f); + key_free(found); + if (!found_key) + debug2("key not found"); +@@ -321,13 +307,153 @@ user_cert_trusted_ca(struct passwd *pw, + return ret; + } + +-/* check whether given key is in .ssh/authorized_keys* */ ++/* return 1 if user allows given key */ ++static int ++user_key_allowed2(struct passwd *pw, Key *key, char *file) ++{ ++ FILE *f; ++ int found_key = 0; ++ ++ /* Temporarily use the user's uid. */ ++ temporarily_use_uid(pw); ++ ++ debug("trying public key file %s", file); ++ f = auth_openkeyfile(file, pw, options.strict_modes); ++ ++ if (f) { ++ found_key = user_search_key_in_file (f, file, key, pw); ++ fclose(f); ++ } ++ ++ restore_uid(); ++ return found_key; ++} ++ ++#ifdef WITH_PUBKEY_AGENT ++ ++#define WHITESPACE " \t\r\n" ++ ++/* return 1 if user allows given key */ ++static int ++user_key_via_agent_allowed2(struct passwd *pw, Key *key) ++{ ++ FILE *f; ++ int found_key = 0; ++ char *pubkey_agent_string = NULL; ++ char *tmp_pubkey_agent_string = NULL; ++ char *progname; ++ char *cp; ++ struct passwd *runas_pw; ++ struct stat st; ++ ++ if (options.pubkey_agent == NULL || options.pubkey_agent[0] != '/') ++ return -1; ++ ++ /* get the run as identity from config */ ++ runas_pw = (options.pubkey_agent_runas == NULL)? pw ++ : getpwnam (options.pubkey_agent_runas); ++ if (!runas_pw) { ++ error("%s: getpwnam(\"%s\"): %s", __func__, ++ options.pubkey_agent_runas, strerror(errno)); ++ return 0; ++ } ++ ++ /* Temporarily use the specified uid. */ ++ if (runas_pw->pw_uid != 0) ++ temporarily_use_uid(runas_pw); ++ ++ pubkey_agent_string = percent_expand(options.pubkey_agent, ++ "h", pw->pw_dir, "u", pw->pw_name, (char *)NULL); ++ ++ /* Test whether agent can be modified by non root user */ ++ tmp_pubkey_agent_string = xstrdup (pubkey_agent_string); ++ progname = strtok (tmp_pubkey_agent_string, WHITESPACE); ++ ++ debug3("%s: checking program '%s'", __func__, progname); ++ ++ if (stat (progname, &st) < 0) { ++ error("%s: stat(\"%s\"): %s", __func__, ++ progname, strerror(errno)); ++ goto go_away; ++ } ++ ++ if (st.st_uid != 0 || (st.st_mode & 022) != 0) { ++ error("bad ownership or modes for pubkey agent \"%s\"", ++ progname); ++ goto go_away; ++ } ++ ++ if (!S_ISREG(st.st_mode)) { ++ error("pubkey agent \"%s\" is not a regular file", ++ progname); ++ goto go_away; ++ } ++ ++ /* ++ * Descend the path, checking that each component is a ++ * root-owned directory with strict permissions. ++ */ ++ do { ++ if ((cp = strrchr(progname, '/')) == NULL) ++ break; ++ else ++ *cp = '\0'; ++ ++ debug3("%s: checking component '%s'", __func__, progname); ++ ++ if (stat(progname, &st) != 0) { ++ error("%s: stat(\"%s\"): %s", __func__, ++ progname, strerror(errno)); ++ goto go_away; ++ } ++ if (st.st_uid != 0 || (st.st_mode & 022) != 0) { ++ error("bad ownership or modes for pubkey agent path component \"%s\"", ++ progname); ++ goto go_away; ++ } ++ if (!S_ISDIR(st.st_mode)) { ++ error("pubkey agent path component \"%s\" is not a directory", ++ progname); ++ goto go_away; ++ } ++ } while (0); ++ ++ /* open the pipe and read the keys */ ++ f = popen (pubkey_agent_string, "r"); ++ if (!f) { ++ error("%s: popen (\"%s\", \"r\"): %s", __func__, ++ pubkey_agent_string, strerror (errno)); ++ goto go_away; ++ } ++ ++ found_key = user_search_key_in_file (f, options.pubkey_agent, key, pw); ++ pclose (f); ++ ++go_away: ++ if (tmp_pubkey_agent_string) ++ xfree (tmp_pubkey_agent_string); ++ if (pubkey_agent_string) ++ xfree (pubkey_agent_string); ++ ++ if (runas_pw->pw_uid != 0) ++ restore_uid(); ++ return found_key; ++} ++#endif ++ ++/* check whether given key is in = 0) ++ return success; ++#endif ++ + if (auth_key_is_revoked(key)) + return 0; + if (key_is_cert(key) && auth_key_is_revoked(key->cert->signature_key)) +diff -up openssh-5.5p1/config.h.in.pka openssh-5.5p1/config.h.in +--- openssh-5.5p1/config.h.in.pka 2010-04-16 02:17:09.000000000 +0200 ++++ openssh-5.5p1/config.h.in 2010-04-29 09:40:17.000000000 +0200 @@ -1,5 +1,8 @@ /* config.h.in. Generated from configure.ac by autoheader. */ @@ -10,7 +206,7 @@ diff -up openssh-5.5p1/config.h.in.ldap openssh-5.5p1/config.h.in /* Define if you have a getaddrinfo that fails for the all-zeros IPv6 address */ #undef AIX_GETNAMEINFO_HACK -@@ -536,6 +539,57 @@ +@@ -536,6 +539,54 @@ /* Define to 1 if you have the header file. */ #undef HAVE_LASTLOG_H @@ -61,34 +257,11 @@ diff -up openssh-5.5p1/config.h.in.ldap openssh-5.5p1/config.h.in + +/* Define to 1 if you have the `ldap_start_tls_s' function. */ +#undef HAVE_LDAP_START_TLS_S -+ -+/* Define to 1 if you have the header file. */ -+#undef HAVE_LIBAUDIT_H + /* Define to 1 if you have the `bsm' library (-lbsm). */ #undef HAVE_LIBBSM -@@ -575,6 +629,9 @@ - /* Define to 1 if you have the header file. */ - #undef HAVE_LIMITS_H - -+/* Define if you want Linux audit support. */ -+#undef HAVE_LINUX_AUDIT -+ - /* Define to 1 if you have the header file. */ - #undef HAVE_LINUX_IF_TUN_H - -@@ -771,6 +828,9 @@ - /* Define to 1 if you have the `setgroups' function. */ - #undef HAVE_SETGROUPS - -+/* Define to 1 if you have the `setkeycreatecon' function. */ -+#undef HAVE_SETKEYCREATECON -+ - /* Define to 1 if you have the `setlogin' function. */ - #undef HAVE_SETLOGIN - -@@ -921,13 +981,13 @@ +@@ -921,13 +972,13 @@ /* define if you have struct sockaddr_in6 data type */ #undef HAVE_STRUCT_SOCKADDR_IN6 @@ -104,7 +277,7 @@ diff -up openssh-5.5p1/config.h.in.ldap openssh-5.5p1/config.h.in #undef HAVE_STRUCT_STAT_ST_BLKSIZE /* Define to 1 if the system has the type `struct timespec'. */ -@@ -1191,6 +1251,9 @@ +@@ -1191,6 +1242,9 @@ /* Define if pututxline updates lastlog too */ #undef LASTLOG_WRITE_PUTUTXLINE @@ -114,7 +287,7 @@ diff -up openssh-5.5p1/config.h.in.ldap openssh-5.5p1/config.h.in /* Define if you want TCP Wrappers support */ #undef LIBWRAP -@@ -1274,6 +1337,9 @@ +@@ -1274,6 +1328,9 @@ /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME @@ -124,38 +297,7 @@ diff -up openssh-5.5p1/config.h.in.ldap openssh-5.5p1/config.h.in /* Define to the version of this package. */ #undef PACKAGE_VERSION -@@ -1360,6 +1426,10 @@ - /* Prepend the address family to IP tunnel traffic */ - #undef SSH_TUN_PREPEND_AF - -+/* Define to your vendor patch level, if it has been modified from the -+ upstream source release. */ -+#undef SSH_VENDOR_PATCHLEVEL -+ - /* Define to 1 if you have the ANSI C header files. */ - #undef STDC_HEADERS - -@@ -1384,6 +1454,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 - -@@ -1396,6 +1469,9 @@ - /* Use PIPES instead of a socketpair() */ - #undef USE_PIPES - -+/* platform has the Security Authorization Session API */ -+#undef USE_SECURITY_SESSION_API -+ - /* Define if you have Solaris process contracts */ - #undef USE_SOLARIS_PROCESS_CONTRACTS - -@@ -1418,12 +1494,26 @@ +@@ -1418,12 +1475,26 @@ /* Define if you want IRIX project management */ #undef WITH_IRIX_PROJECT @@ -185,13 +327,25 @@ diff -up openssh-5.5p1/config.h.in.ldap openssh-5.5p1/config.h.in /* Define if xauth is found in your path */ #undef XAUTH_PATH -diff -up openssh-5.5p1/configure.ac.ldap openssh-5.5p1/configure.ac ---- openssh-5.5p1/configure.ac.ldap 2010-04-28 11:34:09.000000000 +0200 -+++ openssh-5.5p1/configure.ac 2010-04-28 11:34:13.000000000 +0200 -@@ -1382,6 +1382,106 @@ AC_ARG_WITH(pka, - ] +diff -up openssh-5.5p1/configure.ac.pka openssh-5.5p1/configure.ac +--- openssh-5.5p1/configure.ac.pka 2010-04-10 14:58:01.000000000 +0200 ++++ openssh-5.5p1/configure.ac 2010-04-29 11:08:25.000000000 +0200 +@@ -1346,6 +1346,118 @@ AC_ARG_WITH(audit, + esac ] ) ++# Check whether user wants pubkey agent support ++PKA_MSG="no" ++AC_ARG_WITH(pka, ++ [ --with-pka Enable pubkey agent support], ++ [ ++ if test "x$withval" != "xno" ; then ++ AC_DEFINE([WITH_PUBKEY_AGENT], 1, [Enable pubkey agent support]) ++ PKA_MSG="yes" ++ fi ++ ] ++) ++ +# Check whether user wants LDAP support +LDAP_MSG="no" +INSTALL_SSH_LDAP_HELPER="" @@ -295,17 +449,18 @@ diff -up openssh-5.5p1/configure.ac.ldap openssh-5.5p1/configure.ac dnl Checks for library functions. Please keep in alphabetical order AC_CHECK_FUNCS( \ arc4random \ -@@ -4239,6 +4339,7 @@ echo " Smartcard support +@@ -4181,6 +4293,8 @@ echo " SELinux support + echo " Smartcard support: $SCARD_MSG" echo " S/KEY support: $SKEY_MSG" echo " TCP Wrappers support: $TCPW_MSG" - echo " PKA support: $PKA_MSG" ++echo " PKA support: $PKA_MSG" +echo " LDAP support: $LDAP_MSG" echo " MD5 password support: $MD5_MSG" echo " libedit support: $LIBEDIT_MSG" echo " Solaris process contract support: $SPC_MSG" -diff -up openssh-5.5p1/ldapbody.c.ldap openssh-5.5p1/ldapbody.c ---- openssh-5.5p1/ldapbody.c.ldap 2010-04-28 11:34:13.000000000 +0200 -+++ openssh-5.5p1/ldapbody.c 2010-04-28 11:34:13.000000000 +0200 +diff -up openssh-5.5p1/ldapbody.c.pka openssh-5.5p1/ldapbody.c +--- openssh-5.5p1/ldapbody.c.pka 2010-04-29 11:08:25.000000000 +0200 ++++ openssh-5.5p1/ldapbody.c 2010-04-29 11:08:25.000000000 +0200 @@ -0,0 +1,494 @@ +/* $OpenBSD: ldapbody.c,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ +/* @@ -801,9 +956,9 @@ diff -up openssh-5.5p1/ldapbody.c.ldap openssh-5.5p1/ldapbody.c + return; +} + -diff -up openssh-5.5p1/ldapbody.h.ldap openssh-5.5p1/ldapbody.h ---- openssh-5.5p1/ldapbody.h.ldap 2010-04-28 11:34:14.000000000 +0200 -+++ openssh-5.5p1/ldapbody.h 2010-04-28 11:34:14.000000000 +0200 +diff -up openssh-5.5p1/ldapbody.h.pka openssh-5.5p1/ldapbody.h +--- openssh-5.5p1/ldapbody.h.pka 2010-04-29 11:08:25.000000000 +0200 ++++ openssh-5.5p1/ldapbody.h 2010-04-29 11:08:25.000000000 +0200 @@ -0,0 +1,37 @@ +/* $OpenBSD: ldapbody.h,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ +/* @@ -842,9 +997,9 @@ diff -up openssh-5.5p1/ldapbody.h.ldap openssh-5.5p1/ldapbody.h + +#endif /* LDAPBODY_H */ + -diff -up openssh-5.5p1/ldapconf.c.ldap openssh-5.5p1/ldapconf.c ---- openssh-5.5p1/ldapconf.c.ldap 2010-04-28 11:34:14.000000000 +0200 -+++ openssh-5.5p1/ldapconf.c 2010-04-28 11:34:14.000000000 +0200 +diff -up openssh-5.5p1/ldapconf.c.pka openssh-5.5p1/ldapconf.c +--- openssh-5.5p1/ldapconf.c.pka 2010-04-29 11:08:25.000000000 +0200 ++++ openssh-5.5p1/ldapconf.c 2010-04-29 11:08:25.000000000 +0200 @@ -0,0 +1,665 @@ +/* $OpenBSD: ldapconf.c,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ +/* @@ -1511,9 +1666,9 @@ diff -up openssh-5.5p1/ldapconf.c.ldap openssh-5.5p1/ldapconf.c + dump_cfg_string(lSSH_Filter, options.ssh_filter); +} + -diff -up openssh-5.5p1/ldapconf.h.ldap openssh-5.5p1/ldapconf.h ---- openssh-5.5p1/ldapconf.h.ldap 2010-04-28 11:34:14.000000000 +0200 -+++ openssh-5.5p1/ldapconf.h 2010-04-28 11:34:14.000000000 +0200 +diff -up openssh-5.5p1/ldapconf.h.pka openssh-5.5p1/ldapconf.h +--- openssh-5.5p1/ldapconf.h.pka 2010-04-29 11:08:25.000000000 +0200 ++++ openssh-5.5p1/ldapconf.h 2010-04-29 11:08:25.000000000 +0200 @@ -0,0 +1,71 @@ +/* $OpenBSD: ldapconf.c,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ +/* @@ -1586,9 +1741,9 @@ diff -up openssh-5.5p1/ldapconf.h.ldap openssh-5.5p1/ldapconf.h +void dump_config(void); + +#endif /* LDAPCONF_H */ -diff -up openssh-5.5p1/ldap-helper.c.ldap openssh-5.5p1/ldap-helper.c ---- openssh-5.5p1/ldap-helper.c.ldap 2010-04-28 11:34:14.000000000 +0200 -+++ openssh-5.5p1/ldap-helper.c 2010-04-28 11:34:14.000000000 +0200 +diff -up openssh-5.5p1/ldap-helper.c.pka openssh-5.5p1/ldap-helper.c +--- openssh-5.5p1/ldap-helper.c.pka 2010-04-29 11:08:25.000000000 +0200 ++++ openssh-5.5p1/ldap-helper.c 2010-04-29 11:08:25.000000000 +0200 @@ -0,0 +1,154 @@ +/* $OpenBSD: ssh-pka-ldap.c,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ +/* @@ -1744,9 +1899,9 @@ diff -up openssh-5.5p1/ldap-helper.c.ldap openssh-5.5p1/ldap-helper.c +void *buffer_get_string(Buffer *b, u_int *l) {} +void buffer_put_string(Buffer *b, const void *f, u_int l) {} + -diff -up openssh-5.5p1/ldap-helper.h.ldap openssh-5.5p1/ldap-helper.h ---- openssh-5.5p1/ldap-helper.h.ldap 2010-04-28 11:34:14.000000000 +0200 -+++ openssh-5.5p1/ldap-helper.h 2010-04-28 11:34:14.000000000 +0200 +diff -up openssh-5.5p1/ldap-helper.h.pka openssh-5.5p1/ldap-helper.h +--- openssh-5.5p1/ldap-helper.h.pka 2010-04-29 11:08:25.000000000 +0200 ++++ openssh-5.5p1/ldap-helper.h 2010-04-29 11:08:25.000000000 +0200 @@ -0,0 +1,32 @@ +/* $OpenBSD: ldap-helper.h,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ +/* @@ -1780,9 +1935,9 @@ diff -up openssh-5.5p1/ldap-helper.h.ldap openssh-5.5p1/ldap-helper.h +extern int config_warning_config_file; + +#endif /* LDAP_HELPER_H */ -diff -up openssh-5.5p1/ldapincludes.h.ldap openssh-5.5p1/ldapincludes.h ---- openssh-5.5p1/ldapincludes.h.ldap 2010-04-28 11:34:14.000000000 +0200 -+++ openssh-5.5p1/ldapincludes.h 2010-04-28 11:34:14.000000000 +0200 +diff -up openssh-5.5p1/ldapincludes.h.pka openssh-5.5p1/ldapincludes.h +--- openssh-5.5p1/ldapincludes.h.pka 2010-04-29 11:08:26.000000000 +0200 ++++ openssh-5.5p1/ldapincludes.h 2010-04-29 11:08:26.000000000 +0200 @@ -0,0 +1,41 @@ +/* $OpenBSD: ldapconf.c,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ +/* @@ -1825,9 +1980,9 @@ diff -up openssh-5.5p1/ldapincludes.h.ldap openssh-5.5p1/ldapincludes.h +#endif + +#endif /* LDAPINCLUDES_H */ -diff -up openssh-5.5p1/ldapmisc.c.ldap openssh-5.5p1/ldapmisc.c ---- openssh-5.5p1/ldapmisc.c.ldap 2010-04-28 11:34:14.000000000 +0200 -+++ openssh-5.5p1/ldapmisc.c 2010-04-28 11:34:14.000000000 +0200 +diff -up openssh-5.5p1/ldapmisc.c.pka openssh-5.5p1/ldapmisc.c +--- openssh-5.5p1/ldapmisc.c.pka 2010-04-29 11:08:26.000000000 +0200 ++++ openssh-5.5p1/ldapmisc.c 2010-04-29 11:08:26.000000000 +0200 @@ -0,0 +1,79 @@ + +#include "ldapincludes.h" @@ -1908,9 +2063,9 @@ diff -up openssh-5.5p1/ldapmisc.c.ldap openssh-5.5p1/ldapmisc.c +} +#endif + -diff -up openssh-5.5p1/ldapmisc.h.ldap openssh-5.5p1/ldapmisc.h ---- openssh-5.5p1/ldapmisc.h.ldap 2010-04-28 11:34:14.000000000 +0200 -+++ openssh-5.5p1/ldapmisc.h 2010-04-28 11:34:14.000000000 +0200 +diff -up openssh-5.5p1/ldapmisc.h.pka openssh-5.5p1/ldapmisc.h +--- openssh-5.5p1/ldapmisc.h.pka 2010-04-29 11:08:26.000000000 +0200 ++++ openssh-5.5p1/ldapmisc.h 2010-04-29 11:08:26.000000000 +0200 @@ -0,0 +1,35 @@ +/* $OpenBSD: ldapbody.h,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ +/* @@ -1947,9 +2102,9 @@ diff -up openssh-5.5p1/ldapmisc.h.ldap openssh-5.5p1/ldapmisc.h + +#endif /* LDAPMISC_H */ + -diff -up openssh-5.5p1/lpk-user-example.txt.ldap openssh-5.5p1/lpk-user-example.txt ---- openssh-5.5p1/lpk-user-example.txt.ldap 2010-04-28 11:34:14.000000000 +0200 -+++ openssh-5.5p1/lpk-user-example.txt 2010-04-28 11:34:14.000000000 +0200 +diff -up openssh-5.5p1/lpk-user-example.txt.pka openssh-5.5p1/lpk-user-example.txt +--- openssh-5.5p1/lpk-user-example.txt.pka 2010-04-29 11:08:26.000000000 +0200 ++++ openssh-5.5p1/lpk-user-example.txt 2010-04-29 11:08:26.000000000 +0200 @@ -0,0 +1,117 @@ + +Post to ML -> User Made Quick Install Doc. @@ -2068,9 +2223,9 @@ diff -up openssh-5.5p1/lpk-user-example.txt.ldap openssh-5.5p1/lpk-user-example. +puTTY). Login should succeed. + +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -diff -up openssh-5.5p1/Makefile.in.ldap openssh-5.5p1/Makefile.in ---- openssh-5.5p1/Makefile.in.ldap 2010-04-28 11:34:10.000000000 +0200 -+++ openssh-5.5p1/Makefile.in 2010-04-28 11:34:15.000000000 +0200 +diff -up openssh-5.5p1/Makefile.in.pka openssh-5.5p1/Makefile.in +--- openssh-5.5p1/Makefile.in.pka 2010-03-13 22:41:34.000000000 +0100 ++++ openssh-5.5p1/Makefile.in 2010-04-29 11:08:26.000000000 +0200 @@ -26,6 +26,7 @@ ASKPASS_PROGRAM=$(libexecdir)/ssh-askpas SFTP_SERVER=$(libexecdir)/sftp-server SSH_KEYSIGN=$(libexecdir)/ssh-keysign @@ -2092,7 +2247,7 @@ diff -up openssh-5.5p1/Makefile.in.ldap openssh-5.5p1/Makefile.in canohost.o channels.o cipher.o cipher-acss.o cipher-aes.o \ @@ -93,8 +95,8 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passw audit.o audit-bsm.o platform.o sftp-server.o sftp-common.o \ - roaming_common.o roaming_serv.o kexgsss.o + roaming_common.o roaming_serv.o -MANPAGES = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-rand-helper.8.out ssh-keysign.8.out ssh-pkcs11-helper.8.out sshd_config.5.out ssh_config.5.out -MANPAGES_IN = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-rand-helper.8 ssh-keysign.8 ssh-pkcs11-helper.8 sshd_config.5 ssh_config.5 @@ -2101,15 +2256,15 @@ diff -up openssh-5.5p1/Makefile.in.ldap openssh-5.5p1/Makefile.in MANTYPE = @MANTYPE@ CONFIGFILES=sshd_config.out ssh_config.out moduli.out -@@ -165,6 +167,9 @@ ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT) - ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o roaming_dummy.o - $(LD) -o $@ ssh-keyscan.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lfipscheck $(LIBS) +@@ -162,6 +164,9 @@ ssh-keysign$(EXEEXT): $(LIBCOMPAT) libss + ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-pkcs11-helper.o ssh-pkcs11.o + $(LD) -o $@ ssh-pkcs11-helper.o ssh-pkcs11.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) +ssh-ldap-helper$(EXEEXT): $(LIBCOMPAT) libssh.a ldapconf.o ldapbody.o ldapmisc.o ldap-helper.o + $(LD) -o $@ ldapconf.o ldapbody.o ldapmisc.o ldap-helper.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) + - sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-common.o sftp-server.o sftp-server-main.o - $(LD) -o $@ sftp-server.o sftp-common.o sftp-server-main.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) + ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o roaming_dummy.o + $(LD) -o $@ ssh-keyscan.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) @@ -266,6 +271,9 @@ install-files: fi @@ -2139,9 +2294,9 @@ diff -up openssh-5.5p1/Makefile.in.ldap openssh-5.5p1/Makefile.in -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1 tests interop-tests: $(TARGETS) -diff -up openssh-5.5p1/openssh-lpk-openldap.schema.ldap openssh-5.5p1/openssh-lpk-openldap.schema ---- openssh-5.5p1/openssh-lpk-openldap.schema.ldap 2010-04-28 11:34:15.000000000 +0200 -+++ openssh-5.5p1/openssh-lpk-openldap.schema 2010-04-28 11:34:15.000000000 +0200 +diff -up openssh-5.5p1/openssh-lpk-openldap.schema.pka openssh-5.5p1/openssh-lpk-openldap.schema +--- openssh-5.5p1/openssh-lpk-openldap.schema.pka 2010-04-29 11:08:26.000000000 +0200 ++++ openssh-5.5p1/openssh-lpk-openldap.schema 2010-04-29 11:08:26.000000000 +0200 @@ -0,0 +1,21 @@ +# +# LDAP Public Key Patch schema for use with openssh-ldappubkey @@ -2164,9 +2319,9 @@ diff -up openssh-5.5p1/openssh-lpk-openldap.schema.ldap openssh-5.5p1/openssh-lp + DESC 'MANDATORY: OpenSSH LPK objectclass' + MUST ( sshPublicKey $ uid ) + ) -diff -up openssh-5.5p1/openssh-lpk-sun.schema.ldap openssh-5.5p1/openssh-lpk-sun.schema ---- openssh-5.5p1/openssh-lpk-sun.schema.ldap 2010-04-28 11:34:15.000000000 +0200 -+++ openssh-5.5p1/openssh-lpk-sun.schema 2010-04-28 11:34:15.000000000 +0200 +diff -up openssh-5.5p1/openssh-lpk-sun.schema.pka openssh-5.5p1/openssh-lpk-sun.schema +--- openssh-5.5p1/openssh-lpk-sun.schema.pka 2010-04-29 11:08:26.000000000 +0200 ++++ openssh-5.5p1/openssh-lpk-sun.schema 2010-04-29 11:08:26.000000000 +0200 @@ -0,0 +1,23 @@ +# +# LDAP Public Key Patch schema for use with openssh-ldappubkey @@ -2191,9 +2346,9 @@ diff -up openssh-5.5p1/openssh-lpk-sun.schema.ldap openssh-5.5p1/openssh-lpk-sun + DESC 'MANDATORY: OpenSSH LPK objectclass' + MUST ( sshPublicKey $ uid ) + ) -diff -up openssh-5.5p1/README.lpk.ldap openssh-5.5p1/README.lpk ---- openssh-5.5p1/README.lpk.ldap 2010-04-28 11:34:15.000000000 +0200 -+++ openssh-5.5p1/README.lpk 2010-04-28 12:33:34.000000000 +0200 +diff -up openssh-5.5p1/README.lpk.pka openssh-5.5p1/README.lpk +--- openssh-5.5p1/README.lpk.pka 2010-04-29 11:08:26.000000000 +0200 ++++ openssh-5.5p1/README.lpk 2010-04-29 11:08:26.000000000 +0200 @@ -0,0 +1,268 @@ +OpenSSH LDAP PUBLIC KEY PATCH +Copyright (c) 2003 Eric AUGE (eau@phear.org) @@ -2463,9 +2618,167 @@ diff -up openssh-5.5p1/README.lpk.ldap openssh-5.5p1/README.lpk +- CONTACT : + Jan F. Chadima + -diff -up openssh-5.5p1/ssh-ldap-helper.8.ldap openssh-5.5p1/ssh-ldap-helper.8 ---- openssh-5.5p1/ssh-ldap-helper.8.ldap 2010-04-28 11:34:15.000000000 +0200 -+++ openssh-5.5p1/ssh-ldap-helper.8 2010-04-28 11:34:15.000000000 +0200 +diff -up openssh-5.5p1/servconf.c.pka openssh-5.5p1/servconf.c +--- openssh-5.5p1/servconf.c.pka 2010-03-26 00:40:04.000000000 +0100 ++++ openssh-5.5p1/servconf.c 2010-04-29 11:08:25.000000000 +0200 +@@ -128,6 +128,8 @@ initialize_server_options(ServerOptions + options->num_permitted_opens = -1; + options->adm_forced_command = NULL; + options->chroot_directory = NULL; ++ options->pubkey_agent = NULL; ++ options->pubkey_agent_runas = NULL; + options->zero_knowledge_password_authentication = -1; + options->revoked_keys_file = NULL; + options->trusted_user_ca_keys = NULL; +@@ -311,6 +313,7 @@ typedef enum { + sUsePrivilegeSeparation, sAllowAgentForwarding, + sZeroKnowledgePasswordAuthentication, sHostCertificate, + sRevokedKeys, sTrustedUserCAKeys, ++ sPubkeyAgent, sPubkeyAgentRunAs, + sDeprecated, sUnsupported + } ServerOpCodes; + +@@ -432,6 +435,13 @@ static struct { + { "hostcertificate", sHostCertificate, SSHCFG_GLOBAL }, + { "revokedkeys", sRevokedKeys, SSHCFG_ALL }, + { "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL }, ++#ifdef WITH_PUBKEY_AGENT ++ { "pubkeyagent", sPubkeyAgent, SSHCFG_ALL }, ++ { "pubkeyagentrunas", sPubkeyAgentRunAs, SSHCFG_ALL }, ++#else ++ { "pubkeyagent", sUnsupported, SSHCFG_ALL }, ++ { "pubkeyagentrunas", sUnsupported, SSHCFG_ALL }, ++#endif + { NULL, sBadOption, 0 } + }; + +@@ -1345,6 +1355,20 @@ process_server_config_line(ServerOptions + charptr = &options->revoked_keys_file; + goto parse_filename; + ++ case sPubkeyAgent: ++ len = strspn(cp, WHITESPACE); ++ if (*activep && options->pubkey_agent == NULL) ++ options->pubkey_agent = xstrdup(cp + len); ++ return 0; ++ ++ case sPubkeyAgentRunAs: ++ charptr = &options->pubkey_agent_runas; ++ ++ arg = strdelim(&cp); ++ if (*activep && *charptr == NULL) ++ *charptr = xstrdup(arg); ++ break; ++ + case sDeprecated: + logit("%s line %d: Deprecated option %s", + filename, linenum, arg); +@@ -1438,6 +1462,8 @@ copy_set_server_options(ServerOptions *d + M_CP_INTOPT(gss_authentication); + M_CP_INTOPT(rsa_authentication); + M_CP_INTOPT(pubkey_authentication); ++ M_CP_STROPT(pubkey_agent); ++ M_CP_STROPT(pubkey_agent_runas); + M_CP_INTOPT(kerberos_authentication); + M_CP_INTOPT(hostbased_authentication); + M_CP_INTOPT(kbd_interactive_authentication); +@@ -1682,6 +1708,8 @@ dump_config(ServerOptions *o) + dump_cfg_string(sChrootDirectory, o->chroot_directory); + dump_cfg_string(sTrustedUserCAKeys, o->trusted_user_ca_keys); + dump_cfg_string(sRevokedKeys, o->revoked_keys_file); ++ dump_cfg_string(sPubkeyAgent, o->pubkey_agent); ++ dump_cfg_string(sPubkeyAgentRunAs, o->pubkey_agent_runas); + + /* string arguments requiring a lookup */ + dump_cfg_string(sLogLevel, log_level_name(o->log_level)); +diff -up openssh-5.5p1/servconf.h.pka openssh-5.5p1/servconf.h +--- openssh-5.5p1/servconf.h.pka 2010-03-04 11:53:35.000000000 +0100 ++++ openssh-5.5p1/servconf.h 2010-04-29 11:08:25.000000000 +0200 +@@ -156,6 +156,8 @@ typedef struct { + char *chroot_directory; + char *revoked_keys_file; + char *trusted_user_ca_keys; ++ char *pubkey_agent; ++ char *pubkey_agent_runas; + } ServerOptions; + + void initialize_server_options(ServerOptions *); +diff -up openssh-5.5p1/sshd_config.0.pka openssh-5.5p1/sshd_config.0 +--- openssh-5.5p1/sshd_config.0.pka 2010-04-16 02:17:12.000000000 +0200 ++++ openssh-5.5p1/sshd_config.0 2010-04-29 11:08:25.000000000 +0200 +@@ -352,7 +352,8 @@ DESCRIPTION + KbdInteractiveAuthentication, KerberosAuthentication, + MaxAuthTries, MaxSessions, PasswordAuthentication, + PermitEmptyPasswords, PermitOpen, PermitRootLogin, +- PubkeyAuthentication, RhostsRSAAuthentication, RSAAuthentication, ++ PubkeyAuthentication, PubkeyAgent, PubkeyAgentRunAs, ++ RhostsRSAAuthentication, RSAAuthentication, + X11DisplayOffset, X11Forwarding and X11UseLocalHost. + + MaxAuthTries +@@ -467,6 +468,17 @@ DESCRIPTION + this file is not readable, then public key authentication will be + refused for all users. + ++ PubkeyAgent ++ Specifies which agent is used for lookup of the user's public ++ keys. Empty string means to use the authorized_keys file. By ++ default there is no PubkeyAgent set. Note that this option has ++ an effect only with PubkeyAuthentication switched on. ++ ++ PubkeyAgentRunAs ++ Specifies the user under whose account the PubkeyAgent is run. ++ Empty string (the default value) means the user being authorized ++ is used. ++ + RhostsRSAAuthentication + Specifies whether rhosts or /etc/hosts.equiv authentication to- + gether with successful RSA host authentication is allowed. The +diff -up openssh-5.5p1/sshd_config.5.pka openssh-5.5p1/sshd_config.5 +--- openssh-5.5p1/sshd_config.5.pka 2010-03-05 00:41:45.000000000 +0100 ++++ openssh-5.5p1/sshd_config.5 2010-04-29 11:08:25.000000000 +0200 +@@ -618,6 +618,9 @@ Available keywords are + .Cm KerberosAuthentication , + .Cm MaxAuthTries , + .Cm MaxSessions , ++.Cm PubkeyAuthentication , ++.Cm PubkeyAgent , ++.Cm PubkeyAgentRunAs , + .Cm PasswordAuthentication , + .Cm PermitEmptyPasswords , + .Cm PermitOpen , +@@ -819,6 +822,16 @@ Specifies a list of revoked public keys. + Keys listed in this file will be refused for public key authentication. + Note that if this file is not readable, then public key authentication will + be refused for all users. +++.It Cm PubkeyAgent +++Specifies which agent is used for lookup of the user's public +++keys. Empty string means to use the authorized_keys file. +++By default there is no PubkeyAgent set. +++Note that this option has an effect only with PubkeyAuthentication +++switched on. +++.It Cm PubkeyAgentRunAs +++Specifies the user under whose account the PubkeyAgent is run. Empty +++string (the default value) means the user being authorized is used. +++.Dq + .It Cm RhostsRSAAuthentication + Specifies whether rhosts or /etc/hosts.equiv authentication together + with successful RSA host authentication is allowed. +diff -up openssh-5.5p1/sshd_config.pka openssh-5.5p1/sshd_config +--- openssh-5.5p1/sshd_config.pka 2009-10-11 12:51:09.000000000 +0200 ++++ openssh-5.5p1/sshd_config 2010-04-29 11:08:25.000000000 +0200 +@@ -44,6 +44,8 @@ + #RSAAuthentication yes + #PubkeyAuthentication yes + #AuthorizedKeysFile .ssh/authorized_keys ++#PubkeyAgent none ++#PubkeyAgentRunAs nobody + + # For this to work you will also need host keys in /etc/ssh/ssh_known_hosts + #RhostsRSAAuthentication no +diff -up openssh-5.5p1/ssh-ldap-helper.8.pka openssh-5.5p1/ssh-ldap-helper.8 +--- openssh-5.5p1/ssh-ldap-helper.8.pka 2010-04-29 11:08:26.000000000 +0200 ++++ openssh-5.5p1/ssh-ldap-helper.8 2010-04-29 11:08:26.000000000 +0200 @@ -0,0 +1,78 @@ +.\" $OpenBSD: ssh-ldap-helper.8,v 1.1 2010/02/10 23:20:38 markus Exp $ +.\" diff --git a/openssh-5.5p1-stderr.patch b/openssh-5.5p1-stderr.patch new file mode 100644 index 0000000..ef35d80 --- /dev/null +++ b/openssh-5.5p1-stderr.patch @@ -0,0 +1,157 @@ +diff -up openssh-5.5p1/session.c.stderr openssh-5.5p1/session.c +--- openssh-5.5p1/session.c.stderr 2010-04-26 10:35:35.000000000 +0200 ++++ openssh-5.5p1/session.c 2010-04-26 10:41:11.000000000 +0200 +@@ -47,6 +47,7 @@ + #include + + #include ++#include + #include + #ifdef HAVE_PATHS_H + #include +@@ -447,6 +448,9 @@ do_exec_no_pty(Session *s, const char *c + #ifdef USE_PIPES + int pin[2], pout[2], perr[2]; + ++ if (s == NULL) ++ fatal("do_exec_no_pty: no session"); ++ + /* Allocate pipes for communicating with the program. */ + if (pipe(pin) < 0) { + error("%s: pipe in: %.100s", __func__, strerror(errno)); +@@ -458,33 +462,59 @@ do_exec_no_pty(Session *s, const char *c + close(pin[1]); + return -1; + } +- if (pipe(perr) < 0) { +- error("%s: pipe err: %.100s", __func__, strerror(errno)); +- close(pin[0]); +- close(pin[1]); +- close(pout[0]); +- close(pout[1]); +- return -1; ++ if (s->is_subsystem) { ++ if ((perr[1] = open(_PATH_DEVNULL, O_WRONLY)) == -1) { ++ error("%s: open(%s): %s", __func__, _PATH_DEVNULL, ++ strerror(errno)); ++ close(pin[0]); ++ close(pin[1]); ++ close(pout[0]); ++ close(pout[1]); ++ return -1; ++ } ++ perr[0] = -1; ++ } else { ++ if (pipe(perr) < 0) { ++ error("%s: pipe err: %.100s", __func__, ++ strerror(errno)); ++ close(pin[0]); ++ close(pin[1]); ++ close(pout[0]); ++ close(pout[1]); ++ return -1; ++ } + } + #else + int inout[2], err[2]; + ++ if (s == NULL) ++ fatal("do_exec_no_pty: no session"); ++ + /* Uses socket pairs to communicate with the program. */ + if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) < 0) { + error("%s: socketpair #1: %.100s", __func__, strerror(errno)); + return -1; + } +- if (socketpair(AF_UNIX, SOCK_STREAM, 0, err) < 0) { +- error("%s: socketpair #2: %.100s", __func__, strerror(errno)); +- close(inout[0]); +- close(inout[1]); +- return -1; ++ if (s->is_subsystem) { ++ if ((err[0] = open(_PATH_DEVNULL, O_WRONLY)) == -1) { ++ error("%s: open(%s): %s", __func__, _PATH_DEVNULL, ++ strerror(errno)); ++ close(inout[0]); ++ close(inout[1]); ++ return -1; ++ } ++ err[1] = -1; ++ } else { ++ if (socketpair(AF_UNIX, SOCK_STREAM, 0, err) < 0) { ++ error("%s: socketpair #2: %.100s", __func__, ++ strerror(errno)); ++ close(inout[0]); ++ close(inout[1]); ++ return -1; ++ } + } + #endif + +- if (s == NULL) +- fatal("do_exec_no_pty: no session"); +- + session_proctitle(s); + + /* Fork the child. */ +@@ -496,13 +526,15 @@ do_exec_no_pty(Session *s, const char *c + close(pin[1]); + close(pout[0]); + close(pout[1]); +- close(perr[0]); ++ if (perr[0] != -1) ++ close(perr[0]); + close(perr[1]); + #else + close(inout[0]); + close(inout[1]); + close(err[0]); +- close(err[1]); ++ if (err[1] != -1) ++ close(err[1]); + #endif + return -1; + case 0: +@@ -536,7 +568,8 @@ do_exec_no_pty(Session *s, const char *c + close(pout[1]); + + /* Redirect stderr. */ +- close(perr[0]); ++ if (perr[0] != -1) ++ close(perr[0]); + if (dup2(perr[1], 2) < 0) + perror("dup2 stderr"); + close(perr[1]); +@@ -547,7 +580,8 @@ do_exec_no_pty(Session *s, const char *c + * seem to depend on it. + */ + close(inout[1]); +- close(err[1]); ++ if (err[1] != -1) ++ close(err[1]); + if (dup2(inout[0], 0) < 0) /* stdin */ + perror("dup2 stdin"); + if (dup2(inout[0], 1) < 0) /* stdout (same as stdin) */ +@@ -595,10 +629,6 @@ do_exec_no_pty(Session *s, const char *c + close(perr[1]); + + if (compat20) { +- if (s->is_subsystem) { +- close(perr[0]); +- perr[0] = -1; +- } + session_set_fds(s, pin[1], pout[0], perr[0], 0); + } else { + /* Enter the interactive session. */ +@@ -615,10 +645,7 @@ do_exec_no_pty(Session *s, const char *c + * handle the case that fdin and fdout are the same. + */ + if (compat20) { +- session_set_fds(s, inout[1], inout[1], +- s->is_subsystem ? -1 : err[1], 0); +- if (s->is_subsystem) +- close(err[1]); ++ session_set_fds(s, inout[1], inout[1], err[1], 0); + } else { + server_loop(pid, inout[1], inout[1], err[1]); + /* server_loop has closed inout[1] and err[1]. */ diff --git a/openssh.spec b/openssh.spec index 86283d5..aa86695 100644 --- a/openssh.spec +++ b/openssh.spec @@ -70,7 +70,7 @@ %endif # Do not forget to bump pam_ssh_agent_auth release if you rewind the main package release to 1 -%define openssh_rel 4 +%define openssh_rel 5 %define openssh_ver 5.5p1 %define pam_ssh_agent_rel 26 %define pam_ssh_agent_ver 0.9.2 @@ -111,12 +111,11 @@ Patch62: openssh-5.1p1-scp-manpage.patch Patch65: openssh-5.5p1-fips.patch Patch69: openssh-5.3p1-selabel.patch Patch71: openssh-5.2p1-edns.patch -Patch72: openssh-5.4p1-pka.patch -Patch73: openssh-5.4p1-gsskex.patch +Patch72: openssh-5.5p1-pka-ldap.patch +Patch73: openssh-5.5p1-gsskex.patch Patch74: openssh-5.3p1-randclean.patch Patch76: openssh-5.4p1-staterr.patch -Patch77: openssh-5.5p1-stderr.diff -Patch78: openssh-5.5p1-ldap.patch +Patch77: openssh-5.5p1-stderr.patch License: BSD Group: Applications/Internet @@ -184,6 +183,13 @@ Requires(post): chkconfig >= 0.9, /sbin/service Requires(pre): /usr/sbin/useradd Requires: pam >= 1.0.1-3 +%if %{ldap} +%package ldap +Summary: A LDAP support for open source SSH server daemon +Requires: openssh = %{version}-%{release} +Group: System Environment/Daemons +%endif + %package askpass Summary: A passphrase dialog for OpenSSH and X Group: Applications/Internet @@ -223,6 +229,12 @@ into and executing commands on a remote machine. This package contains the secure shell daemon (sshd). The sshd daemon allows SSH clients to securely connect to your SSH server. +%if %{ldap} +%description ldap +OpenSSH LDAP backend is a way how to distribute the authorized tokens +among the servers in the network. +%endif + %description askpass OpenSSH is a free version of SSH (Secure SHell), a program for logging into and executing commands on a remote machine. This package contains @@ -258,6 +270,7 @@ popd %patch18 -p1 -b .pam_selinux %endif +%patch72 -p1 -b .pka %patch24 -p1 -b .fromto-remote %patch27 -p1 -b .log-chroot %patch30 -p1 -b .exit-deadlock @@ -269,14 +282,10 @@ popd %patch65 -p1 -b .fips %patch69 -p1 -b .selabel %patch71 -p1 -b .edns -%patch72 -p1 -b .pka %patch73 -p1 -b .gsskex %patch74 -p1 -b .randclean %patch76 -p1 -b .staterr %patch77 -p1 -b .stderr -%if %{ldap} -%patch78 -p1 -b .ldap -%endif autoreconf pushd pam_ssh_agent_auth-%{pam_ssh_agent_ver} @@ -515,28 +524,27 @@ fi %if ! %{rescue} %files server %defattr(-,root,root) -%if %{ldap} -%doc README.lpk lpk-user-example.txt openssh-lpk-openldap.schema openssh-lpk-sun.schema -%endif %dir %attr(0711,root,root) %{_var}/empty/sshd %attr(0755,root,root) %{_sbindir}/sshd %attr(0644,root,root) %{_sbindir}/.sshd.hmac %attr(0755,root,root) %{_libexecdir}/openssh/sftp-server -%if %{ldap} -%attr(0755,root,root) %{_libexecdir}/openssh/ssh-ldap-helper -%endif %attr(0644,root,root) %{_mandir}/man5/sshd_config.5* %attr(0644,root,root) %{_mandir}/man5/moduli.5* %attr(0644,root,root) %{_mandir}/man8/sshd.8* %attr(0644,root,root) %{_mandir}/man8/sftp-server.8* -%if %{ldap} -%attr(0644,root,root) %{_mandir}/man8/ssh-ldap-helper.8* -%endif %attr(0600,root,root) %config(noreplace) %{_sysconfdir}/ssh/sshd_config %attr(0644,root,root) %config(noreplace) /etc/pam.d/sshd %attr(0755,root,root) /etc/rc.d/init.d/sshd %endif +%if %{ldap} +%files ldap +%defattr(-,root,root) +%doc README.lpk lpk-user-example.txt openssh-lpk-openldap.schema openssh-lpk-sun.schema +%attr(0755,root,root) %{_libexecdir}/openssh/ssh-ldap-helper +%attr(0644,root,root) %{_mandir}/man8/ssh-ldap-helper.8* +%endif + %if ! %{no_gnome_askpass} %files askpass %defattr(-,root,root) @@ -554,6 +562,11 @@ fi %endif %changelog +* Mon May 3 2010 Jan F. Chadima - 5.5p1-5 + 0.9.2-26 +- Create separate ldap package +- Tweak the ldap patch +- Rename stderr patch properly + * Wed Apr 29 2010 Jan F. Chadima - 5.5p1-4 + 0.9.2-26 - Added LDAP support