17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. * 37c478bd9Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 47c478bd9Sstevel@tonic-gate * modification, are permitted provided that the following conditions 57c478bd9Sstevel@tonic-gate * are met: 67c478bd9Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright 77c478bd9Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 87c478bd9Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 97c478bd9Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the 107c478bd9Sstevel@tonic-gate * documentation and/or other materials provided with the distribution. 117c478bd9Sstevel@tonic-gate * 127c478bd9Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR 137c478bd9Sstevel@tonic-gate * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 147c478bd9Sstevel@tonic-gate * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 157c478bd9Sstevel@tonic-gate * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 167c478bd9Sstevel@tonic-gate * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 177c478bd9Sstevel@tonic-gate * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 187c478bd9Sstevel@tonic-gate * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 197c478bd9Sstevel@tonic-gate * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 207c478bd9Sstevel@tonic-gate * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 217c478bd9Sstevel@tonic-gate * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 227c478bd9Sstevel@tonic-gate */ 237c478bd9Sstevel@tonic-gate /* 24*9a8058b5Sjp161948 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 257c478bd9Sstevel@tonic-gate * Use is subject to license terms. 267c478bd9Sstevel@tonic-gate */ 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #include "includes.h" 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate #ifdef GSSAPI 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 337c478bd9Sstevel@tonic-gate 347c478bd9Sstevel@tonic-gate #include "ssh.h" 357c478bd9Sstevel@tonic-gate #include "ssh2.h" 367c478bd9Sstevel@tonic-gate #include "xmalloc.h" 377c478bd9Sstevel@tonic-gate #include "buffer.h" 387c478bd9Sstevel@tonic-gate #include "bufaux.h" 397c478bd9Sstevel@tonic-gate #include "packet.h" 407c478bd9Sstevel@tonic-gate #include "compat.h" 417c478bd9Sstevel@tonic-gate #include <openssl/evp.h> 427c478bd9Sstevel@tonic-gate #include "cipher.h" 437c478bd9Sstevel@tonic-gate #include "kex.h" 447c478bd9Sstevel@tonic-gate #include "log.h" 457c478bd9Sstevel@tonic-gate #include "compat.h" 467c478bd9Sstevel@tonic-gate 477c478bd9Sstevel@tonic-gate #include <netdb.h> 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate #include "ssh-gss.h" 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate void 527c478bd9Sstevel@tonic-gate ssh_gssapi_client_kex_hook(Kex *kex, char **proposal) 537c478bd9Sstevel@tonic-gate { 547c478bd9Sstevel@tonic-gate gss_OID_set mechs = GSS_C_NULL_OID_SET; 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate if (kex == NULL || kex->serverhost == NULL) 577c478bd9Sstevel@tonic-gate fatal("INTERNAL ERROR (%s)", __func__); 587c478bd9Sstevel@tonic-gate 597c478bd9Sstevel@tonic-gate ssh_gssapi_client_mechs(kex->serverhost, &mechs); 607c478bd9Sstevel@tonic-gate ssh_gssapi_modify_kex(kex, mechs, proposal); 617c478bd9Sstevel@tonic-gate } 627c478bd9Sstevel@tonic-gate 637c478bd9Sstevel@tonic-gate void 647c478bd9Sstevel@tonic-gate ssh_gssapi_client_mechs(const char *server_host, gss_OID_set *mechs) 657c478bd9Sstevel@tonic-gate { 667c478bd9Sstevel@tonic-gate gss_OID_set indicated = GSS_C_NULL_OID_SET; 677c478bd9Sstevel@tonic-gate gss_OID_set acquired, supported; 687c478bd9Sstevel@tonic-gate gss_OID mech; 697c478bd9Sstevel@tonic-gate gss_cred_id_t creds; 707c478bd9Sstevel@tonic-gate Gssctxt *ctxt = NULL; 717c478bd9Sstevel@tonic-gate gss_buffer_desc tok; 727c478bd9Sstevel@tonic-gate OM_uint32 maj, min; 737c478bd9Sstevel@tonic-gate int i; 74*9a8058b5Sjp161948 char *errmsg; 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gate if (!mechs) 777c478bd9Sstevel@tonic-gate return; 787c478bd9Sstevel@tonic-gate *mechs = GSS_C_NULL_OID_SET; 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate maj = gss_indicate_mechs(&min, &indicated); 817c478bd9Sstevel@tonic-gate if (GSS_ERROR(maj)) { 827c478bd9Sstevel@tonic-gate debug("No GSS-API mechanisms are installed"); 837c478bd9Sstevel@tonic-gate return; 847c478bd9Sstevel@tonic-gate } 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate maj = gss_create_empty_oid_set(&min, &supported); 877c478bd9Sstevel@tonic-gate if (GSS_ERROR(maj)) { 88*9a8058b5Sjp161948 errmsg = ssh_gssapi_last_error(NULL, &maj, &min); 89*9a8058b5Sjp161948 debug("Failed to allocate resources (%s) for GSS-API", errmsg); 90*9a8058b5Sjp161948 xfree(errmsg); 917c478bd9Sstevel@tonic-gate (void) gss_release_oid_set(&min, &indicated); 927c478bd9Sstevel@tonic-gate return; 937c478bd9Sstevel@tonic-gate } 947c478bd9Sstevel@tonic-gate maj = gss_acquire_cred(&min, GSS_C_NO_NAME, 0, indicated, 957c478bd9Sstevel@tonic-gate GSS_C_INITIATE, &creds, &acquired, NULL); 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate if (GSS_ERROR(maj)) { 98*9a8058b5Sjp161948 errmsg = ssh_gssapi_last_error(NULL, &maj, &min); 997c478bd9Sstevel@tonic-gate debug("Failed to acquire GSS-API credentials for any " 100*9a8058b5Sjp161948 "mechanisms (%s)", errmsg); 101*9a8058b5Sjp161948 xfree(errmsg); 1027c478bd9Sstevel@tonic-gate (void) gss_release_oid_set(&min, &indicated); 1037c478bd9Sstevel@tonic-gate (void) gss_release_oid_set(&min, &supported); 1047c478bd9Sstevel@tonic-gate return; 1057c478bd9Sstevel@tonic-gate } 1067c478bd9Sstevel@tonic-gate (void) gss_release_cred(&min, &creds); 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gate for (i = 0 ; i < acquired->count ; i++) { 1097c478bd9Sstevel@tonic-gate mech = &acquired->elements[i]; 1107c478bd9Sstevel@tonic-gate 1117c478bd9Sstevel@tonic-gate if (ssh_gssapi_is_spnego(mech)) 1127c478bd9Sstevel@tonic-gate continue; 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate ssh_gssapi_build_ctx(&ctxt, 1, mech); 1157c478bd9Sstevel@tonic-gate if (!ctxt) 1167c478bd9Sstevel@tonic-gate continue; 1177c478bd9Sstevel@tonic-gate 1187c478bd9Sstevel@tonic-gate /* 1197c478bd9Sstevel@tonic-gate * This is useful for mechs like Kerberos, which can 1207c478bd9Sstevel@tonic-gate * detect unknown target princs here, but not for 1217c478bd9Sstevel@tonic-gate * mechs like SPKM, which cannot detect unknown princs 1227c478bd9Sstevel@tonic-gate * until context tokens are actually exchanged. 1237c478bd9Sstevel@tonic-gate * 1247c478bd9Sstevel@tonic-gate * 'Twould be useful to have a test that could save us 1257c478bd9Sstevel@tonic-gate * the bother of trying this for SPKM and the such... 1267c478bd9Sstevel@tonic-gate */ 1277c478bd9Sstevel@tonic-gate maj = ssh_gssapi_init_ctx(ctxt, server_host, 0, 1287c478bd9Sstevel@tonic-gate NULL, &tok); 1297c478bd9Sstevel@tonic-gate if (GSS_ERROR(maj)) { 130*9a8058b5Sjp161948 errmsg = ssh_gssapi_last_error(ctxt, NULL, NULL); 1317c478bd9Sstevel@tonic-gate debug("Skipping GSS-API mechanism %s (%s)", 132*9a8058b5Sjp161948 ssh_gssapi_oid_to_name(mech), errmsg); 133*9a8058b5Sjp161948 xfree(errmsg); 1347c478bd9Sstevel@tonic-gate continue; 1357c478bd9Sstevel@tonic-gate } 1367c478bd9Sstevel@tonic-gate 1377c478bd9Sstevel@tonic-gate (void) gss_release_buffer(&min, &tok); 1387c478bd9Sstevel@tonic-gate 1397c478bd9Sstevel@tonic-gate maj = gss_add_oid_set_member(&min, mech, &supported); 140*9a8058b5Sjp161948 if (GSS_ERROR(maj)) { 141*9a8058b5Sjp161948 errmsg = ssh_gssapi_last_error(NULL, &maj, &min); 1427c478bd9Sstevel@tonic-gate debug("Failed to allocate resources (%s) for GSS-API", 143*9a8058b5Sjp161948 errmsg); 144*9a8058b5Sjp161948 xfree(errmsg); 145*9a8058b5Sjp161948 } 1467c478bd9Sstevel@tonic-gate } 1477c478bd9Sstevel@tonic-gate 1487c478bd9Sstevel@tonic-gate *mechs = supported; 1497c478bd9Sstevel@tonic-gate } 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate 1527c478bd9Sstevel@tonic-gate /* Wrapper to init_sec_context 1537c478bd9Sstevel@tonic-gate * Requires that the context contains: 1547c478bd9Sstevel@tonic-gate * oid 1557c478bd9Sstevel@tonic-gate * server name (from ssh_gssapi_import_name) 1567c478bd9Sstevel@tonic-gate */ 1577c478bd9Sstevel@tonic-gate OM_uint32 1587c478bd9Sstevel@tonic-gate ssh_gssapi_init_ctx(Gssctxt *ctx, const char *server_host, int deleg_creds, 1597c478bd9Sstevel@tonic-gate gss_buffer_t recv_tok, gss_buffer_t send_tok) 1607c478bd9Sstevel@tonic-gate { 1617c478bd9Sstevel@tonic-gate int flags = GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG; 1627c478bd9Sstevel@tonic-gate 1637c478bd9Sstevel@tonic-gate debug("%s(%p, %s, %d, %p, %p)", __func__, ctx, server_host, 1647c478bd9Sstevel@tonic-gate deleg_creds, recv_tok, send_tok); 1657c478bd9Sstevel@tonic-gate 1667c478bd9Sstevel@tonic-gate if (deleg_creds) { 1677c478bd9Sstevel@tonic-gate flags |= GSS_C_DELEG_FLAG; 1687c478bd9Sstevel@tonic-gate debug("Delegating GSS-API credentials"); 1697c478bd9Sstevel@tonic-gate } 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gate /* Build target principal */ 1727c478bd9Sstevel@tonic-gate if (ctx->desired_name == GSS_C_NO_NAME && 1737c478bd9Sstevel@tonic-gate !ssh_gssapi_import_name(ctx, server_host)) 1747c478bd9Sstevel@tonic-gate return ctx->major; 1757c478bd9Sstevel@tonic-gate 1767c478bd9Sstevel@tonic-gate ctx->major=gss_init_sec_context(&ctx->minor, 1777c478bd9Sstevel@tonic-gate GSS_C_NO_CREDENTIAL, 1787c478bd9Sstevel@tonic-gate &ctx->context, 1797c478bd9Sstevel@tonic-gate ctx->desired_name, 1807c478bd9Sstevel@tonic-gate ctx->desired_mech, 1817c478bd9Sstevel@tonic-gate flags, 1827c478bd9Sstevel@tonic-gate 0, /* default lifetime */ 1837c478bd9Sstevel@tonic-gate NULL, /* no channel bindings */ 1847c478bd9Sstevel@tonic-gate recv_tok, 1857c478bd9Sstevel@tonic-gate NULL, /* actual mech type */ 1867c478bd9Sstevel@tonic-gate send_tok, 1877c478bd9Sstevel@tonic-gate &ctx->flags, 1887c478bd9Sstevel@tonic-gate NULL); /* actual lifetime */ 1897c478bd9Sstevel@tonic-gate 1907c478bd9Sstevel@tonic-gate if (GSS_ERROR(ctx->major)) 1917c478bd9Sstevel@tonic-gate ssh_gssapi_error(ctx, "calling GSS_Init_sec_context()"); 1927c478bd9Sstevel@tonic-gate 1937c478bd9Sstevel@tonic-gate return(ctx->major); 1947c478bd9Sstevel@tonic-gate } 1957c478bd9Sstevel@tonic-gate #endif /* GSSAPI */ 196