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