Index: openssh-5.3p1/gss-genr.c =================================================================== --- openssh-5.3p1.orig/gss-genr.c 2010-01-24 10:30:18.000000000 +0000 +++ openssh-5.3p1/gss-genr.c 2010-01-24 10:35:28.000000000 +0000 @@ -76,7 +76,7 @@ */ char * -ssh_gssapi_client_mechanisms(const char *host) { +ssh_gssapi_client_mechanisms(const char *host, const char *client) { gss_OID_set gss_supported; OM_uint32 min_status; @@ -84,12 +84,12 @@ return NULL; return(ssh_gssapi_kex_mechs(gss_supported, ssh_gssapi_check_mechanism, - host)); + host, client)); } char * ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check, - const char *data) { + const char *host, const char *client) { Buffer buf; size_t i; int oidpos, enclen; @@ -113,7 +113,7 @@ oidpos = 0; for (i = 0; i < gss_supported->count; i++) { if (gss_supported->elements[i].length < 128 && - (*check)(NULL, &(gss_supported->elements[i]), data)) { + (*check)(NULL, &(gss_supported->elements[i]), host, client)) { deroid[0] = SSH_GSS_OIDTYPE; deroid[1] = gss_supported->elements[i].length; @@ -352,7 +352,7 @@ } 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); @@ -382,6 +382,37 @@ } 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) @@ -420,7 +451,8 @@ } 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; @@ -438,6 +470,10 @@ 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); Index: openssh-5.3p1/gss-serv.c =================================================================== --- openssh-5.3p1.orig/gss-serv.c 2010-01-24 10:30:18.000000000 +0000 +++ openssh-5.3p1/gss-serv.c 2010-01-24 10:35:28.000000000 +0000 @@ -131,12 +131,13 @@ ssh_gssapi_supported_oids(&supported); return (ssh_gssapi_kex_mechs(supported, &ssh_gssapi_server_check_mech, - NULL)); + NULL, NULL)); } /* Unprivileged */ int -ssh_gssapi_server_check_mech(Gssctxt **dum, gss_OID oid, const char *data) { +ssh_gssapi_server_check_mech(Gssctxt **dum, gss_OID oid, const char *data, + const char *dummy) { Gssctxt *ctx = NULL; int res; Index: openssh-5.3p1/kex.h =================================================================== --- openssh-5.3p1.orig/kex.h 2010-01-24 10:30:18.000000000 +0000 +++ openssh-5.3p1/kex.h 2010-01-24 10:35:28.000000000 +0000 @@ -128,6 +128,7 @@ int gss_deleg_creds; int gss_trust_dns; char *gss_host; + char *gss_client; #endif char *client_version_string; char *server_version_string; Index: openssh-5.3p1/kexgssc.c =================================================================== --- openssh-5.3p1.orig/kexgssc.c 2010-01-24 10:30:18.000000000 +0000 +++ openssh-5.3p1/kexgssc.c 2010-01-24 10:35:28.000000000 +0000 @@ -74,7 +74,11 @@ 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(); Index: openssh-5.3p1/readconf.c =================================================================== --- openssh-5.3p1.orig/readconf.c 2010-01-24 10:30:18.000000000 +0000 +++ openssh-5.3p1/readconf.c 2010-01-24 10:35:28.000000000 +0000 @@ -127,7 +127,7 @@ oClearAllForwardings, oNoHostAuthenticationForLocalhost, oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, oAddressFamily, oGssAuthentication, oGssDelegateCreds, - oGssTrustDns, oGssKeyEx, + oGssTrustDns, oGssKeyEx, oGssClientIdentity, oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, oSendEnv, oControlPath, oControlMaster, oHashKnownHosts, oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand, @@ -168,11 +168,13 @@ { "gssapikeyexchange", oGssKeyEx }, { "gssapidelegatecredentials", oGssDelegateCreds }, { "gssapitrustdns", oGssTrustDns }, + { "gssapiclientidentity", oGssClientIdentity }, #else { "gssapiauthentication", oUnsupported }, { "gssapikeyexchange", oUnsupported }, { "gssapidelegatecredentials", oUnsupported }, { "gssapitrustdns", oUnsupported }, + { "gssapiclientidentity", oUnsupported }, #endif { "fallbacktorsh", oDeprecated }, { "usersh", oDeprecated }, @@ -471,6 +473,10 @@ intptr = &options->gss_trust_dns; goto parse_flag; + case oGssClientIdentity: + charptr = &options->gss_client_identity; + goto parse_string; + case oBatchMode: intptr = &options->batch_mode; goto parse_flag; @@ -1029,6 +1035,7 @@ options->gss_keyex = -1; options->gss_deleg_creds = -1; options->gss_trust_dns = -1; + options->gss_client_identity = NULL; options->password_authentication = -1; options->kbd_interactive_authentication = -1; options->kbd_interactive_devices = NULL; Index: openssh-5.3p1/readconf.h =================================================================== --- openssh-5.3p1.orig/readconf.h 2010-01-24 10:30:18.000000000 +0000 +++ openssh-5.3p1/readconf.h 2010-01-24 10:35:28.000000000 +0000 @@ -47,6 +47,7 @@ int gss_keyex; /* Try GSS key exchange */ int gss_deleg_creds; /* Delegate GSS credentials */ int gss_trust_dns; /* Trust DNS for GSS canonicalization */ + char *gss_client_identity; /* Principal to initiate GSSAPI with */ int password_authentication; /* Try password * authentication. */ int kbd_interactive_authentication; /* Try keyboard-interactive auth. */ Index: openssh-5.3p1/ssh-gss.h =================================================================== --- openssh-5.3p1.orig/ssh-gss.h 2010-01-24 10:30:18.000000000 +0000 +++ openssh-5.3p1/ssh-gss.h 2010-01-24 10:35:28.000000000 +0000 @@ -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 @@ -104,7 +104,7 @@ 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[]; @@ -128,14 +128,18 @@ 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 *); /* In the server */ -typedef int ssh_gssapi_check_fn(Gssctxt **, gss_OID, const char *); -char *ssh_gssapi_client_mechanisms(const char *host); -char *ssh_gssapi_kex_mechs(gss_OID_set, ssh_gssapi_check_fn *, const char *); +typedef int ssh_gssapi_check_fn(Gssctxt **, gss_OID, const char *, + const char *); +char *ssh_gssapi_client_mechanisms(const char *, const char *); +char *ssh_gssapi_kex_mechs(gss_OID_set, ssh_gssapi_check_fn *, const char *, + const char *); gss_OID ssh_gssapi_id_kex(Gssctxt *, char *, int); -int ssh_gssapi_server_check_mech(Gssctxt **,gss_OID, const char *); +int ssh_gssapi_server_check_mech(Gssctxt **,gss_OID, const char *, + const char *); OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID); int ssh_gssapi_userok(char *name); OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t); Index: openssh-5.3p1/sshconnect2.c =================================================================== --- openssh-5.3p1.orig/sshconnect2.c 2010-01-24 10:31:52.000000000 +0000 +++ openssh-5.3p1/sshconnect2.c 2010-01-24 10:35:28.000000000 +0000 @@ -124,7 +124,7 @@ else gss_host = host; - gss = ssh_gssapi_client_mechanisms(gss_host); + gss = ssh_gssapi_client_mechanisms(gss_host, options.gss_client_identity); if (gss) { debug("Offering GSSAPI proposal: %s", gss); xasprintf(&myproposal[PROPOSAL_KEX_ALGS], @@ -195,6 +195,7 @@ 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 @@ -620,7 +621,8 @@ /* My DER encoding requires length<128 */ if (gss_supported->elements[mech].length < 128 && ssh_gssapi_check_mechanism(&gssctxt, - &gss_supported->elements[mech], gss_host)) { + &gss_supported->elements[mech], gss_host, + options.gss_client_identity)) { ok = 1; /* Mechanism works */ } else { mech++; Index: openssh-5.3p1/ssh_config.5 =================================================================== --- openssh-5.3p1.orig/ssh_config.5 2010-01-24 10:30:18.000000000 +0000 +++ openssh-5.3p1/ssh_config.5 2010-01-24 10:35:28.000000000 +0000 @@ -484,6 +484,10 @@ 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 Index: openssh-5.3p1/ChangeLog.gssapi =================================================================== --- openssh-5.3p1.orig/ChangeLog.gssapi 2010-01-24 10:34:34.000000000 +0000 +++ openssh-5.3p1/ChangeLog.gssapi 2010-01-24 10:35:28.000000000 +0000 @@ -16,7 +16,13 @@ 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