1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. * 3*7c478bd9Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 4*7c478bd9Sstevel@tonic-gate * modification, are permitted provided that the following conditions 5*7c478bd9Sstevel@tonic-gate * are met: 6*7c478bd9Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright 7*7c478bd9Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 8*7c478bd9Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 9*7c478bd9Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the 10*7c478bd9Sstevel@tonic-gate * documentation and/or other materials provided with the distribution. 11*7c478bd9Sstevel@tonic-gate * 12*7c478bd9Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR 13*7c478bd9Sstevel@tonic-gate * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 14*7c478bd9Sstevel@tonic-gate * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 15*7c478bd9Sstevel@tonic-gate * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 16*7c478bd9Sstevel@tonic-gate * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 17*7c478bd9Sstevel@tonic-gate * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 18*7c478bd9Sstevel@tonic-gate * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 19*7c478bd9Sstevel@tonic-gate * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 20*7c478bd9Sstevel@tonic-gate * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 21*7c478bd9Sstevel@tonic-gate * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22*7c478bd9Sstevel@tonic-gate */ 23*7c478bd9Sstevel@tonic-gate /* 24*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 25*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 26*7c478bd9Sstevel@tonic-gate */ 27*7c478bd9Sstevel@tonic-gate 28*7c478bd9Sstevel@tonic-gate #include "includes.h" 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate #ifdef GSSAPI 31*7c478bd9Sstevel@tonic-gate 32*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 33*7c478bd9Sstevel@tonic-gate 34*7c478bd9Sstevel@tonic-gate #include "ssh.h" 35*7c478bd9Sstevel@tonic-gate #include "ssh2.h" 36*7c478bd9Sstevel@tonic-gate #include "xmalloc.h" 37*7c478bd9Sstevel@tonic-gate #include "buffer.h" 38*7c478bd9Sstevel@tonic-gate #include "bufaux.h" 39*7c478bd9Sstevel@tonic-gate #include "packet.h" 40*7c478bd9Sstevel@tonic-gate #include "compat.h" 41*7c478bd9Sstevel@tonic-gate #include <openssl/evp.h> 42*7c478bd9Sstevel@tonic-gate #include "cipher.h" 43*7c478bd9Sstevel@tonic-gate #include "kex.h" 44*7c478bd9Sstevel@tonic-gate #include "log.h" 45*7c478bd9Sstevel@tonic-gate #include "compat.h" 46*7c478bd9Sstevel@tonic-gate #include "monitor_wrap.h" 47*7c478bd9Sstevel@tonic-gate 48*7c478bd9Sstevel@tonic-gate #include <netdb.h> 49*7c478bd9Sstevel@tonic-gate 50*7c478bd9Sstevel@tonic-gate #include "ssh-gss.h" 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate void 53*7c478bd9Sstevel@tonic-gate ssh_gssapi_client_kex_hook(Kex *kex, char **proposal) 54*7c478bd9Sstevel@tonic-gate { 55*7c478bd9Sstevel@tonic-gate gss_OID_set mechs = GSS_C_NULL_OID_SET; 56*7c478bd9Sstevel@tonic-gate 57*7c478bd9Sstevel@tonic-gate if (kex == NULL || kex->serverhost == NULL) 58*7c478bd9Sstevel@tonic-gate fatal("INTERNAL ERROR (%s)", __func__); 59*7c478bd9Sstevel@tonic-gate 60*7c478bd9Sstevel@tonic-gate ssh_gssapi_client_mechs(kex->serverhost, &mechs); 61*7c478bd9Sstevel@tonic-gate ssh_gssapi_modify_kex(kex, mechs, proposal); 62*7c478bd9Sstevel@tonic-gate } 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate void 65*7c478bd9Sstevel@tonic-gate ssh_gssapi_client_mechs(const char *server_host, gss_OID_set *mechs) 66*7c478bd9Sstevel@tonic-gate { 67*7c478bd9Sstevel@tonic-gate gss_OID_set indicated = GSS_C_NULL_OID_SET; 68*7c478bd9Sstevel@tonic-gate gss_OID_set acquired, supported; 69*7c478bd9Sstevel@tonic-gate gss_OID mech; 70*7c478bd9Sstevel@tonic-gate gss_cred_id_t creds; 71*7c478bd9Sstevel@tonic-gate Gssctxt *ctxt = NULL; 72*7c478bd9Sstevel@tonic-gate gss_buffer_desc tok; 73*7c478bd9Sstevel@tonic-gate OM_uint32 maj, min; 74*7c478bd9Sstevel@tonic-gate int i; 75*7c478bd9Sstevel@tonic-gate 76*7c478bd9Sstevel@tonic-gate if (!mechs) 77*7c478bd9Sstevel@tonic-gate return; 78*7c478bd9Sstevel@tonic-gate *mechs = GSS_C_NULL_OID_SET; 79*7c478bd9Sstevel@tonic-gate 80*7c478bd9Sstevel@tonic-gate maj = gss_indicate_mechs(&min, &indicated); 81*7c478bd9Sstevel@tonic-gate if (GSS_ERROR(maj)) { 82*7c478bd9Sstevel@tonic-gate debug("No GSS-API mechanisms are installed"); 83*7c478bd9Sstevel@tonic-gate return; 84*7c478bd9Sstevel@tonic-gate } 85*7c478bd9Sstevel@tonic-gate 86*7c478bd9Sstevel@tonic-gate maj = gss_create_empty_oid_set(&min, &supported); 87*7c478bd9Sstevel@tonic-gate if (GSS_ERROR(maj)) { 88*7c478bd9Sstevel@tonic-gate debug("Failed to allocate resources (%s) for GSS-API", 89*7c478bd9Sstevel@tonic-gate ssh_gssapi_last_error(NULL, &maj, &min)); 90*7c478bd9Sstevel@tonic-gate (void) gss_release_oid_set(&min, &indicated); 91*7c478bd9Sstevel@tonic-gate return; 92*7c478bd9Sstevel@tonic-gate } 93*7c478bd9Sstevel@tonic-gate maj = gss_acquire_cred(&min, GSS_C_NO_NAME, 0, indicated, 94*7c478bd9Sstevel@tonic-gate GSS_C_INITIATE, &creds, &acquired, NULL); 95*7c478bd9Sstevel@tonic-gate 96*7c478bd9Sstevel@tonic-gate if (GSS_ERROR(maj)) { 97*7c478bd9Sstevel@tonic-gate debug("Failed to acquire GSS-API credentials for any " 98*7c478bd9Sstevel@tonic-gate "mechanisms (%s)", 99*7c478bd9Sstevel@tonic-gate ssh_gssapi_last_error(NULL, &maj, &min)); 100*7c478bd9Sstevel@tonic-gate (void) gss_release_oid_set(&min, &indicated); 101*7c478bd9Sstevel@tonic-gate (void) gss_release_oid_set(&min, &supported); 102*7c478bd9Sstevel@tonic-gate return; 103*7c478bd9Sstevel@tonic-gate } 104*7c478bd9Sstevel@tonic-gate (void) gss_release_cred(&min, &creds); 105*7c478bd9Sstevel@tonic-gate 106*7c478bd9Sstevel@tonic-gate for (i = 0 ; i < acquired->count ; i++) { 107*7c478bd9Sstevel@tonic-gate mech = &acquired->elements[i]; 108*7c478bd9Sstevel@tonic-gate 109*7c478bd9Sstevel@tonic-gate if (ssh_gssapi_is_spnego(mech)) 110*7c478bd9Sstevel@tonic-gate continue; 111*7c478bd9Sstevel@tonic-gate 112*7c478bd9Sstevel@tonic-gate ssh_gssapi_build_ctx(&ctxt, 1, mech); 113*7c478bd9Sstevel@tonic-gate if (!ctxt) 114*7c478bd9Sstevel@tonic-gate continue; 115*7c478bd9Sstevel@tonic-gate 116*7c478bd9Sstevel@tonic-gate /* 117*7c478bd9Sstevel@tonic-gate * This is useful for mechs like Kerberos, which can 118*7c478bd9Sstevel@tonic-gate * detect unknown target princs here, but not for 119*7c478bd9Sstevel@tonic-gate * mechs like SPKM, which cannot detect unknown princs 120*7c478bd9Sstevel@tonic-gate * until context tokens are actually exchanged. 121*7c478bd9Sstevel@tonic-gate * 122*7c478bd9Sstevel@tonic-gate * 'Twould be useful to have a test that could save us 123*7c478bd9Sstevel@tonic-gate * the bother of trying this for SPKM and the such... 124*7c478bd9Sstevel@tonic-gate */ 125*7c478bd9Sstevel@tonic-gate maj = ssh_gssapi_init_ctx(ctxt, server_host, 0, 126*7c478bd9Sstevel@tonic-gate NULL, &tok); 127*7c478bd9Sstevel@tonic-gate if (GSS_ERROR(maj)) { 128*7c478bd9Sstevel@tonic-gate debug("Skipping GSS-API mechanism %s (%s)", 129*7c478bd9Sstevel@tonic-gate ssh_gssapi_oid_to_name(mech), 130*7c478bd9Sstevel@tonic-gate ssh_gssapi_last_error(ctxt, NULL, NULL)); 131*7c478bd9Sstevel@tonic-gate continue; 132*7c478bd9Sstevel@tonic-gate } 133*7c478bd9Sstevel@tonic-gate 134*7c478bd9Sstevel@tonic-gate (void) gss_release_buffer(&min, &tok); 135*7c478bd9Sstevel@tonic-gate 136*7c478bd9Sstevel@tonic-gate maj = gss_add_oid_set_member(&min, mech, &supported); 137*7c478bd9Sstevel@tonic-gate if (GSS_ERROR(maj)) 138*7c478bd9Sstevel@tonic-gate debug("Failed to allocate resources (%s) for GSS-API", 139*7c478bd9Sstevel@tonic-gate ssh_gssapi_last_error(NULL, &maj, &min)); 140*7c478bd9Sstevel@tonic-gate } 141*7c478bd9Sstevel@tonic-gate 142*7c478bd9Sstevel@tonic-gate *mechs = supported; 143*7c478bd9Sstevel@tonic-gate } 144*7c478bd9Sstevel@tonic-gate 145*7c478bd9Sstevel@tonic-gate 146*7c478bd9Sstevel@tonic-gate /* Wrapper to init_sec_context 147*7c478bd9Sstevel@tonic-gate * Requires that the context contains: 148*7c478bd9Sstevel@tonic-gate * oid 149*7c478bd9Sstevel@tonic-gate * server name (from ssh_gssapi_import_name) 150*7c478bd9Sstevel@tonic-gate */ 151*7c478bd9Sstevel@tonic-gate OM_uint32 152*7c478bd9Sstevel@tonic-gate ssh_gssapi_init_ctx(Gssctxt *ctx, const char *server_host, int deleg_creds, 153*7c478bd9Sstevel@tonic-gate gss_buffer_t recv_tok, gss_buffer_t send_tok) 154*7c478bd9Sstevel@tonic-gate { 155*7c478bd9Sstevel@tonic-gate int flags = GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG; 156*7c478bd9Sstevel@tonic-gate 157*7c478bd9Sstevel@tonic-gate debug("%s(%p, %s, %d, %p, %p)", __func__, ctx, server_host, 158*7c478bd9Sstevel@tonic-gate deleg_creds, recv_tok, send_tok); 159*7c478bd9Sstevel@tonic-gate 160*7c478bd9Sstevel@tonic-gate if (deleg_creds) { 161*7c478bd9Sstevel@tonic-gate flags |= GSS_C_DELEG_FLAG; 162*7c478bd9Sstevel@tonic-gate debug("Delegating GSS-API credentials"); 163*7c478bd9Sstevel@tonic-gate } 164*7c478bd9Sstevel@tonic-gate 165*7c478bd9Sstevel@tonic-gate /* Build target principal */ 166*7c478bd9Sstevel@tonic-gate if (ctx->desired_name == GSS_C_NO_NAME && 167*7c478bd9Sstevel@tonic-gate !ssh_gssapi_import_name(ctx, server_host)) 168*7c478bd9Sstevel@tonic-gate return ctx->major; 169*7c478bd9Sstevel@tonic-gate 170*7c478bd9Sstevel@tonic-gate ctx->major=gss_init_sec_context(&ctx->minor, 171*7c478bd9Sstevel@tonic-gate GSS_C_NO_CREDENTIAL, 172*7c478bd9Sstevel@tonic-gate &ctx->context, 173*7c478bd9Sstevel@tonic-gate ctx->desired_name, 174*7c478bd9Sstevel@tonic-gate ctx->desired_mech, 175*7c478bd9Sstevel@tonic-gate flags, 176*7c478bd9Sstevel@tonic-gate 0, /* default lifetime */ 177*7c478bd9Sstevel@tonic-gate NULL, /* no channel bindings */ 178*7c478bd9Sstevel@tonic-gate recv_tok, 179*7c478bd9Sstevel@tonic-gate NULL, /* actual mech type */ 180*7c478bd9Sstevel@tonic-gate send_tok, 181*7c478bd9Sstevel@tonic-gate &ctx->flags, 182*7c478bd9Sstevel@tonic-gate NULL); /* actual lifetime */ 183*7c478bd9Sstevel@tonic-gate 184*7c478bd9Sstevel@tonic-gate if (GSS_ERROR(ctx->major)) 185*7c478bd9Sstevel@tonic-gate ssh_gssapi_error(ctx, "calling GSS_Init_sec_context()"); 186*7c478bd9Sstevel@tonic-gate 187*7c478bd9Sstevel@tonic-gate return(ctx->major); 188*7c478bd9Sstevel@tonic-gate } 189*7c478bd9Sstevel@tonic-gate #endif /* GSSAPI */ 190