From: Luke Howard Date: Mon, 21 Mar 2011 08:18:52 +0000 (+1100) Subject: initial port of GSS generic fixes X-Git-Url: http://www.project-moonshot.org/gitweb/?p=openssh.git;a=commitdiff_plain;h=556d8b0fedd26a7a817d6702ca167c16853390db initial port of GSS generic fixes --- diff --git a/Makefile.in b/Makefile.in index c18ba70..b6730b0 100644 --- a/Makefile.in +++ b/Makefile.in @@ -94,7 +94,7 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \ auth2-none.o auth2-passwd.o auth2-pubkey.o auth2-jpake.o \ monitor_mm.o monitor.o monitor_wrap.o kexdhs.o kexgexs.o kexecdhs.o \ auth-krb5.o \ - auth2-gss.o gss-serv.o gss-serv-krb5.o kexgsss.o\ + auth2-gss.o gss-serv.o kexgsss.o\ loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \ sftp-server.o sftp-common.o \ roaming_common.o roaming_serv.o diff --git a/gss-serv-krb5.c b/gss-serv-krb5.c deleted file mode 100644 index e7170ee..0000000 --- a/gss-serv-krb5.c +++ /dev/null @@ -1,271 +0,0 @@ -/* $OpenBSD: gss-serv-krb5.c,v 1.7 2006/08/03 03:34:42 deraadt Exp $ */ - -/* - * 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 - * 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 KRB5 - -#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; - -#ifdef HEIMDAL -# include -#else -# ifdef HAVE_GSSAPI_KRB5_H -# include -# elif HAVE_GSSAPI_GSSAPI_KRB5_H -# include -# endif -#endif - -static krb5_context krb_context = NULL; - -/* Initialise the krb5 library, for the stuff that GSSAPI won't do */ - -static int -ssh_gssapi_krb5_init(void) -{ - krb5_error_code problem; - - if (krb_context != NULL) - return 1; - - problem = krb5_init_context(&krb_context); - if (problem) { - logit("Cannot initialize krb5 context"); - return 0; - } - - return 1; -} - -/* Check if this user is OK to login. This only works with krb5 - other - * GSSAPI mechanisms will need their own. - * Returns true if the user is OK to log in, otherwise returns 0 - */ - -static int -ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name) -{ - krb5_principal princ; - int retval; - - if (ssh_gssapi_krb5_init() == 0) - return 0; - - if ((retval = krb5_parse_name(krb_context, client->exportedname.value, - &princ))) { - logit("krb5_parse_name(): %.100s", - krb5_get_err_text(krb_context, retval)); - return 0; - } - if (krb5_kuserok(krb_context, princ, name)) { - retval = 1; - logit("Authorized to %s, krb5 principal %s (krb5_kuserok)", - name, (char *)client->displayname.value); - } else - retval = 0; - - krb5_free_principal(krb_context, princ); - return retval; -} - - -/* This writes out any forwarded credentials from the structure populated - * during userauth. Called after we have setuid to the user */ - -static void -ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) -{ - krb5_ccache ccache; - krb5_error_code problem; - krb5_principal princ; - OM_uint32 maj_status, min_status; - int len; - const char *new_ccname; - - if (client->creds == NULL) { - debug("No credentials stored"); - return; - } - - if (ssh_gssapi_krb5_init() == 0) - return; - -#ifdef HEIMDAL - if ((problem = krb5_cc_gen_new(krb_context, &krb5_fcc_ops, &ccache))) { - logit("krb5_cc_gen_new(): %.100s", - krb5_get_err_text(krb_context, problem)); - return; - } -#else - if ((problem = ssh_krb5_cc_gen(krb_context, &ccache))) { - logit("ssh_krb5_cc_gen(): %.100s", - krb5_get_err_text(krb_context, problem)); - return; - } -#endif /* #ifdef HEIMDAL */ - - if ((problem = krb5_parse_name(krb_context, - client->exportedname.value, &princ))) { - logit("krb5_parse_name(): %.100s", - krb5_get_err_text(krb_context, problem)); - krb5_cc_destroy(krb_context, ccache); - return; - } - - if ((problem = krb5_cc_initialize(krb_context, ccache, princ))) { - logit("krb5_cc_initialize(): %.100s", - krb5_get_err_text(krb_context, problem)); - krb5_free_principal(krb_context, princ); - krb5_cc_destroy(krb_context, ccache); - return; - } - - krb5_free_principal(krb_context, princ); - - if ((maj_status = gss_krb5_copy_ccache(&min_status, - client->creds, ccache))) { - logit("gss_krb5_copy_ccache() failed"); - krb5_cc_destroy(krb_context, ccache); - return; - } - - new_ccname = krb5_cc_get_name(krb_context, ccache); - - client->store.envvar = "KRB5CCNAME"; -#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) - do_pam_putenv(client->store.envvar, client->store.envval); -#endif - - krb5_cc_close(krb_context, ccache); - - 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 --git a/gss-serv.c b/gss-serv.c index 365e48d..4812c75 100644 --- a/gss-serv.c +++ b/gss-serv.c @@ -55,22 +55,7 @@ extern ServerOptions options; static ssh_gssapi_client gssapi_client = { GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER, - 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}; - -#ifdef KRB5 -extern ssh_gssapi_mech gssapi_kerberos_mech; -#endif - -ssh_gssapi_mech* supported_mechs[]= { -#ifdef KRB5 - &gssapi_kerberos_mech, -#endif - &gssapi_null_mech, -}; - + GSS_C_NO_CREDENTIAL, GSS_C_NO_NAME, {NULL, NULL, NULL}, 0, 0}; /* * Acquire credentials for a server running on the current host. @@ -152,27 +137,9 @@ ssh_gssapi_server_check_mech(Gssctxt **dum, gss_OID oid, const char *data, void ssh_gssapi_supported_oids(gss_OID_set *oidset) { - int i = 0; OM_uint32 min_status; - int present; - gss_OID_set supported; - - gss_create_empty_oid_set(&min_status, oidset); - - 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, - &supported_mechs[i]->oid, supported, &present))) - present = 0; - if (present) - gss_add_oid_set_member(&min_status, - &supported_mechs[i]->oid, oidset); - i++; - } - gss_release_oid_set(&min_status, &supported); + gss_indicate_mechs(&min_status, oidset); } @@ -283,72 +250,16 @@ ssh_gssapi_parse_ename(Gssctxt *ctx, gss_buffer_t ename, gss_buffer_t name) 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); - - 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; + gss_buffer_desc ename; - while (supported_mechs[i]->name != NULL) { - if (supported_mechs[i]->oid.length == ctx->oid->length && - (memcmp(supported_mechs[i]->oid.elements, - ctx->oid->elements, ctx->oid->length) == 0)) - client->mech = supported_mechs[i]; - i++; - } - - 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))) { + if ((ctx->major = gss_display_name(&ctx->minor, ctx->client, + &client->displayname, NULL))) { ssh_gssapi_error(ctx); return (ctx->major); } - if ((ctx->major = gss_display_name(&ctx->minor, ctx->client, - &client->displayname, NULL))) { + if ((ctx->major = gss_duplicate_name(&ctx->minor, ctx->client, + &client->name))) { ssh_gssapi_error(ctx); return (ctx->major); } @@ -388,10 +299,11 @@ ssh_gssapi_cleanup_creds(void) void ssh_gssapi_storecreds(void) { - if (gssapi_client.mech && gssapi_client.mech->storecreds) { - (*gssapi_client.mech->storecreds)(&gssapi_client); - } else - debug("ssh_gssapi_storecreds: Not a GSSAPI mechanism"); + OM_uint32 lmin; + + gss_store_cred(&lmin, gssapi_client.creds, + GSS_C_INITIATE, GSS_C_NO_OID, + 1, 1, NULL, NULL); } /* This allows GSSAPI methods to do things to the childs environment based @@ -416,28 +328,25 @@ int ssh_gssapi_userok(char *user, struct passwd *pw) { OM_uint32 lmin; + int userok = 0; if (gssapi_client.exportedname.length == 0 || gssapi_client.exportedname.value == NULL) { debug("No suitable client data"); return 0; } - if (gssapi_client.mech && gssapi_client.mech->userok) - if ((*gssapi_client.mech->userok)(&gssapi_client, user)) { - gssapi_client.used = 1; - gssapi_client.store.owner = pw; - return 1; - } else { - /* Destroy delegated credentials if userok fails */ - gss_release_buffer(&lmin, &gssapi_client.displayname); - gss_release_buffer(&lmin, &gssapi_client.exportedname); - gss_release_cred(&lmin, &gssapi_client.creds); - memset(&gssapi_client, 0, sizeof(ssh_gssapi_client)); - return 0; - } - else - debug("ssh_gssapi_userok: Unknown GSSAPI mechanism"); - return (0); + if (GSS_ERROR(gss_userok(&lmin, gssapi_client.name, user, &userok)) || + userok == 0) { + /* Destroy delegated credentials if userok fails */ + gss_release_buffer(&lmin, &gssapi_client.displayname); + gss_release_buffer(&lmin, &gssapi_client.exportedname); + gss_release_name(&lmin, &gssapi_client.name); + gss_release_cred(&lmin, &gssapi_client.creds); + memset(&gssapi_client, 0, sizeof(ssh_gssapi_client)); + return 0; + } + + return (userok); } /* These bits are only used for rekeying. The unpriviledged child is running diff --git a/ssh-gss.h b/ssh-gss.h index 31d5a08..1975a0f 100644 --- a/ssh-gss.h +++ b/ssh-gss.h @@ -42,6 +42,10 @@ # include # endif +#ifndef HEIMDAL +#include +#endif + /* MIT Kerberos doesn't seem to define GSS_NT_HOSTBASED_SERVICE */ #ifndef GSS_C_NT_HOSTBASED_SERVICE @@ -84,23 +88,11 @@ typedef struct { 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 { - char *enc_name; - char *name; - gss_OID_desc oid; - int (*dochild) (ssh_gssapi_client *); - 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 { OM_uint32 major; /* both */ OM_uint32 minor; /* both */ @@ -112,14 +104,12 @@ typedef struct { 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); void ssh_gssapi_set_oid(Gssctxt *, gss_OID); void ssh_gssapi_supported_oids(gss_OID_set *); -ssh_gssapi_mech *ssh_gssapi_get_ctype(Gssctxt *); OM_uint32 ssh_gssapi_import_name(Gssctxt *, const char *); OM_uint32 ssh_gssapi_init_ctx(Gssctxt *, int,