blob: b771b41466fb64dcc8d8595d9fba9f96264b9e14 [file] [log] [blame]
Patrick Williamsb48b7b42016-08-17 15:04:38 -05001From f6e57c402688f4bc386d1a39512657a30f0bafd3 Mon Sep 17 00:00:00 2001
2From: Nicolas Williams <nico@twosigma.com>
3Date: Mon, 14 Sep 2015 12:28:36 -0400
4Subject: [PATCH 2/4] Fix IAKERB context aliasing bugs [CVE-2015-2696]
5
6The IAKERB mechanism currently replaces its context handle with the
7krb5 mechanism handle upon establishment, under the assumption that
8most GSS functions are only called after context establishment. This
9assumption is incorrect, and can lead to aliasing violations for some
10programs. Maintain the IAKERB context structure after context
11establishment and add new IAKERB entry points to refer to it with that
12type. Add initiate and established flags to the IAKERB context
13structure for use in gss_inquire_context() prior to context
14establishment.
15
16CVE-2015-2696:
17
18In MIT krb5 1.9 and later, applications which call
19gss_inquire_context() on a partially-established IAKERB context can
20cause the GSS-API library to read from a pointer using the wrong type,
21generally causing a process crash. Java server applications using the
22native JGSS provider are vulnerable to this bug. A carefully crafted
23IAKERB packet might allow the gss_inquire_context() call to succeed
24with attacker-determined results, but applications should not make
25access control decisions based on gss_inquire_context() results prior
26to context establishment.
27
28 CVSSv2 Vector: AV:N/AC:M/Au:N/C:N/I:N/A:C/E:POC/RL:OF/RC:C
29
30[ghudson@mit.edu: several bugfixes, style changes, and edge-case
31behavior changes; commit message and CVE description]
32
33ticket: 8244
34target_version: 1.14
35tags: pullup
36
37Backport upstream commit:
38https://github.com/krb5/krb5/commit/e04f0283516e80d2f93366e0d479d13c9b5c8c2a
39
40Upstream-Status: Backport
41---
42 src/lib/gssapi/krb5/gssapiP_krb5.h | 114 ++++++++++++
43 src/lib/gssapi/krb5/gssapi_krb5.c | 105 +++++++++--
44 src/lib/gssapi/krb5/iakerb.c | 351 +++++++++++++++++++++++++++++++++----
45 3 files changed, 529 insertions(+), 41 deletions(-)
46
47diff --git a/src/lib/gssapi/krb5/gssapiP_krb5.h b/src/lib/gssapi/krb5/gssapiP_krb5.h
48index a0e8625..05dc321 100644
49--- a/src/lib/gssapi/krb5/gssapiP_krb5.h
50+++ b/src/lib/gssapi/krb5/gssapiP_krb5.h
51@@ -620,6 +620,21 @@ OM_uint32 KRB5_CALLCONV krb5_gss_accept_sec_context_ext
52 );
53 #endif /* LEAN_CLIENT */
54
55+OM_uint32 KRB5_CALLCONV krb5_gss_inquire_sec_context_by_oid
56+(OM_uint32*, /* minor_status */
57+ const gss_ctx_id_t,
58+ /* context_handle */
59+ const gss_OID, /* desired_object */
60+ gss_buffer_set_t* /* data_set */
61+);
62+
63+OM_uint32 KRB5_CALLCONV krb5_gss_set_sec_context_option
64+(OM_uint32*, /* minor_status */
65+ gss_ctx_id_t*, /* context_handle */
66+ const gss_OID, /* desired_object */
67+ const gss_buffer_t/* value */
68+);
69+
70 OM_uint32 KRB5_CALLCONV krb5_gss_process_context_token
71 (OM_uint32*, /* minor_status */
72 gss_ctx_id_t, /* context_handle */
73@@ -1301,6 +1316,105 @@ OM_uint32 KRB5_CALLCONV
74 krb5_gss_import_cred(OM_uint32 *minor_status, gss_buffer_t token,
75 gss_cred_id_t *cred_handle);
76
77+OM_uint32 KRB5_CALLCONV
78+iakerb_gss_process_context_token(OM_uint32 *minor_status,
79+ const gss_ctx_id_t context_handle,
80+ const gss_buffer_t token_buffer);
81+
82+OM_uint32 KRB5_CALLCONV
83+iakerb_gss_context_time(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
84+ OM_uint32 *time_rec);
85+
86+OM_uint32 KRB5_CALLCONV
87+iakerb_gss_inquire_context(OM_uint32 *minor_status,
88+ gss_ctx_id_t context_handle, gss_name_t *src_name,
89+ gss_name_t *targ_name, OM_uint32 *lifetime_rec,
90+ gss_OID *mech_type, OM_uint32 *ctx_flags,
91+ int *locally_initiated, int *opened);
92+
93+OM_uint32 KRB5_CALLCONV
94+iakerb_gss_get_mic(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
95+ gss_qop_t qop_req, gss_buffer_t message_buffer,
96+ gss_buffer_t message_token);
97+
98+OM_uint32 KRB5_CALLCONV
99+iakerb_gss_get_mic_iov(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
100+ gss_qop_t qop_req, gss_iov_buffer_desc *iov,
101+ int iov_count);
102+
103+OM_uint32 KRB5_CALLCONV
104+iakerb_gss_get_mic_iov_length(OM_uint32 *minor_status,
105+ gss_ctx_id_t context_handle, gss_qop_t qop_req,
106+ gss_iov_buffer_desc *iov, int iov_count);
107+
108+OM_uint32 KRB5_CALLCONV
109+iakerb_gss_verify_mic(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
110+ gss_buffer_t msg_buffer, gss_buffer_t token_buffer,
111+ gss_qop_t *qop_state);
112+
113+OM_uint32 KRB5_CALLCONV
114+iakerb_gss_verify_mic_iov(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
115+ gss_qop_t *qop_state, gss_iov_buffer_desc *iov,
116+ int iov_count);
117+
118+OM_uint32 KRB5_CALLCONV
119+iakerb_gss_wrap(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
120+ int conf_req_flag, gss_qop_t qop_req,
121+ gss_buffer_t input_message_buffer, int *conf_state,
122+ gss_buffer_t output_message_buffer);
123+
124+OM_uint32 KRB5_CALLCONV
125+iakerb_gss_wrap_iov(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
126+ int conf_req_flag, gss_qop_t qop_req, int *conf_state,
127+ gss_iov_buffer_desc *iov, int iov_count);
128+
129+OM_uint32 KRB5_CALLCONV
130+iakerb_gss_wrap_iov_length(OM_uint32 *minor_status,
131+ gss_ctx_id_t context_handle, int conf_req_flag,
132+ gss_qop_t qop_req, int *conf_state,
133+ gss_iov_buffer_desc *iov, int iov_count);
134+
135+OM_uint32 KRB5_CALLCONV
136+iakerb_gss_unwrap(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
137+ gss_buffer_t input_message_buffer,
138+ gss_buffer_t output_message_buffer, int *conf_state,
139+ gss_qop_t *qop_state);
140+
141+OM_uint32 KRB5_CALLCONV
142+iakerb_gss_unwrap_iov(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
143+ int *conf_state, gss_qop_t *qop_state,
144+ gss_iov_buffer_desc *iov, int iov_count);
145+
146+OM_uint32 KRB5_CALLCONV
147+iakerb_gss_wrap_size_limit(OM_uint32 *minor_status,
148+ gss_ctx_id_t context_handle, int conf_req_flag,
149+ gss_qop_t qop_req, OM_uint32 req_output_size,
150+ OM_uint32 *max_input_size);
151+
152+#ifndef LEAN_CLIENT
153+OM_uint32 KRB5_CALLCONV
154+iakerb_gss_export_sec_context(OM_uint32 *minor_status,
155+ gss_ctx_id_t *context_handle,
156+ gss_buffer_t interprocess_token);
157+#endif /* LEAN_CLIENT */
158+
159+OM_uint32 KRB5_CALLCONV
160+iakerb_gss_inquire_sec_context_by_oid(OM_uint32 *minor_status,
161+ const gss_ctx_id_t context_handle,
162+ const gss_OID desired_object,
163+ gss_buffer_set_t *data_set);
164+
165+OM_uint32 KRB5_CALLCONV
166+iakerb_gss_set_sec_context_option(OM_uint32 *minor_status,
167+ gss_ctx_id_t *context_handle,
168+ const gss_OID desired_object,
169+ const gss_buffer_t value);
170+
171+OM_uint32 KRB5_CALLCONV
172+iakerb_gss_pseudo_random(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
173+ int prf_key, const gss_buffer_t prf_in,
174+ ssize_t desired_output_len, gss_buffer_t prf_out);
175+
176 /* Magic string to identify exported krb5 GSS credentials. Increment this if
177 * the format changes. */
178 #define CRED_EXPORT_MAGIC "K5C1"
179diff --git a/src/lib/gssapi/krb5/gssapi_krb5.c b/src/lib/gssapi/krb5/gssapi_krb5.c
180index 77b7fff..9a23656 100644
181--- a/src/lib/gssapi/krb5/gssapi_krb5.c
182+++ b/src/lib/gssapi/krb5/gssapi_krb5.c
183@@ -345,7 +345,7 @@ static struct {
184 }
185 };
186
187-static OM_uint32 KRB5_CALLCONV
188+OM_uint32 KRB5_CALLCONV
189 krb5_gss_inquire_sec_context_by_oid (OM_uint32 *minor_status,
190 const gss_ctx_id_t context_handle,
191 const gss_OID desired_object,
192@@ -459,7 +459,7 @@ static struct {
193 };
194 #endif
195
196-static OM_uint32 KRB5_CALLCONV
197+OM_uint32 KRB5_CALLCONV
198 krb5_gss_set_sec_context_option (OM_uint32 *minor_status,
199 gss_ctx_id_t *context_handle,
200 const gss_OID desired_object,
201@@ -904,20 +904,103 @@ static struct gss_config krb5_mechanism = {
202 krb5_gss_get_mic_iov_length,
203 };
204
205+/* Functions which use security contexts or acquire creds are IAKERB-specific;
206+ * other functions can borrow from the krb5 mech. */
207+static struct gss_config iakerb_mechanism = {
208+ { GSS_MECH_KRB5_OID_LENGTH, GSS_MECH_KRB5_OID },
209+ NULL,
210+ iakerb_gss_acquire_cred,
211+ krb5_gss_release_cred,
212+ iakerb_gss_init_sec_context,
213+#ifdef LEAN_CLIENT
214+ NULL,
215+#else
216+ iakerb_gss_accept_sec_context,
217+#endif
218+ iakerb_gss_process_context_token,
219+ iakerb_gss_delete_sec_context,
220+ iakerb_gss_context_time,
221+ iakerb_gss_get_mic,
222+ iakerb_gss_verify_mic,
223+#if defined(IOV_SHIM_EXERCISE_WRAP) || defined(IOV_SHIM_EXERCISE)
224+ NULL,
225+#else
226+ iakerb_gss_wrap,
227+#endif
228+#if defined(IOV_SHIM_EXERCISE_UNWRAP) || defined(IOV_SHIM_EXERCISE)
229+ NULL,
230+#else
231+ iakerb_gss_unwrap,
232+#endif
233+ krb5_gss_display_status,
234+ krb5_gss_indicate_mechs,
235+ krb5_gss_compare_name,
236+ krb5_gss_display_name,
237+ krb5_gss_import_name,
238+ krb5_gss_release_name,
239+ krb5_gss_inquire_cred,
240+ NULL, /* add_cred */
241+#ifdef LEAN_CLIENT
242+ NULL,
243+ NULL,
244+#else
245+ iakerb_gss_export_sec_context,
246+ NULL,
247+#endif
248+ krb5_gss_inquire_cred_by_mech,
249+ krb5_gss_inquire_names_for_mech,
250+ iakerb_gss_inquire_context,
251+ krb5_gss_internal_release_oid,
252+ iakerb_gss_wrap_size_limit,
253+ krb5_gss_localname,
254+ krb5_gss_authorize_localname,
255+ krb5_gss_export_name,
256+ krb5_gss_duplicate_name,
257+ krb5_gss_store_cred,
258+ iakerb_gss_inquire_sec_context_by_oid,
259+ krb5_gss_inquire_cred_by_oid,
260+ iakerb_gss_set_sec_context_option,
261+ krb5_gssspi_set_cred_option,
262+ krb5_gssspi_mech_invoke,
263+ NULL, /* wrap_aead */
264+ NULL, /* unwrap_aead */
265+ iakerb_gss_wrap_iov,
266+ iakerb_gss_unwrap_iov,
267+ iakerb_gss_wrap_iov_length,
268+ NULL, /* complete_auth_token */
269+ NULL, /* acquire_cred_impersonate_name */
270+ NULL, /* add_cred_impersonate_name */
271+ NULL, /* display_name_ext */
272+ krb5_gss_inquire_name,
273+ krb5_gss_get_name_attribute,
274+ krb5_gss_set_name_attribute,
275+ krb5_gss_delete_name_attribute,
276+ krb5_gss_export_name_composite,
277+ krb5_gss_map_name_to_any,
278+ krb5_gss_release_any_name_mapping,
279+ iakerb_gss_pseudo_random,
280+ NULL, /* set_neg_mechs */
281+ krb5_gss_inquire_saslname_for_mech,
282+ krb5_gss_inquire_mech_for_saslname,
283+ krb5_gss_inquire_attrs_for_mech,
284+ krb5_gss_acquire_cred_from,
285+ krb5_gss_store_cred_into,
286+ iakerb_gss_acquire_cred_with_password,
287+ krb5_gss_export_cred,
288+ krb5_gss_import_cred,
289+ NULL, /* import_sec_context_by_mech */
290+ NULL, /* import_name_by_mech */
291+ NULL, /* import_cred_by_mech */
292+ iakerb_gss_get_mic_iov,
293+ iakerb_gss_verify_mic_iov,
294+ iakerb_gss_get_mic_iov_length,
295+};
296+
297 #ifdef _GSS_STATIC_LINK
298 #include "mglueP.h"
299 static int gss_iakerbmechglue_init(void)
300 {
301 struct gss_mech_config mech_iakerb;
302- struct gss_config iakerb_mechanism = krb5_mechanism;
303-
304- /* IAKERB mechanism mirrors krb5, but with different context SPIs */
305- iakerb_mechanism.gss_accept_sec_context = iakerb_gss_accept_sec_context;
306- iakerb_mechanism.gss_init_sec_context = iakerb_gss_init_sec_context;
307- iakerb_mechanism.gss_delete_sec_context = iakerb_gss_delete_sec_context;
308- iakerb_mechanism.gss_acquire_cred = iakerb_gss_acquire_cred;
309- iakerb_mechanism.gssspi_acquire_cred_with_password
310- = iakerb_gss_acquire_cred_with_password;
311
312 memset(&mech_iakerb, 0, sizeof(mech_iakerb));
313 mech_iakerb.mech = &iakerb_mechanism;
314diff --git a/src/lib/gssapi/krb5/iakerb.c b/src/lib/gssapi/krb5/iakerb.c
315index f30de32..4662bd9 100644
316--- a/src/lib/gssapi/krb5/iakerb.c
317+++ b/src/lib/gssapi/krb5/iakerb.c
318@@ -47,6 +47,8 @@ struct _iakerb_ctx_id_rec {
319 gss_ctx_id_t gssc;
320 krb5_data conv; /* conversation for checksumming */
321 unsigned int count; /* number of round trips */
322+ int initiate;
323+ int established;
324 krb5_get_init_creds_opt *gic_opts;
325 };
326
327@@ -695,7 +697,7 @@ cleanup:
328 * Allocate and initialise an IAKERB context
329 */
330 static krb5_error_code
331-iakerb_alloc_context(iakerb_ctx_id_t *pctx)
332+iakerb_alloc_context(iakerb_ctx_id_t *pctx, int initiate)
333 {
334 iakerb_ctx_id_t ctx;
335 krb5_error_code code;
336@@ -709,6 +711,8 @@ iakerb_alloc_context(iakerb_ctx_id_t *pctx)
337 ctx->magic = KG_IAKERB_CONTEXT;
338 ctx->state = IAKERB_AS_REQ;
339 ctx->count = 0;
340+ ctx->initiate = initiate;
341+ ctx->established = 0;
342
343 code = krb5_gss_init_context(&ctx->k5c);
344 if (code != 0)
345@@ -732,7 +736,7 @@ iakerb_gss_delete_sec_context(OM_uint32 *minor_status,
346 gss_ctx_id_t *context_handle,
347 gss_buffer_t output_token)
348 {
349- OM_uint32 major_status = GSS_S_COMPLETE;
350+ iakerb_ctx_id_t iakerb_ctx = (iakerb_ctx_id_t)*context_handle;
351
352 if (output_token != GSS_C_NO_BUFFER) {
353 output_token->length = 0;
354@@ -740,23 +744,10 @@ iakerb_gss_delete_sec_context(OM_uint32 *minor_status,
355 }
356
357 *minor_status = 0;
358+ *context_handle = GSS_C_NO_CONTEXT;
359+ iakerb_release_context(iakerb_ctx);
360
361- if (*context_handle != GSS_C_NO_CONTEXT) {
362- iakerb_ctx_id_t iakerb_ctx = (iakerb_ctx_id_t)*context_handle;
363-
364- if (iakerb_ctx->magic == KG_IAKERB_CONTEXT) {
365- iakerb_release_context(iakerb_ctx);
366- *context_handle = GSS_C_NO_CONTEXT;
367- } else {
368- assert(iakerb_ctx->magic == KG_CONTEXT);
369-
370- major_status = krb5_gss_delete_sec_context(minor_status,
371- context_handle,
372- output_token);
373- }
374- }
375-
376- return major_status;
377+ return GSS_S_COMPLETE;
378 }
379
380 static krb5_boolean
381@@ -802,7 +793,7 @@ iakerb_gss_accept_sec_context(OM_uint32 *minor_status,
382 int initialContextToken = (*context_handle == GSS_C_NO_CONTEXT);
383
384 if (initialContextToken) {
385- code = iakerb_alloc_context(&ctx);
386+ code = iakerb_alloc_context(&ctx, 0);
387 if (code != 0)
388 goto cleanup;
389
390@@ -854,11 +845,8 @@ iakerb_gss_accept_sec_context(OM_uint32 *minor_status,
391 time_rec,
392 delegated_cred_handle,
393 &exts);
394- if (major_status == GSS_S_COMPLETE) {
395- *context_handle = ctx->gssc;
396- ctx->gssc = NULL;
397- iakerb_release_context(ctx);
398- }
399+ if (major_status == GSS_S_COMPLETE)
400+ ctx->established = 1;
401 if (mech_type != NULL)
402 *mech_type = (gss_OID)gss_mech_krb5;
403 }
404@@ -897,7 +885,7 @@ iakerb_gss_init_sec_context(OM_uint32 *minor_status,
405 int initialContextToken = (*context_handle == GSS_C_NO_CONTEXT);
406
407 if (initialContextToken) {
408- code = iakerb_alloc_context(&ctx);
409+ code = iakerb_alloc_context(&ctx, 1);
410 if (code != 0) {
411 *minor_status = code;
412 goto cleanup;
413@@ -983,11 +971,8 @@ iakerb_gss_init_sec_context(OM_uint32 *minor_status,
414 ret_flags,
415 time_rec,
416 &exts);
417- if (major_status == GSS_S_COMPLETE) {
418- *context_handle = ctx->gssc;
419- ctx->gssc = GSS_C_NO_CONTEXT;
420- iakerb_release_context(ctx);
421- }
422+ if (major_status == GSS_S_COMPLETE)
423+ ctx->established = 1;
424 if (actual_mech_type != NULL)
425 *actual_mech_type = (gss_OID)gss_mech_krb5;
426 } else {
427@@ -1010,3 +995,309 @@ cleanup:
428
429 return major_status;
430 }
431+
432+OM_uint32 KRB5_CALLCONV
433+iakerb_gss_unwrap(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
434+ gss_buffer_t input_message_buffer,
435+ gss_buffer_t output_message_buffer, int *conf_state,
436+ gss_qop_t *qop_state)
437+{
438+ iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle;
439+
440+ if (ctx->gssc == GSS_C_NO_CONTEXT)
441+ return GSS_S_NO_CONTEXT;
442+
443+ return krb5_gss_unwrap(minor_status, ctx->gssc, input_message_buffer,
444+ output_message_buffer, conf_state, qop_state);
445+}
446+
447+OM_uint32 KRB5_CALLCONV
448+iakerb_gss_wrap(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
449+ int conf_req_flag, gss_qop_t qop_req,
450+ gss_buffer_t input_message_buffer, int *conf_state,
451+ gss_buffer_t output_message_buffer)
452+{
453+ iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle;
454+
455+ if (ctx->gssc == GSS_C_NO_CONTEXT)
456+ return GSS_S_NO_CONTEXT;
457+
458+ return krb5_gss_wrap(minor_status, ctx->gssc, conf_req_flag, qop_req,
459+ input_message_buffer, conf_state,
460+ output_message_buffer);
461+}
462+
463+OM_uint32 KRB5_CALLCONV
464+iakerb_gss_process_context_token(OM_uint32 *minor_status,
465+ const gss_ctx_id_t context_handle,
466+ const gss_buffer_t token_buffer)
467+{
468+ iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle;
469+
470+ if (ctx->gssc == GSS_C_NO_CONTEXT)
471+ return GSS_S_DEFECTIVE_TOKEN;
472+
473+ return krb5_gss_process_context_token(minor_status, ctx->gssc,
474+ token_buffer);
475+}
476+
477+OM_uint32 KRB5_CALLCONV
478+iakerb_gss_context_time(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
479+ OM_uint32 *time_rec)
480+{
481+ iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle;
482+
483+ if (ctx->gssc == GSS_C_NO_CONTEXT)
484+ return GSS_S_NO_CONTEXT;
485+
486+ return krb5_gss_context_time(minor_status, ctx->gssc, time_rec);
487+}
488+
489+#ifndef LEAN_CLIENT
490+
491+OM_uint32 KRB5_CALLCONV
492+iakerb_gss_export_sec_context(OM_uint32 *minor_status,
493+ gss_ctx_id_t *context_handle,
494+ gss_buffer_t interprocess_token)
495+{
496+ OM_uint32 maj;
497+ iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle;
498+
499+ /* We don't currently support exporting partially established contexts. */
500+ if (!ctx->established)
501+ return GSS_S_UNAVAILABLE;
502+
503+ maj = krb5_gss_export_sec_context(minor_status, &ctx->gssc,
504+ interprocess_token);
505+ if (ctx->gssc == GSS_C_NO_CONTEXT) {
506+ iakerb_release_context(ctx);
507+ *context_handle = GSS_C_NO_CONTEXT;
508+ }
509+ return maj;
510+}
511+
512+/*
513+ * Until we implement partial context exports, there are no SPNEGO exported
514+ * context tokens, only tokens for the underlying krb5 context. So we do not
515+ * need to implement an iakerb_gss_import_sec_context() yet; it would be
516+ * unreachable except via a manually constructed token.
517+ */
518+
519+#endif /* LEAN_CLIENT */
520+
521+OM_uint32 KRB5_CALLCONV
522+iakerb_gss_inquire_context(OM_uint32 *minor_status,
523+ gss_ctx_id_t context_handle, gss_name_t *src_name,
524+ gss_name_t *targ_name, OM_uint32 *lifetime_rec,
525+ gss_OID *mech_type, OM_uint32 *ctx_flags,
526+ int *initiate, int *opened)
527+{
528+ OM_uint32 ret;
529+ iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle;
530+
531+ if (src_name != NULL)
532+ *src_name = GSS_C_NO_NAME;
533+ if (targ_name != NULL)
534+ *targ_name = GSS_C_NO_NAME;
535+ if (lifetime_rec != NULL)
536+ *lifetime_rec = 0;
537+ if (mech_type != NULL)
538+ *mech_type = (gss_OID)gss_mech_iakerb;
539+ if (ctx_flags != NULL)
540+ *ctx_flags = 0;
541+ if (initiate != NULL)
542+ *initiate = ctx->initiate;
543+ if (opened != NULL)
544+ *opened = ctx->established;
545+
546+ if (ctx->gssc == GSS_C_NO_CONTEXT)
547+ return GSS_S_COMPLETE;
548+
549+ ret = krb5_gss_inquire_context(minor_status, ctx->gssc, src_name,
550+ targ_name, lifetime_rec, mech_type,
551+ ctx_flags, initiate, opened);
552+
553+ if (!ctx->established) {
554+ /* Report IAKERB as the mech OID until the context is established. */
555+ if (mech_type != NULL)
556+ *mech_type = (gss_OID)gss_mech_iakerb;
557+
558+ /* We don't support exporting partially-established contexts. */
559+ if (ctx_flags != NULL)
560+ *ctx_flags &= ~GSS_C_TRANS_FLAG;
561+ }
562+
563+ return ret;
564+}
565+
566+OM_uint32 KRB5_CALLCONV
567+iakerb_gss_wrap_size_limit(OM_uint32 *minor_status,
568+ gss_ctx_id_t context_handle, int conf_req_flag,
569+ gss_qop_t qop_req, OM_uint32 req_output_size,
570+ OM_uint32 *max_input_size)
571+{
572+ iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle;
573+
574+ if (ctx->gssc == GSS_C_NO_CONTEXT)
575+ return GSS_S_NO_CONTEXT;
576+
577+ return krb5_gss_wrap_size_limit(minor_status, ctx->gssc, conf_req_flag,
578+ qop_req, req_output_size, max_input_size);
579+}
580+
581+OM_uint32 KRB5_CALLCONV
582+iakerb_gss_get_mic(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
583+ gss_qop_t qop_req, gss_buffer_t message_buffer,
584+ gss_buffer_t message_token)
585+{
586+ iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle;
587+
588+ if (ctx->gssc == GSS_C_NO_CONTEXT)
589+ return GSS_S_NO_CONTEXT;
590+
591+ return krb5_gss_get_mic(minor_status, ctx->gssc, qop_req, message_buffer,
592+ message_token);
593+}
594+
595+OM_uint32 KRB5_CALLCONV
596+iakerb_gss_verify_mic(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
597+ gss_buffer_t msg_buffer, gss_buffer_t token_buffer,
598+ gss_qop_t *qop_state)
599+{
600+ iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle;
601+
602+ if (ctx->gssc == GSS_C_NO_CONTEXT)
603+ return GSS_S_NO_CONTEXT;
604+
605+ return krb5_gss_verify_mic(minor_status, ctx->gssc, msg_buffer,
606+ token_buffer, qop_state);
607+}
608+
609+OM_uint32 KRB5_CALLCONV
610+iakerb_gss_inquire_sec_context_by_oid(OM_uint32 *minor_status,
611+ const gss_ctx_id_t context_handle,
612+ const gss_OID desired_object,
613+ gss_buffer_set_t *data_set)
614+{
615+ iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle;
616+
617+ if (ctx->gssc == GSS_C_NO_CONTEXT)
618+ return GSS_S_UNAVAILABLE;
619+
620+ return krb5_gss_inquire_sec_context_by_oid(minor_status, ctx->gssc,
621+ desired_object, data_set);
622+}
623+
624+OM_uint32 KRB5_CALLCONV
625+iakerb_gss_set_sec_context_option(OM_uint32 *minor_status,
626+ gss_ctx_id_t *context_handle,
627+ const gss_OID desired_object,
628+ const gss_buffer_t value)
629+{
630+ iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)*context_handle;
631+
632+ if (ctx == NULL || ctx->gssc == GSS_C_NO_CONTEXT)
633+ return GSS_S_UNAVAILABLE;
634+
635+ return krb5_gss_set_sec_context_option(minor_status, &ctx->gssc,
636+ desired_object, value);
637+}
638+
639+OM_uint32 KRB5_CALLCONV
640+iakerb_gss_wrap_iov(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
641+ int conf_req_flag, gss_qop_t qop_req, int *conf_state,
642+ gss_iov_buffer_desc *iov, int iov_count)
643+{
644+ iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle;
645+
646+ if (ctx->gssc == GSS_C_NO_CONTEXT)
647+ return GSS_S_NO_CONTEXT;
648+
649+ return krb5_gss_wrap_iov(minor_status, ctx->gssc, conf_req_flag, qop_req,
650+ conf_state, iov, iov_count);
651+}
652+
653+OM_uint32 KRB5_CALLCONV
654+iakerb_gss_unwrap_iov(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
655+ int *conf_state, gss_qop_t *qop_state,
656+ gss_iov_buffer_desc *iov, int iov_count)
657+{
658+ iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle;
659+
660+ if (ctx->gssc == GSS_C_NO_CONTEXT)
661+ return GSS_S_NO_CONTEXT;
662+
663+ return krb5_gss_unwrap_iov(minor_status, ctx->gssc, conf_state, qop_state,
664+ iov, iov_count);
665+}
666+
667+OM_uint32 KRB5_CALLCONV
668+iakerb_gss_wrap_iov_length(OM_uint32 *minor_status,
669+ gss_ctx_id_t context_handle, int conf_req_flag,
670+ gss_qop_t qop_req, int *conf_state,
671+ gss_iov_buffer_desc *iov, int iov_count)
672+{
673+ iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle;
674+
675+ if (ctx->gssc == GSS_C_NO_CONTEXT)
676+ return GSS_S_NO_CONTEXT;
677+
678+ return krb5_gss_wrap_iov_length(minor_status, ctx->gssc, conf_req_flag,
679+ qop_req, conf_state, iov, iov_count);
680+}
681+
682+OM_uint32 KRB5_CALLCONV
683+iakerb_gss_pseudo_random(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
684+ int prf_key, const gss_buffer_t prf_in,
685+ ssize_t desired_output_len, gss_buffer_t prf_out)
686+{
687+ iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle;
688+
689+ if (ctx->gssc == GSS_C_NO_CONTEXT)
690+ return GSS_S_NO_CONTEXT;
691+
692+ return krb5_gss_pseudo_random(minor_status, ctx->gssc, prf_key, prf_in,
693+ desired_output_len, prf_out);
694+}
695+
696+OM_uint32 KRB5_CALLCONV
697+iakerb_gss_get_mic_iov(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
698+ gss_qop_t qop_req, gss_iov_buffer_desc *iov,
699+ int iov_count)
700+{
701+ iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle;
702+
703+ if (ctx->gssc == GSS_C_NO_CONTEXT)
704+ return GSS_S_NO_CONTEXT;
705+
706+ return krb5_gss_get_mic_iov(minor_status, ctx->gssc, qop_req, iov,
707+ iov_count);
708+}
709+
710+OM_uint32 KRB5_CALLCONV
711+iakerb_gss_verify_mic_iov(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
712+ gss_qop_t *qop_state, gss_iov_buffer_desc *iov,
713+ int iov_count)
714+{
715+ iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle;
716+
717+ if (ctx->gssc == GSS_C_NO_CONTEXT)
718+ return GSS_S_NO_CONTEXT;
719+
720+ return krb5_gss_verify_mic_iov(minor_status, ctx->gssc, qop_state, iov,
721+ iov_count);
722+}
723+
724+OM_uint32 KRB5_CALLCONV
725+iakerb_gss_get_mic_iov_length(OM_uint32 *minor_status,
726+ gss_ctx_id_t context_handle, gss_qop_t qop_req,
727+ gss_iov_buffer_desc *iov, int iov_count)
728+{
729+ iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle;
730+
731+ if (ctx->gssc == GSS_C_NO_CONTEXT)
732+ return GSS_S_NO_CONTEXT;
733+
734+ return krb5_gss_get_mic_iov_length(minor_status, ctx->gssc, qop_req, iov,
735+ iov_count);
736+}
737--
7381.9.1
739