Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/krb5/src/lib/gssapi/mechglue/g_dsp_status.c
39586 views
1
/* #pragma ident "@(#)g_dsp_status.c 1.17 04/02/23 SMI" */
2
3
/*
4
* Copyright 1996 by Sun Microsystems, Inc.
5
*
6
* Permission to use, copy, modify, distribute, and sell this software
7
* and its documentation for any purpose is hereby granted without fee,
8
* provided that the above copyright notice appears in all copies and
9
* that both that copyright notice and this permission notice appear in
10
* supporting documentation, and that the name of Sun Microsystems not be used
11
* in advertising or publicity pertaining to distribution of the software
12
* without specific, written prior permission. Sun Microsystems makes no
13
* representations about the suitability of this software for any
14
* purpose. It is provided "as is" without express or implied warranty.
15
*
16
* SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18
* EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
20
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
21
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22
* PERFORMANCE OF THIS SOFTWARE.
23
*/
24
25
/*
26
* glue routine gss_display_status
27
*
28
*/
29
30
#include "mglueP.h"
31
#include <stdio.h>
32
#include <stdlib.h>
33
#include <string.h>
34
35
/* local function */
36
static OM_uint32 displayMajor(OM_uint32, OM_uint32 *, gss_buffer_t);
37
38
OM_uint32 KRB5_CALLCONV
39
gss_display_status(OM_uint32 *minor_status, OM_uint32 status_value,
40
int status_type, gss_OID req_mech_type,
41
OM_uint32 *message_context, gss_buffer_t status_string)
42
{
43
gss_OID mech_type = (gss_OID) req_mech_type;
44
gss_mechanism mech;
45
gss_OID_desc m_oid = { 0, 0 };
46
47
if (minor_status != NULL)
48
*minor_status = 0;
49
50
if (status_string != GSS_C_NO_BUFFER) {
51
status_string->length = 0;
52
status_string->value = NULL;
53
}
54
55
if (minor_status == NULL ||
56
message_context == NULL ||
57
status_string == GSS_C_NO_BUFFER)
58
59
return (GSS_S_CALL_INACCESSIBLE_WRITE);
60
61
/* we handle major status codes, and the mechs do the minor */
62
if (status_type == GSS_C_GSS_CODE)
63
return (displayMajor(status_value, message_context,
64
status_string));
65
66
/*
67
* must be the minor status - let mechs do the work
68
* select the appropriate underlying mechanism routine and
69
* call it.
70
*/
71
72
/* In this version, we only handle status codes that have been
73
mapped to a flat numbering space. Look up the value we got
74
passed. If it's not found, complain. */
75
if (status_value == 0) {
76
status_string->value = gssalloc_strdup("Unknown error");
77
if (status_string->value == NULL) {
78
*minor_status = ENOMEM;
79
map_errcode(minor_status);
80
return GSS_S_FAILURE;
81
}
82
status_string->length = strlen(status_string->value);
83
*message_context = 0;
84
*minor_status = 0;
85
return GSS_S_COMPLETE;
86
}
87
{
88
int err;
89
OM_uint32 m_status = 0, status;
90
91
err = gssint_mecherrmap_get(status_value, &m_oid, &m_status);
92
if (err) {
93
*minor_status = err;
94
map_errcode(minor_status);
95
return GSS_S_BAD_STATUS;
96
}
97
if (m_oid.length == 0) {
98
/* Magic flag for com_err values. */
99
status = g_display_com_err_status(minor_status, m_status, status_string);
100
if (status != GSS_S_COMPLETE)
101
map_errcode(minor_status);
102
return status;
103
}
104
mech_type = &m_oid;
105
status_value = m_status;
106
}
107
108
mech = gssint_get_mechanism (mech_type);
109
110
if (mech && mech->gss_display_status) {
111
OM_uint32 r;
112
113
r = mech->gss_display_status(minor_status,
114
status_value, status_type, mech_type,
115
message_context, status_string);
116
/* How's this for weird? If we get an error returning the
117
mechanism-specific error code, we save away the
118
mechanism-specific error code describing the error. */
119
if (r != GSS_S_COMPLETE)
120
map_error(minor_status, mech);
121
return r;
122
}
123
124
if (!mech)
125
return (GSS_S_BAD_MECH);
126
127
return (GSS_S_UNAVAILABLE);
128
}
129
130
/*
131
* function to map the major error codes
132
* it uses case statements so that the strings could be wrapped by gettext
133
* msgCtxt is interpreted as:
134
* 0 - first call
135
* 1 - routine error
136
* >= 2 - the supplementary error code bit shifted by 1
137
*/
138
static OM_uint32
139
displayMajor(OM_uint32 status, OM_uint32 *msgCtxt, gss_buffer_t outStr)
140
{
141
OM_uint32 oneVal, mask = 0x1, currErr;
142
char *errStr = NULL;
143
int i, haveErr = 0;
144
145
/* take care of the success value first */
146
if (status == GSS_S_COMPLETE)
147
errStr = _("The routine completed successfully");
148
else if (*msgCtxt == 0 && (oneVal = GSS_CALLING_ERROR(status))) {
149
switch (oneVal) {
150
case GSS_S_CALL_INACCESSIBLE_READ:
151
errStr = _("A required input parameter could not be "
152
"read");
153
break;
154
155
case GSS_S_CALL_INACCESSIBLE_WRITE:
156
errStr = _("A required output parameter could not be "
157
"written");
158
break;
159
160
case GSS_S_CALL_BAD_STRUCTURE:
161
errStr = _("A parameter was malformed");
162
break;
163
164
default:
165
errStr = _("An invalid status code was supplied");
166
break;
167
}
168
169
/* we now need to determine new value of msgCtxt */
170
if (GSS_ROUTINE_ERROR(status))
171
*msgCtxt = 1;
172
else if ((oneVal = GSS_SUPPLEMENTARY_INFO(status)) != 0)
173
*msgCtxt = (OM_uint32)(oneVal << 1);
174
else
175
*msgCtxt = 0;
176
177
} else if ((*msgCtxt == 0 || *msgCtxt == 1) &&
178
(oneVal = GSS_ROUTINE_ERROR(status))) {
179
switch (oneVal) {
180
case GSS_S_BAD_MECH:
181
errStr = _("An unsupported mechanism was requested");
182
break;
183
184
case GSS_S_BAD_NAME:
185
errStr = _("An invalid name was supplied");
186
break;
187
188
case GSS_S_BAD_NAMETYPE:
189
errStr = _("A supplied name was of an unsupported "
190
"type");
191
break;
192
193
case GSS_S_BAD_BINDINGS:
194
errStr = _("Incorrect channel bindings were supplied");
195
break;
196
197
case GSS_S_BAD_SIG: /* same as GSS_S_BAD_MIC: */
198
errStr = _("A token had an invalid Message Integrity "
199
"Check (MIC)");
200
break;
201
202
case GSS_S_NO_CRED:
203
errStr = _("No credentials were supplied, or the "
204
"credentials were unavailable or "
205
"inaccessible");
206
break;
207
208
case GSS_S_NO_CONTEXT:
209
errStr = _("No context has been established");
210
break;
211
212
case GSS_S_DEFECTIVE_TOKEN:
213
errStr = _("Invalid token was supplied");
214
break;
215
216
case GSS_S_DEFECTIVE_CREDENTIAL:
217
errStr = _("Invalid credential was supplied");
218
break;
219
220
case GSS_S_CREDENTIALS_EXPIRED:
221
errStr = _("The referenced credential has expired");
222
break;
223
224
case GSS_S_CONTEXT_EXPIRED:
225
errStr = _("The referenced context has expired");
226
break;
227
228
case GSS_S_FAILURE:
229
errStr = _("Unspecified GSS failure. Minor code "
230
"may provide more information");
231
break;
232
233
case GSS_S_BAD_QOP:
234
errStr = _("The quality-of-protection (QOP) "
235
"requested could not be provided");
236
break;
237
238
case GSS_S_UNAUTHORIZED:
239
errStr = _("The operation is forbidden by local "
240
"security policy");
241
break;
242
243
case GSS_S_UNAVAILABLE:
244
errStr = _("The operation or option is not "
245
"available or unsupported");
246
break;
247
248
case GSS_S_DUPLICATE_ELEMENT:
249
errStr = _("The requested credential element "
250
"already exists");
251
break;
252
253
case GSS_S_NAME_NOT_MN:
254
errStr = _("The provided name was not mechanism "
255
"specific (MN)");
256
break;
257
258
case GSS_S_BAD_STATUS:
259
default:
260
errStr = _("An invalid status code was supplied");
261
}
262
263
/* we must determine if the caller should call us again */
264
if ((oneVal = GSS_SUPPLEMENTARY_INFO(status)) != 0)
265
*msgCtxt = (OM_uint32)(oneVal << 1);
266
else
267
*msgCtxt = 0;
268
269
} else if ((*msgCtxt == 0 || *msgCtxt >= 2) &&
270
(oneVal = GSS_SUPPLEMENTARY_INFO(status))) {
271
/*
272
* if msgCtxt is not 0, then it should encode
273
* the supplementary error code we should be printing
274
*/
275
if (*msgCtxt >= 2)
276
oneVal = (OM_uint32) (*msgCtxt) >> 1;
277
else
278
oneVal = GSS_SUPPLEMENTARY_INFO(status);
279
280
/* we display the errors LSB first */
281
for (i = 0; i < 16; i++) {
282
if (oneVal & mask) {
283
haveErr = 1;
284
break;
285
}
286
mask <<= 1;
287
}
288
289
/* isolate the bit or if not found set to illegal value */
290
if (haveErr)
291
currErr = oneVal & mask;
292
else
293
currErr = 1 << 17; /* illegal value */
294
295
switch (currErr) {
296
case GSS_S_CONTINUE_NEEDED:
297
errStr = _("The routine must be called again to "
298
"complete its function");
299
break;
300
301
case GSS_S_DUPLICATE_TOKEN:
302
errStr = _("The token was a duplicate of an earlier "
303
"token");
304
break;
305
306
case GSS_S_OLD_TOKEN:
307
errStr = _("The token's validity period has expired");
308
break;
309
310
case GSS_S_UNSEQ_TOKEN:
311
errStr = _("A later token has already been processed");
312
break;
313
314
case GSS_S_GAP_TOKEN:
315
errStr = _("An expected per-message token was not "
316
"received");
317
break;
318
319
default:
320
errStr = _("An invalid status code was supplied");
321
}
322
323
/*
324
* we must check if there is any other supplementary errors
325
* if found, then turn off current bit, and store next value
326
* in msgCtxt shifted by 1 bit
327
*/
328
if (!haveErr)
329
*msgCtxt = 0;
330
else if (GSS_SUPPLEMENTARY_INFO(oneVal) ^ mask)
331
*msgCtxt = (OM_uint32)
332
((GSS_SUPPLEMENTARY_INFO(oneVal) ^ mask) << 1);
333
else
334
*msgCtxt = 0;
335
}
336
337
if (errStr == NULL)
338
errStr = "An invalid status code was supplied";
339
340
/* now copy the status code and return to caller */
341
outStr->length = strlen(errStr);
342
outStr->value = gssalloc_strdup(errStr);
343
if (outStr->value == NULL) {
344
outStr->length = 0;
345
return (GSS_S_FAILURE);
346
}
347
348
return (GSS_S_COMPLETE);
349
} /* displayMajor */
350
351