From: basney Date: Mon, 31 Aug 2009 18:45:53 +0000 (+0000) Subject: merging OPENSSH_5_2P1_SIMON_20090726_HPN13V6 to trunk: X-Git-Tag: OPENSSH_5_2P1_GSSAPI_20090831~4 X-Git-Url: http://andersk.mit.edu/gitweb/gssapi-openssh.git/commitdiff_plain/c7931c9aedd8e12fdd0df715dcefce0e0c95be6a merging OPENSSH_5_2P1_SIMON_20090726_HPN13V6 to trunk: http://www.psc.edu/networking/projects/hpn-ssh/openssh-5.2p1-hpn13v6.diff.gz http://www.sxw.org.uk/computing/patches/openssh-5.2p1-gsskex-all-20090726.patch --- c7931c9aedd8e12fdd0df715dcefce0e0c95be6a diff --cc openssh/Makefile.in index d448c75,ac8d66d..3d10d92 --- a/openssh/Makefile.in +++ b/openssh/Makefile.in @@@ -86,9 -85,7 +86,8 @@@ SSHDOBJS=sshd.o auth-rhosts.o auth-pass auth2-none.o auth2-passwd.o auth2-pubkey.o auth2-jpake.o \ monitor_mm.o monitor.o monitor_wrap.o kexdhs.o kexgexs.o \ auth-krb5.o \ - auth2-gss.o gss-serv.o gss-serv-krb5.o \ - kexgsss.o \ + auth2-gss.o gss-serv.o gss-serv-krb5.o kexgsss.o\ + gss-serv-gsi.o \ loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \ audit.o audit-bsm.o platform.o sftp-server.o sftp-common.o diff --cc openssh/auth2-gss.c index 2cf6929,a192d28..1db62c4 --- a/openssh/auth2-gss.c +++ b/openssh/auth2-gss.c @@@ -53,20 -52,6 +53,20 @@@ static void input_gssapi_mic(int type, static void input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt); static void input_gssapi_errtok(int, u_int32_t, void *); +static int gssapi_with_mic = 1; /* flag to toggle "gssapi-with-mic" vs. + "gssapi" */ + +static int +userauth_external(Authctxt *authctxt) +{ + packet_check_eom(); + + if (authctxt->valid && authctxt->user && authctxt->user[0]) { - return(PRIVSEP(ssh_gssapi_userok(authctxt->user))); ++ return(PRIVSEP(ssh_gssapi_userok(authctxt->user, authctxt->pw))); + } + return 0; +} + /* * The 'gssapi_keyex' userauth mechanism. */ @@@ -89,25 -74,13 +89,26 @@@ userauth_gsskeyex(Authctxt *authctxt gssbuf.value = buffer_ptr(&b); gssbuf.length = buffer_len(&b); + /* client may have used empty username to determine target + name from GSSAPI context */ + ssh_gssapi_buildmic(&b2, "", authctxt->service, "gssapi-keyex"); + + gssbuf2.value = buffer_ptr(&b2); + gssbuf2.length = buffer_len(&b2); + /* 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)); + &gssbuf, &mic))) || + !GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gss_kex_context, + &gssbuf2, &mic)))) { + if (authctxt->valid && authctxt->user && authctxt->user[0]) { - authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user)); ++ authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user, ++ authctxt->pw)); + } + } buffer_free(&b); + buffer_free(&b2); xfree(mic.value); return (authenticated); @@@ -339,12 -278,8 +340,13 @@@ input_gssapi_exchange_complete(int type packet_check_eom(); - authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user, - authctxt->pw)); + /* user should be set if valid but we double-check here */ + if (authctxt->valid && authctxt->user && authctxt->user[0]) { - authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user)); ++ authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user, ++ authctxt->pw)); + } else { + authenticated = 0; + } authctxt->postponed = 0; dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); @@@ -393,14 -313,9 +395,15 @@@ input_gssapi_mic(int type, u_int32_t pl gssbuf.value = buffer_ptr(&b); gssbuf.length = buffer_len(&b); + gssapi_set_username(authctxt); + if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic)))) - authenticated = - PRIVSEP(ssh_gssapi_userok(authctxt->user, authctxt->pw)); + if (authctxt->valid && authctxt->user && authctxt->user[0]) { - authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user)); ++ authenticated = ++ PRIVSEP(ssh_gssapi_userok(authctxt->user, authctxt->pw)); + } else { - authenticated = 0; ++ authenticated = 0; + } else logit("GSSAPI MIC check failed"); diff --cc openssh/auth2.c index 2e46638,c6c983a..1cd3e10 --- a/openssh/auth2.c +++ b/openssh/auth2.c @@@ -408,10 -356,10 +408,10 @@@ userauth_finish(Authctxt *authctxt, in /* now we can break out */ authctxt->success = 1; } else { - + /* Dont count server configuration issues against the client */ /* Allow initial try of "none" auth without failure penalty */ if (!authctxt->server_caused_failure && - (authctxt->attempt > 1 || strcmp(method, "none") != 0)) + (authctxt->attempt > 1 || strcmp(method, "none") != 0)) authctxt->failures++; if (authctxt->failures >= options.max_authtries) { #ifdef SSH_AUDIT_EVENTS diff --cc openssh/gss-serv-gsi.c index e31d70c,0000000..e77db62 mode 100644,000000..100644 --- a/openssh/gss-serv-gsi.c +++ b/openssh/gss-serv-gsi.c @@@ -1,225 -1,0 +1,226 @@@ +/* + * Copyright (c) 2001-2003 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 +#ifdef GSI + +#include + +#include +#include + +#include "xmalloc.h" +#include "key.h" +#include "hostfile.h" +#include "auth.h" +#include "log.h" +#include "servconf.h" + +#include "buffer.h" +#include "ssh-gss.h" + +extern ServerOptions options; + +#include + +static int ssh_gssapi_gsi_userok(ssh_gssapi_client *client, char *name); +static int ssh_gssapi_gsi_localname(ssh_gssapi_client *client, char **user); +static void ssh_gssapi_gsi_storecreds(ssh_gssapi_client *client); + +ssh_gssapi_mech gssapi_gsi_mech = { + "dZuIebMjgUqaxvbF7hDbAw==", + "GSI", + {9, "\x2B\x06\x01\x04\x01\x9B\x50\x01\x01"}, + NULL, + &ssh_gssapi_gsi_userok, + &ssh_gssapi_gsi_localname, - &ssh_gssapi_gsi_storecreds ++ &ssh_gssapi_gsi_storecreds, ++ NULL +}; + +/* + * Check if this user is OK to login under GSI. User has been authenticated + * as identity in global 'client_name.value' and is trying to log in as passed + * username in 'name'. + * + * Returns non-zero if user is authorized, 0 otherwise. + */ +static int +ssh_gssapi_gsi_userok(ssh_gssapi_client *client, char *name) +{ + int authorized = 0; + globus_result_t res; +#ifdef HAVE_GLOBUS_GSS_ASSIST_MAP_AND_AUTHORIZE + char lname[256] = ""; +#endif + +#ifdef GLOBUS_GSI_GSS_ASSIST_MODULE + if (globus_module_activate(GLOBUS_GSI_GSS_ASSIST_MODULE) != 0) { + return 0; + } +#endif + +/* use new globus_gss_assist_map_and_authorize() interface if available */ +#ifdef HAVE_GLOBUS_GSS_ASSIST_MAP_AND_AUTHORIZE + debug("calling globus_gss_assist_map_and_authorize()"); + if (GLOBUS_SUCCESS != + (res = globus_gss_assist_map_and_authorize(client->context, "ssh", + name, lname, 256))) { + debug("%s", globus_error_print_chain(globus_error_get(res))); + } else if (lname && lname[0] && strcmp(name, lname) != 0) { + debug("GSI user maps to %s, not %s", lname, name); + } else { + authorized = 1; + } +#else + debug("calling globus_gss_assist_userok()"); + if (GLOBUS_SUCCESS != + (res = (globus_gss_assist_userok(client->displayname.value, + name)))) { + debug("%s", globus_error_print_chain(globus_error_get(res))); + } else { + authorized = 1; + } +#endif + + logit("GSI user %s is%s authorized as target user %s", + (char *) client->displayname.value, (authorized ? "" : " not"), name); + + return authorized; +} + +/* + * Return the local username associated with the GSI credentials. + */ +int +ssh_gssapi_gsi_localname(ssh_gssapi_client *client, char **user) +{ + globus_result_t res; +#ifdef HAVE_GLOBUS_GSS_ASSIST_MAP_AND_AUTHORIZE + char lname[256] = ""; +#endif + +#ifdef GLOBUS_GSI_GSS_ASSIST_MODULE + if (globus_module_activate(GLOBUS_GSI_GSS_ASSIST_MODULE) != 0) { + return 0; + } +#endif + +/* use new globus_gss_assist_map_and_authorize() interface if available */ +#ifdef HAVE_GLOBUS_GSS_ASSIST_MAP_AND_AUTHORIZE + debug("calling globus_gss_assist_map_and_authorize()"); + if (GLOBUS_SUCCESS != + (res = globus_gss_assist_map_and_authorize(client->context, "ssh", + NULL, lname, 256))) { + debug("%s", globus_error_print_chain(globus_error_get(res))); + logit("failed to map GSI user %s", (char *)client->displayname.value); + return 0; + } + *user = strdup(lname); +#else + debug("calling globus_gss_assist_gridmap()"); + if (GLOBUS_SUCCESS != + (res = globus_gss_assist_gridmap(client->displayname.value, user))) { + debug("%s", globus_error_print_chain(globus_error_get(res))); + logit("failed to map GSI user %s", (char *)client->displayname.value); + return 0; + } +#endif + + logit("GSI user %s mapped to target user %s", + (char *) client->displayname.value, *user); + + return 1; +} + +/* + * Export GSI credentials to disk. + */ +static void +ssh_gssapi_gsi_storecreds(ssh_gssapi_client *client) +{ + OM_uint32 major_status; + OM_uint32 minor_status; + gss_buffer_desc export_cred = GSS_C_EMPTY_BUFFER; + char * p; + + if (!client || !client->creds) { + return; + } + + major_status = gss_export_cred(&minor_status, + client->creds, + GSS_C_NO_OID, + 1, + &export_cred); + if (GSS_ERROR(major_status) && major_status != GSS_S_UNAVAILABLE) { + Gssctxt *ctx; + ssh_gssapi_build_ctx(&ctx); + ctx->major = major_status; + ctx->minor = minor_status; + ssh_gssapi_set_oid(ctx, &gssapi_gsi_mech.oid); + ssh_gssapi_error(ctx); + ssh_gssapi_delete_ctx(&ctx); + return; + } + + p = strchr((char *) export_cred.value, '='); + if (p == NULL) { + logit("Failed to parse exported credentials string '%.100s'", + (char *)export_cred.value); + gss_release_buffer(&minor_status, &export_cred); + return; + } + *p++ = '\0'; + if (strcmp((char *)export_cred.value,"X509_USER_DELEG_PROXY") == 0) { + client->store.envvar = strdup("X509_USER_PROXY"); + } else { + client->store.envvar = strdup((char *)export_cred.value); + } + if (access(p, R_OK) == 0) { + if (client->store.filename) { + if (rename(p, client->store.filename) < 0) { + logit("Failed to rename %s to %s: %s", p, + client->store.filename, strerror(errno)); + xfree(client->store.filename); + client->store.filename = strdup(p); + } else { + p = client->store.filename; + } + } else { + client->store.filename = strdup(p); + } + } + client->store.envval = strdup(p); +#ifdef USE_PAM + if (options.use_pam) + do_pam_putenv(client->store.envvar, client->store.envval); +#endif + gss_release_buffer(&minor_status, &export_cred); +} + +#endif /* GSI */ +#endif /* GSSAPI */ diff --cc openssh/gss-serv-krb5.c index bea0eae,e7170ee..a439393 --- a/openssh/gss-serv-krb5.c +++ b/openssh/gss-serv-krb5.c @@@ -57,20 -57,6 +57,21 @@@ extern ServerOptions options #endif static krb5_context krb_context = NULL; +static int ssh_gssapi_krb5_init(); +static int ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name); +static int ssh_gssapi_krb5_localname(ssh_gssapi_client *client, char **user); +static void ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client); + +ssh_gssapi_mech gssapi_kerberos_mech = { + "toWM5Slw5Ew8Mqkay+al2g==", + "Kerberos", + {9, "\x2A\x86\x48\x86\xF7\x12\x01\x02\x02"}, + NULL, + &ssh_gssapi_krb5_userok, + &ssh_gssapi_krb5_localname, - &ssh_gssapi_krb5_storecreds ++ &ssh_gssapi_krb5_storecreds, ++ &ssh_gssapi_krb5_updatecreds +}; /* Initialise the krb5 library, for the stuff that GSSAPI won't do */ @@@ -242,6 -190,82 +243,71 @@@ ssh_gssapi_krb5_storecreds(ssh_gssapi_c 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", - {9, "\x2A\x86\x48\x86\xF7\x12\x01\x02\x02"}, - NULL, - &ssh_gssapi_krb5_userok, - NULL, - &ssh_gssapi_krb5_storecreds, - &ssh_gssapi_krb5_updatecreds -}; - #endif /* KRB5 */ #endif /* GSSAPI */ diff --cc openssh/gss-serv.c index bf88d71,365e48d..e1b2b43 --- a/openssh/gss-serv.c +++ b/openssh/gss-serv.c @@@ -46,8 -46,8 +46,9 @@@ #include "session.h" #include "misc.h" #include "servconf.h" + #include "uidswap.h" +#include "xmalloc.h" #include "ssh-gss.h" #include "monitor_wrap.h" @@@ -78,32 -71,7 +79,10 @@@ ssh_gssapi_mech* supported_mechs[]= &gssapi_null_mech, }; +#ifdef GSS_C_GLOBUS_LIMITED_PROXY_FLAG +static int limited = 0; +#endif - /* Unprivileged */ - char * - ssh_gssapi_server_mechanisms() { - gss_OID_set supported; - - ssh_gssapi_supported_oids(&supported); - return (ssh_gssapi_kex_mechs(supported, &ssh_gssapi_server_check_mech, - NULL)); - } - - /* Unprivileged */ - int - ssh_gssapi_server_check_mech(Gssctxt **dum, gss_OID oid, const char *data) { - Gssctxt *ctx = NULL; - int res; - - res = !GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctx, oid))); - ssh_gssapi_delete_ctx(&ctx); - - return (res); - } - /* * Acquire credentials for a server running on the current host. * Requires that the context structure contains a valid OID @@@ -168,8 -158,9 +169,10 @@@ ssh_gssapi_supported_oids(gss_OID_set * gss_OID_set supported; gss_create_empty_oid_set(&min_status, oidset); - /* Ask priviledged process what mechanisms it supports. */ - PRIVSEP(gss_indicate_mechs(&min_status, &supported)); + - if (GSS_ERROR(gss_indicate_mechs(&min_status, &supported))) ++ /* Ask privileged process what mechanisms it supports. */ ++ if (GSS_ERROR(PRIVSEP(gss_indicate_mechs(&min_status, &supported)))) + return; while (supported_mechs[i]->name != NULL) { if (GSS_ERROR(gss_test_oid_set_member(&min_status, @@@ -308,8 -284,48 +311,51 @@@ OM_uint3 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, ++ /* Call gss_inquire_cred rather than gss_inquire_cred_by_mech ++ because GSI doesn't support the latter. -jbasney */ ++ ++ if ((ctx->major = gss_inquire_cred(&ctx->minor, ++ ctx->client_creds, &new_name, + NULL, NULL, NULL))) { + ssh_gssapi_error(ctx); + return (ctx->major); + } - gss_buffer_desc ename; + ctx->major = gss_compare_name(&ctx->minor, client->name, + new_name, &equal); + + if (GSS_ERROR(ctx->major)) { + ssh_gssapi_error(ctx); + return (ctx->major); + } + + if (!equal) { + debug("Rekeyed credentials have different name"); + return GSS_S_COMPLETE; + } + + debug("Marking rekeyed credentials for export"); + + gss_release_name(&ctx->minor, &client->name); + gss_release_cred(&ctx->minor, &client->creds); + client->name = new_name; + client->creds = ctx->client_creds; + ctx->client_creds = GSS_C_NO_CREDENTIAL; + client->updated = 1; + return GSS_S_COMPLETE; + } client->mech = NULL; @@@ -324,6 -340,13 +370,16 @@@ if (client->mech == NULL) return GSS_S_FAILURE; ++ /* Call gss_inquire_cred rather than gss_inquire_cred_by_mech ++ because GSI doesn't support the latter. -jbasney */ ++ + if (ctx->client_creds && - (ctx->major = gss_inquire_cred_by_mech(&ctx->minor, - ctx->client_creds, ctx->oid, &client->name, NULL, NULL, NULL))) { ++ (ctx->major = gss_inquire_cred(&ctx->minor, ++ ctx->client_creds, &client->name, NULL, NULL, NULL))) { + ssh_gssapi_error(ctx); + return (ctx->major); + } + if ((ctx->major = gss_display_name(&ctx->minor, ctx->client, &client->displayname, NULL))) { ssh_gssapi_error(ctx); @@@ -406,16 -422,12 +464,18 @@@ ssh_gssapi_userok(char *user, struct pa debug("No suitable client data"); return 0; } +#ifdef GSS_C_GLOBUS_LIMITED_PROXY_FLAG + if (limited && options.gsi_allow_limited_proxy != 1) { + debug("limited proxy not acceptable for remote login"); + return 0; + } +#endif if (gssapi_client.mech && gssapi_client.mech->userok) - if ((*gssapi_client.mech->userok)(&gssapi_client, user)) + if ((*gssapi_client.mech->userok)(&gssapi_client, user)) { + gssapi_client.used = 1; + gssapi_client.store.owner = pw; return 1; - else { + } else { /* Destroy delegated credentials if userok fails */ gss_release_buffer(&lmin, &gssapi_client.displayname); gss_release_buffer(&lmin, &gssapi_client.exportedname); @@@ -428,25 -440,90 +488,111 @@@ return (0); } +/* ssh_gssapi_checkmic() moved to gss-genr.c so it can be called by + kexgss_client(). */ + +/* Priviledged */ +int +ssh_gssapi_localname(char **user) +{ + *user = NULL; + if (gssapi_client.displayname.length==0 || + gssapi_client.displayname.value==NULL) { + debug("No suitable client data"); + return(0);; + } + if (gssapi_client.mech && gssapi_client.mech->localname) { + return((*gssapi_client.mech->localname)(&gssapi_client,user)); + } else { + debug("Unknown client authentication type"); + } + return(0); +} + + /* These bits are only used for rekeying. The unpriviledged child is running + * as the user, the monitor is root. + * + * In the child, we want to : + * *) Ask the monitor to store our credentials into the store we specify + * *) If it succeeds, maybe do a PAM update + */ + + /* Stuff for PAM */ + + #ifdef USE_PAM + static int ssh_gssapi_simple_conv(int n, const struct pam_message **msg, + struct pam_response **resp, void *data) + { + return (PAM_CONV_ERR); + } + #endif + + void + ssh_gssapi_rekey_creds() { + int ok; + int ret; + #ifdef USE_PAM + pam_handle_t *pamh = NULL; + struct pam_conv pamconv = {ssh_gssapi_simple_conv, NULL}; + char *envstr; + #endif + + if (gssapi_client.store.filename == NULL && + gssapi_client.store.envval == NULL && + gssapi_client.store.envvar == NULL) + return; + + ok = PRIVSEP(ssh_gssapi_update_creds(&gssapi_client.store)); + + if (!ok) + return; + + debug("Rekeyed credentials stored successfully"); + + /* Actually managing to play with the ssh pam stack from here will + * be next to impossible. In any case, we may want different options + * for rekeying. So, use our own :) + */ + #ifdef USE_PAM + if (!use_privsep) { + debug("Not even going to try and do PAM with privsep disabled"); + return; + } + + ret = pam_start("sshd-rekey", gssapi_client.store.owner->pw_name, + &pamconv, &pamh); + if (ret) + return; + + xasprintf(&envstr, "%s=%s", gssapi_client.store.envvar, + gssapi_client.store.envval); + + ret = pam_putenv(pamh, envstr); + if (!ret) + pam_setcred(pamh, PAM_REINITIALIZE_CRED); + pam_end(pamh, PAM_SUCCESS); + #endif + } + + int + ssh_gssapi_update_creds(ssh_gssapi_ccache *store) { + int ok = 0; + + /* Check we've got credentials to store */ + if (!gssapi_client.updated) + return 0; + + gssapi_client.updated = 0; + + temporarily_use_uid(gssapi_client.store.owner); + if (gssapi_client.mech && gssapi_client.mech->updatecreds) + ok = (*gssapi_client.mech->updatecreds)(store, &gssapi_client); + else + debug("No update function for this mechanism"); + + restore_uid(); + + return ok; + } + #endif diff --cc openssh/kexgsss.c index ae58cac,0c3eeaa..3e5205c --- a/openssh/kexgsss.c +++ b/openssh/kexgsss.c @@@ -42,8 -42,9 +42,10 @@@ #include "dh.h" #include "ssh-gss.h" #include "monitor_wrap.h" + #include "servconf.h" +static void kex_gss_send_error(Gssctxt *ctxt); + extern ServerOptions options; void kexgss_server(Kex *kex) @@@ -168,20 -169,19 +172,20 @@@ if (maj_status & GSS_S_CONTINUE_NEEDED) { debug("Sending GSSAPI_CONTINUE"); packet_start(SSH2_MSG_KEXGSS_CONTINUE); -- packet_put_string(send_tok.value, send_tok.length); ++ packet_put_string((char *)send_tok.value, send_tok.length); packet_send(); gss_release_buffer(&min_status, &send_tok); } } while (maj_status & GSS_S_CONTINUE_NEEDED); if (GSS_ERROR(maj_status)) { + kex_gss_send_error(ctxt); if (send_tok.length > 0) { packet_start(SSH2_MSG_KEXGSS_CONTINUE); -- packet_put_string(send_tok.value, send_tok.length); ++ packet_put_string((char *)send_tok.value, send_tok.length); packet_send(); } - fatal("accept_ctx died"); + packet_disconnect("GSSAPI Key Exchange handshake failed"); } if (!(ret_flags & GSS_C_MUTUAL_FLAG)) @@@ -272,24 -279,10 +283,29 @@@ kex_derive_keys(kex, hash, hashlen, shared_secret); BN_clear_free(shared_secret); kex_finish(kex); + + /* If this was a rekey, then save out any delegated credentials we + * just exchanged. */ + if (options.gss_store_rekey) + ssh_gssapi_rekey_creds(); } + +static void +kex_gss_send_error(Gssctxt *ctxt) { + char *errstr; + OM_uint32 maj,min; + + errstr=PRIVSEP(ssh_gssapi_last_error(ctxt,&maj,&min)); + if (errstr) { + packet_start(SSH2_MSG_KEXGSS_ERROR); + packet_put_int(maj); + packet_put_int(min); + packet_put_cstring(errstr); + packet_put_cstring(""); + packet_send(); + packet_write_wait(); + /* XXX - We should probably log the error locally here */ + xfree(errstr); + } +} #endif /* GSSAPI */ diff --cc openssh/monitor.c index bc018a4,6a82936..e0434d5 --- a/openssh/monitor.c +++ b/openssh/monitor.c @@@ -171,9 -171,7 +171,10 @@@ int mm_answer_gss_accept_ctx(int, Buffe 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_error(int, Buffer *); +int mm_answer_gss_indicate_mechs(int, Buffer *); +int mm_answer_gss_localname(int, Buffer *); + int mm_answer_gss_updatecreds(int, Buffer *); #endif #ifdef SSH_AUDIT_EVENTS @@@ -263,8 -258,7 +264,9 @@@ struct mon_table mon_dispatch_postauth2 {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_GSSERR, 0, mm_answer_gss_error}, + {MONITOR_REQ_GSSMECHS, 0, mm_answer_gss_indicate_mechs}, + {MONITOR_REQ_GSSUPCREDS, 0, mm_answer_gss_updatecreds}, #endif {MONITOR_REQ_MODULI, 0, mm_answer_moduli}, {MONITOR_REQ_SIGN, 0, mm_answer_sign}, @@@ -2037,106 -2031,73 +2054,137 @@@ mm_answer_gss_userok(int sock, Buffer * return (authenticated); } - int - mm_answer_gss_sign(int socket, Buffer *m) - { - gss_buffer_desc data; - gss_buffer_desc hash = GSS_C_EMPTY_BUFFER; - OM_uint32 major, minor; - u_int len; - - data.value = buffer_get_string(m, &len); - data.length = len; - if (data.length != 20) - fatal("%s: data length incorrect: %d", __func__, (int)data.length); - - /* Save the session ID on the first time around */ - if (session_id2_len == 0) { - session_id2_len = data.length; - session_id2 = xmalloc(session_id2_len); - memcpy(session_id2, data.value, session_id2_len); - } - major = ssh_gssapi_sign(gsscontext, &data, &hash); - - xfree(data.value); - - buffer_clear(m); - buffer_put_int(m, major); - buffer_put_string(m, hash.value, hash.length); - - mm_request_send(socket, MONITOR_ANS_GSSSIGN, m); - - gss_release_buffer(&minor, &hash); - - /* Turn on getpwnam permissions */ - monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1); - - return (0); - } - +int +mm_answer_gss_error(int socket, Buffer *m) { + OM_uint32 major,minor; + char *msg; + + msg=ssh_gssapi_last_error(gsscontext,&major,&minor); + buffer_clear(m); + buffer_put_int(m,major); + buffer_put_int(m,minor); + buffer_put_cstring(m,msg); + + mm_request_send(socket,MONITOR_ANS_GSSERR,m); + + xfree(msg); + + return(0); +} + +int +mm_answer_gss_indicate_mechs(int socket, Buffer *m) { + OM_uint32 major,minor; + gss_OID_set mech_set; + size_t i; + + major=gss_indicate_mechs(&minor, &mech_set); + + buffer_clear(m); + buffer_put_int(m, major); + buffer_put_int(m, mech_set->count); + for (i=0; i < mech_set->count; i++) { + buffer_put_string(m, mech_set->elements[i].elements, + mech_set->elements[i].length); + } + +#if !defined(MECHGLUE) /* mechglue memory management bug ??? */ + gss_release_oid_set(&minor,&mech_set); +#endif + + mm_request_send(socket,MONITOR_ANS_GSSMECHS,m); + + return(0); +} + +int +mm_answer_gss_localname(int socket, Buffer *m) { + char *name; + + ssh_gssapi_localname(&name); + + buffer_clear(m); + if (name) { + buffer_put_cstring(m, name); + debug3("%s: sending result %s", __func__, name); + xfree(name); + } else { + buffer_put_cstring(m, ""); + debug3("%s: sending result \"\"", __func__); + } + + mm_request_send(socket, MONITOR_ANS_GSSLOCALNAME, m); + + return(0); +} ++ + int + mm_answer_gss_sign(int socket, Buffer *m) + { + gss_buffer_desc data; + gss_buffer_desc hash = GSS_C_EMPTY_BUFFER; + OM_uint32 major, minor; + u_int len; + + if (!options.gss_authentication && !options.gss_keyex) + fatal("In GSSAPI monitor when GSSAPI is disabled"); + + data.value = buffer_get_string(m, &len); + data.length = len; + if (data.length != 20) + fatal("%s: data length incorrect: %d", __func__, + (int) data.length); + + /* Save the session ID on the first time around */ + if (session_id2_len == 0) { + session_id2_len = data.length; + session_id2 = xmalloc(session_id2_len); + memcpy(session_id2, data.value, session_id2_len); + } + major = ssh_gssapi_sign(gsscontext, &data, &hash); + + xfree(data.value); + + buffer_clear(m); + buffer_put_int(m, major); + buffer_put_string(m, hash.value, hash.length); + + mm_request_send(socket, MONITOR_ANS_GSSSIGN, m); + + gss_release_buffer(&minor, &hash); + + /* Turn on getpwnam permissions */ + monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1); + + /* And credential updating, for when rekeying */ + monitor_permit(mon_dispatch, MONITOR_REQ_GSSUPCREDS, 1); + + return (0); + } + + int + mm_answer_gss_updatecreds(int socket, Buffer *m) { + ssh_gssapi_ccache store; + int ok; + + store.filename = buffer_get_string(m, NULL); + store.envvar = buffer_get_string(m, NULL); + store.envval = buffer_get_string(m, NULL); + + ok = ssh_gssapi_update_creds(&store); + + xfree(store.filename); + xfree(store.envvar); + xfree(store.envval); + + buffer_clear(m); + buffer_put_int(m, ok); + + mm_request_send(socket, MONITOR_ANS_GSSUPCREDS, m); + + return(0); + } + #endif /* GSSAPI */ #ifdef JPAKE diff --cc openssh/monitor.h index 3b40f13,aa38b16..9219f4a --- a/openssh/monitor.h +++ b/openssh/monitor.h @@@ -52,11 -52,9 +52,12 @@@ enum monitor_reqtype MONITOR_REQ_GSSSETUP, MONITOR_ANS_GSSSETUP, MONITOR_REQ_GSSSTEP, MONITOR_ANS_GSSSTEP, MONITOR_REQ_GSSUSEROK, MONITOR_ANS_GSSUSEROK, + MONITOR_REQ_GSSMECHS, MONITOR_ANS_GSSMECHS, + MONITOR_REQ_GSSLOCALNAME, MONITOR_ANS_GSSLOCALNAME, + MONITOR_REQ_GSSERR, MONITOR_ANS_GSSERR, MONITOR_REQ_GSSCHECKMIC, MONITOR_ANS_GSSCHECKMIC, MONITOR_REQ_GSSSIGN, MONITOR_ANS_GSSSIGN, + MONITOR_REQ_GSSUPCREDS, MONITOR_ANS_GSSUPCREDS, MONITOR_REQ_PAM_START, MONITOR_REQ_PAM_ACCOUNT, MONITOR_ANS_PAM_ACCOUNT, MONITOR_REQ_PAM_INIT_CTX, MONITOR_ANS_PAM_INIT_CTX, diff --cc openssh/monitor_wrap.c index 368738f,5f608b3..a2bc3a6 --- a/openssh/monitor_wrap.c +++ b/openssh/monitor_wrap.c @@@ -1257,105 -1257,50 +1257,127 @@@ mm_ssh_gssapi_userok(char *user, struc return (authenticated); } - OM_uint32 - mm_ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_desc *data, gss_buffer_desc *hash) - { - Buffer m; - OM_uint32 major; - u_int len; - - buffer_init(&m); - buffer_put_string(&m, data->value, data->length); - - mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSIGN, &m); - mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSIGN, &m); - - major = buffer_get_int(&m); - hash->value = buffer_get_string(&m, &len); - hash->length = len; - - buffer_free(&m); - - return(major); - } - +char * +mm_ssh_gssapi_last_error(Gssctxt *ctx, OM_uint32 *major, OM_uint32 *minor) { + Buffer m; + OM_uint32 maj,min; + char *errstr; + + buffer_init(&m); + + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSERR, &m); + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSERR, &m); + + maj = buffer_get_int(&m); + min = buffer_get_int(&m); + + if (major) *major=maj; + if (minor) *minor=min; + + errstr=buffer_get_string(&m,NULL); + + buffer_free(&m); + + return(errstr); +} + +OM_uint32 +mm_gss_indicate_mechs(OM_uint32 *minor_status, gss_OID_set *mech_set) +{ + Buffer m; + OM_uint32 major,minor; + int count; + gss_OID_desc oid; + u_int length; + + buffer_init(&m); + + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSMECHS, &m); + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSMECHS, + &m); + major=buffer_get_int(&m); + count=buffer_get_int(&m); + + gss_create_empty_oid_set(&minor,mech_set); + while(count-->0) { + oid.elements=buffer_get_string(&m,&length); + oid.length=length; + gss_add_oid_set_member(&minor,&oid,mech_set); + } + + buffer_free(&m); + + return(major); +} + +int +mm_ssh_gssapi_localname(char **lname) +{ + Buffer m; + + buffer_init(&m); + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSLOCALNAME, &m); + + debug3("%s: waiting for MONITOR_ANS_GSSLOCALNAME", __func__); + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSLOCALNAME, + &m); + + *lname = buffer_get_string(&m, NULL); + + buffer_free(&m); + if (lname[0] == '\0') { + debug3("%s: gssapi identity mapping failed", __func__); + } else { + debug3("%s: gssapi identity mapped to %s", __func__, *lname); + } + + return(0); +} + + OM_uint32 + mm_ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_desc *data, gss_buffer_desc *hash) + { + Buffer m; + OM_uint32 major; + u_int len; + + buffer_init(&m); + buffer_put_string(&m, data->value, data->length); + + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSIGN, &m); + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSIGN, &m); + + major = buffer_get_int(&m); + hash->value = buffer_get_string(&m, &len); + hash->length = len; + + buffer_free(&m); + + return(major); + } + + int + mm_ssh_gssapi_update_creds(ssh_gssapi_ccache *store) + { + Buffer m; + int ok; + + buffer_init(&m); + + buffer_put_cstring(&m, store->filename ? store->filename : ""); + buffer_put_cstring(&m, store->envvar ? store->envvar : ""); + buffer_put_cstring(&m, store->envval ? store->envval : ""); + + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUPCREDS, &m); + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSUPCREDS, &m); + + ok = buffer_get_int(&m); + + buffer_free(&m); + + return (ok); + } + #endif /* GSSAPI */ #ifdef JPAKE diff --cc openssh/monitor_wrap.h index a190a26,1e6f8b3..e4a3d48 --- a/openssh/monitor_wrap.h +++ b/openssh/monitor_wrap.h @@@ -57,13 -57,10 +57,14 @@@ BIGNUM *mm_auth_rsa_generate_challenge( OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **, gss_OID); OM_uint32 mm_ssh_gssapi_accept_ctx(Gssctxt *, gss_buffer_desc *, gss_buffer_desc *, OM_uint32 *); - int mm_ssh_gssapi_userok(char *user); + int mm_ssh_gssapi_userok(char *user, struct passwd *); OM_uint32 mm_ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t); OM_uint32 mm_ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t); +int mm_ssh_gssapi_localname(char **user); +OM_uint32 mm_gss_indicate_mechs(OM_uint32 *minor_status, + gss_OID_set *mech_set); +char *mm_ssh_gssapi_last_error(Gssctxt *ctxt, OM_uint32 *maj, OM_uint32 *min); + int mm_ssh_gssapi_update_creds(ssh_gssapi_ccache *); #endif #ifdef USE_PAM diff --cc openssh/readconf.c index 6d05b4e,dc78c6f..0f29417 --- a/openssh/readconf.c +++ b/openssh/readconf.c @@@ -254,6 -245,13 +245,12 @@@ static struct #else { "zeroknowledgepasswordauthentication", oUnsupported }, #endif + { "noneenabled", oNoneEnabled }, + { "tcprcvbufpoll", oTcpRcvBufPoll }, + { "tcprcvbuf", oTcpRcvBuf }, + { "noneswitch", oNoneSwitch }, + { "hpndisabled", oHPNDisabled }, + { "hpnbuffersize", oHPNBufferSize }, - { NULL, oBadOption } }; @@@ -1127,20 -1135,14 +1134,26 @@@ initialize_options(Options * options options->tun_remote = -1; options->local_command = NULL; options->permit_local_command = -1; + options->none_switch = -1; + options->none_enabled = -1; + options->hpn_disabled = -1; + options->hpn_buffer_size = -1; + options->tcp_rcv_buf_poll = -1; + options->tcp_rcv_buf = -1; options->visual_host_key = -1; + options->none_switch = -1; + options->none_enabled = -1; + options->hpn_disabled = -1; + options->hpn_buffer_size = -1; + options->tcp_rcv_buf_poll = -1; + options->tcp_rcv_buf = -1; options->zero_knowledge_password_authentication = -1; + options->none_switch = -1; + options->none_enabled = -1; + options->hpn_disabled = -1; + options->hpn_buffer_size = -1; + options->tcp_rcv_buf_poll = -1; + options->tcp_rcv_buf = -1; } /* @@@ -1174,13 -1176,15 +1187,15 @@@ fill_default_options(Options * options if (options->challenge_response_authentication == -1) options->challenge_response_authentication = 1; if (options->gss_authentication == -1) - options->gss_authentication = 0; + options->gss_authentication = 1; if (options->gss_keyex == -1) - options->gss_keyex = 0; + options->gss_keyex = 1; if (options->gss_deleg_creds == -1) - options->gss_deleg_creds = 0; + options->gss_deleg_creds = 1; if (options->gss_trust_dns == -1) - options->gss_trust_dns = 0; + options->gss_trust_dns = 1; + if (options->gss_renewal_rekey == -1) + options->gss_renewal_rekey = 0; if (options->password_authentication == -1) options->password_authentication = 1; if (options->kbd_interactive_authentication == -1) diff --cc openssh/servconf.c index 90c0eb7,95fe3b6..96a27f3 --- a/openssh/servconf.c +++ b/openssh/servconf.c @@@ -102,7 -95,7 +102,8 @@@ initialize_server_options(ServerOption options->gss_keyex = -1; options->gss_cleanup_creds = -1; options->gss_strict_acceptor = -1; + options->gsi_allow_limited_proxy = -1; + options->gss_store_rekey = -1; options->password_authentication = -1; options->kbd_interactive_authentication = -1; options->challenge_response_authentication = -1; @@@ -239,8 -228,8 +240,10 @@@ fill_default_server_options(ServerOptio options->gss_cleanup_creds = 1; if (options->gss_strict_acceptor == -1) options->gss_strict_acceptor = 1; + if (options->gsi_allow_limited_proxy == -1) + options->gsi_allow_limited_proxy = 0; + if (options->gss_store_rekey == -1) + options->gss_store_rekey = 0; if (options->password_authentication == -1) options->password_authentication = 1; if (options->kbd_interactive_authentication == -1) @@@ -370,17 -356,13 +373,16 @@@ typedef enum sBanner, sUseDNS, sHostbasedAuthentication, sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2, - sGssAuthentication, sGssCleanupCreds, + sGssDelegateCreds, - sGssStrictAcceptor, - sGssKeyEx, + sGssCredsPath, + sGsiAllowLimitedProxy, - sAcceptEnv, sPermitTunnel, + sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor, + sGssKeyEx, sGssStoreRekey, + sAcceptEnv, sPermitTunnel, sMatch, sPermitOpen, sForceCommand, sChrootDirectory, sUsePrivilegeSeparation, sAllowAgentForwarding, - sNoneEnabled, sTcpRcvBufPoll, sHPNDisabled, sHPNBufferSize, sZeroKnowledgePasswordAuthentication, + sNoneEnabled, sTcpRcvBufPoll, sHPNDisabled, sHPNBufferSize, sDeprecated, sUnsupported } ServerOpCodes; @@@ -440,30 -420,17 +442,32 @@@ static struct { "afstokenpassing", sUnsupported, SSHCFG_GLOBAL }, #ifdef GSSAPI { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL }, + { "gssapidelegatecredentials", sGssDelegateCreds, SSHCFG_ALL }, { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL }, - { "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL }, + { "gssapicredentialspath", sGssCredsPath, SSHCFG_GLOBAL }, - { "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL }, +#ifdef GSI + { "gsiallowlimitedproxy", sGsiAllowLimitedProxy, SSHCFG_GLOBAL }, +#endif + { "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL }, + { "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL }, + { "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL }, #else { "gssapiauthentication", sUnsupported, SSHCFG_ALL }, + { "gssapidelegatecredentials", sUnsupported, SSHCFG_ALL }, { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL }, - { "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL }, + { "gssapicredentialspath", sUnsupported, SSHCFG_GLOBAL }, - { "gssapikeyexchange", sUnsupported, SSHCFG_GLOBAL }, +#ifdef GSI + { "gsiallowlimitedproxy", sUnsupported, SSHCFG_GLOBAL }, +#endif + { "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL }, + { "gssapikeyexchange", sUnsupported, SSHCFG_GLOBAL }, + { "gssapistorecredentialsonrekey", sUnsupported, SSHCFG_GLOBAL }, #endif +#ifdef SESSION_HOOKS + { "allowsessionhooks", sAllowSessionHooks, SSHCFG_GLOBAL }, + { "sessionhookstartupcmd", sSessionHookStartupCmd, SSHCFG_GLOBAL }, + { "sessionhookshutdowncmd", sSessionHookShutdownCmd, SSHCFG_GLOBAL }, +#endif { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL }, { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, { "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, @@@ -1024,35 -983,14 +1028,41 @@@ process_server_config_line(ServerOption intptr = &options->gss_cleanup_creds; goto parse_flag; ++ case sGssCredsPath: ++ charptr = &options->gss_creds_path; ++ goto parse_filename; ++ case sGssStrictAcceptor: intptr = &options->gss_strict_acceptor; goto parse_flag; - case sGssCredsPath: - charptr = &options->gss_creds_path; - goto parse_filename; + case sGssStoreRekey: + intptr = &options->gss_store_rekey; + goto parse_flag; ++#ifdef GSI + case sGsiAllowLimitedProxy: + intptr = &options->gsi_allow_limited_proxy; + goto parse_flag; ++#endif + +#ifdef SESSION_HOOKS + case sAllowSessionHooks: + intptr = &options->session_hooks_allow; + goto parse_flag; + case sSessionHookStartupCmd: + case sSessionHookShutdownCmd: + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: empty session hook command", + filename, linenum); + if (opcode==sSessionHookStartupCmd) + options->session_hooks_startup_cmd = strdup(arg); + else + options->session_hooks_shutdown_cmd = strdup(arg); + break; +#endif + case sPasswordAuthentication: intptr = &options->password_authentication; goto parse_flag; diff --cc openssh/servconf.h index fd8b909,1dcd25c..2c9f00e --- a/openssh/servconf.h +++ b/openssh/servconf.h @@@ -88,20 -88,13 +88,21 @@@ typedef struct * /etc/passwd */ int kerberos_ticket_cleanup; /* If true, destroy ticket * file on logout. */ +#ifdef SESSION_HOOKS + int session_hooks_allow; /* If true, permit user hooks */ + char* session_hooks_startup_cmd; /* cmd to be executed before */ + char* session_hooks_shutdown_cmd; /* cmd to be executed after */ +#endif int kerberos_get_afs_token; /* If true, try to get AFS token if * authenticated with Kerberos. */ ++ int gsi_allow_limited_proxy; /* If true, accept limited proxies */ int gss_authentication; /* If true, permit GSSAPI authentication */ + int gss_deleg_creds; /* If true, store delegated GSSAPI credentials*/ - int gss_keyex; /* If true, permit GSSAPI key exchange */ + int gss_keyex; /* If true, permit GSSAPI key exchange */ int gss_cleanup_creds; /* If true, destroy cred cache on logout */ - int gss_strict_acceptor; /* If true, restrict the GSSAPI acceptor name */ + char* gss_creds_path; /* If true, destroy cred cache on logout */ - int gsi_allow_limited_proxy; /* If true, accept limited proxies */ + int gss_strict_acceptor; /* If true, restrict the GSSAPI acceptor name */ + int gss_store_rekey; int password_authentication; /* If true, permit password * authentication. */ int kbd_interactive_authentication; /* If true, permit */ diff --cc openssh/ssh-gss.h index 794e670,31d5a08..dcb9bca --- a/openssh/ssh-gss.h +++ b/openssh/ssh-gss.h @@@ -84,9 -83,11 +85,12 @@@ typedef struct gss_buffer_desc displayname; gss_buffer_desc exportedname; gss_cred_id_t creds; + gss_name_t name; struct ssh_gssapi_mech_struct *mech; ssh_gssapi_ccache store; + gss_ctx_id_t context; + int used; + int updated; } ssh_gssapi_client; typedef struct ssh_gssapi_mech_struct { @@@ -104,10 -106,10 +109,10 @@@ typedef struct OM_uint32 minor; /* both */ gss_ctx_id_t context; /* both */ gss_name_t name; /* both */ - gss_OID oid; /* client */ + gss_OID oid; /* both */ gss_cred_id_t creds; /* server */ gss_name_t client; /* server */ - gss_cred_id_t client_creds; /* server */ + gss_cred_id_t client_creds; /* both */ } Gssctxt; extern ssh_gssapi_mech *supported_mechs[]; @@@ -131,32 -133,30 +136,39 @@@ void ssh_gssapi_build_ctx(Gssctxt **) void ssh_gssapi_delete_ctx(Gssctxt **); OM_uint32 ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t); void ssh_gssapi_buildmic(Buffer *, const char *, const char *, const char *); - int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *); + int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *, const char *); + OM_uint32 ssh_gssapi_client_identity(Gssctxt *, const char *); + int ssh_gssapi_credentials_updated(Gssctxt *); +int ssh_gssapi_localname(char **name); + /* In the server */ - typedef int ssh_gssapi_check_fn(Gssctxt **, gss_OID, const char *); - char *ssh_gssapi_client_mechanisms(const char *host); - char *ssh_gssapi_kex_mechs(gss_OID_set, ssh_gssapi_check_fn *, const char *); + typedef int ssh_gssapi_check_fn(Gssctxt **, gss_OID, const char *, + const char *); + char *ssh_gssapi_client_mechanisms(const char *, const char *); + char *ssh_gssapi_kex_mechs(gss_OID_set, ssh_gssapi_check_fn *, const char *, + const char *); gss_OID ssh_gssapi_id_kex(Gssctxt *, char *, int); - int ssh_gssapi_server_check_mech(Gssctxt **,gss_OID, const char *); + int ssh_gssapi_server_check_mech(Gssctxt **,gss_OID, const char *, + const char *); OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID); - int ssh_gssapi_userok(char *name); + int ssh_gssapi_userok(char *name, struct passwd *); OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t); void ssh_gssapi_do_child(char ***, u_int *); void ssh_gssapi_cleanup_creds(void); void ssh_gssapi_storecreds(void); - char * ssh_gssapi_server_mechanisms(void); - int ssh_gssapi_oid_table_ok(); +#ifdef MECHGLUE +gss_cred_id_t __gss_get_mechanism_cred + (gss_cred_id_t, /* union_cred */ + gss_OID /* mech_type */ + ); +#endif + + char *ssh_gssapi_server_mechanisms(void); + int ssh_gssapi_oid_table_ok(); + + int ssh_gssapi_update_creds(ssh_gssapi_ccache *store); #endif /* GSSAPI */ #endif /* _SSH_GSS_H */ diff --cc openssh/ssh_config.5 index 073d038,024491b..a72a35b --- a/openssh/ssh_config.5 +++ b/openssh/ssh_config.5 @@@ -488,23 -482,33 +488,33 @@@ Note that this option applies to protoc 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 . +.Dq yes . Note that this option applies to protocol version 2 only. + .It Cm GSSAPIClientIdentity + If set, specifies the GSSAPI client identity that ssh should use when + connecting to the server. The default is unset, which means that the default + identity will be used. .It Cm GSSAPIDelegateCredentials Forward (delegate) credentials to the server. The default is -.Dq no . +.Dq yes . - Note that this option applies to protocol version 2 only. + Note that this option applies to protocol version 2 connections using GSSAPI. + .It Cm GSSAPIRenewalForcesRekey + If set to + .Dq yes + then renewal of the client's GSSAPI credentials will force the rekeying of the + ssh connection. With a compatible server, this can delegate the renewed + credentials to a session on the server. + The default is -.Dq no . ++.Dq yes . .It Cm GSSAPITrustDns Set to - .Dq yes - to indicate that the DNS is trusted to securely canonicalize + .Dq yes to indicate that the DNS is trusted to securely canonicalize the name of the host being connected to. If - .Dq no , - the hostname entered on the + .Dq no, the hostname entered on the command line will be passed untouched to the GSSAPI library. The default is -.Dq no . +.Dq yes . This option only applies to protocol version 2 connections using GSSAPI. .It Cm HashKnownHosts Indicates that diff --cc openssh/sshconnect2.c index 4696f34,1ff0ff5..c7aadb4 --- a/openssh/sshconnect2.c +++ b/openssh/sshconnect2.c @@@ -78,17 -78,13 +78,23 @@@ extern char *client_version_string; extern char *server_version_string; extern Options options; + extern Kex *xxx_kex; + + /* tty_flag is set in ssh.c. use this in ssh_userauth2 */ + /* if it is set then prevent the switch to the null cipher */ + + extern int tty_flag; +/* tty_flag is set in ssh.c. use this in ssh_userauth2 */ +/* if it is set then prevent the switch to the null cipher */ + +extern int tty_flag; + +/* tty_flag is set in ssh.c. use this in ssh_userauth2 */ +/* if it is set then prevent the switch to the null cipher */ + +extern int tty_flag; + /* * SSH2 key exchange */ @@@ -871,48 -857,6 +887,48 @@@ input_gssapi_error(int type, u_int32_t xfree(lang); } +#ifdef GSI +extern +const gss_OID_desc * const gss_mech_globus_gssapi_openssl; +#define is_gsi_oid(oid) \ + (oid->length == gss_mech_globus_gssapi_openssl->length && \ + (memcmp(oid->elements, gss_mech_globus_gssapi_openssl->elements, \ + oid->length) == 0)) +#endif + +int +userauth_external(Authctxt *authctxt) +{ - static int attempt = 0; ++ static int attempt = 0; + - if (attempt++ >= 1) - return 0; ++ if (attempt++ >= 1) ++ return 0; + + /* The client MUST NOT try this method if initial key exchange + was not performed using a GSSAPI-based key exchange + method. */ + if (gss_kex_context == NULL) { + debug2("gsskex not performed, skipping external-keyx"); + return 0; + } + - debug2("userauth_external"); - packet_start(SSH2_MSG_USERAUTH_REQUEST); ++ debug2("userauth_external"); ++ packet_start(SSH2_MSG_USERAUTH_REQUEST); +#ifdef GSI - if (options.implicit && is_gsi_oid(gss_kex_context->oid)) { - packet_put_cstring(""); ++ if (options.implicit && is_gsi_oid(gss_kex_context->oid)) { ++ packet_put_cstring(""); + } else { +#endif - packet_put_cstring(authctxt->server_user); ++ packet_put_cstring(authctxt->server_user); +#ifdef GSI + } +#endif - packet_put_cstring(authctxt->service); - packet_put_cstring(authctxt->method->name); - packet_send(); - packet_write_wait(); - return 1; ++ packet_put_cstring(authctxt->service); ++ packet_put_cstring(authctxt->method->name); ++ packet_send(); ++ packet_write_wait(); ++ return 1; +} int userauth_gsskeyex(Authctxt *authctxt) { @@@ -930,16 -874,8 +946,16 @@@ return (0); } - ssh_gssapi_buildmic(&b, authctxt->server_user, authctxt->service, - "gssapi-keyex"); +#ifdef GSI - if (options.implicit && is_gsi_oid(gss_kex_context->oid)) { - ssh_gssapi_buildmic(&b, "", authctxt->service, "gssapi-keyex"); ++ if (options.implicit && is_gsi_oid(gss_kex_context->oid)) { ++ ssh_gssapi_buildmic(&b, "", authctxt->service, "gssapi-keyex"); + } else { +#endif - ssh_gssapi_buildmic(&b, authctxt->server_user, authctxt->service, - "gssapi-keyex"); ++ ssh_gssapi_buildmic(&b, authctxt->server_user, authctxt->service, ++ "gssapi-keyex"); +#ifdef GSI + } +#endif gssbuf.value = buffer_ptr(&b); gssbuf.length = buffer_len(&b); @@@ -950,15 -886,7 +966,15 @@@ } packet_start(SSH2_MSG_USERAUTH_REQUEST); +#ifdef GSI - if (options.implicit && is_gsi_oid(gss_kex_context->oid)) { - packet_put_cstring(""); ++ if (options.implicit && is_gsi_oid(gss_kex_context->oid)) { ++ packet_put_cstring(""); + } else { +#endif packet_put_cstring(authctxt->server_user); +#ifdef GSI + } +#endif packet_put_cstring(authctxt->service); packet_put_cstring(authctxt->method->name); packet_put_string(mic.value, mic.length); diff --cc openssh/sshd_config.5 index 414be24,a3357d4..0602495 --- a/openssh/sshd_config.5 +++ b/openssh/sshd_config.5 @@@ -390,6 -386,6 +390,22 @@@ on logout The default is .Dq yes . Note that this option applies to protocol version 2 only. ++.It Cm GSSAPICredentialsPath ++If specified, the delegated GSSAPI credential is stored in the ++given path, overwriting any existing credentials. ++Paths can be specified with syntax similar to the AuthorizedKeysFile ++option (i.e., accepting %h and %u tokens). ++When using this option, ++setting 'GssapiCleanupCredentials no' is recommended, ++so logging out of one session ++doesn't remove the credentials in use by another session of ++the same user. ++Currently only implemented for the GSI mechanism. ++.It Cm GSIAllowLimitedProxy ++Specifies whether to accept limited proxy credentials for ++authentication. ++The default is ++.Dq no . .It Cm GSSAPIStrictAcceptorCheck Determines whether to be strict about the identity of the GSSAPI acceptor a client authenticates against. If diff --cc openssh/version.h index bf3a368,d57d174..1c416ad --- a/openssh/version.h +++ b/openssh/version.h @@@ -23,6 -3,5 +23,6 @@@ #define SSH_VERSION "OpenSSH_5.2" #define SSH_PORTABLE "p1" - #define SSH_HPN "-hpn13v5" + #define SSH_HPN "-hpn13v6" -#define SSH_RELEASE SSH_VERSION SSH_PORTABLE SSH_HPN +#define SSH_RELEASE SSH_VERSION SSH_PORTABLE SSH_HPN \ + NCSA_VERSION GSI_VERSION KRB5_VERSION MGLUE_VERSION