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 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 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 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 82 errout(const char *msg) 83 { 84 fprintf(stderr, "%s\n", msg); 85 exit(1); 86 } 87 88 gss_name_t 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 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 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 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 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 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 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 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 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