Path: blob/main/crypto/krb5/src/lib/gssapi/generic/util_errmap.c
39563 views
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */1/*2* Copyright 2007, 2008 by the Massachusetts Institute of Technology.3* All Rights Reserved.4*5* Export of this software from the United States of America may6* require a specific license from the United States Government.7* It is the responsibility of any person or organization contemplating8* export to obtain such a license before exporting.9*10* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and11* distribute this software and its documentation for any purpose and12* without fee is hereby granted, provided that the above copyright13* notice appear in all copies and that both that copyright notice and14* this permission notice appear in supporting documentation, and that15* the name of M.I.T. not be used in advertising or publicity pertaining16* to distribution of the software without specific, written prior17* permission. Furthermore if you modify this software you must label18* your software as modified software and not distribute it in such a19* fashion that it might be confused with the original M.I.T. software.20* M.I.T. makes no representations about the suitability of21* this software for any purpose. It is provided "as is" without express22* or implied warranty.23*24*/2526#include "gssapiP_generic.h"27#include <mglueP.h>28#include <string.h>29#ifndef _WIN3230#include <unistd.h>31#endif3233/* The mapping table is 0-based, but let's export codes that are341-based, keeping 0 for errors or unknown errors.3536The elements in the mapping table currently have separate copies of37each OID stored. This is a bit wasteful, but we are assuming the38table isn't likely to grow very large. */3940struct mecherror {41gss_OID_desc mech;42OM_uint32 code;43};4445static inline int46cmp_OM_uint32(OM_uint32 m1, OM_uint32 m2)47{48if (m1 < m2)49return -1;50else if (m1 > m2)51return 1;52else53return 0;54}5556static inline int57mecherror_cmp(struct mecherror m1, struct mecherror m2)58{59if (m1.code < m2.code)60return -1;61if (m1.code > m2.code)62return 1;63if (m1.mech.length < m2.mech.length)64return -1;65if (m1.mech.length > m2.mech.length)66return 1;67if (m1.mech.length == 0)68return 0;69return memcmp(m1.mech.elements, m2.mech.elements, m1.mech.length);70}7172static void73print_OM_uint32 (OM_uint32 value, FILE *f)74{75fprintf(f, "%lu", (unsigned long) value);76}7778static inline int79mecherror_copy(struct mecherror *dest, struct mecherror src)80{81*dest = src;82if (src.mech.length > 0) {83dest->mech.elements = malloc(src.mech.length);84if (dest->mech.elements == NULL)85return ENOMEM;86memcpy(dest->mech.elements, src.mech.elements, src.mech.length);87} else {88dest->mech.elements = NULL;89}90return 0;91}9293static void94mecherror_print(struct mecherror value, FILE *f)95{96OM_uint32 minor;97gss_buffer_desc str;98static const struct {99const char *oidstr, *name;100} mechnames[] = {101{ "{ 1 2 840 113554 1 2 2 }", "krb5-new" },102{ "{ 1 3 5 1 5 2 }", "krb5-old" },103{ "{ 1 2 840 48018 1 2 2 }", "krb5-microsoft" },104{ "{ 1 3 6 1 5 5 2 }", "spnego" },105};106unsigned int i;107108fprintf(f, "%lu@", (unsigned long) value.code);109110if (value.mech.length == 0) {111fprintf(f, "(com_err)");112return;113}114fprintf(f, "%p=", value.mech.elements);115if (generic_gss_oid_to_str(&minor, &value.mech, &str)) {116fprintf(f, "(error in conversion)");117return;118}119/* Note: generic_gss_oid_to_str returns a null-terminated string. */120for (i = 0; i < sizeof(mechnames)/sizeof(mechnames[0]); i++) {121if (!strcmp(str.value, mechnames[i].oidstr) && mechnames[i].name != 0) {122fprintf(f, "%s", mechnames[i].name);123break;124}125}126if (i == sizeof(mechnames)/sizeof(mechnames[0]))127fprintf(f, "%s", (char *) str.value);128generic_gss_release_buffer(&minor, &str);129}130131#include "errmap.h"132#include "krb5.h" /* for KRB5KRB_AP_WRONG_PRINC */133134static mecherrmap m;135static k5_mutex_t mutex = K5_MUTEX_PARTIAL_INITIALIZER;136static OM_uint32 next_fake = 100000;137138int gssint_mecherrmap_init(void)139{140int err;141142err = mecherrmap_init(&m);143if (err)144return err;145err = k5_mutex_finish_init(&mutex);146if (err) {147mecherrmap_destroy(&m);148return err;149}150151return 0;152}153154/* Currently the enumeration template doesn't handle freeing155element storage when destroying the collection. */156static int free_one(OM_uint32 i, struct mecherror value, void *p)157{158free(value.mech.elements);159return 0;160}161162void gssint_mecherrmap_destroy(void)163{164mecherrmap_foreach(&m, free_one, NULL);165mecherrmap_destroy(&m);166k5_mutex_destroy(&mutex);167}168169OM_uint32 gssint_mecherrmap_map(OM_uint32 minor, const gss_OID_desc * oid)170{171const struct mecherror *mep;172struct mecherror me, me_copy;173const OM_uint32 *p;174int err;175OM_uint32 new_status;176177#ifdef DEBUG178FILE *f;179f = fopen("/dev/pts/9", "w+");180if (f == NULL)181f = stderr;182#endif183184if (gssint_mechglue_initialize_library() != 0)185return 0;186187me.code = minor;188me.mech = *oid;189k5_mutex_lock(&mutex);190191/* Is this status+oid already mapped? */192p = mecherrmap_findright(&m, me);193if (p != NULL) {194k5_mutex_unlock(&mutex);195#ifdef DEBUG196fprintf(f, "%s: found ", __FUNCTION__);197mecherror_print(me, f);198fprintf(f, " in map as %lu\n", (unsigned long) *p);199if (f != stderr) fclose(f);200#endif201return *p;202}203/* Is this status code already mapped to something else204mech-specific? */205mep = mecherrmap_findleft(&m, minor);206if (mep == NULL) {207/* Map it to itself plus this mech-oid. */208new_status = minor;209} else {210/* Already assigned. Pick a fake new value and map it. */211/* There's a theoretical infinite loop risk here, if we fill212in 2**32 values. Also, returning 0 has a special213meaning. */214do {215next_fake++;216new_status = next_fake;217if (new_status == 0)218/* ??? */;219} while (mecherrmap_findleft(&m, new_status) != NULL);220}221err = mecherror_copy(&me_copy, me);222if (err) {223k5_mutex_unlock(&mutex);224return err;225}226err = mecherrmap_add(&m, new_status, me_copy);227k5_mutex_unlock(&mutex);228if (err)229free(me_copy.mech.elements);230#ifdef DEBUG231fprintf(f, "%s: mapping ", __FUNCTION__);232mecherror_print(me, f);233fprintf(f, " to %lu: err=%d\nnew map: ", (unsigned long) new_status, err);234mecherrmap_printmap(&m, f);235fprintf(f, "\n");236if (f != stderr) fclose(f);237#endif238if (err)239return 0;240else241return new_status;242}243244static gss_OID_desc no_oid = { 0, 0 };245OM_uint32 gssint_mecherrmap_map_errcode(OM_uint32 errcode)246{247return gssint_mecherrmap_map(errcode, &no_oid);248}249250int gssint_mecherrmap_get(OM_uint32 minor, gss_OID mech_oid,251OM_uint32 *mech_minor)252{253const struct mecherror *p;254255if (minor == 0 || gssint_mechglue_initialize_library() != 0) {256return EINVAL;257}258k5_mutex_lock(&mutex);259p = mecherrmap_findleft(&m, minor);260k5_mutex_unlock(&mutex);261if (!p) {262return EINVAL;263}264*mech_oid = p->mech;265*mech_minor = p->code;266return 0;267}268269270