2N/A/*
2N/A * Copyright 1993 by OpenVision Technologies, Inc.
2N/A *
2N/A * Permission to use, copy, modify, distribute, and sell this software
2N/A * and its documentation for any purpose is hereby granted without fee,
2N/A * provided that the above copyright notice appears in all copies and
2N/A * that both that copyright notice and this permission notice appear in
2N/A * supporting documentation, and that the name of OpenVision not be used
2N/A * in advertising or publicity pertaining to distribution of the software
2N/A * without specific, written prior permission. OpenVision makes no
2N/A * representations about the suitability of this software for any
2N/A * purpose. It is provided "as is" without express or implied warranty.
2N/A *
2N/A * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
2N/A * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
2N/A * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
2N/A * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
2N/A * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
2N/A * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
2N/A * PERFORMANCE OF THIS SOFTWARE.
2N/A */
2N/A
2N/A/*
2N/A * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
2N/A */
2N/A
2N/A#include <sys/param.h>
2N/A#include <unistd.h>
2N/A#include <assert.h>
2N/A#include <stdio.h>
2N/A#include <stdlib.h>
2N/A#include <string.h>
2N/A#include <k5-int.h>
2N/A#include <krb5.h>
2N/A#include <mglueP.h>
2N/A#include "gssapiP_spnego.h"
2N/A#include "gssapiP_generic.h"
2N/A#include <gssapi_err_generic.h>
2N/A
2N/A/* X internationalization!! */
2N/A
2N/Astatic inline int
2N/Acompare_OM_uint32 (OM_uint32 a, OM_uint32 b)
2N/A{
2N/A if (a < b)
2N/A return -1;
2N/A else if (a == b)
2N/A return 0;
2N/A else
2N/A return 1;
2N/A}
2N/Astatic inline void
2N/Afree_string (char *s)
2N/A{
2N/A free(s);
2N/A}
2N/A#include "error_map.h"
2N/A#include <stdio.h>
2N/A
2N/A#define get_error_message spnego_gss_get_error_message
2N/Achar *get_error_message(OM_uint32 minor_code)
2N/A{
2N/A gsserrmap *p = k5_getspecific(K5_KEY_GSS_SPNEGO_ERROR_MESSAGE);
2N/A char *msg = NULL;
2N/A
2N/A#ifdef DEBUG
2N/A fprintf(stderr, "%s(%lu, p=%p)", __func__, (unsigned long) minor_code,
2N/A (void *) p);
2N/A#endif
2N/A if (p) {
2N/A char **v = gsserrmap_find(p, minor_code);
2N/A if (v) {
2N/A msg = *v;
2N/A#ifdef DEBUG
2N/A fprintf(stderr, " FOUND!");
2N/A#endif
2N/A }
2N/A }
2N/A if (msg == 0)
2N/A msg = (char *)error_message(minor_code);
2N/A#ifdef DEBUG
2N/A fprintf(stderr, " -> %p/%s\n", (void *) msg, msg);
2N/A#endif
2N/A
2N/A return msg;
2N/A}
2N/A
2N/Astatic int save_error_string_nocopy(OM_uint32 minor_code, char *msg)
2N/A{
2N/A gsserrmap *p;
2N/A int ret;
2N/A
2N/A#ifdef DEBUG
2N/A fprintf(stderr, "%s(%lu, %s)", __func__, (unsigned long) minor_code, msg);
2N/A#endif
2N/A p = k5_getspecific(K5_KEY_GSS_SPNEGO_ERROR_MESSAGE);
2N/A if (!p) {
2N/A p = malloc(sizeof(*p));
2N/A if (p == NULL) {
2N/A ret = 1;
2N/A goto fail;
2N/A }
2N/A if (gsserrmap_init(p) != 0) {
2N/A free(p);
2N/A p = NULL;
2N/A ret = 1;
2N/A goto fail;
2N/A }
2N/A if (k5_setspecific(K5_KEY_GSS_SPNEGO_ERROR_MESSAGE, p) != 0) {
2N/A gsserrmap_destroy(p);
2N/A free(p);
2N/A p = NULL;
2N/A ret = 1;
2N/A goto fail;
2N/A }
2N/A }
2N/A ret = gsserrmap_replace_or_insert(p, minor_code, msg);
2N/A /* Solaris SPNEGO */
2N/A if (ret) {
2N/A gsserrmap_destroy(p);
2N/A free(p);
2N/A p = NULL;
2N/A (void) k5_setspecific(K5_KEY_GSS_SPNEGO_ERROR_MESSAGE, NULL);
2N/A }
2N/A
2N/Afail:
2N/A#ifdef DEBUG
2N/A fprintf(stderr, " p=%p %s\n", (void *)p, ret ? "FAIL" : "SUCCESS");
2N/A#endif
2N/A return ret;
2N/A}
2N/Avoid save_error_string(OM_uint32 minor_code, char *msg)
2N/A{
2N/A char *s = strdup(msg);
2N/A if (s) {
2N/A if (save_error_string_nocopy(minor_code, s) != 0)
2N/A free(s);
2N/A }
2N/A}
2N/Avoid save_error_message(OM_uint32 minor_code, const char *format, ...)
2N/A{
2N/A char *s;
2N/A int n;
2N/A va_list ap;
2N/A
2N/A va_start(ap, format);
2N/A n = vasprintf(&s, format, ap);
2N/A va_end(ap);
2N/A if (n >= 0) {
2N/A if (save_error_string_nocopy(minor_code, s) != 0)
2N/A free(s);
2N/A }
2N/A}
2N/Avoid spnego_gss_save_error_info(OM_uint32 minor_code, spnego_gss_ctx_id_t ctx)
2N/A{
2N/A char *s;
2N/A
2N/A#ifdef DEBUG
2N/A fprintf(stderr, "%s(%lu, ctx=%p)\n", __func__,
2N/A (unsigned long) minor_code, (void *)ctx);
2N/A#endif
2N/A s = (char *)spnego_get_error_message(ctx, minor_code);
2N/A#ifdef DEBUG
2N/A fprintf(stderr, "%s(%lu, ctx=%p) saving: %s\n", __func__,
2N/A (unsigned long) minor_code, (void *)ctx, s);
2N/A#endif
2N/A save_error_string(minor_code, s);
2N/A /* The get_error_message call above resets the error message in
2N/A ctx. Put it back, in case we make this call again *sigh*. */
2N/A spnego_set_error_message(ctx, minor_code, "%s", s);
2N/A spnego_free_error_message(ctx, s);
2N/A}
2N/Avoid spnego_gss_delete_error_info(void *p)
2N/A{
2N/A gsserrmap_destroy(p);
2N/A}
2N/A
2N/AOM_uint32
2N/Aspnego_gss_display_status2(minor_status, status_value, status_type,
2N/A mech_type, message_context, status_string)
2N/A OM_uint32 *minor_status;
2N/A OM_uint32 status_value;
2N/A int status_type;
2N/A gss_OID mech_type;
2N/A OM_uint32 *message_context;
2N/A gss_buffer_t status_string;
2N/A{
2N/A status_string->length = 0;
2N/A status_string->value = NULL;
2N/A
2N/A if ((mech_type != GSS_C_NULL_OID) &&
2N/A !g_OID_equal(gss_mech_spnego, mech_type)) {
2N/A *minor_status = 0;
2N/A return(GSS_S_BAD_MECH);
2N/A }
2N/A
2N/A if (status_type == GSS_C_GSS_CODE) {
2N/A return(g_display_major_status(minor_status, status_value,
2N/A message_context, status_string));
2N/A } else if (status_type == GSS_C_MECH_CODE) {
2N/A /*
2N/A * Solaris SPNEGO
2N/A * This init call appears to be not needed as
2N/A * gss_spnegoint_lib_init() is called on dl open.
2N/A */
2N/A#if 0
2N/A (void) gss_spnegoint_initialize_library();
2N/A#endif
2N/A
2N/A if (*message_context) {
2N/A *minor_status = (OM_uint32) G_BAD_MSG_CTX;
2N/A return(GSS_S_FAILURE);
2N/A }
2N/A
2N/A /* If this fails, there's not much we can do... */
2N/A /* Solaris Kerberos - g_make_string_buffer() returns 0 on failure */
2N/A if (g_make_string_buffer(spnego_gss_get_error_message(status_value),
2N/A status_string) == 0) {
2N/A *minor_status = ENOMEM;
2N/A return(GSS_S_FAILURE);
2N/A } else
2N/A *minor_status = 0;
2N/A return(0);
2N/A } else {
2N/A *minor_status = 0;
2N/A return(GSS_S_BAD_STATUS);
2N/A }
2N/A}