10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without
50Sstevel@tonic-gate * modification, are permitted provided that the following conditions
60Sstevel@tonic-gate * are met:
70Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright
80Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer.
90Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright
100Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the
110Sstevel@tonic-gate * documentation and/or other materials provided with the distribution.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
140Sstevel@tonic-gate * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
150Sstevel@tonic-gate * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
160Sstevel@tonic-gate * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
170Sstevel@tonic-gate * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
180Sstevel@tonic-gate * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
190Sstevel@tonic-gate * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
200Sstevel@tonic-gate * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
210Sstevel@tonic-gate * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
220Sstevel@tonic-gate * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
230Sstevel@tonic-gate */
240Sstevel@tonic-gate /*
25*6080Sjp161948 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
260Sstevel@tonic-gate * Use is subject to license terms.
270Sstevel@tonic-gate */
280Sstevel@tonic-gate
290Sstevel@tonic-gate #include "includes.h"
300Sstevel@tonic-gate
310Sstevel@tonic-gate #ifdef GSSAPI
320Sstevel@tonic-gate
330Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
340Sstevel@tonic-gate
350Sstevel@tonic-gate #include "includes.h"
360Sstevel@tonic-gate #include "ssh.h"
370Sstevel@tonic-gate #include "ssh2.h"
380Sstevel@tonic-gate #include "xmalloc.h"
390Sstevel@tonic-gate #include "buffer.h"
400Sstevel@tonic-gate #include "bufaux.h"
410Sstevel@tonic-gate #include "packet.h"
420Sstevel@tonic-gate #include "compat.h"
430Sstevel@tonic-gate #include <openssl/evp.h>
440Sstevel@tonic-gate #include "cipher.h"
450Sstevel@tonic-gate #include "kex.h"
460Sstevel@tonic-gate #include "auth.h"
470Sstevel@tonic-gate #include "log.h"
480Sstevel@tonic-gate #include "channels.h"
490Sstevel@tonic-gate #include "session.h"
500Sstevel@tonic-gate #include "dispatch.h"
510Sstevel@tonic-gate #include "servconf.h"
520Sstevel@tonic-gate #include "uidswap.h"
530Sstevel@tonic-gate #include "compat.h"
540Sstevel@tonic-gate #include <pwd.h>
550Sstevel@tonic-gate
560Sstevel@tonic-gate #include "ssh-gss.h"
570Sstevel@tonic-gate
580Sstevel@tonic-gate extern char **environ;
590Sstevel@tonic-gate
600Sstevel@tonic-gate extern ServerOptions options;
61*6080Sjp161948 extern uchar_t *session_id2;
620Sstevel@tonic-gate extern int session_id2_len;
630Sstevel@tonic-gate
640Sstevel@tonic-gate Gssctxt *xxx_gssctxt;
650Sstevel@tonic-gate
660Sstevel@tonic-gate void
ssh_gssapi_server_kex_hook(Kex * kex,char ** proposal)670Sstevel@tonic-gate ssh_gssapi_server_kex_hook(Kex *kex, char **proposal)
680Sstevel@tonic-gate {
690Sstevel@tonic-gate gss_OID_set mechs = GSS_C_NULL_OID_SET;
700Sstevel@tonic-gate
710Sstevel@tonic-gate if (kex == NULL || !kex->server)
720Sstevel@tonic-gate fatal("INTERNAL ERROR (%s)", __func__);
730Sstevel@tonic-gate
740Sstevel@tonic-gate ssh_gssapi_server_mechs(&mechs);
750Sstevel@tonic-gate ssh_gssapi_modify_kex(kex, mechs, proposal);
760Sstevel@tonic-gate }
770Sstevel@tonic-gate
780Sstevel@tonic-gate void
ssh_gssapi_server_mechs(gss_OID_set * mechs)790Sstevel@tonic-gate ssh_gssapi_server_mechs(gss_OID_set *mechs)
800Sstevel@tonic-gate {
810Sstevel@tonic-gate static gss_OID_set supported = GSS_C_NULL_OID_SET;
820Sstevel@tonic-gate gss_OID_set s, acquired, indicated = GSS_C_NULL_OID_SET;
830Sstevel@tonic-gate gss_cred_id_t creds;
840Sstevel@tonic-gate OM_uint32 maj, min;
850Sstevel@tonic-gate int i;
860Sstevel@tonic-gate
870Sstevel@tonic-gate if (!mechs) {
880Sstevel@tonic-gate (void) gss_release_oid_set(&min, &supported);
890Sstevel@tonic-gate return;
900Sstevel@tonic-gate }
910Sstevel@tonic-gate
920Sstevel@tonic-gate if (supported != GSS_C_NULL_OID_SET) {
930Sstevel@tonic-gate *mechs = supported;
940Sstevel@tonic-gate return;
950Sstevel@tonic-gate }
960Sstevel@tonic-gate
970Sstevel@tonic-gate *mechs = GSS_C_NULL_OID_SET;
980Sstevel@tonic-gate
990Sstevel@tonic-gate maj = gss_create_empty_oid_set(&min, &s);
1000Sstevel@tonic-gate if (GSS_ERROR(maj)) {
1010Sstevel@tonic-gate debug("Could not allocate GSS-API resources (%s)",
102*6080Sjp161948 ssh_gssapi_last_error(NULL, &maj, &min));
1030Sstevel@tonic-gate return;
1040Sstevel@tonic-gate }
1050Sstevel@tonic-gate
1060Sstevel@tonic-gate maj = gss_indicate_mechs(&min, &indicated);
1070Sstevel@tonic-gate if (GSS_ERROR(maj)) {
1080Sstevel@tonic-gate debug("No GSS-API mechanisms are installed");
1090Sstevel@tonic-gate return;
1100Sstevel@tonic-gate }
1110Sstevel@tonic-gate
1120Sstevel@tonic-gate maj = gss_acquire_cred(&min, GSS_C_NO_NAME, 0, indicated,
113*6080Sjp161948 GSS_C_ACCEPT, &creds, &acquired, NULL);
1140Sstevel@tonic-gate
1150Sstevel@tonic-gate if (GSS_ERROR(maj))
1160Sstevel@tonic-gate debug("Failed to acquire GSS-API credentials for any "
117*6080Sjp161948 "mechanisms (%s)", ssh_gssapi_last_error(NULL, &maj, &min));
1180Sstevel@tonic-gate
1190Sstevel@tonic-gate (void) gss_release_oid_set(&min, &indicated);
1200Sstevel@tonic-gate (void) gss_release_cred(&min, &creds);
1210Sstevel@tonic-gate
1220Sstevel@tonic-gate if (acquired == GSS_C_NULL_OID_SET || acquired->count == 0)
1230Sstevel@tonic-gate return;
1240Sstevel@tonic-gate
125*6080Sjp161948 for (i = 0; i < acquired->count; i++) {
1260Sstevel@tonic-gate if (ssh_gssapi_is_spnego(&acquired->elements[i]))
1270Sstevel@tonic-gate continue;
1280Sstevel@tonic-gate
1290Sstevel@tonic-gate maj = gss_add_oid_set_member(&min, &acquired->elements[i], &s);
1300Sstevel@tonic-gate if (GSS_ERROR(maj)) {
1310Sstevel@tonic-gate debug("Could not allocate GSS-API resources (%s)",
132*6080Sjp161948 ssh_gssapi_last_error(NULL, &maj, &min));
1330Sstevel@tonic-gate return;
1340Sstevel@tonic-gate }
1350Sstevel@tonic-gate }
1360Sstevel@tonic-gate (void) gss_release_oid_set(&min, &acquired);
1370Sstevel@tonic-gate
1380Sstevel@tonic-gate if (s->count) {
1390Sstevel@tonic-gate supported = s;
1400Sstevel@tonic-gate *mechs = s;
1410Sstevel@tonic-gate }
1420Sstevel@tonic-gate }
1430Sstevel@tonic-gate
144*6080Sjp161948 /*
145*6080Sjp161948 * Wrapper around accept_sec_context. Requires that the context contains:
146*6080Sjp161948 *
1470Sstevel@tonic-gate * oid
1480Sstevel@tonic-gate * credentials (from ssh_gssapi_acquire_cred)
1490Sstevel@tonic-gate */
1500Sstevel@tonic-gate /* Priviledged */
151*6080Sjp161948 OM_uint32
ssh_gssapi_accept_ctx(Gssctxt * ctx,gss_buffer_t recv_tok,gss_buffer_t send_tok)152*6080Sjp161948 ssh_gssapi_accept_ctx(Gssctxt *ctx, gss_buffer_t recv_tok,
153*6080Sjp161948 gss_buffer_t send_tok)
1540Sstevel@tonic-gate {
1550Sstevel@tonic-gate /*
1560Sstevel@tonic-gate * Acquiring a cred for the ctx->desired_mech for GSS_C_NO_NAME
1570Sstevel@tonic-gate * may well be probably better than using GSS_C_NO_CREDENTIAL
1580Sstevel@tonic-gate * and then checking that ctx->desired_mech agrees with
1590Sstevel@tonic-gate * ctx->actual_mech...
1600Sstevel@tonic-gate */
161*6080Sjp161948 ctx->major = gss_accept_sec_context(&ctx->minor, &ctx->context,
162*6080Sjp161948 GSS_C_NO_CREDENTIAL, recv_tok, GSS_C_NO_CHANNEL_BINDINGS,
163*6080Sjp161948 &ctx->src_name, &ctx->actual_mech, send_tok, &ctx->flags,
164*6080Sjp161948 NULL, &ctx->deleg_creds);
165*6080Sjp161948
1660Sstevel@tonic-gate if (GSS_ERROR(ctx->major))
1670Sstevel@tonic-gate ssh_gssapi_error(ctx, "accepting security context");
1680Sstevel@tonic-gate
1690Sstevel@tonic-gate if (ctx->major == GSS_S_CONTINUE_NEEDED && send_tok->length == 0)
170*6080Sjp161948 fatal("Zero length GSS context token output when "
171*6080Sjp161948 "continue needed");
1720Sstevel@tonic-gate else if (GSS_ERROR(ctx->major) && send_tok->length == 0)
1730Sstevel@tonic-gate debug2("Zero length GSS context error token output");
1740Sstevel@tonic-gate
1750Sstevel@tonic-gate if (ctx->major == GSS_S_COMPLETE &&
1760Sstevel@tonic-gate ctx->desired_mech != GSS_C_NULL_OID &&
1770Sstevel@tonic-gate (ctx->desired_mech->length != ctx->actual_mech->length ||
178*6080Sjp161948 memcmp(ctx->desired_mech->elements, ctx->actual_mech->elements,
179*6080Sjp161948 ctx->desired_mech->length) != 0)) {
180*6080Sjp161948
1810Sstevel@tonic-gate gss_OID_set supported;
182*6080Sjp161948 OM_uint32 min;
183*6080Sjp161948 int present = 0;
1840Sstevel@tonic-gate
185*6080Sjp161948 debug("The client did not use the GSS-API mechanism it "
186*6080Sjp161948 "asked for");
1870Sstevel@tonic-gate
1880Sstevel@tonic-gate /* Let it slide as long as the mech is supported */
1890Sstevel@tonic-gate ssh_gssapi_server_mechs(&supported);
190*6080Sjp161948 if (supported != GSS_C_NULL_OID_SET) {
191*6080Sjp161948 (void) gss_test_oid_set_member(&min, ctx->actual_mech,
192*6080Sjp161948 supported, &present);
193*6080Sjp161948 }
1940Sstevel@tonic-gate if (!present)
1950Sstevel@tonic-gate ctx->major = GSS_S_BAD_MECH;
1960Sstevel@tonic-gate }
1970Sstevel@tonic-gate
1980Sstevel@tonic-gate if (ctx->deleg_creds)
1990Sstevel@tonic-gate debug("Received delegated GSS credentials");
2000Sstevel@tonic-gate
2010Sstevel@tonic-gate if (ctx->major == GSS_S_COMPLETE) {
2020Sstevel@tonic-gate ctx->major = gss_inquire_context(&ctx->minor, ctx->context,
203*6080Sjp161948 NULL, &ctx->dst_name, NULL, NULL, NULL, NULL,
204*6080Sjp161948 &ctx->established);
2050Sstevel@tonic-gate
2060Sstevel@tonic-gate if (GSS_ERROR(ctx->major)) {
207*6080Sjp161948 ssh_gssapi_error(ctx,
208*6080Sjp161948 "inquiring established sec context");
2090Sstevel@tonic-gate return (ctx->major);
2100Sstevel@tonic-gate }
2110Sstevel@tonic-gate
2120Sstevel@tonic-gate xxx_gssctxt = ctx;
2130Sstevel@tonic-gate }
2140Sstevel@tonic-gate
2150Sstevel@tonic-gate return (ctx->major);
2160Sstevel@tonic-gate }
2170Sstevel@tonic-gate
2180Sstevel@tonic-gate
2190Sstevel@tonic-gate /* As user - called through fatal cleanup hook */
2200Sstevel@tonic-gate void
ssh_gssapi_cleanup_creds(Gssctxt * ctx)2210Sstevel@tonic-gate ssh_gssapi_cleanup_creds(Gssctxt *ctx)
2220Sstevel@tonic-gate {
2230Sstevel@tonic-gate #ifdef HAVE_GSS_STORE_CRED
2240Sstevel@tonic-gate /* pam_setcred() will take care of this */
2250Sstevel@tonic-gate return;
2260Sstevel@tonic-gate #else
2270Sstevel@tonic-gate return;
228*6080Sjp161948 /* #error "Portability broken in cleanup of stored creds" */
2290Sstevel@tonic-gate #endif /* HAVE_GSS_STORE_CRED */
2300Sstevel@tonic-gate }
2310Sstevel@tonic-gate
2320Sstevel@tonic-gate void
ssh_gssapi_storecreds(Gssctxt * ctx,Authctxt * authctxt)2330Sstevel@tonic-gate ssh_gssapi_storecreds(Gssctxt *ctx, Authctxt *authctxt)
2340Sstevel@tonic-gate {
2350Sstevel@tonic-gate #ifdef USE_PAM
2360Sstevel@tonic-gate char **penv, **tmp_env;
2370Sstevel@tonic-gate #endif /* USE_PAM */
238*6080Sjp161948
2390Sstevel@tonic-gate if (authctxt == NULL) {
2400Sstevel@tonic-gate error("Missing context while storing GSS-API credentials");
2410Sstevel@tonic-gate return;
2420Sstevel@tonic-gate }
2430Sstevel@tonic-gate
2440Sstevel@tonic-gate if (ctx == NULL && xxx_gssctxt == NULL)
2450Sstevel@tonic-gate return;
2460Sstevel@tonic-gate
2470Sstevel@tonic-gate if (ctx == NULL)
2480Sstevel@tonic-gate ctx = xxx_gssctxt;
2490Sstevel@tonic-gate
250*6080Sjp161948 if (!options.gss_cleanup_creds ||
2510Sstevel@tonic-gate ctx->deleg_creds == GSS_C_NO_CREDENTIAL) {
2520Sstevel@tonic-gate debug3("Not storing delegated GSS credentials"
253*6080Sjp161948 " (none delegated)");
2540Sstevel@tonic-gate return;
2550Sstevel@tonic-gate }
2560Sstevel@tonic-gate
2570Sstevel@tonic-gate if (!authctxt->valid || authctxt->pw == NULL) {
2580Sstevel@tonic-gate debug3("Not storing delegated GSS credentials"
259*6080Sjp161948 " for invalid user");
2600Sstevel@tonic-gate return;
2610Sstevel@tonic-gate }
2620Sstevel@tonic-gate
2630Sstevel@tonic-gate debug("Storing delegated GSS-API credentials");
2640Sstevel@tonic-gate
2650Sstevel@tonic-gate /*
2660Sstevel@tonic-gate * The GSS-API has a flaw in that it does not provide a
2670Sstevel@tonic-gate * mechanism by which delegated credentials can be made
2680Sstevel@tonic-gate * available for acquisition by GSS_Acquire_cred() et. al.;
2690Sstevel@tonic-gate * gss_store_cred() is the proposed GSS-API extension for
2700Sstevel@tonic-gate * generically storing delegated credentials.
2710Sstevel@tonic-gate *
2720Sstevel@tonic-gate * gss_store_cred() does not speak to how credential stores are
2730Sstevel@tonic-gate * referenced. Generically this may be done by switching to the
2740Sstevel@tonic-gate * user context of the user in whose default credential store we
2750Sstevel@tonic-gate * wish to place delegated credentials. But environment
2760Sstevel@tonic-gate * variables could conceivably affect the choice of credential
2770Sstevel@tonic-gate * store as well, and perhaps in a mechanism-specific manner.
2780Sstevel@tonic-gate *
2790Sstevel@tonic-gate * SUNW -- On Solaris the euid selects the current credential
2800Sstevel@tonic-gate * store, but PAM modules could select alternate stores by
2810Sstevel@tonic-gate * setting, for example, KRB5CCNAME, so we also use the PAM
2820Sstevel@tonic-gate * environment temporarily.
2830Sstevel@tonic-gate */
2840Sstevel@tonic-gate
2850Sstevel@tonic-gate #ifdef HAVE_GSS_STORE_CRED
2860Sstevel@tonic-gate #ifdef USE_PAM
2870Sstevel@tonic-gate /*
2880Sstevel@tonic-gate * PAM may have set mechanism-specific variables (e.g.,
2890Sstevel@tonic-gate * KRB5CCNAME). fetch_pam_environment() protects against LD_*
2900Sstevel@tonic-gate * and other environment variables.
2910Sstevel@tonic-gate */
2920Sstevel@tonic-gate penv = fetch_pam_environment(authctxt);
2930Sstevel@tonic-gate tmp_env = environ;
2940Sstevel@tonic-gate environ = penv;
2950Sstevel@tonic-gate #endif /* USE_PAM */
2960Sstevel@tonic-gate if (authctxt->pw->pw_uid != geteuid()) {
2970Sstevel@tonic-gate temporarily_use_uid(authctxt->pw);
2980Sstevel@tonic-gate ctx->major = gss_store_cred(&ctx->minor, ctx->deleg_creds,
299*6080Sjp161948 GSS_C_INITIATE, GSS_C_NULL_OID, 0, ctx->default_creds,
300*6080Sjp161948 NULL, NULL);
3010Sstevel@tonic-gate restore_uid();
3020Sstevel@tonic-gate } else {
3030Sstevel@tonic-gate /* only when logging in as the privileged user used by sshd */
3040Sstevel@tonic-gate ctx->major = gss_store_cred(&ctx->minor, ctx->deleg_creds,
305*6080Sjp161948 GSS_C_INITIATE, GSS_C_NULL_OID, 0, ctx->default_creds,
306*6080Sjp161948 NULL, NULL);
3070Sstevel@tonic-gate }
3080Sstevel@tonic-gate #ifdef USE_PAM
3090Sstevel@tonic-gate environ = tmp_env;
3100Sstevel@tonic-gate free_pam_environment(penv);
3110Sstevel@tonic-gate #endif /* USE_PAM */
3120Sstevel@tonic-gate if (GSS_ERROR(ctx->major))
3130Sstevel@tonic-gate ssh_gssapi_error(ctx, "storing delegated credentials");
3140Sstevel@tonic-gate
3150Sstevel@tonic-gate #else
3160Sstevel@tonic-gate #ifdef KRB5_GSS
3170Sstevel@tonic-gate #error "MIT/Heimdal krb5-specific code missing in ssh_gssapi_storecreds()"
3180Sstevel@tonic-gate if (ssh_gssapi_is_krb5(ctx->mech))
3190Sstevel@tonic-gate ssh_gssapi_krb5_storecreds(ctx);
3200Sstevel@tonic-gate #endif /* KRB5_GSS */
3210Sstevel@tonic-gate #ifdef GSI_GSS
3220Sstevel@tonic-gate #error "GSI krb5-specific code missing in ssh_gssapi_storecreds()"
3230Sstevel@tonic-gate if (ssh_gssapi_is_gsi(ctx->mech))
3240Sstevel@tonic-gate ssh_gssapi_krb5_storecreds(ctx);
3250Sstevel@tonic-gate #endif /* GSI_GSS */
326*6080Sjp161948 /* #error "Mechanism-specific code missing in ssh_gssapi_storecreds()" */
3270Sstevel@tonic-gate return;
3280Sstevel@tonic-gate #endif /* HAVE_GSS_STORE_CRED */
3290Sstevel@tonic-gate }
3300Sstevel@tonic-gate
3310Sstevel@tonic-gate void
ssh_gssapi_do_child(Gssctxt * ctx,char *** envp,uint_t * envsizep)332*6080Sjp161948 ssh_gssapi_do_child(Gssctxt *ctx, char ***envp, uint_t *envsizep)
3330Sstevel@tonic-gate {
3340Sstevel@tonic-gate /*
3350Sstevel@tonic-gate * MIT/Heimdal/GSI specific code goes here.
3360Sstevel@tonic-gate *
3370Sstevel@tonic-gate * On Solaris there's nothing to do here as the GSS store and
3380Sstevel@tonic-gate * related environment variables are to be set by PAM, if at all
3390Sstevel@tonic-gate * (no environment variables are needed to address the default
3400Sstevel@tonic-gate * credential store -- the euid does that).
3410Sstevel@tonic-gate */
3420Sstevel@tonic-gate #ifdef KRB5_GSS
3430Sstevel@tonic-gate #error "MIT/Heimdal krb5-specific code missing in ssh_gssapi_storecreds()"
3440Sstevel@tonic-gate #endif /* KRB5_GSS */
3450Sstevel@tonic-gate #ifdef GSI_GSS
3460Sstevel@tonic-gate #error "GSI krb5-specific code missing in ssh_gssapi_storecreds()"
3470Sstevel@tonic-gate #endif /* GSI_GSS */
3480Sstevel@tonic-gate }
3490Sstevel@tonic-gate
3500Sstevel@tonic-gate int
ssh_gssapi_userok(Gssctxt * ctx,char * user)3510Sstevel@tonic-gate ssh_gssapi_userok(Gssctxt *ctx, char *user)
3520Sstevel@tonic-gate {
3530Sstevel@tonic-gate if (ctx == NULL) {
3540Sstevel@tonic-gate debug3("INTERNAL ERROR: %s", __func__);
3550Sstevel@tonic-gate return (0);
3560Sstevel@tonic-gate }
3570Sstevel@tonic-gate
3580Sstevel@tonic-gate if (user == NULL || *user == '\0')
3590Sstevel@tonic-gate return (0);
3600Sstevel@tonic-gate
3610Sstevel@tonic-gate #ifdef HAVE___GSS_USEROK
3620Sstevel@tonic-gate {
3630Sstevel@tonic-gate int user_ok = 0;
3640Sstevel@tonic-gate
3650Sstevel@tonic-gate ctx->major = __gss_userok(&ctx->minor, ctx->src_name, user,
366*6080Sjp161948 &user_ok);
3670Sstevel@tonic-gate if (GSS_ERROR(ctx->major)) {
3680Sstevel@tonic-gate debug2("__GSS_userok() failed");
3690Sstevel@tonic-gate return (0);
3700Sstevel@tonic-gate }
3710Sstevel@tonic-gate
3720Sstevel@tonic-gate if (user_ok)
3730Sstevel@tonic-gate return (1);
3740Sstevel@tonic-gate
3750Sstevel@tonic-gate /* fall through */
3760Sstevel@tonic-gate }
3770Sstevel@tonic-gate #else
3780Sstevel@tonic-gate #ifdef GSSAPI_SIMPLE_USEROK
3790Sstevel@tonic-gate {
3800Sstevel@tonic-gate /* Mechanism-generic */
3810Sstevel@tonic-gate OM_uint32 min;
3820Sstevel@tonic-gate gss_buffer_desc buf, ename1, ename2;
3830Sstevel@tonic-gate gss_name_t iname, cname;
3840Sstevel@tonic-gate int eql;
3850Sstevel@tonic-gate
3860Sstevel@tonic-gate buf.value = user;
3870Sstevel@tonic-gate buf.length = strlen(user);
3880Sstevel@tonic-gate ctx->major = gss_import_name(&ctx->minor, &buf,
389*6080Sjp161948 GSS_C_NULL_OID, &iname);
3900Sstevel@tonic-gate if (GSS_ERROR(ctx->major)) {
3910Sstevel@tonic-gate ssh_gssapi_error(ctx,
392*6080Sjp161948 "importing name for authorizing initiator");
3930Sstevel@tonic-gate goto failed_simple_userok;
3940Sstevel@tonic-gate }
3950Sstevel@tonic-gate
3960Sstevel@tonic-gate ctx->major = gss_canonicalize_name(&ctx->minor, iname,
397*6080Sjp161948 ctx->actual_mech, &cname);
3980Sstevel@tonic-gate (void) gss_release_name(&min, &iname);
3990Sstevel@tonic-gate if (GSS_ERROR(ctx->major)) {
4000Sstevel@tonic-gate ssh_gssapi_error(ctx, "canonicalizing name");
4010Sstevel@tonic-gate goto failed_simple_userok;
4020Sstevel@tonic-gate }
4030Sstevel@tonic-gate
4040Sstevel@tonic-gate ctx->major = gss_export_name(&ctx->minor, cname, &ename1);
4050Sstevel@tonic-gate (void) gss_release_name(&min, &cname);
4060Sstevel@tonic-gate if (GSS_ERROR(ctx->major)) {
4070Sstevel@tonic-gate ssh_gssapi_error(ctx, "exporting name");
4080Sstevel@tonic-gate goto failed_simple_userok;
4090Sstevel@tonic-gate }
4100Sstevel@tonic-gate
4110Sstevel@tonic-gate ctx->major = gss_export_name(&ctx->minor, ctx->src_name,
412*6080Sjp161948 &ename2);
4130Sstevel@tonic-gate if (GSS_ERROR(ctx->major)) {
4140Sstevel@tonic-gate ssh_gssapi_error(ctx,
415*6080Sjp161948 "exporting client principal name");
4160Sstevel@tonic-gate (void) gss_release_buffer(&min, &ename1);
4170Sstevel@tonic-gate goto failed_simple_userok;
4180Sstevel@tonic-gate }
4190Sstevel@tonic-gate
4200Sstevel@tonic-gate eql = (ename1.length == ename2.length &&
421*6080Sjp161948 memcmp(ename1.value, ename2.value, ename1.length) == 0);
4220Sstevel@tonic-gate
4230Sstevel@tonic-gate (void) gss_release_buffer(&min, &ename1);
4240Sstevel@tonic-gate (void) gss_release_buffer(&min, &ename2);
4250Sstevel@tonic-gate
4260Sstevel@tonic-gate if (eql)
4270Sstevel@tonic-gate return (1);
4280Sstevel@tonic-gate /* fall through */
4290Sstevel@tonic-gate }
4300Sstevel@tonic-gate failed_simple_userok:
4310Sstevel@tonic-gate #endif /* GSSAPI_SIMPLE_USEROK */
4320Sstevel@tonic-gate #ifdef HAVE_GSSCRED_API
4330Sstevel@tonic-gate {
4340Sstevel@tonic-gate /* Mechanism-generic, Solaris-specific */
4350Sstevel@tonic-gate OM_uint32 maj;
4360Sstevel@tonic-gate uid_t uid;
4370Sstevel@tonic-gate struct passwd *pw;
4380Sstevel@tonic-gate
4390Sstevel@tonic-gate maj = gsscred_name_to_unix_cred(ctx->src_name,
440*6080Sjp161948 ctx->actual_mech, &uid, NULL, NULL, NULL);
4410Sstevel@tonic-gate
4420Sstevel@tonic-gate if (GSS_ERROR(maj))
4430Sstevel@tonic-gate goto failed_simple_gsscred_userok;
4440Sstevel@tonic-gate
4450Sstevel@tonic-gate if ((pw = getpwnam(user)) == NULL)
4460Sstevel@tonic-gate goto failed_simple_gsscred_userok;
4470Sstevel@tonic-gate
4480Sstevel@tonic-gate if (pw->pw_uid == uid)
4490Sstevel@tonic-gate return (1);
4500Sstevel@tonic-gate /* fall through */
4510Sstevel@tonic-gate }
452*6080Sjp161948
4530Sstevel@tonic-gate failed_simple_gsscred_userok:
4540Sstevel@tonic-gate #endif /* HAVE_GSSCRED_API */
4550Sstevel@tonic-gate #ifdef KRB5_GSS
4560Sstevel@tonic-gate if (ssh_gssapi_is_krb5(ctx->mech))
4570Sstevel@tonic-gate if (ssh_gssapi_krb5_userok(ctx->src_name, user))
4580Sstevel@tonic-gate return (1);
4590Sstevel@tonic-gate #endif /* KRB5_GSS */
4600Sstevel@tonic-gate #ifdef GSI_GSS
4610Sstevel@tonic-gate if (ssh_gssapi_is_gsi(ctx->mech))
4620Sstevel@tonic-gate if (ssh_gssapi_gsi_userok(ctx->src_name, user))
4630Sstevel@tonic-gate return (1);
4640Sstevel@tonic-gate #endif /* GSI_GSS */
4650Sstevel@tonic-gate #endif /* HAVE___GSS_USEROK */
4660Sstevel@tonic-gate
4670Sstevel@tonic-gate /* default to not authorized */
4680Sstevel@tonic-gate return (0);
4690Sstevel@tonic-gate }
4700Sstevel@tonic-gate
4710Sstevel@tonic-gate char *
ssh_gssapi_localname(Gssctxt * ctx)4720Sstevel@tonic-gate ssh_gssapi_localname(Gssctxt *ctx)
4730Sstevel@tonic-gate {
4740Sstevel@tonic-gate if (ctx == NULL) {
4750Sstevel@tonic-gate debug3("INTERNAL ERROR: %s", __func__);
4760Sstevel@tonic-gate return (NULL);
4770Sstevel@tonic-gate }
4780Sstevel@tonic-gate
4790Sstevel@tonic-gate debug2("Mapping initiator GSS-API principal to local username");
4800Sstevel@tonic-gate #ifdef HAVE_GSSCRED_API
4810Sstevel@tonic-gate {
4820Sstevel@tonic-gate /* Mechanism-generic, Solaris-specific */
4830Sstevel@tonic-gate OM_uint32 maj;
4840Sstevel@tonic-gate uid_t uid;
4850Sstevel@tonic-gate struct passwd *pw;
4860Sstevel@tonic-gate
4870Sstevel@tonic-gate if (ctx->src_name == GSS_C_NO_NAME)
4880Sstevel@tonic-gate goto failed_gsscred_localname;
4890Sstevel@tonic-gate
4900Sstevel@tonic-gate maj = gsscred_name_to_unix_cred(ctx->src_name,
491*6080Sjp161948 ctx->actual_mech, &uid, NULL, NULL, NULL);
4920Sstevel@tonic-gate
4930Sstevel@tonic-gate if (GSS_ERROR(maj))
4940Sstevel@tonic-gate goto failed_gsscred_localname;
4950Sstevel@tonic-gate
4960Sstevel@tonic-gate if ((pw = getpwuid(uid)) == NULL)
4970Sstevel@tonic-gate goto failed_gsscred_localname;
4980Sstevel@tonic-gate
4990Sstevel@tonic-gate debug2("Mapped the initiator to: %s", pw->pw_name);
5000Sstevel@tonic-gate return (xstrdup(pw->pw_name));
5010Sstevel@tonic-gate }
5020Sstevel@tonic-gate failed_gsscred_localname:
5030Sstevel@tonic-gate #endif /* HAVE_GSSCRED_API */
5040Sstevel@tonic-gate #ifdef KRB5_GSS
5050Sstevel@tonic-gate #error "ssh_gssapi_krb5_localname() not implemented"
5060Sstevel@tonic-gate if (ssh_gssapi_is_krb5(ctx->mech))
5070Sstevel@tonic-gate return (ssh_gssapi_krb5_localname(ctx->src_name));
5080Sstevel@tonic-gate #endif /* KRB5_GSS */
5090Sstevel@tonic-gate #ifdef GSI_GSS
5100Sstevel@tonic-gate #error "ssh_gssapi_gsi_localname() not implemented"
5110Sstevel@tonic-gate if (ssh_gssapi_is_gsi(ctx->mech))
5120Sstevel@tonic-gate return (ssh_gssapi_gsi_localname(ctx->src_name));
5130Sstevel@tonic-gate #endif /* GSI_GSS */
5140Sstevel@tonic-gate return (NULL);
5150Sstevel@tonic-gate }
516*6080Sjp161948 #endif /* GSSAPI */
517