xref: /freebsd/crypto/krb5/src/tests/gssapi/common.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* tests/gssapi/common.c - Common utility functions for GSSAPI test programs */
3 /*
4  * Copyright (C) 2012 by the Massachusetts Institute of Technology.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  *   notice, this list of conditions and the following disclaimer.
13  *
14  * * Redistributions in binary form must reproduce the above copyright
15  *   notice, this list of conditions and the following disclaimer in
16  *   the documentation and/or other materials provided with the
17  *   distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
24  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
30  * OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #include <stdio.h>
34 #include <string.h>
35 #include "common.h"
36 
37 gss_OID_desc mech_krb5 = { 9, "\052\206\110\206\367\022\001\002\002" };
38 gss_OID_desc mech_spnego = { 6, "\053\006\001\005\005\002" };
39 gss_OID_desc mech_iakerb = { 6, "\053\006\001\005\002\005" };
40 gss_OID_set_desc mechset_krb5 = { 1, &mech_krb5 };
41 gss_OID_set_desc mechset_spnego = { 1, &mech_spnego };
42 gss_OID_set_desc mechset_iakerb = { 1, &mech_iakerb };
43 
44 static void
display_status(const char * msg,OM_uint32 code,int type)45 display_status(const char *msg, OM_uint32 code, int type)
46 {
47     OM_uint32 min_stat, msg_ctx = 0;
48     gss_buffer_desc buf;
49 
50     do {
51         (void)gss_display_status(&min_stat, code, type, GSS_C_NULL_OID,
52                                  &msg_ctx, &buf);
53         fprintf(stderr, "%s: %.*s\n", msg, (int)buf.length, (char *)buf.value);
54         (void)gss_release_buffer(&min_stat, &buf);
55     } while (msg_ctx != 0);
56 }
57 
58 void
check_gsserr(const char * msg,OM_uint32 major,OM_uint32 minor)59 check_gsserr(const char *msg, OM_uint32 major, OM_uint32 minor)
60 {
61     if (GSS_ERROR(major)) {
62         display_status(msg, major, GSS_C_GSS_CODE);
63         display_status(msg, minor, GSS_C_MECH_CODE);
64         exit(1);
65     }
66 }
67 
68 void
check_k5err(krb5_context context,const char * msg,krb5_error_code code)69 check_k5err(krb5_context context, const char *msg, krb5_error_code code)
70 {
71     const char *errmsg;
72 
73     if (code) {
74         errmsg = krb5_get_error_message(context, code);
75         printf("%s: %s\n", msg, errmsg);
76         krb5_free_error_message(context, errmsg);
77         exit(1);
78     }
79 }
80 
81 void
errout(const char * msg)82 errout(const char *msg)
83 {
84     fprintf(stderr, "%s\n", msg);
85     exit(1);
86 }
87 
88 gss_name_t
import_name(const char * str)89 import_name(const char *str)
90 {
91     OM_uint32 major, minor;
92     gss_name_t name;
93     gss_buffer_desc buf;
94     gss_OID nametype = NULL;
95 
96     if (*str == 'u')
97         nametype = GSS_C_NT_USER_NAME;
98     else if (*str == 'p')
99         nametype = (gss_OID)GSS_KRB5_NT_PRINCIPAL_NAME;
100     else if (*str == 'e')
101         nametype = (gss_OID)GSS_KRB5_NT_ENTERPRISE_NAME;
102     else if (*str == 'c')
103         nametype = (gss_OID)GSS_KRB5_NT_X509_CERT;
104     else if (*str == 'h')
105         nametype = GSS_C_NT_HOSTBASED_SERVICE;
106     if (nametype == NULL || str[1] != ':')
107         errout("names must begin with u: or p: or e: or c: or h:");
108     buf.value = (char *)str + 2;
109     buf.length = strlen(str) - 2;
110     major = gss_import_name(&minor, &buf, nametype, &name);
111     check_gsserr("gss_import_name", major, minor);
112     return name;
113 }
114 
115 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 establish_contexts(gss_OID imech, gss_cred_id_t icred, gss_cred_id_t acred,
117                    gss_name_t tname, OM_uint32 flags, gss_ctx_id_t *ictx,
118                    gss_ctx_id_t *actx, gss_name_t *src_name, gss_OID *amech,
119                    gss_cred_id_t *deleg_cred)
120 {
121     establish_contexts_ex(imech, icred, acred, tname, flags, ictx, actx,
122                           GSS_C_NO_CHANNEL_BINDINGS, GSS_C_NO_CHANNEL_BINDINGS,
123                           NULL, src_name, amech, deleg_cred);
124 }
125 
126 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 establish_contexts_ex(gss_OID imech, gss_cred_id_t icred, gss_cred_id_t acred,
128                       gss_name_t tname, OM_uint32 flags, gss_ctx_id_t *ictx,
129                       gss_ctx_id_t *actx, gss_channel_bindings_t icb,
130                       gss_channel_bindings_t acb, OM_uint32 *aret_flags,
131                       gss_name_t *src_name, gss_OID *amech,
132                       gss_cred_id_t *deleg_cred)
133 {
134     OM_uint32 minor, imaj, amaj;
135     gss_buffer_desc itok, atok;
136 
137     *ictx = *actx = GSS_C_NO_CONTEXT;
138     imaj = amaj = GSS_S_CONTINUE_NEEDED;
139     itok.value = atok.value = NULL;
140     itok.length = atok.length = 0;
141     for (;;) {
142         (void)gss_release_buffer(&minor, &itok);
143         imaj = gss_init_sec_context(&minor, icred, ictx, tname, imech, flags,
144                                     GSS_C_INDEFINITE, icb, &atok, NULL, &itok,
145                                     NULL, NULL);
146         check_gsserr("gss_init_sec_context", imaj, minor);
147         if (amaj == GSS_S_COMPLETE)
148             break;
149 
150         (void)gss_release_buffer(&minor, &atok);
151         amaj = gss_accept_sec_context(&minor, actx, acred, &itok, acb,
152                                       src_name, amech, &atok, aret_flags, NULL,
153                                       deleg_cred);
154         check_gsserr("gss_accept_sec_context", amaj, minor);
155         (void)gss_release_buffer(&minor, &itok);
156         if (imaj == GSS_S_COMPLETE)
157             break;
158     }
159 
160     if (imaj != GSS_S_COMPLETE || amaj != GSS_S_COMPLETE)
161         errout("One side wants to continue after the other is done");
162 
163     (void)gss_release_buffer(&minor, &itok);
164     (void)gss_release_buffer(&minor, &atok);
165 }
166 
167 void
export_import_cred(gss_cred_id_t * cred)168 export_import_cred(gss_cred_id_t *cred)
169 {
170     OM_uint32 major, minor;
171     gss_buffer_desc buf;
172 
173     major = gss_export_cred(&minor, *cred, &buf);
174     check_gsserr("gss_export_cred", major, minor);
175     (void)gss_release_cred(&minor, cred);
176     major = gss_import_cred(&minor, &buf, cred);
177     check_gsserr("gss_import_cred", major, minor);
178     (void)gss_release_buffer(&minor, &buf);
179 }
180 
181 void
display_canon_name(const char * tag,gss_name_t name,gss_OID mech)182 display_canon_name(const char *tag, gss_name_t name, gss_OID mech)
183 {
184     gss_name_t canon;
185     OM_uint32 major, minor;
186     gss_buffer_desc buf;
187 
188     major = gss_canonicalize_name(&minor, name, mech, &canon);
189     check_gsserr("gss_canonicalize_name", major, minor);
190 
191     major = gss_display_name(&minor, canon, &buf, NULL);
192     check_gsserr("gss_display_name", major, minor);
193 
194     printf("%s:\t%.*s\n", tag, (int)buf.length, (char *)buf.value);
195 
196     (void)gss_release_name(&minor, &canon);
197     (void)gss_release_buffer(&minor, &buf);
198 }
199 
200 void
display_oid(const char * tag,gss_OID oid)201 display_oid(const char *tag, gss_OID oid)
202 {
203     OM_uint32 major, minor;
204     gss_buffer_desc buf;
205 
206     major = gss_oid_to_str(&minor, oid, &buf);
207     check_gsserr("gss_oid_to_str", major, minor);
208     if (tag != NULL)
209         printf("%s:\t", tag);
210     printf("%.*s\n", (int)buf.length, (char *)buf.value);
211     (void)gss_release_buffer(&minor, &buf);
212 }
213 
214 static void
dump_attribute(gss_name_t name,gss_buffer_t attribute,int noisy)215 dump_attribute(gss_name_t name, gss_buffer_t attribute, int noisy)
216 {
217     OM_uint32 major, minor;
218     gss_buffer_desc value;
219     gss_buffer_desc display_value;
220     int authenticated = 0;
221     int complete = 0;
222     int more = -1;
223     unsigned int i;
224 
225     while (more != 0) {
226         value.value = NULL;
227         display_value.value = NULL;
228 
229         major = gss_get_name_attribute(&minor, name, attribute, &authenticated,
230                                        &complete, &value, &display_value,
231                                        &more);
232         check_gsserr("gss_get_name_attribute", major, minor);
233 
234         printf("Attribute %.*s %s %s\n\n%.*s\n",
235                (int)attribute->length, (char *)attribute->value,
236                authenticated ? "Authenticated" : "",
237                complete ? "Complete" : "",
238                (int)display_value.length, (char *)display_value.value);
239 
240         if (noisy) {
241             for (i = 0; i < value.length; i++) {
242                 if ((i % 32) == 0)
243                     printf("\n");
244                 printf("%02x", ((char *)value.value)[i] & 0xFF);
245             }
246             printf("\n\n");
247         }
248 
249         (void)gss_release_buffer(&minor, &value);
250         (void)gss_release_buffer(&minor, &display_value);
251     }
252 }
253 
254 void
enumerate_attributes(gss_name_t name,int noisy)255 enumerate_attributes(gss_name_t name, int noisy)
256 {
257     OM_uint32 major, minor;
258     int is_mechname;
259     gss_buffer_set_t attrs = GSS_C_NO_BUFFER_SET;
260     size_t i;
261 
262     major = gss_inquire_name(&minor, name, &is_mechname, NULL, &attrs);
263     check_gsserr("gss_inquire_name", major, minor);
264 
265     if (attrs != GSS_C_NO_BUFFER_SET) {
266         for (i = 0; i < attrs->count; i++)
267             dump_attribute(name, &attrs->elements[i], noisy);
268     }
269 
270     (void)gss_release_buffer_set(&minor, &attrs);
271 }
272 
273 void
print_hex(FILE * fp,gss_buffer_t buf)274 print_hex(FILE *fp, gss_buffer_t buf)
275 {
276     size_t i;
277     const unsigned char *bytes = buf->value;
278 
279     for (i = 0; i < buf->length; i++)
280         printf("%02X", bytes[i]);
281     printf("\n");
282 }
283