summaryrefslogtreecommitdiff
path: root/usr/src/cmd/ssh/libssh/common/ssh-gss.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/ssh/libssh/common/ssh-gss.c')
-rw-r--r--usr/src/cmd/ssh/libssh/common/ssh-gss.c782
1 files changed, 0 insertions, 782 deletions
diff --git a/usr/src/cmd/ssh/libssh/common/ssh-gss.c b/usr/src/cmd/ssh/libssh/common/ssh-gss.c
deleted file mode 100644
index 37aeb04873..0000000000
--- a/usr/src/cmd/ssh/libssh/common/ssh-gss.c
+++ /dev/null
@@ -1,782 +0,0 @@
-/*
- * 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.
- */
-/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#include "includes.h"
-
-#ifdef GSSAPI
-
-#include "ssh.h"
-#include "ssh2.h"
-#include "xmalloc.h"
-#include "buffer.h"
-#include "bufaux.h"
-#include "packet.h"
-#include "compat.h"
-#include <openssl/evp.h>
-#include "cipher.h"
-#include "kex.h"
-#include "log.h"
-#include "compat.h"
-#include "xlist.h"
-
-#include <netdb.h>
-
-#include "ssh-gss.h"
-
-#ifdef HAVE_GSS_OID_TO_MECH
-#include <gssapi/gssapi_ext.h>
-#endif /* HAVE_GSS_OID_TO_MECH */
-
-typedef struct {
- char *encoded;
- gss_OID oid;
-} ssh_gss_kex_mapping;
-
-static ssh_gss_kex_mapping **gss_enc2oid = NULL;
-
-static void ssh_gssapi_encode_oid_for_kex(const gss_OID oid, char **enc_name);
-static char *ssh_gssapi_make_kexalgs_list(gss_OID_set mechs,
- const char *old_kexalgs);
-
-/*
- * Populate gss_enc2oid table and return list of kexnames.
- *
- * If called with both mechs == GSS_C_NULL_OID_SET and kexname_list == NULL
- * then cached gss_enc2oid table is cleaned up.
- */
-void
-ssh_gssapi_mech_oids_to_kexnames(const gss_OID_set mechs, char **kexname_list)
-{
- ssh_gss_kex_mapping **new_gss_enc2oid, **p;
- Buffer buf;
- char *enc_name;
- int i;
-
- if (kexname_list != NULL)
- *kexname_list = NULL; /* default to failed */
-
- if (mechs != GSS_C_NULL_OID_SET || kexname_list == NULL) {
- /* Cleanup gss_enc2oid table */
- for (p = gss_enc2oid; p != NULL && *p != NULL; p++) {
- if ((*p)->encoded)
- xfree((*p)->encoded);
- ssh_gssapi_release_oid(&(*p)->oid);
- xfree(*p);
- }
- if (gss_enc2oid)
- xfree(gss_enc2oid);
- }
-
- if (mechs == GSS_C_NULL_OID_SET && kexname_list == NULL)
- return; /* nothing left to do */
-
- if (mechs) {
- gss_OID mech;
- /* Populate gss_enc2oid table */
- new_gss_enc2oid = xmalloc(sizeof (ssh_gss_kex_mapping *) *
- (mechs->count + 1));
- memset(new_gss_enc2oid, 0,
- sizeof (ssh_gss_kex_mapping *) * (mechs->count + 1));
-
- for (i = 0; i < mechs->count; i++) {
- mech = &mechs->elements[i];
- ssh_gssapi_encode_oid_for_kex((const gss_OID)mech,
- &enc_name);
-
- if (!enc_name)
- continue;
-
- new_gss_enc2oid[i] =
- xmalloc(sizeof (ssh_gss_kex_mapping));
- (new_gss_enc2oid[i])->encoded = enc_name;
- (new_gss_enc2oid[i])->oid =
- ssh_gssapi_dup_oid(&mechs->elements[i]);
- }
-
- /* Do this last to avoid run-ins with fatal_cleanups */
- gss_enc2oid = new_gss_enc2oid;
- }
-
- if (!kexname_list)
- return; /* nothing left to do */
-
- /* Make kex name list */
- buffer_init(&buf);
- for (p = gss_enc2oid; p && *p; p++) {
- buffer_put_char(&buf, ',');
- buffer_append(&buf, (*p)->encoded, strlen((*p)->encoded));
- }
-
- if (buffer_len(&buf) == 0) {
- buffer_free(&buf);
- return;
- }
-
- buffer_consume(&buf, 1); /* consume leading ',' */
- buffer_put_char(&buf, '\0');
-
- *kexname_list = xstrdup(buffer_ptr(&buf));
- buffer_free(&buf);
-}
-
-void
-ssh_gssapi_mech_oid_to_kexname(const gss_OID mech, char **kexname)
-{
- ssh_gss_kex_mapping **p;
-
- if (mech == GSS_C_NULL_OID || !kexname)
- return;
-
- *kexname = NULL; /* default to not found */
- if (gss_enc2oid) {
- for (p = gss_enc2oid; p && *p; p++) {
- if (mech->length == (*p)->oid->length &&
- memcmp(mech->elements, (*p)->oid->elements,
- mech->length) == 0)
- *kexname = xstrdup((*p)->encoded);
- }
- }
-
- if (*kexname)
- return; /* found */
-
- ssh_gssapi_encode_oid_for_kex(mech, kexname);
-}
-
-void
-ssh_gssapi_oid_of_kexname(const char *kexname, gss_OID *mech)
-{
- ssh_gss_kex_mapping **p;
-
- if (!mech || !kexname || !*kexname)
- return;
-
- *mech = GSS_C_NULL_OID; /* default to not found */
-
- if (!gss_enc2oid)
- return;
-
- for (p = gss_enc2oid; p && *p; p++) {
- if (strcmp(kexname, (*p)->encoded) == 0) {
- *mech = (*p)->oid;
- return;
- }
- }
-}
-
-static
-void
-ssh_gssapi_encode_oid_for_kex(const gss_OID oid, char **enc_name)
-{
- Buffer buf;
- OM_uint32 oidlen;
- uint_t enclen;
- const EVP_MD *evp_md = EVP_md5();
- EVP_MD_CTX md;
- uchar_t digest[EVP_MAX_MD_SIZE];
- char *encoded;
-
- if (oid == GSS_C_NULL_OID || !enc_name)
- return;
-
- *enc_name = NULL;
-
- oidlen = oid->length;
-
- /* No GSS mechs have OIDs as long as 128 -- simplify DER encoding */
- if (oidlen > 128)
- return; /* fail gracefully */
-
- /*
- * NOTE: If we need to support SSH_BUG_GSSAPI_BER this is where
- * we'd do it.
- *
- * That means using "Se3H81ismmOC3OE+FwYCiQ==" for the Kerberos
- * V mech and "N3+k7/4wGxHyuP8Yxi4RhA==" for the GSI mech. Ick.
- */
-
- buffer_init(&buf);
-
- /* UNIVERSAL class tag for OBJECT IDENTIFIER */
- buffer_put_char(&buf, 0x06);
- buffer_put_char(&buf, oidlen); /* one octet DER length -- see above */
-
- /* OID elements */
- buffer_append(&buf, oid->elements, oidlen);
-
- /* Make digest */
- EVP_DigestInit(&md, evp_md);
- EVP_DigestUpdate(&md, buffer_ptr(&buf), buffer_len(&buf));
- EVP_DigestFinal(&md, digest, NULL);
- buffer_free(&buf);
-
- /* Base 64 encoding */
- encoded = xmalloc(EVP_MD_size(evp_md)*2);
- enclen = __b64_ntop(digest, EVP_MD_size(evp_md),
- encoded, EVP_MD_size(evp_md) * 2);
- buffer_init(&buf);
- buffer_append(&buf, KEX_GSS_SHA1, sizeof (KEX_GSS_SHA1) - 1);
- buffer_append(&buf, encoded, enclen);
- buffer_put_char(&buf, '\0');
-
- debug2("GSS-API Mechanism encoded as %s", encoded);
- xfree(encoded);
-
- *enc_name = xstrdup(buffer_ptr(&buf));
- buffer_free(&buf);
-}
-
-static char *
-ssh_gssapi_make_kexalgs_list(gss_OID_set mechs, const char *old_kexalgs)
-{
- char *gss_kexalgs, *new_kexalgs;
- int len;
-
- if (mechs == GSS_C_NULL_OID_SET)
- return (xstrdup(old_kexalgs)); /* never null */
-
- ssh_gssapi_mech_oids_to_kexnames(mechs, &gss_kexalgs);
-
- if (gss_kexalgs == NULL || *gss_kexalgs == '\0')
- return (xstrdup(old_kexalgs)); /* never null */
-
- if (old_kexalgs == NULL || *old_kexalgs == '\0')
- return (gss_kexalgs);
-
- len = strlen(old_kexalgs) + strlen(gss_kexalgs) + 2;
- new_kexalgs = xmalloc(len);
- (void) snprintf(new_kexalgs, len, "%s,%s", gss_kexalgs, old_kexalgs);
- xfree(gss_kexalgs);
-
- return (new_kexalgs);
-}
-
-void
-ssh_gssapi_modify_kex(Kex *kex, gss_OID_set mechs, char **proposal)
-{
- char *kexalgs, *orig_kexalgs, *p;
- char **hostalg, *orig_hostalgs, *new_hostalgs;
- char **hostalgs;
- gss_OID_set dup_mechs;
- OM_uint32 maj, min;
- int i;
-
- if (kex == NULL || proposal == NULL ||
- proposal[PROPOSAL_KEX_ALGS] == NULL) {
- fatal("INTERNAL ERROR (%s)", __func__);
- }
-
- orig_hostalgs = proposal[PROPOSAL_SERVER_HOST_KEY_ALGS];
-
- if (kex->mechs == GSS_C_NULL_OID_SET && mechs == GSS_C_NULL_OID_SET)
- return; /* didn't offer GSS last time, not offering now */
-
- if (kex->mechs == GSS_C_NULL_OID_SET || mechs == GSS_C_NULL_OID_SET)
- goto mod_offer; /* didn't offer last time or not offering now */
-
- /* Check if mechs is congruent to kex->mechs (last offered) */
- if (kex->mechs->count == mechs->count) {
- int present, matches = 0;
-
- for (i = 0; i < mechs->count; i++) {
- maj = gss_test_oid_set_member(&min,
- &kex->mechs->elements[i], mechs, &present);
-
- if (GSS_ERROR(maj)) {
- mechs = GSS_C_NULL_OID_SET;
- break;
- }
-
- matches += (present) ? 1 : 0;
- }
-
- if (matches == kex->mechs->count)
- return; /* no change in offer from last time */
- }
-
-mod_offer:
- /*
- * Remove previously offered mechs from PROPOSAL_KEX_ALGS proposal
- *
- * ASSUMPTION: GSS-API kex algs always go in front, so removing
- * them is a matter of skipping them.
- */
- p = kexalgs = orig_kexalgs = proposal[PROPOSAL_KEX_ALGS];
- while (p != NULL && *p != '\0' &&
- strncmp(p, KEX_GSS_SHA1, strlen(KEX_GSS_SHA1)) == 0) {
-
- if ((p = strchr(p, ',')) == NULL)
- break;
- p++;
- kexalgs = p;
-
- }
- kexalgs = proposal[PROPOSAL_KEX_ALGS] = xstrdup(kexalgs);
- xfree(orig_kexalgs);
-
- (void) gss_release_oid_set(&min, &kex->mechs); /* ok if !kex->mechs */
-
- /* Not offering GSS kex algorithms now -> all done */
- if (mechs == GSS_C_NULL_OID_SET)
- return;
-
- /* Remember mechs we're offering */
- maj = gss_create_empty_oid_set(&min, &dup_mechs);
- if (GSS_ERROR(maj))
- return;
- for (i = 0; i < mechs->count; i++) {
- maj = gss_add_oid_set_member(&min, &mechs->elements[i],
- &dup_mechs);
-
- if (GSS_ERROR(maj)) {
- (void) gss_release_oid_set(&min, &dup_mechs);
- return;
- }
- }
-
- /* Add mechs to kex algorithms ... */
- proposal[PROPOSAL_KEX_ALGS] = ssh_gssapi_make_kexalgs_list(mechs,
- kexalgs);
- xfree(kexalgs);
- kex->mechs = dup_mechs; /* remember what we offer now */
-
- /*
- * ... and add null host key alg, if it wasn't there before, but
- * not if we're the server and we have other host key algs to
- * offer.
- *
- * NOTE: Never remove "null" host key alg once added.
- */
- if (orig_hostalgs == NULL || *orig_hostalgs == '\0') {
- proposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = xstrdup("null");
- } else if (!kex->server) {
- hostalgs = xsplit(orig_hostalgs, ',');
- for (hostalg = hostalgs; *hostalg != NULL; hostalg++) {
- if (strcmp(*hostalg, "null") == 0) {
- xfree_split_list(hostalgs);
- return;
- }
- }
- xfree_split_list(hostalgs);
-
- if (kex->mechs != GSS_C_NULL_OID_SET) {
- int len;
-
- len = strlen(orig_hostalgs) + sizeof (",null");
- new_hostalgs = xmalloc(len);
- (void) snprintf(new_hostalgs, len, "%s,null",
- orig_hostalgs);
- proposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = new_hostalgs;
- }
-
- xfree(orig_hostalgs);
- }
-}
-
-/*
- * Yes, we harcode OIDs for some things, for now it's all we can do.
- *
- * We have to reference particular mechanisms due to lack of generality
- * in the GSS-API in several areas: authorization, mapping principal
- * names to usernames, "storing" delegated credentials, and discovering
- * whether a mechanism is a pseudo-mechanism that negotiates mechanisms.
- *
- * Even if they were in some header file or if __gss_mech_to_oid()
- * and/or __gss_oid_to_mech() were standard we'd still have to hardcode
- * the mechanism names, and since the mechanisms have no standard names
- * other than their OIDs it's actually worse [less portable] to hardcode
- * names than OIDs, so we hardcode OIDs.
- *
- * SPNEGO is a difficult problem though -- it MUST NOT be used in SSHv2,
- * but that's true of all possible pseudo-mechanisms that can perform
- * mechanism negotiation, and SPNEGO could have new OIDs in the future.
- * Ideally we could query each mechanism for its feature set and then
- * ignore any mechanisms that negotiate mechanisms, but, alas, there's
- * no interface to do that.
- *
- * In the future, if the necessary generic GSS interfaces for the issues
- * listed above are made available (even if they differ by platform, as
- * we can expect authorization interfaces will), then we can stop
- * referencing specific mechanism OIDs here.
- */
-int
-ssh_gssapi_is_spnego(gss_OID oid)
-{
- return (oid->length == 6 &&
- memcmp("\053\006\001\005\005\002", oid->elements, 6) == 0);
-}
-
-int
-ssh_gssapi_is_krb5(gss_OID oid)
-{
- return (oid->length == 9 &&
- memcmp("\x2A\x86\x48\x86\xF7\x12\x01\x02\x02",
- oid->elements, 9) == 0);
-}
-
-int
-ssh_gssapi_is_dh(gss_OID oid)
-{
- return (oid->length == 9 &&
- memcmp("\053\006\004\001\052\002\032\002\005",
- oid->elements, 9) == 0);
-}
-
-int
-ssh_gssapi_is_gsi(gss_OID oid)
-{
- return (oid->length == 9 &&
- memcmp("\x2B\x06\x01\x04\x01\x9B\x50\x01\x01",
- oid->elements, 9) == 0);
-}
-
-const char *
-ssh_gssapi_oid_to_name(gss_OID oid)
-{
-#ifdef HAVE_GSS_OID_TO_MECH
- return (__gss_oid_to_mech(oid));
-#else
- if (ssh_gssapi_is_krb5(oid))
- return ("Kerberos");
- if (ssh_gssapi_is_gsi(oid))
- return ("GSI");
- return ("(unknown)");
-#endif /* HAVE_GSS_OID_TO_MECH */
-}
-
-char *
-ssh_gssapi_oid_to_str(gss_OID oid)
-{
-#ifdef HAVE_GSS_OID_TO_STR
- gss_buffer_desc str_buf;
- char *str;
- OM_uint32 maj, min;
-
- maj = gss_oid_to_str(&min, oid, &str_buf);
-
- if (GSS_ERROR(maj))
- return (xstrdup("<gss_oid_to_str() failed>"));
-
- str = xmalloc(str_buf.length + 1);
- memset(str, 0, str_buf.length + 1);
- strlcpy(str, str_buf.value, str_buf.length + 1);
- (void) gss_release_buffer(&min, &str_buf);
-
- return (str);
-#else
- return (xstrdup("<gss_oid_to_str() unsupported>"));
-#endif /* HAVE_GSS_OID_TO_STR */
-}
-
-/* Check that the OID in a data stream matches that in the context */
-int
-ssh_gssapi_check_mech_oid(Gssctxt *ctx, void *data, size_t len)
-{
-
- return (ctx != NULL && ctx->desired_mech != GSS_C_NULL_OID &&
- ctx->desired_mech->length == len &&
- memcmp(ctx->desired_mech->elements, data, len) == 0);
-}
-
-/* Set the contexts OID from a data stream */
-void
-ssh_gssapi_set_oid_data(Gssctxt *ctx, void *data, size_t len)
-{
- if (ctx->actual_mech != GSS_C_NULL_OID) {
- xfree(ctx->actual_mech->elements);
- xfree(ctx->actual_mech);
- }
- ctx->actual_mech = xmalloc(sizeof (gss_OID_desc));
- ctx->actual_mech->length = len;
- ctx->actual_mech->elements = xmalloc(len);
- memcpy(ctx->actual_mech->elements, data, len);
-}
-
-/* Set the contexts OID */
-void
-ssh_gssapi_set_oid(Gssctxt *ctx, gss_OID oid)
-{
- ssh_gssapi_set_oid_data(ctx, oid->elements, oid->length);
-}
-
-/* All this effort to report an error ... */
-
-void
-ssh_gssapi_error(Gssctxt *ctxt, const char *where)
-{
- char *errmsg = ssh_gssapi_last_error(ctxt, NULL, NULL);
-
- if (where != NULL)
- debug("GSS-API error while %s: %s", where, errmsg);
- else
- debug("GSS-API error: %s", errmsg);
-
- /* ssh_gssapi_last_error() can't return NULL */
- xfree(errmsg);
-}
-
-char *
-ssh_gssapi_last_error(Gssctxt *ctxt, OM_uint32 *major_status,
- OM_uint32 *minor_status)
-{
- OM_uint32 lmin, more;
- OM_uint32 maj, min;
- gss_OID mech = GSS_C_NULL_OID;
- gss_buffer_desc msg;
- Buffer b;
- char *ret;
-
- buffer_init(&b);
-
- if (ctxt) {
- /* Get status codes from the Gssctxt */
- maj = ctxt->major;
- min = ctxt->minor;
- /* Output them if desired */
- if (major_status)
- *major_status = maj;
- if (minor_status)
- *minor_status = min;
- /* Get mechanism for minor status display */
- mech = (ctxt->actual_mech != GSS_C_NULL_OID) ?
- ctxt->actual_mech : ctxt->desired_mech;
- } else if (major_status && minor_status) {
- maj = *major_status;
- min = *major_status;
- } else {
- maj = GSS_S_COMPLETE;
- min = 0;
- }
-
- more = 0;
- /* The GSSAPI error */
- do {
- gss_display_status(&lmin, maj, GSS_C_GSS_CODE,
- GSS_C_NULL_OID, &more, &msg);
-
- buffer_append(&b, msg.value, msg.length);
- buffer_put_char(&b, '\n');
- gss_release_buffer(&lmin, &msg);
- } while (more != 0);
-
- /* The mechanism specific error */
- do {
- /*
- * If mech == GSS_C_NULL_OID we may get the default
- * mechanism, whatever that is, and that may not be
- * useful.
- */
- gss_display_status(&lmin, min, GSS_C_MECH_CODE, mech, &more,
- &msg);
-
- buffer_append(&b, msg.value, msg.length);
- buffer_put_char(&b, '\n');
-
- gss_release_buffer(&lmin, &msg);
- } while (more != 0);
-
- buffer_put_char(&b, '\0');
- ret = xstrdup(buffer_ptr(&b));
- buffer_free(&b);
-
- return (ret);
-}
-
-/*
- * Initialise our GSSAPI context. We use this opaque structure to contain all
- * of the data which both the client and server need to persist across
- * {accept,init}_sec_context calls, so that when we do it from the userauth
- * stuff life is a little easier
- */
-void
-ssh_gssapi_build_ctx(Gssctxt **ctx, int client, gss_OID mech)
-{
- Gssctxt *newctx;
-
-
- newctx = (Gssctxt*)xmalloc(sizeof (Gssctxt));
- memset(newctx, 0, sizeof (Gssctxt));
-
-
- newctx->local = client;
- newctx->desired_mech = ssh_gssapi_dup_oid(mech);
-
- /* This happens to be redundant given the memset() above */
- newctx->major = GSS_S_COMPLETE;
- newctx->context = GSS_C_NO_CONTEXT;
- newctx->actual_mech = GSS_C_NULL_OID;
- newctx->desired_name = GSS_C_NO_NAME;
- newctx->src_name = GSS_C_NO_NAME;
- newctx->dst_name = GSS_C_NO_NAME;
- newctx->creds = GSS_C_NO_CREDENTIAL;
- newctx->deleg_creds = GSS_C_NO_CREDENTIAL;
-
- newctx->default_creds = (*ctx != NULL) ? (*ctx)->default_creds : 0;
-
- ssh_gssapi_delete_ctx(ctx);
-
- *ctx = newctx;
-}
-
-gss_OID
-ssh_gssapi_dup_oid(gss_OID oid)
-{
- gss_OID new_oid;
-
- new_oid = xmalloc(sizeof (gss_OID_desc));
-
- new_oid->elements = xmalloc(oid->length);
- new_oid->length = oid->length;
- memcpy(new_oid->elements, oid->elements, oid->length);
-
- return (new_oid);
-}
-
-gss_OID
-ssh_gssapi_make_oid(size_t length, void *elements)
-{
- gss_OID_desc oid;
-
- oid.length = length;
- oid.elements = elements;
-
- return (ssh_gssapi_dup_oid(&oid));
-}
-
-void
-ssh_gssapi_release_oid(gss_OID *oid)
-{
- OM_uint32 min;
-
- if (oid && *oid == GSS_C_NULL_OID)
- return;
- (void) gss_release_oid(&min, oid);
-
- if (*oid == GSS_C_NULL_OID)
- return; /* libgss did own this gss_OID and released it */
-
- xfree((*oid)->elements);
- xfree(*oid);
- *oid = GSS_C_NULL_OID;
-}
-
-struct gss_name {
- gss_OID name_type;
- gss_buffer_t external_name;
- gss_OID mech_type;
- void *mech_name;
-};
-
-/* Delete our context, providing it has been built correctly */
-void
-ssh_gssapi_delete_ctx(Gssctxt **ctx)
-{
- OM_uint32 ms;
-
- if ((*ctx) == NULL)
- return;
-
- if ((*ctx)->context != GSS_C_NO_CONTEXT)
- gss_delete_sec_context(&ms, &(*ctx)->context, GSS_C_NO_BUFFER);
-#if 0
- /* XXX */
- if ((*ctx)->desired_mech != GSS_C_NULL_OID)
- ssh_gssapi_release_oid(&(*ctx)->desired_mech);
-#endif
- if ((*ctx)->actual_mech != GSS_C_NULL_OID)
- (void) ssh_gssapi_release_oid(&(*ctx)->actual_mech);
- if ((*ctx)->desired_name != GSS_C_NO_NAME)
- gss_release_name(&ms, &(*ctx)->desired_name);
-#if 0
- if ((*ctx)->src_name != GSS_C_NO_NAME)
- gss_release_name(&ms, &(*ctx)->src_name);
-#endif
- if ((*ctx)->dst_name != GSS_C_NO_NAME)
- gss_release_name(&ms, &(*ctx)->dst_name);
- if ((*ctx)->creds != GSS_C_NO_CREDENTIAL)
- gss_release_cred(&ms, &(*ctx)->creds);
- if ((*ctx)->deleg_creds != GSS_C_NO_CREDENTIAL)
- gss_release_cred(&ms, &(*ctx)->deleg_creds);
-
- xfree(*ctx);
- *ctx = NULL;
-}
-
-/* Create a GSS hostbased service principal name for a given server hostname */
-int
-ssh_gssapi_import_name(Gssctxt *ctx, const char *server_host)
-{
- gss_buffer_desc name_buf;
- int ret;
-
- /* Build target principal */
- name_buf.length = strlen(SSH_GSS_HOSTBASED_SERVICE) +
- strlen(server_host) + 1; /* +1 for '@' */
- name_buf.value = xmalloc(name_buf.length + 1); /* +1 for NUL */
- ret = snprintf(name_buf.value, name_buf.length + 1, "%s@%s",
- SSH_GSS_HOSTBASED_SERVICE, server_host);
-
- debug3("%s: snprintf() returned %d, expected %d", __func__, ret,
- name_buf.length);
-
- ctx->major = gss_import_name(&ctx->minor, &name_buf,
- GSS_C_NT_HOSTBASED_SERVICE, &ctx->desired_name);
-
- if (GSS_ERROR(ctx->major)) {
- ssh_gssapi_error(ctx, "calling GSS_Import_name()");
- return (0);
- }
-
- xfree(name_buf.value);
-
- return (1);
-}
-
-OM_uint32
-ssh_gssapi_get_mic(Gssctxt *ctx, gss_buffer_desc *buffer, gss_buffer_desc *hash)
-{
-
- ctx->major = gss_get_mic(&ctx->minor, ctx->context,
- GSS_C_QOP_DEFAULT, buffer, hash);
- if (GSS_ERROR(ctx->major))
- ssh_gssapi_error(ctx, "while getting MIC");
- return (ctx->major);
-}
-
-OM_uint32
-ssh_gssapi_verify_mic(Gssctxt *ctx, gss_buffer_desc *buffer,
- gss_buffer_desc *hash)
-{
- gss_qop_t qop;
-
- ctx->major = gss_verify_mic(&ctx->minor, ctx->context, buffer,
- hash, &qop);
- if (GSS_ERROR(ctx->major))
- ssh_gssapi_error(ctx, "while verifying MIC");
- return (ctx->major);
-}
-#endif /* GSSAPI */