1*7f2fe78bSCy Schubert /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2*7f2fe78bSCy Schubert /* tests/gssapi/common.c - Common utility functions for GSSAPI test programs */
3*7f2fe78bSCy Schubert /*
4*7f2fe78bSCy Schubert * Copyright (C) 2012 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 <stdio.h>
34*7f2fe78bSCy Schubert #include <string.h>
35*7f2fe78bSCy Schubert #include "common.h"
36*7f2fe78bSCy Schubert
37*7f2fe78bSCy Schubert gss_OID_desc mech_krb5 = { 9, "\052\206\110\206\367\022\001\002\002" };
38*7f2fe78bSCy Schubert gss_OID_desc mech_spnego = { 6, "\053\006\001\005\005\002" };
39*7f2fe78bSCy Schubert gss_OID_desc mech_iakerb = { 6, "\053\006\001\005\002\005" };
40*7f2fe78bSCy Schubert gss_OID_set_desc mechset_krb5 = { 1, &mech_krb5 };
41*7f2fe78bSCy Schubert gss_OID_set_desc mechset_spnego = { 1, &mech_spnego };
42*7f2fe78bSCy Schubert gss_OID_set_desc mechset_iakerb = { 1, &mech_iakerb };
43*7f2fe78bSCy Schubert
44*7f2fe78bSCy Schubert static void
display_status(const char * msg,OM_uint32 code,int type)45*7f2fe78bSCy Schubert display_status(const char *msg, OM_uint32 code, int type)
46*7f2fe78bSCy Schubert {
47*7f2fe78bSCy Schubert OM_uint32 min_stat, msg_ctx = 0;
48*7f2fe78bSCy Schubert gss_buffer_desc buf;
49*7f2fe78bSCy Schubert
50*7f2fe78bSCy Schubert do {
51*7f2fe78bSCy Schubert (void)gss_display_status(&min_stat, code, type, GSS_C_NULL_OID,
52*7f2fe78bSCy Schubert &msg_ctx, &buf);
53*7f2fe78bSCy Schubert fprintf(stderr, "%s: %.*s\n", msg, (int)buf.length, (char *)buf.value);
54*7f2fe78bSCy Schubert (void)gss_release_buffer(&min_stat, &buf);
55*7f2fe78bSCy Schubert } while (msg_ctx != 0);
56*7f2fe78bSCy Schubert }
57*7f2fe78bSCy Schubert
58*7f2fe78bSCy Schubert void
check_gsserr(const char * msg,OM_uint32 major,OM_uint32 minor)59*7f2fe78bSCy Schubert check_gsserr(const char *msg, OM_uint32 major, OM_uint32 minor)
60*7f2fe78bSCy Schubert {
61*7f2fe78bSCy Schubert if (GSS_ERROR(major)) {
62*7f2fe78bSCy Schubert display_status(msg, major, GSS_C_GSS_CODE);
63*7f2fe78bSCy Schubert display_status(msg, minor, GSS_C_MECH_CODE);
64*7f2fe78bSCy Schubert exit(1);
65*7f2fe78bSCy Schubert }
66*7f2fe78bSCy Schubert }
67*7f2fe78bSCy Schubert
68*7f2fe78bSCy Schubert void
check_k5err(krb5_context context,const char * msg,krb5_error_code code)69*7f2fe78bSCy Schubert check_k5err(krb5_context context, const char *msg, krb5_error_code code)
70*7f2fe78bSCy Schubert {
71*7f2fe78bSCy Schubert const char *errmsg;
72*7f2fe78bSCy Schubert
73*7f2fe78bSCy Schubert if (code) {
74*7f2fe78bSCy Schubert errmsg = krb5_get_error_message(context, code);
75*7f2fe78bSCy Schubert printf("%s: %s\n", msg, errmsg);
76*7f2fe78bSCy Schubert krb5_free_error_message(context, errmsg);
77*7f2fe78bSCy Schubert exit(1);
78*7f2fe78bSCy Schubert }
79*7f2fe78bSCy Schubert }
80*7f2fe78bSCy Schubert
81*7f2fe78bSCy Schubert void
errout(const char * msg)82*7f2fe78bSCy Schubert errout(const char *msg)
83*7f2fe78bSCy Schubert {
84*7f2fe78bSCy Schubert fprintf(stderr, "%s\n", msg);
85*7f2fe78bSCy Schubert exit(1);
86*7f2fe78bSCy Schubert }
87*7f2fe78bSCy Schubert
88*7f2fe78bSCy Schubert gss_name_t
import_name(const char * str)89*7f2fe78bSCy Schubert import_name(const char *str)
90*7f2fe78bSCy Schubert {
91*7f2fe78bSCy Schubert OM_uint32 major, minor;
92*7f2fe78bSCy Schubert gss_name_t name;
93*7f2fe78bSCy Schubert gss_buffer_desc buf;
94*7f2fe78bSCy Schubert gss_OID nametype = NULL;
95*7f2fe78bSCy Schubert
96*7f2fe78bSCy Schubert if (*str == 'u')
97*7f2fe78bSCy Schubert nametype = GSS_C_NT_USER_NAME;
98*7f2fe78bSCy Schubert else if (*str == 'p')
99*7f2fe78bSCy Schubert nametype = (gss_OID)GSS_KRB5_NT_PRINCIPAL_NAME;
100*7f2fe78bSCy Schubert else if (*str == 'e')
101*7f2fe78bSCy Schubert nametype = (gss_OID)GSS_KRB5_NT_ENTERPRISE_NAME;
102*7f2fe78bSCy Schubert else if (*str == 'c')
103*7f2fe78bSCy Schubert nametype = (gss_OID)GSS_KRB5_NT_X509_CERT;
104*7f2fe78bSCy Schubert else if (*str == 'h')
105*7f2fe78bSCy Schubert nametype = GSS_C_NT_HOSTBASED_SERVICE;
106*7f2fe78bSCy Schubert if (nametype == NULL || str[1] != ':')
107*7f2fe78bSCy Schubert errout("names must begin with u: or p: or e: or c: or h:");
108*7f2fe78bSCy Schubert buf.value = (char *)str + 2;
109*7f2fe78bSCy Schubert buf.length = strlen(str) - 2;
110*7f2fe78bSCy Schubert major = gss_import_name(&minor, &buf, nametype, &name);
111*7f2fe78bSCy Schubert check_gsserr("gss_import_name", major, minor);
112*7f2fe78bSCy Schubert return name;
113*7f2fe78bSCy Schubert }
114*7f2fe78bSCy Schubert
115*7f2fe78bSCy Schubert void
establish_contexts(gss_OID imech,gss_cred_id_t icred,gss_cred_id_t acred,gss_name_t tname,OM_uint32 flags,gss_ctx_id_t * ictx,gss_ctx_id_t * actx,gss_name_t * src_name,gss_OID * amech,gss_cred_id_t * deleg_cred)116*7f2fe78bSCy Schubert establish_contexts(gss_OID imech, gss_cred_id_t icred, gss_cred_id_t acred,
117*7f2fe78bSCy Schubert gss_name_t tname, OM_uint32 flags, gss_ctx_id_t *ictx,
118*7f2fe78bSCy Schubert gss_ctx_id_t *actx, gss_name_t *src_name, gss_OID *amech,
119*7f2fe78bSCy Schubert gss_cred_id_t *deleg_cred)
120*7f2fe78bSCy Schubert {
121*7f2fe78bSCy Schubert establish_contexts_ex(imech, icred, acred, tname, flags, ictx, actx,
122*7f2fe78bSCy Schubert GSS_C_NO_CHANNEL_BINDINGS, GSS_C_NO_CHANNEL_BINDINGS,
123*7f2fe78bSCy Schubert NULL, src_name, amech, deleg_cred);
124*7f2fe78bSCy Schubert }
125*7f2fe78bSCy Schubert
126*7f2fe78bSCy Schubert void
establish_contexts_ex(gss_OID imech,gss_cred_id_t icred,gss_cred_id_t acred,gss_name_t tname,OM_uint32 flags,gss_ctx_id_t * ictx,gss_ctx_id_t * actx,gss_channel_bindings_t icb,gss_channel_bindings_t acb,OM_uint32 * aret_flags,gss_name_t * src_name,gss_OID * amech,gss_cred_id_t * deleg_cred)127*7f2fe78bSCy Schubert establish_contexts_ex(gss_OID imech, gss_cred_id_t icred, gss_cred_id_t acred,
128*7f2fe78bSCy Schubert gss_name_t tname, OM_uint32 flags, gss_ctx_id_t *ictx,
129*7f2fe78bSCy Schubert gss_ctx_id_t *actx, gss_channel_bindings_t icb,
130*7f2fe78bSCy Schubert gss_channel_bindings_t acb, OM_uint32 *aret_flags,
131*7f2fe78bSCy Schubert gss_name_t *src_name, gss_OID *amech,
132*7f2fe78bSCy Schubert gss_cred_id_t *deleg_cred)
133*7f2fe78bSCy Schubert {
134*7f2fe78bSCy Schubert OM_uint32 minor, imaj, amaj;
135*7f2fe78bSCy Schubert gss_buffer_desc itok, atok;
136*7f2fe78bSCy Schubert
137*7f2fe78bSCy Schubert *ictx = *actx = GSS_C_NO_CONTEXT;
138*7f2fe78bSCy Schubert imaj = amaj = GSS_S_CONTINUE_NEEDED;
139*7f2fe78bSCy Schubert itok.value = atok.value = NULL;
140*7f2fe78bSCy Schubert itok.length = atok.length = 0;
141*7f2fe78bSCy Schubert for (;;) {
142*7f2fe78bSCy Schubert (void)gss_release_buffer(&minor, &itok);
143*7f2fe78bSCy Schubert imaj = gss_init_sec_context(&minor, icred, ictx, tname, imech, flags,
144*7f2fe78bSCy Schubert GSS_C_INDEFINITE, icb, &atok, NULL, &itok,
145*7f2fe78bSCy Schubert NULL, NULL);
146*7f2fe78bSCy Schubert check_gsserr("gss_init_sec_context", imaj, minor);
147*7f2fe78bSCy Schubert if (amaj == GSS_S_COMPLETE)
148*7f2fe78bSCy Schubert break;
149*7f2fe78bSCy Schubert
150*7f2fe78bSCy Schubert (void)gss_release_buffer(&minor, &atok);
151*7f2fe78bSCy Schubert amaj = gss_accept_sec_context(&minor, actx, acred, &itok, acb,
152*7f2fe78bSCy Schubert src_name, amech, &atok, aret_flags, NULL,
153*7f2fe78bSCy Schubert deleg_cred);
154*7f2fe78bSCy Schubert check_gsserr("gss_accept_sec_context", amaj, minor);
155*7f2fe78bSCy Schubert (void)gss_release_buffer(&minor, &itok);
156*7f2fe78bSCy Schubert if (imaj == GSS_S_COMPLETE)
157*7f2fe78bSCy Schubert break;
158*7f2fe78bSCy Schubert }
159*7f2fe78bSCy Schubert
160*7f2fe78bSCy Schubert if (imaj != GSS_S_COMPLETE || amaj != GSS_S_COMPLETE)
161*7f2fe78bSCy Schubert errout("One side wants to continue after the other is done");
162*7f2fe78bSCy Schubert
163*7f2fe78bSCy Schubert (void)gss_release_buffer(&minor, &itok);
164*7f2fe78bSCy Schubert (void)gss_release_buffer(&minor, &atok);
165*7f2fe78bSCy Schubert }
166*7f2fe78bSCy Schubert
167*7f2fe78bSCy Schubert void
export_import_cred(gss_cred_id_t * cred)168*7f2fe78bSCy Schubert export_import_cred(gss_cred_id_t *cred)
169*7f2fe78bSCy Schubert {
170*7f2fe78bSCy Schubert OM_uint32 major, minor;
171*7f2fe78bSCy Schubert gss_buffer_desc buf;
172*7f2fe78bSCy Schubert
173*7f2fe78bSCy Schubert major = gss_export_cred(&minor, *cred, &buf);
174*7f2fe78bSCy Schubert check_gsserr("gss_export_cred", major, minor);
175*7f2fe78bSCy Schubert (void)gss_release_cred(&minor, cred);
176*7f2fe78bSCy Schubert major = gss_import_cred(&minor, &buf, cred);
177*7f2fe78bSCy Schubert check_gsserr("gss_import_cred", major, minor);
178*7f2fe78bSCy Schubert (void)gss_release_buffer(&minor, &buf);
179*7f2fe78bSCy Schubert }
180*7f2fe78bSCy Schubert
181*7f2fe78bSCy Schubert void
display_canon_name(const char * tag,gss_name_t name,gss_OID mech)182*7f2fe78bSCy Schubert display_canon_name(const char *tag, gss_name_t name, gss_OID mech)
183*7f2fe78bSCy Schubert {
184*7f2fe78bSCy Schubert gss_name_t canon;
185*7f2fe78bSCy Schubert OM_uint32 major, minor;
186*7f2fe78bSCy Schubert gss_buffer_desc buf;
187*7f2fe78bSCy Schubert
188*7f2fe78bSCy Schubert major = gss_canonicalize_name(&minor, name, mech, &canon);
189*7f2fe78bSCy Schubert check_gsserr("gss_canonicalize_name", major, minor);
190*7f2fe78bSCy Schubert
191*7f2fe78bSCy Schubert major = gss_display_name(&minor, canon, &buf, NULL);
192*7f2fe78bSCy Schubert check_gsserr("gss_display_name", major, minor);
193*7f2fe78bSCy Schubert
194*7f2fe78bSCy Schubert printf("%s:\t%.*s\n", tag, (int)buf.length, (char *)buf.value);
195*7f2fe78bSCy Schubert
196*7f2fe78bSCy Schubert (void)gss_release_name(&minor, &canon);
197*7f2fe78bSCy Schubert (void)gss_release_buffer(&minor, &buf);
198*7f2fe78bSCy Schubert }
199*7f2fe78bSCy Schubert
200*7f2fe78bSCy Schubert void
display_oid(const char * tag,gss_OID oid)201*7f2fe78bSCy Schubert display_oid(const char *tag, gss_OID oid)
202*7f2fe78bSCy Schubert {
203*7f2fe78bSCy Schubert OM_uint32 major, minor;
204*7f2fe78bSCy Schubert gss_buffer_desc buf;
205*7f2fe78bSCy Schubert
206*7f2fe78bSCy Schubert major = gss_oid_to_str(&minor, oid, &buf);
207*7f2fe78bSCy Schubert check_gsserr("gss_oid_to_str", major, minor);
208*7f2fe78bSCy Schubert if (tag != NULL)
209*7f2fe78bSCy Schubert printf("%s:\t", tag);
210*7f2fe78bSCy Schubert printf("%.*s\n", (int)buf.length, (char *)buf.value);
211*7f2fe78bSCy Schubert (void)gss_release_buffer(&minor, &buf);
212*7f2fe78bSCy Schubert }
213*7f2fe78bSCy Schubert
214*7f2fe78bSCy Schubert static void
dump_attribute(gss_name_t name,gss_buffer_t attribute,int noisy)215*7f2fe78bSCy Schubert dump_attribute(gss_name_t name, gss_buffer_t attribute, int noisy)
216*7f2fe78bSCy Schubert {
217*7f2fe78bSCy Schubert OM_uint32 major, minor;
218*7f2fe78bSCy Schubert gss_buffer_desc value;
219*7f2fe78bSCy Schubert gss_buffer_desc display_value;
220*7f2fe78bSCy Schubert int authenticated = 0;
221*7f2fe78bSCy Schubert int complete = 0;
222*7f2fe78bSCy Schubert int more = -1;
223*7f2fe78bSCy Schubert unsigned int i;
224*7f2fe78bSCy Schubert
225*7f2fe78bSCy Schubert while (more != 0) {
226*7f2fe78bSCy Schubert value.value = NULL;
227*7f2fe78bSCy Schubert display_value.value = NULL;
228*7f2fe78bSCy Schubert
229*7f2fe78bSCy Schubert major = gss_get_name_attribute(&minor, name, attribute, &authenticated,
230*7f2fe78bSCy Schubert &complete, &value, &display_value,
231*7f2fe78bSCy Schubert &more);
232*7f2fe78bSCy Schubert check_gsserr("gss_get_name_attribute", major, minor);
233*7f2fe78bSCy Schubert
234*7f2fe78bSCy Schubert printf("Attribute %.*s %s %s\n\n%.*s\n",
235*7f2fe78bSCy Schubert (int)attribute->length, (char *)attribute->value,
236*7f2fe78bSCy Schubert authenticated ? "Authenticated" : "",
237*7f2fe78bSCy Schubert complete ? "Complete" : "",
238*7f2fe78bSCy Schubert (int)display_value.length, (char *)display_value.value);
239*7f2fe78bSCy Schubert
240*7f2fe78bSCy Schubert if (noisy) {
241*7f2fe78bSCy Schubert for (i = 0; i < value.length; i++) {
242*7f2fe78bSCy Schubert if ((i % 32) == 0)
243*7f2fe78bSCy Schubert printf("\n");
244*7f2fe78bSCy Schubert printf("%02x", ((char *)value.value)[i] & 0xFF);
245*7f2fe78bSCy Schubert }
246*7f2fe78bSCy Schubert printf("\n\n");
247*7f2fe78bSCy Schubert }
248*7f2fe78bSCy Schubert
249*7f2fe78bSCy Schubert (void)gss_release_buffer(&minor, &value);
250*7f2fe78bSCy Schubert (void)gss_release_buffer(&minor, &display_value);
251*7f2fe78bSCy Schubert }
252*7f2fe78bSCy Schubert }
253*7f2fe78bSCy Schubert
254*7f2fe78bSCy Schubert void
enumerate_attributes(gss_name_t name,int noisy)255*7f2fe78bSCy Schubert enumerate_attributes(gss_name_t name, int noisy)
256*7f2fe78bSCy Schubert {
257*7f2fe78bSCy Schubert OM_uint32 major, minor;
258*7f2fe78bSCy Schubert int is_mechname;
259*7f2fe78bSCy Schubert gss_buffer_set_t attrs = GSS_C_NO_BUFFER_SET;
260*7f2fe78bSCy Schubert size_t i;
261*7f2fe78bSCy Schubert
262*7f2fe78bSCy Schubert major = gss_inquire_name(&minor, name, &is_mechname, NULL, &attrs);
263*7f2fe78bSCy Schubert check_gsserr("gss_inquire_name", major, minor);
264*7f2fe78bSCy Schubert
265*7f2fe78bSCy Schubert if (attrs != GSS_C_NO_BUFFER_SET) {
266*7f2fe78bSCy Schubert for (i = 0; i < attrs->count; i++)
267*7f2fe78bSCy Schubert dump_attribute(name, &attrs->elements[i], noisy);
268*7f2fe78bSCy Schubert }
269*7f2fe78bSCy Schubert
270*7f2fe78bSCy Schubert (void)gss_release_buffer_set(&minor, &attrs);
271*7f2fe78bSCy Schubert }
272*7f2fe78bSCy Schubert
273*7f2fe78bSCy Schubert void
print_hex(FILE * fp,gss_buffer_t buf)274*7f2fe78bSCy Schubert print_hex(FILE *fp, gss_buffer_t buf)
275*7f2fe78bSCy Schubert {
276*7f2fe78bSCy Schubert size_t i;
277*7f2fe78bSCy Schubert const unsigned char *bytes = buf->value;
278*7f2fe78bSCy Schubert
279*7f2fe78bSCy Schubert for (i = 0; i < buf->length; i++)
280*7f2fe78bSCy Schubert printf("%02X", bytes[i]);
281*7f2fe78bSCy Schubert printf("\n");
282*7f2fe78bSCy Schubert }
283