Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/krb5/src/lib/gssapi/generic/util_errmap.c
39563 views
1
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
/*
3
* Copyright 2007, 2008 by the Massachusetts Institute of Technology.
4
* All Rights Reserved.
5
*
6
* Export of this software from the United States of America may
7
* require a specific license from the United States Government.
8
* It is the responsibility of any person or organization contemplating
9
* export to obtain such a license before exporting.
10
*
11
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
12
* distribute this software and its documentation for any purpose and
13
* without fee is hereby granted, provided that the above copyright
14
* notice appear in all copies and that both that copyright notice and
15
* this permission notice appear in supporting documentation, and that
16
* the name of M.I.T. not be used in advertising or publicity pertaining
17
* to distribution of the software without specific, written prior
18
* permission. Furthermore if you modify this software you must label
19
* your software as modified software and not distribute it in such a
20
* fashion that it might be confused with the original M.I.T. software.
21
* M.I.T. makes no representations about the suitability of
22
* this software for any purpose. It is provided "as is" without express
23
* or implied warranty.
24
*
25
*/
26
27
#include "gssapiP_generic.h"
28
#include <mglueP.h>
29
#include <string.h>
30
#ifndef _WIN32
31
#include <unistd.h>
32
#endif
33
34
/* The mapping table is 0-based, but let's export codes that are
35
1-based, keeping 0 for errors or unknown errors.
36
37
The elements in the mapping table currently have separate copies of
38
each OID stored. This is a bit wasteful, but we are assuming the
39
table isn't likely to grow very large. */
40
41
struct mecherror {
42
gss_OID_desc mech;
43
OM_uint32 code;
44
};
45
46
static inline int
47
cmp_OM_uint32(OM_uint32 m1, OM_uint32 m2)
48
{
49
if (m1 < m2)
50
return -1;
51
else if (m1 > m2)
52
return 1;
53
else
54
return 0;
55
}
56
57
static inline int
58
mecherror_cmp(struct mecherror m1, struct mecherror m2)
59
{
60
if (m1.code < m2.code)
61
return -1;
62
if (m1.code > m2.code)
63
return 1;
64
if (m1.mech.length < m2.mech.length)
65
return -1;
66
if (m1.mech.length > m2.mech.length)
67
return 1;
68
if (m1.mech.length == 0)
69
return 0;
70
return memcmp(m1.mech.elements, m2.mech.elements, m1.mech.length);
71
}
72
73
static void
74
print_OM_uint32 (OM_uint32 value, FILE *f)
75
{
76
fprintf(f, "%lu", (unsigned long) value);
77
}
78
79
static inline int
80
mecherror_copy(struct mecherror *dest, struct mecherror src)
81
{
82
*dest = src;
83
if (src.mech.length > 0) {
84
dest->mech.elements = malloc(src.mech.length);
85
if (dest->mech.elements == NULL)
86
return ENOMEM;
87
memcpy(dest->mech.elements, src.mech.elements, src.mech.length);
88
} else {
89
dest->mech.elements = NULL;
90
}
91
return 0;
92
}
93
94
static void
95
mecherror_print(struct mecherror value, FILE *f)
96
{
97
OM_uint32 minor;
98
gss_buffer_desc str;
99
static const struct {
100
const char *oidstr, *name;
101
} mechnames[] = {
102
{ "{ 1 2 840 113554 1 2 2 }", "krb5-new" },
103
{ "{ 1 3 5 1 5 2 }", "krb5-old" },
104
{ "{ 1 2 840 48018 1 2 2 }", "krb5-microsoft" },
105
{ "{ 1 3 6 1 5 5 2 }", "spnego" },
106
};
107
unsigned int i;
108
109
fprintf(f, "%lu@", (unsigned long) value.code);
110
111
if (value.mech.length == 0) {
112
fprintf(f, "(com_err)");
113
return;
114
}
115
fprintf(f, "%p=", value.mech.elements);
116
if (generic_gss_oid_to_str(&minor, &value.mech, &str)) {
117
fprintf(f, "(error in conversion)");
118
return;
119
}
120
/* Note: generic_gss_oid_to_str returns a null-terminated string. */
121
for (i = 0; i < sizeof(mechnames)/sizeof(mechnames[0]); i++) {
122
if (!strcmp(str.value, mechnames[i].oidstr) && mechnames[i].name != 0) {
123
fprintf(f, "%s", mechnames[i].name);
124
break;
125
}
126
}
127
if (i == sizeof(mechnames)/sizeof(mechnames[0]))
128
fprintf(f, "%s", (char *) str.value);
129
generic_gss_release_buffer(&minor, &str);
130
}
131
132
#include "errmap.h"
133
#include "krb5.h" /* for KRB5KRB_AP_WRONG_PRINC */
134
135
static mecherrmap m;
136
static k5_mutex_t mutex = K5_MUTEX_PARTIAL_INITIALIZER;
137
static OM_uint32 next_fake = 100000;
138
139
int gssint_mecherrmap_init(void)
140
{
141
int err;
142
143
err = mecherrmap_init(&m);
144
if (err)
145
return err;
146
err = k5_mutex_finish_init(&mutex);
147
if (err) {
148
mecherrmap_destroy(&m);
149
return err;
150
}
151
152
return 0;
153
}
154
155
/* Currently the enumeration template doesn't handle freeing
156
element storage when destroying the collection. */
157
static int free_one(OM_uint32 i, struct mecherror value, void *p)
158
{
159
free(value.mech.elements);
160
return 0;
161
}
162
163
void gssint_mecherrmap_destroy(void)
164
{
165
mecherrmap_foreach(&m, free_one, NULL);
166
mecherrmap_destroy(&m);
167
k5_mutex_destroy(&mutex);
168
}
169
170
OM_uint32 gssint_mecherrmap_map(OM_uint32 minor, const gss_OID_desc * oid)
171
{
172
const struct mecherror *mep;
173
struct mecherror me, me_copy;
174
const OM_uint32 *p;
175
int err;
176
OM_uint32 new_status;
177
178
#ifdef DEBUG
179
FILE *f;
180
f = fopen("/dev/pts/9", "w+");
181
if (f == NULL)
182
f = stderr;
183
#endif
184
185
if (gssint_mechglue_initialize_library() != 0)
186
return 0;
187
188
me.code = minor;
189
me.mech = *oid;
190
k5_mutex_lock(&mutex);
191
192
/* Is this status+oid already mapped? */
193
p = mecherrmap_findright(&m, me);
194
if (p != NULL) {
195
k5_mutex_unlock(&mutex);
196
#ifdef DEBUG
197
fprintf(f, "%s: found ", __FUNCTION__);
198
mecherror_print(me, f);
199
fprintf(f, " in map as %lu\n", (unsigned long) *p);
200
if (f != stderr) fclose(f);
201
#endif
202
return *p;
203
}
204
/* Is this status code already mapped to something else
205
mech-specific? */
206
mep = mecherrmap_findleft(&m, minor);
207
if (mep == NULL) {
208
/* Map it to itself plus this mech-oid. */
209
new_status = minor;
210
} else {
211
/* Already assigned. Pick a fake new value and map it. */
212
/* There's a theoretical infinite loop risk here, if we fill
213
in 2**32 values. Also, returning 0 has a special
214
meaning. */
215
do {
216
next_fake++;
217
new_status = next_fake;
218
if (new_status == 0)
219
/* ??? */;
220
} while (mecherrmap_findleft(&m, new_status) != NULL);
221
}
222
err = mecherror_copy(&me_copy, me);
223
if (err) {
224
k5_mutex_unlock(&mutex);
225
return err;
226
}
227
err = mecherrmap_add(&m, new_status, me_copy);
228
k5_mutex_unlock(&mutex);
229
if (err)
230
free(me_copy.mech.elements);
231
#ifdef DEBUG
232
fprintf(f, "%s: mapping ", __FUNCTION__);
233
mecherror_print(me, f);
234
fprintf(f, " to %lu: err=%d\nnew map: ", (unsigned long) new_status, err);
235
mecherrmap_printmap(&m, f);
236
fprintf(f, "\n");
237
if (f != stderr) fclose(f);
238
#endif
239
if (err)
240
return 0;
241
else
242
return new_status;
243
}
244
245
static gss_OID_desc no_oid = { 0, 0 };
246
OM_uint32 gssint_mecherrmap_map_errcode(OM_uint32 errcode)
247
{
248
return gssint_mecherrmap_map(errcode, &no_oid);
249
}
250
251
int gssint_mecherrmap_get(OM_uint32 minor, gss_OID mech_oid,
252
OM_uint32 *mech_minor)
253
{
254
const struct mecherror *p;
255
256
if (minor == 0 || gssint_mechglue_initialize_library() != 0) {
257
return EINVAL;
258
}
259
k5_mutex_lock(&mutex);
260
p = mecherrmap_findleft(&m, minor);
261
k5_mutex_unlock(&mutex);
262
if (!p) {
263
return EINVAL;
264
}
265
*mech_oid = p->mech;
266
*mech_minor = p->code;
267
return 0;
268
}
269
270