5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry/* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. */
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry/* -*- mode: c; indent-tabs-mode: nil -*- */
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry/*
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry * Copyright 2007, 2008 by the Massachusetts Institute of Technology.
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry * All Rights Reserved.
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry *
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry * Export of this software from the United States of America may
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry * require a specific license from the United States Government.
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry * It is the responsibility of any person or organization contemplating
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry * export to obtain such a license before exporting.
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry *
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry * distribute this software and its documentation for any purpose and
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry * without fee is hereby granted, provided that the above copyright
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry * notice appear in all copies and that both that copyright notice and
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry * this permission notice appear in supporting documentation, and that
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry * the name of M.I.T. not be used in advertising or publicity pertaining
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry * to distribution of the software without specific, written prior
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry * permission. Furthermore if you modify this software you must label
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry * your software as modified software and not distribute it in such a
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry * fashion that it might be confused with the original M.I.T. software.
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry * M.I.T. makes no representations about the suitability of
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry * this software for any purpose. It is provided "as is" without express
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry * or implied warranty.
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry *
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry */
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry#include "gssapiP_generic.h"
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry#include "mechglueP.h"
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry#include <string.h>
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry#include <stdio.h>
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry#ifndef _WIN32
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry#include <unistd.h>
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry#endif
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry/* Solaris Kerberos */
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry#define inline
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry#ifdef DEBUG
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry#undef DEBUG
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry#endif
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry/* The mapping table is 0-based, but let's export codes that are
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry 1-based, keeping 0 for errors or unknown errors.
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry The elements in the mapping table currently have separate copies of
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry each OID stored. This is a bit wasteful, but we are assuming the
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry table isn't likely to grow very large. */
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barrystruct mecherror {
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry gss_OID_desc mech;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry OM_uint32 code;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry};
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barrystatic inline int
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barrycmp_OM_uint32(OM_uint32 m1, OM_uint32 m2)
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry{
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry if (m1 < m2)
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry return -1;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry else if (m1 > m2)
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry return 1;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry else
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry return 0;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry}
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barrystatic inline int
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barrymecherror_cmp(struct mecherror m1, struct mecherror m2)
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry{
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry if (m1.code < m2.code)
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry return -1;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry if (m1.code > m2.code)
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry return 1;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry if (m1.mech.length < m2.mech.length)
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry return -1;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry if (m1.mech.length > m2.mech.length)
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry return 1;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry if (m1.mech.length == 0)
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry return 0;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry return memcmp(m1.mech.elements, m2.mech.elements, m1.mech.length);
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry}
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barrystatic void
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barryprint_OM_uint32 (OM_uint32 value, FILE *f)
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry{
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry fprintf(f, "%lu", (unsigned long) value);
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry}
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barrystatic inline int
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barrymecherror_copy(struct mecherror *dest, struct mecherror src)
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry{
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry *dest = src;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry dest->mech.elements = malloc(src.mech.length);
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry if (dest->mech.elements == NULL) {
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry if (src.mech.length)
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry return ENOMEM;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry else
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry return 0;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry }
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry memcpy(dest->mech.elements, src.mech.elements, src.mech.length);
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry return 0;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry}
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barrystatic void
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barrymecherror_print(struct mecherror value, FILE *f)
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry{
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry OM_uint32 minor;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry gss_buffer_desc str;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry static const struct {
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry const char *oidstr, *name;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry } mechnames[] = {
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry { "{ 1 2 840 113554 1 2 2 }", "krb5-new" },
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry { "{ 1 3 5 1 5 2 }", "krb5-old" },
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry { "{ 1 2 840 48018 1 2 2 }", "krb5-microsoft" },
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry { "{ 1 3 6 1 5 5 2 }", "spnego" },
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry };
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry unsigned int i;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry fprintf(f, "%lu@", (unsigned long) value.code);
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry if (value.mech.length == 0) {
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry fprintf(f, "(com_err)");
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry return;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry }
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry fprintf(f, "%p=", value.mech.elements);
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry if (generic_gss_oid_to_str(&minor, &value.mech, &str)) {
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry fprintf(f, "(error in conversion)");
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry return;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry }
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry /* Note: generic_gss_oid_to_str returns a null-terminated string. */
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry for (i = 0; i < sizeof(mechnames)/sizeof(mechnames[0]); i++) {
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry if (!strcmp(str.value, mechnames[i].oidstr) && mechnames[i].name != 0) {
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry fprintf(f, "%s", mechnames[i].name);
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry break;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry }
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry }
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry if (i == sizeof(mechnames)/sizeof(mechnames[0]))
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry fprintf(f, "%s", (char *) str.value);
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry generic_gss_release_buffer(&minor, &str);
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry}
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry#include "errmap.h"
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry#include "krb5.h" /* for KRB5KRB_AP_WRONG_PRINC */
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barrystatic mecherrmap m;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barrystatic k5_mutex_t mutex = K5_MUTEX_PARTIAL_INITIALIZER;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barrystatic OM_uint32 next_fake = 100000;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barryint gssint_mecherrmap_init(void)
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry{
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry int err;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry err = mecherrmap_init(&m);
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry if (err)
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry return err;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry err = k5_mutex_finish_init(&mutex);
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry if (err) {
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry mecherrmap_destroy(&m);
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry return err;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry }
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry return 0;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry}
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry/* Currently the enumeration template doesn't handle freeing
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry element storage when destroying the collection. */
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barrystatic int free_one(OM_uint32 i, struct mecherror value, void *p)
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry{
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry if (value.mech.length && value.mech.elements)
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry free(value.mech.elements);
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry return 0;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry}
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barryvoid gssint_mecherrmap_destroy(void)
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry{
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry mecherrmap_foreach(&m, free_one, NULL);
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry mecherrmap_destroy(&m);
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry k5_mutex_destroy(&mutex);
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry}
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn BarryOM_uint32 gssint_mecherrmap_map(OM_uint32 minor, const gss_OID_desc * oid)
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry{
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry const struct mecherror *mep;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry struct mecherror me, me_copy;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry const OM_uint32 *p;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry int err;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry OM_uint32 new_status;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry#ifdef DEBUG
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry FILE *f;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry f = fopen("/dev/pts/9", "w+");
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry if (f == NULL)
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry f = stderr;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry#endif
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry me.code = minor;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry me.mech = *oid;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry err = k5_mutex_lock(&mutex);
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry if (err) {
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry#ifdef DEBUG
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry if (f != stderr) fclose(f);
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry#endif
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry return 0;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry }
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry /* Is this status+oid already mapped? */
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry p = mecherrmap_findright(&m, me);
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry if (p != NULL) {
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry k5_mutex_unlock(&mutex);
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry#ifdef DEBUG
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry fprintf(f, "%s: found ", __func__);
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry mecherror_print(me, f);
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry fprintf(f, " in map as %lu\n", (unsigned long) *p);
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry if (f != stderr) fclose(f);
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry#endif
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry return *p;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry }
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry /* Is this status code already mapped to something else
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry mech-specific? */
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry mep = mecherrmap_findleft(&m, minor);
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry if (mep == NULL) {
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry /* Map it to itself plus this mech-oid. */
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry new_status = minor;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry } else {
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry /* Already assigned. Pick a fake new value and map it. */
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry /* There's a theoretical infinite loop risk here, if we fill
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry in 2**32 values. Also, returning 0 has a special
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry meaning. */
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry do {
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry next_fake++;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry new_status = next_fake;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry if (new_status == 0)
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry /* ??? */;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry } while (mecherrmap_findleft(&m, new_status) != NULL);
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry }
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry err = mecherror_copy(&me_copy, me);
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry if (err) {
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry k5_mutex_unlock(&mutex);
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry return err;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry }
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry err = mecherrmap_add(&m, new_status, me_copy);
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry k5_mutex_unlock(&mutex);
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry if (err) {
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry if (me_copy.mech.length)
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry free(me_copy.mech.elements);
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry }
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry#ifdef DEBUG
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry fprintf(f, "%s: mapping ", __func__);
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry mecherror_print(me, f);
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry fprintf(f, " to %lu: err=%d\nnew map: ", (unsigned long) new_status, err);
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry mecherrmap_printmap(&m, f);
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry fprintf(f, "\n");
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry if (f != stderr) fclose(f);
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry#endif
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry if (err)
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry return 0;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry else
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry return new_status;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry}
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barrystatic gss_OID_desc no_oid = { 0, 0 };
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn BarryOM_uint32 gssint_mecherrmap_map_errcode(OM_uint32 errcode)
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry{
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry return gssint_mecherrmap_map(errcode, &no_oid);
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry}
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barryint gssint_mecherrmap_get(OM_uint32 minor, gss_OID mech_oid,
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry OM_uint32 *mech_minor)
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry{
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry const struct mecherror *p;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry int err;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry if (minor == 0) {
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry return EINVAL;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry }
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry err = k5_mutex_lock(&mutex);
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry if (err)
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry return err;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry p = mecherrmap_findleft(&m, minor);
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry k5_mutex_unlock(&mutex);
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry if (!p) {
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry return EINVAL;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry }
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry *mech_oid = p->mech;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry *mech_minor = p->code;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry return 0;
5e01956f3000408c2a2c5a08c8d0acf2c2a9d8eeGlenn Barry}