1*7f2fe78bSCy Schubert /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2*7f2fe78bSCy Schubert /* plugins/gssapi/negoextest/main.c - GSS test module for NegoEx */
3*7f2fe78bSCy Schubert /*
4*7f2fe78bSCy Schubert * Copyright (C) 2019 by the Massachusetts Institute of Technology.
5*7f2fe78bSCy Schubert * All rights reserved.
6*7f2fe78bSCy Schubert *
7*7f2fe78bSCy Schubert * Redistribution and use in source and binary forms, with or without
8*7f2fe78bSCy Schubert * modification, are permitted provided that the following conditions
9*7f2fe78bSCy Schubert * are met:
10*7f2fe78bSCy Schubert *
11*7f2fe78bSCy Schubert * * Redistributions of source code must retain the above copyright
12*7f2fe78bSCy Schubert * notice, this list of conditions and the following disclaimer.
13*7f2fe78bSCy Schubert *
14*7f2fe78bSCy Schubert * * Redistributions in binary form must reproduce the above copyright
15*7f2fe78bSCy Schubert * notice, this list of conditions and the following disclaimer in
16*7f2fe78bSCy Schubert * the documentation and/or other materials provided with the
17*7f2fe78bSCy Schubert * distribution.
18*7f2fe78bSCy Schubert *
19*7f2fe78bSCy Schubert * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20*7f2fe78bSCy Schubert * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21*7f2fe78bSCy Schubert * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22*7f2fe78bSCy Schubert * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23*7f2fe78bSCy Schubert * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
24*7f2fe78bSCy Schubert * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25*7f2fe78bSCy Schubert * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26*7f2fe78bSCy Schubert * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27*7f2fe78bSCy Schubert * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28*7f2fe78bSCy Schubert * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29*7f2fe78bSCy Schubert * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
30*7f2fe78bSCy Schubert * OF THE POSSIBILITY OF SUCH DAMAGE.
31*7f2fe78bSCy Schubert */
32*7f2fe78bSCy Schubert
33*7f2fe78bSCy Schubert #include "k5-int.h"
34*7f2fe78bSCy Schubert #include <gssapi/gssapi.h>
35*7f2fe78bSCy Schubert #include <gssapi/gssapi_ext.h>
36*7f2fe78bSCy Schubert #include <gssapi/gssapi_alloc.h>
37*7f2fe78bSCy Schubert
38*7f2fe78bSCy Schubert struct test_context {
39*7f2fe78bSCy Schubert int initiator;
40*7f2fe78bSCy Schubert uint8_t hops; /* hops remaining; 0 means established */
41*7f2fe78bSCy Schubert };
42*7f2fe78bSCy Schubert
43*7f2fe78bSCy Schubert OM_uint32 KRB5_CALLCONV
gss_init_sec_context(OM_uint32 * minor_status,gss_cred_id_t claimant_cred_handle,gss_ctx_id_t * context_handle,gss_name_t target_name,gss_OID mech_type,OM_uint32 req_flags,OM_uint32 time_req,gss_channel_bindings_t input_chan_bindings,gss_buffer_t input_token,gss_OID * actual_mech,gss_buffer_t output_token,OM_uint32 * ret_flags,OM_uint32 * time_rec)44*7f2fe78bSCy Schubert gss_init_sec_context(OM_uint32 *minor_status,
45*7f2fe78bSCy Schubert gss_cred_id_t claimant_cred_handle,
46*7f2fe78bSCy Schubert gss_ctx_id_t *context_handle, gss_name_t target_name,
47*7f2fe78bSCy Schubert gss_OID mech_type, OM_uint32 req_flags,
48*7f2fe78bSCy Schubert OM_uint32 time_req,
49*7f2fe78bSCy Schubert gss_channel_bindings_t input_chan_bindings,
50*7f2fe78bSCy Schubert gss_buffer_t input_token, gss_OID *actual_mech,
51*7f2fe78bSCy Schubert gss_buffer_t output_token, OM_uint32 *ret_flags,
52*7f2fe78bSCy Schubert OM_uint32 *time_rec)
53*7f2fe78bSCy Schubert {
54*7f2fe78bSCy Schubert struct test_context *ctx = (struct test_context *)*context_handle;
55*7f2fe78bSCy Schubert OM_uint32 major;
56*7f2fe78bSCy Schubert gss_buffer_desc tok;
57*7f2fe78bSCy Schubert const char *envstr;
58*7f2fe78bSCy Schubert uint8_t hops, mech_last_octet;
59*7f2fe78bSCy Schubert
60*7f2fe78bSCy Schubert envstr = getenv("GSS_INIT_BINDING");
61*7f2fe78bSCy Schubert if (envstr != NULL) {
62*7f2fe78bSCy Schubert assert(strlen(envstr) > 0);
63*7f2fe78bSCy Schubert assert(input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS);
64*7f2fe78bSCy Schubert assert(strlen(envstr) == input_chan_bindings->application_data.length);
65*7f2fe78bSCy Schubert assert(strcmp((char *)input_chan_bindings->application_data.value,
66*7f2fe78bSCy Schubert envstr) == 0);
67*7f2fe78bSCy Schubert }
68*7f2fe78bSCy Schubert
69*7f2fe78bSCy Schubert if (input_token == GSS_C_NO_BUFFER || input_token->length == 0) {
70*7f2fe78bSCy Schubert envstr = getenv("HOPS");
71*7f2fe78bSCy Schubert hops = (envstr != NULL) ? atoi(envstr) : 1;
72*7f2fe78bSCy Schubert assert(hops > 0);
73*7f2fe78bSCy Schubert } else if (input_token->length == 4 &&
74*7f2fe78bSCy Schubert memcmp(input_token->value, "fail", 4) == 0) {
75*7f2fe78bSCy Schubert *minor_status = 12345;
76*7f2fe78bSCy Schubert return GSS_S_FAILURE;
77*7f2fe78bSCy Schubert } else {
78*7f2fe78bSCy Schubert hops = ((uint8_t *)input_token->value)[0];
79*7f2fe78bSCy Schubert }
80*7f2fe78bSCy Schubert
81*7f2fe78bSCy Schubert mech_last_octet = ((uint8_t *)mech_type->elements)[mech_type->length - 1];
82*7f2fe78bSCy Schubert envstr = getenv("INIT_FAIL");
83*7f2fe78bSCy Schubert if (envstr != NULL && atoi(envstr) == mech_last_octet)
84*7f2fe78bSCy Schubert return GSS_S_FAILURE;
85*7f2fe78bSCy Schubert
86*7f2fe78bSCy Schubert if (ctx == NULL) {
87*7f2fe78bSCy Schubert ctx = malloc(sizeof(*ctx));
88*7f2fe78bSCy Schubert assert(ctx != NULL);
89*7f2fe78bSCy Schubert ctx->initiator = 1;
90*7f2fe78bSCy Schubert ctx->hops = hops;
91*7f2fe78bSCy Schubert *context_handle = (gss_ctx_id_t)ctx;
92*7f2fe78bSCy Schubert } else if (ctx != NULL) {
93*7f2fe78bSCy Schubert assert(ctx->initiator);
94*7f2fe78bSCy Schubert ctx->hops--;
95*7f2fe78bSCy Schubert assert(ctx->hops == hops);
96*7f2fe78bSCy Schubert }
97*7f2fe78bSCy Schubert
98*7f2fe78bSCy Schubert if (ctx->hops > 0) {
99*7f2fe78bSCy Schubert /* Generate a token containing the remaining hop count. */
100*7f2fe78bSCy Schubert ctx->hops--;
101*7f2fe78bSCy Schubert tok.value = &ctx->hops;
102*7f2fe78bSCy Schubert tok.length = 1;
103*7f2fe78bSCy Schubert major = gss_encapsulate_token(&tok, mech_type, output_token);
104*7f2fe78bSCy Schubert assert(major == GSS_S_COMPLETE);
105*7f2fe78bSCy Schubert }
106*7f2fe78bSCy Schubert
107*7f2fe78bSCy Schubert return (ctx->hops > 0) ? GSS_S_CONTINUE_NEEDED : GSS_S_COMPLETE;
108*7f2fe78bSCy Schubert }
109*7f2fe78bSCy Schubert
110*7f2fe78bSCy Schubert OM_uint32 KRB5_CALLCONV
gss_accept_sec_context(OM_uint32 * minor_status,gss_ctx_id_t * context_handle,gss_cred_id_t verifier_cred_handle,gss_buffer_t input_token,gss_channel_bindings_t input_chan_bindings,gss_name_t * src_name,gss_OID * mech_type,gss_buffer_t output_token,OM_uint32 * ret_flags,OM_uint32 * time_rec,gss_cred_id_t * delegated_cred_handle)111*7f2fe78bSCy Schubert gss_accept_sec_context(OM_uint32 *minor_status, gss_ctx_id_t *context_handle,
112*7f2fe78bSCy Schubert gss_cred_id_t verifier_cred_handle,
113*7f2fe78bSCy Schubert gss_buffer_t input_token,
114*7f2fe78bSCy Schubert gss_channel_bindings_t input_chan_bindings,
115*7f2fe78bSCy Schubert gss_name_t *src_name, gss_OID *mech_type,
116*7f2fe78bSCy Schubert gss_buffer_t output_token, OM_uint32 *ret_flags,
117*7f2fe78bSCy Schubert OM_uint32 *time_rec,
118*7f2fe78bSCy Schubert gss_cred_id_t *delegated_cred_handle)
119*7f2fe78bSCy Schubert {
120*7f2fe78bSCy Schubert struct test_context *ctx = (struct test_context *)*context_handle;
121*7f2fe78bSCy Schubert uint8_t hops, mech_last_octet;
122*7f2fe78bSCy Schubert const char *envstr;
123*7f2fe78bSCy Schubert
124*7f2fe78bSCy Schubert envstr = getenv("GSS_ACCEPT_BINDING");
125*7f2fe78bSCy Schubert if (envstr != NULL) {
126*7f2fe78bSCy Schubert assert(strlen(envstr) > 0);
127*7f2fe78bSCy Schubert assert(input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS);
128*7f2fe78bSCy Schubert assert(strlen(envstr) == input_chan_bindings->application_data.length);
129*7f2fe78bSCy Schubert assert(strcmp((char *)input_chan_bindings->application_data.value,
130*7f2fe78bSCy Schubert envstr) == 0);
131*7f2fe78bSCy Schubert }
132*7f2fe78bSCy Schubert
133*7f2fe78bSCy Schubert /*
134*7f2fe78bSCy Schubert * The unwrapped token sits at the end and is just one byte giving the
135*7f2fe78bSCy Schubert * remaining number of hops. The final octet of the mech encoding should
136*7f2fe78bSCy Schubert * be just prior to it.
137*7f2fe78bSCy Schubert */
138*7f2fe78bSCy Schubert assert(input_token->length >= 2);
139*7f2fe78bSCy Schubert hops = ((uint8_t *)input_token->value)[input_token->length - 1];
140*7f2fe78bSCy Schubert mech_last_octet = ((uint8_t *)input_token->value)[input_token->length - 2];
141*7f2fe78bSCy Schubert
142*7f2fe78bSCy Schubert envstr = getenv("ACCEPT_FAIL");
143*7f2fe78bSCy Schubert if (envstr != NULL && atoi(envstr) == mech_last_octet) {
144*7f2fe78bSCy Schubert output_token->value = gssalloc_strdup("fail");
145*7f2fe78bSCy Schubert assert(output_token->value != NULL);
146*7f2fe78bSCy Schubert output_token->length = 4;
147*7f2fe78bSCy Schubert return GSS_S_FAILURE;
148*7f2fe78bSCy Schubert }
149*7f2fe78bSCy Schubert
150*7f2fe78bSCy Schubert if (*context_handle == GSS_C_NO_CONTEXT) {
151*7f2fe78bSCy Schubert ctx = malloc(sizeof(*ctx));
152*7f2fe78bSCy Schubert assert(ctx != NULL);
153*7f2fe78bSCy Schubert ctx->initiator = 0;
154*7f2fe78bSCy Schubert ctx->hops = hops;
155*7f2fe78bSCy Schubert *context_handle = (gss_ctx_id_t)ctx;
156*7f2fe78bSCy Schubert } else {
157*7f2fe78bSCy Schubert assert(!ctx->initiator);
158*7f2fe78bSCy Schubert ctx->hops--;
159*7f2fe78bSCy Schubert assert(ctx->hops == hops);
160*7f2fe78bSCy Schubert }
161*7f2fe78bSCy Schubert
162*7f2fe78bSCy Schubert if (ctx->hops > 0) {
163*7f2fe78bSCy Schubert /* Generate a token containing the remaining hop count. */
164*7f2fe78bSCy Schubert ctx->hops--;
165*7f2fe78bSCy Schubert output_token->value = gssalloc_malloc(1);
166*7f2fe78bSCy Schubert assert(output_token->value != NULL);
167*7f2fe78bSCy Schubert memcpy(output_token->value, &ctx->hops, 1);
168*7f2fe78bSCy Schubert output_token->length = 1;
169*7f2fe78bSCy Schubert }
170*7f2fe78bSCy Schubert
171*7f2fe78bSCy Schubert return (ctx->hops > 0) ? GSS_S_CONTINUE_NEEDED : GSS_S_COMPLETE;
172*7f2fe78bSCy Schubert }
173*7f2fe78bSCy Schubert
174*7f2fe78bSCy Schubert OM_uint32 KRB5_CALLCONV
gss_delete_sec_context(OM_uint32 * minor_status,gss_ctx_id_t * context_handle,gss_buffer_t output_token)175*7f2fe78bSCy Schubert gss_delete_sec_context(OM_uint32 *minor_status, gss_ctx_id_t *context_handle,
176*7f2fe78bSCy Schubert gss_buffer_t output_token)
177*7f2fe78bSCy Schubert {
178*7f2fe78bSCy Schubert free(*context_handle);
179*7f2fe78bSCy Schubert *context_handle = GSS_C_NO_CONTEXT;
180*7f2fe78bSCy Schubert return GSS_S_COMPLETE;
181*7f2fe78bSCy Schubert }
182*7f2fe78bSCy Schubert
183*7f2fe78bSCy Schubert OM_uint32 KRB5_CALLCONV
gss_acquire_cred(OM_uint32 * minor_status,gss_name_t desired_name,OM_uint32 time_req,gss_OID_set desired_mechs,gss_cred_usage_t cred_usage,gss_cred_id_t * output_cred_handle,gss_OID_set * actual_mechs,OM_uint32 * time_rec)184*7f2fe78bSCy Schubert gss_acquire_cred(OM_uint32 *minor_status, gss_name_t desired_name,
185*7f2fe78bSCy Schubert OM_uint32 time_req, gss_OID_set desired_mechs,
186*7f2fe78bSCy Schubert gss_cred_usage_t cred_usage,
187*7f2fe78bSCy Schubert gss_cred_id_t *output_cred_handle, gss_OID_set *actual_mechs,
188*7f2fe78bSCy Schubert OM_uint32 *time_rec)
189*7f2fe78bSCy Schubert {
190*7f2fe78bSCy Schubert return GSS_S_COMPLETE;
191*7f2fe78bSCy Schubert }
192*7f2fe78bSCy Schubert
193*7f2fe78bSCy Schubert OM_uint32 KRB5_CALLCONV
gss_acquire_cred_with_password(OM_uint32 * minor_status,const gss_name_t desired_name,const gss_buffer_t password,OM_uint32 time_req,const gss_OID_set desired_mechs,gss_cred_usage_t cred_usage,gss_cred_id_t * output_cred_handle,gss_OID_set * actual_mechs,OM_uint32 * time_rec)194*7f2fe78bSCy Schubert gss_acquire_cred_with_password(OM_uint32 *minor_status,
195*7f2fe78bSCy Schubert const gss_name_t desired_name,
196*7f2fe78bSCy Schubert const gss_buffer_t password, OM_uint32 time_req,
197*7f2fe78bSCy Schubert const gss_OID_set desired_mechs,
198*7f2fe78bSCy Schubert gss_cred_usage_t cred_usage,
199*7f2fe78bSCy Schubert gss_cred_id_t *output_cred_handle,
200*7f2fe78bSCy Schubert gss_OID_set *actual_mechs, OM_uint32 *time_rec)
201*7f2fe78bSCy Schubert {
202*7f2fe78bSCy Schubert return GSS_S_COMPLETE;
203*7f2fe78bSCy Schubert }
204*7f2fe78bSCy Schubert
205*7f2fe78bSCy Schubert OM_uint32 KRB5_CALLCONV
gss_release_cred(OM_uint32 * minor_status,gss_cred_id_t * cred_handle)206*7f2fe78bSCy Schubert gss_release_cred(OM_uint32 *minor_status, gss_cred_id_t *cred_handle)
207*7f2fe78bSCy Schubert {
208*7f2fe78bSCy Schubert return GSS_S_COMPLETE;
209*7f2fe78bSCy Schubert }
210*7f2fe78bSCy Schubert
211*7f2fe78bSCy Schubert OM_uint32 KRB5_CALLCONV
gss_import_name(OM_uint32 * minor_status,gss_buffer_t input_name_buffer,gss_OID input_name_type,gss_name_t * output_name)212*7f2fe78bSCy Schubert gss_import_name(OM_uint32 *minor_status, gss_buffer_t input_name_buffer,
213*7f2fe78bSCy Schubert gss_OID input_name_type, gss_name_t *output_name)
214*7f2fe78bSCy Schubert {
215*7f2fe78bSCy Schubert static int dummy;
216*7f2fe78bSCy Schubert
217*7f2fe78bSCy Schubert /*
218*7f2fe78bSCy Schubert * We don't need to remember anything about names, but we do need to
219*7f2fe78bSCy Schubert * distinguish them from GSS_C_NO_NAME (to determine the direction of
220*7f2fe78bSCy Schubert * gss_query_meta_data() and gss_exchange_meta_data()), so assign an
221*7f2fe78bSCy Schubert * arbitrary data pointer.
222*7f2fe78bSCy Schubert */
223*7f2fe78bSCy Schubert *output_name = (gss_name_t)&dummy;
224*7f2fe78bSCy Schubert return GSS_S_COMPLETE;
225*7f2fe78bSCy Schubert }
226*7f2fe78bSCy Schubert
227*7f2fe78bSCy Schubert OM_uint32 KRB5_CALLCONV
gss_release_name(OM_uint32 * minor_status,gss_name_t * input_name)228*7f2fe78bSCy Schubert gss_release_name(OM_uint32 *minor_status, gss_name_t *input_name)
229*7f2fe78bSCy Schubert {
230*7f2fe78bSCy Schubert return GSS_S_COMPLETE;
231*7f2fe78bSCy Schubert }
232*7f2fe78bSCy Schubert
233*7f2fe78bSCy Schubert OM_uint32 KRB5_CALLCONV
gss_display_status(OM_uint32 * minor_status,OM_uint32 status_value,int status_type,gss_OID mech_type,OM_uint32 * message_context,gss_buffer_t status_string)234*7f2fe78bSCy Schubert gss_display_status(OM_uint32 *minor_status, OM_uint32 status_value,
235*7f2fe78bSCy Schubert int status_type, gss_OID mech_type,
236*7f2fe78bSCy Schubert OM_uint32 *message_context, gss_buffer_t status_string)
237*7f2fe78bSCy Schubert {
238*7f2fe78bSCy Schubert if (status_type == GSS_C_MECH_CODE && status_value == 12345) {
239*7f2fe78bSCy Schubert status_string->value = gssalloc_strdup("failure from acceptor");
240*7f2fe78bSCy Schubert assert(status_string->value != NULL);
241*7f2fe78bSCy Schubert status_string->length = strlen(status_string->value);
242*7f2fe78bSCy Schubert return GSS_S_COMPLETE;
243*7f2fe78bSCy Schubert }
244*7f2fe78bSCy Schubert return GSS_S_BAD_STATUS;
245*7f2fe78bSCy Schubert }
246*7f2fe78bSCy Schubert
247*7f2fe78bSCy Schubert OM_uint32 KRB5_CALLCONV
gssspi_query_meta_data(OM_uint32 * minor_status,gss_const_OID mech_oid,gss_cred_id_t cred_handle,gss_ctx_id_t * context_handle,const gss_name_t targ_name,OM_uint32 req_flags,gss_buffer_t meta_data)248*7f2fe78bSCy Schubert gssspi_query_meta_data(OM_uint32 *minor_status, gss_const_OID mech_oid,
249*7f2fe78bSCy Schubert gss_cred_id_t cred_handle, gss_ctx_id_t *context_handle,
250*7f2fe78bSCy Schubert const gss_name_t targ_name, OM_uint32 req_flags,
251*7f2fe78bSCy Schubert gss_buffer_t meta_data)
252*7f2fe78bSCy Schubert {
253*7f2fe78bSCy Schubert const char *envstr;
254*7f2fe78bSCy Schubert uint8_t mech_last_octet;
255*7f2fe78bSCy Schubert int initiator = (targ_name != GSS_C_NO_NAME);
256*7f2fe78bSCy Schubert
257*7f2fe78bSCy Schubert mech_last_octet = ((uint8_t *)mech_oid->elements)[mech_oid->length - 1];
258*7f2fe78bSCy Schubert envstr = getenv(initiator ? "INIT_QUERY_FAIL" : "ACCEPT_QUERY_FAIL");
259*7f2fe78bSCy Schubert if (envstr != NULL && atoi(envstr) == mech_last_octet)
260*7f2fe78bSCy Schubert return GSS_S_FAILURE;
261*7f2fe78bSCy Schubert envstr = getenv(initiator ? "INIT_QUERY_NONE" : "ACCEPT_QUERY_NONE");
262*7f2fe78bSCy Schubert if (envstr != NULL && atoi(envstr) == mech_last_octet)
263*7f2fe78bSCy Schubert return GSS_S_COMPLETE;
264*7f2fe78bSCy Schubert
265*7f2fe78bSCy Schubert meta_data->value = gssalloc_strdup("X");
266*7f2fe78bSCy Schubert meta_data->length = 1;
267*7f2fe78bSCy Schubert return GSS_S_COMPLETE;
268*7f2fe78bSCy Schubert }
269*7f2fe78bSCy Schubert
270*7f2fe78bSCy Schubert OM_uint32 KRB5_CALLCONV
gssspi_exchange_meta_data(OM_uint32 * minor_status,gss_const_OID mech_oid,gss_cred_id_t cred_handle,gss_ctx_id_t * context_handle,const gss_name_t targ_name,OM_uint32 req_flags,gss_const_buffer_t meta_data)271*7f2fe78bSCy Schubert gssspi_exchange_meta_data(OM_uint32 *minor_status, gss_const_OID mech_oid,
272*7f2fe78bSCy Schubert gss_cred_id_t cred_handle,
273*7f2fe78bSCy Schubert gss_ctx_id_t *context_handle,
274*7f2fe78bSCy Schubert const gss_name_t targ_name, OM_uint32 req_flags,
275*7f2fe78bSCy Schubert gss_const_buffer_t meta_data)
276*7f2fe78bSCy Schubert {
277*7f2fe78bSCy Schubert const char *envstr;
278*7f2fe78bSCy Schubert uint8_t mech_last_octet;
279*7f2fe78bSCy Schubert int initiator = (targ_name != GSS_C_NO_NAME);
280*7f2fe78bSCy Schubert
281*7f2fe78bSCy Schubert mech_last_octet = ((uint8_t *)mech_oid->elements)[mech_oid->length - 1];
282*7f2fe78bSCy Schubert envstr = getenv(initiator ? "INIT_EXCHANGE_FAIL" : "ACCEPT_EXCHANGE_FAIL");
283*7f2fe78bSCy Schubert if (envstr != NULL && atoi(envstr) == mech_last_octet)
284*7f2fe78bSCy Schubert return GSS_S_FAILURE;
285*7f2fe78bSCy Schubert
286*7f2fe78bSCy Schubert assert(meta_data->length == 1 && memcmp(meta_data->value, "X", 1) == 0);
287*7f2fe78bSCy Schubert return GSS_S_COMPLETE;
288*7f2fe78bSCy Schubert }
289*7f2fe78bSCy Schubert
290*7f2fe78bSCy Schubert OM_uint32 KRB5_CALLCONV
gssspi_query_mechanism_info(OM_uint32 * minor_status,gss_const_OID mech_oid,unsigned char auth_scheme[16])291*7f2fe78bSCy Schubert gssspi_query_mechanism_info(OM_uint32 *minor_status, gss_const_OID mech_oid,
292*7f2fe78bSCy Schubert unsigned char auth_scheme[16])
293*7f2fe78bSCy Schubert {
294*7f2fe78bSCy Schubert /* Copy the mech OID encoding and right-pad it with zeros. */
295*7f2fe78bSCy Schubert memset(auth_scheme, 0, 16);
296*7f2fe78bSCy Schubert assert(mech_oid->length <= 16);
297*7f2fe78bSCy Schubert memcpy(auth_scheme, mech_oid->elements, mech_oid->length);
298*7f2fe78bSCy Schubert return GSS_S_COMPLETE;
299*7f2fe78bSCy Schubert }
300*7f2fe78bSCy Schubert
301*7f2fe78bSCy Schubert OM_uint32 KRB5_CALLCONV
gss_inquire_sec_context_by_oid(OM_uint32 * minor_status,const gss_ctx_id_t context_handle,const gss_OID desired_object,gss_buffer_set_t * data_set)302*7f2fe78bSCy Schubert gss_inquire_sec_context_by_oid(OM_uint32 *minor_status,
303*7f2fe78bSCy Schubert const gss_ctx_id_t context_handle,
304*7f2fe78bSCy Schubert const gss_OID desired_object,
305*7f2fe78bSCy Schubert gss_buffer_set_t *data_set)
306*7f2fe78bSCy Schubert {
307*7f2fe78bSCy Schubert struct test_context *ctx = (struct test_context *)context_handle;
308*7f2fe78bSCy Schubert OM_uint32 major;
309*7f2fe78bSCy Schubert uint8_t keybytes[32] = { 0 };
310*7f2fe78bSCy Schubert uint8_t typebytes[4];
311*7f2fe78bSCy Schubert gss_buffer_desc key, type;
312*7f2fe78bSCy Schubert const char *envstr;
313*7f2fe78bSCy Schubert int ask_verify;
314*7f2fe78bSCy Schubert
315*7f2fe78bSCy Schubert if (gss_oid_equal(desired_object, GSS_C_INQ_NEGOEX_KEY))
316*7f2fe78bSCy Schubert ask_verify = 0;
317*7f2fe78bSCy Schubert else if (gss_oid_equal(desired_object, GSS_C_INQ_NEGOEX_VERIFY_KEY))
318*7f2fe78bSCy Schubert ask_verify = 1;
319*7f2fe78bSCy Schubert else
320*7f2fe78bSCy Schubert return GSS_S_UNAVAILABLE;
321*7f2fe78bSCy Schubert
322*7f2fe78bSCy Schubert /*
323*7f2fe78bSCy Schubert * By default, make a key available only if the context is established.
324*7f2fe78bSCy Schubert * This can be overridden to "always", "init-always", "accept-always",
325*7f2fe78bSCy Schubert * or "never".
326*7f2fe78bSCy Schubert */
327*7f2fe78bSCy Schubert envstr = getenv("KEY");
328*7f2fe78bSCy Schubert if (envstr != NULL && strcmp(envstr, "never") == 0) {
329*7f2fe78bSCy Schubert return GSS_S_UNAVAILABLE;
330*7f2fe78bSCy Schubert } else if (ctx->hops > 0) {
331*7f2fe78bSCy Schubert if (envstr == NULL)
332*7f2fe78bSCy Schubert return GSS_S_UNAVAILABLE;
333*7f2fe78bSCy Schubert else if (strcmp(envstr, "init-always") == 0 && !ctx->initiator)
334*7f2fe78bSCy Schubert return GSS_S_UNAVAILABLE;
335*7f2fe78bSCy Schubert else if (strcmp(envstr, "accept-always") == 0 && ctx->initiator)
336*7f2fe78bSCy Schubert return GSS_S_UNAVAILABLE;
337*7f2fe78bSCy Schubert }
338*7f2fe78bSCy Schubert
339*7f2fe78bSCy Schubert /* Perturb the key so that each side's verifier key is equal to the other's
340*7f2fe78bSCy Schubert * checksum key. */
341*7f2fe78bSCy Schubert keybytes[0] = ask_verify ^ ctx->initiator;
342*7f2fe78bSCy Schubert
343*7f2fe78bSCy Schubert /* Supply an all-zeros aes256-sha1 negoex key. */
344*7f2fe78bSCy Schubert if (gss_oid_equal(desired_object, GSS_C_INQ_NEGOEX_KEY) ||
345*7f2fe78bSCy Schubert gss_oid_equal(desired_object, GSS_C_INQ_NEGOEX_VERIFY_KEY)) {
346*7f2fe78bSCy Schubert store_32_le(ENCTYPE_AES256_CTS_HMAC_SHA1_96, typebytes);
347*7f2fe78bSCy Schubert key.value = keybytes;
348*7f2fe78bSCy Schubert key.length = sizeof(keybytes);
349*7f2fe78bSCy Schubert type.value = typebytes;
350*7f2fe78bSCy Schubert type.length = sizeof(typebytes);
351*7f2fe78bSCy Schubert major = gss_add_buffer_set_member(minor_status, &key, data_set);
352*7f2fe78bSCy Schubert if (major != GSS_S_COMPLETE)
353*7f2fe78bSCy Schubert return major;
354*7f2fe78bSCy Schubert return gss_add_buffer_set_member(minor_status, &type, data_set);
355*7f2fe78bSCy Schubert }
356*7f2fe78bSCy Schubert
357*7f2fe78bSCy Schubert return GSS_S_UNAVAILABLE;
358*7f2fe78bSCy Schubert }
359