1/* 2 * Copyright (c) 2003-2007 Kungliga Tekniska Högskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * 3. Neither the name of KTH nor the names of its contributors may be 18 * used to endorse or promote products derived from this software without 19 * specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY 22 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE 25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 28 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34#include <config.h> 35 36#include <roken.h> 37#include <stdio.h> 38#include <stdlib.h> 39#include <string.h> 40#include <stdarg.h> 41#include <gssapi.h> 42#include <gssapi_krb5.h> 43#include <gssapi_spi.h> 44#include <err.h> 45#include <getarg.h> 46#include <base64.h> 47 48#include "test_common.h" 49 50static int verbose_flag; 51 52static void 53print_time(OM_uint32 time_rec) 54{ 55 if (time_rec == GSS_C_INDEFINITE) { 56 printf("cred never expire\n"); 57 } else { 58 time_t t = time_rec + time(NULL); 59 printf("expiration time: %s", ctime(&t)); 60 } 61} 62 63static void 64test_add(gss_const_OID mech, int flag, gss_cred_id_t cred_handle) 65{ 66 OM_uint32 major_status, minor_status; 67 gss_cred_id_t copy_cred; 68 OM_uint32 time_rec; 69 70 if (verbose_flag) 71 printf("trying add cred\n"); 72 73 major_status = gss_add_cred (&minor_status, 74 cred_handle, 75 GSS_C_NO_NAME, 76 rk_UNCONST(mech), 77 flag, 78 0, 79 0, 80 ©_cred, 81 NULL, 82 &time_rec, 83 NULL); 84 85 if (GSS_ERROR(major_status)) 86 errx(1, "add_cred failed"); 87 88 if (verbose_flag) 89 print_time(time_rec); 90 91 major_status = gss_release_cred(&minor_status, 92 ©_cred); 93 if (GSS_ERROR(major_status)) 94 errx(1, "release_cred failed"); 95} 96 97#if 0 98 99static void 100copy_cred(void) 101{ 102 OM_uint32 major_status, minor_status; 103 gss_cred_id_t cred_handle; 104 OM_uint32 time_rec; 105 106 major_status = gss_acquire_cred(&minor_status, 107 GSS_C_NO_NAME, 108 0, 109 NULL, 110 GSS_C_INITIATE, 111 &cred_handle, 112 NULL, 113 &time_rec); 114 if (GSS_ERROR(major_status)) 115 errx(1, "acquire_cred failed"); 116 117 if (verbose_flag) 118 print_time(time_rec); 119 120 test_add(cred_handle); 121 test_add(cred_handle); 122 test_add(cred_handle); 123 124 major_status = gss_release_cred(&minor_status, 125 &cred_handle); 126 if (GSS_ERROR(major_status)) 127 errx(1, "release_cred failed"); 128} 129#endif 130 131static gss_cred_id_t 132acquire_cred_service(gss_buffer_t name_buffer, 133 gss_OID nametype, 134 gss_OID_set oidset, 135 int flags) 136{ 137 OM_uint32 major_status, minor_status; 138 gss_cred_id_t cred_handle; 139 OM_uint32 time_rec; 140 gss_name_t name = GSS_C_NO_NAME; 141 142 if (name_buffer) { 143 major_status = gss_import_name(&minor_status, 144 name_buffer, 145 nametype, 146 &name); 147 if (GSS_ERROR(major_status)) 148 errx(1, "import_name failed"); 149 } 150 151 major_status = gss_acquire_cred(&minor_status, 152 name, 153 0, 154 oidset, 155 flags, 156 &cred_handle, 157 NULL, 158 &time_rec); 159 if (GSS_ERROR(major_status)) { 160 warnx("acquire_cred failed: %s", 161 gssapi_err(major_status, minor_status, GSS_C_NO_OID)); 162 } else { 163 if (verbose_flag) 164 print_time(time_rec); 165 } 166 167 if (name != GSS_C_NO_NAME) 168 gss_release_name(&minor_status, &name); 169 170 if (GSS_ERROR(major_status)) 171 exit(1); 172 173 return cred_handle; 174} 175 176static int version_flag = 0; 177static int help_flag = 0; 178static int kerberos_flag = 0; 179static int enctype = 0; 180static int no_ui_flag = 0; 181static char *acquire_name; 182static char *acquire_type; 183static char *cred_type; 184static char *mech_type; 185static char *target_name; 186static char *name_type; 187static char *ccache; 188static int anonymous_flag; 189static int num_loops = 1; 190 191static struct getargs args[] = { 192 {"acquire-name", 0, arg_string, &acquire_name, "name", NULL }, 193 {"acquire-type", 0, arg_string, &acquire_type, "type", NULL }, 194 {"enctype", 0, arg_integer, &enctype, "enctype-num", NULL }, 195 {"loops", 0, arg_integer, &num_loops, "enctype-num", NULL }, 196 {"kerberos", 0, arg_flag, &kerberos_flag, "enctype-num", NULL }, 197 {"target-name", 0, arg_string, &target_name, "name", NULL }, 198 {"ccache", 0, arg_string, &ccache, "name", NULL }, 199 {"name-type", 0, arg_string, &name_type, "type", NULL }, 200 {"cred-type", 0, arg_string, &cred_type, "mech-oid", NULL }, 201 {"mech-type", 0, arg_string, &mech_type, "mech-oid", NULL }, 202 {"no-ui", 0, arg_flag, &no_ui_flag, NULL }, 203 {"anonymous", 0, arg_flag, &anonymous_flag, NULL }, 204 {"verbose", 0, arg_flag, &verbose_flag, NULL }, 205 {"version", 0, arg_flag, &version_flag, "print version", NULL }, 206 {"help", 0, arg_flag, &help_flag, NULL, NULL } 207}; 208 209static void 210usage (int ret) 211{ 212 arg_printusage (args, sizeof(args)/sizeof(*args), NULL, ""); 213 exit (ret); 214} 215 216int 217main(int argc, char **argv) 218{ 219 gss_OID_set oidset = GSS_C_NULL_OID_SET; 220 gss_const_OID mechoid = GSS_C_NO_OID; 221 gss_const_OID credoid = GSS_C_NO_OID; 222 OM_uint32 maj_stat, min_stat, isc_flags; 223 gss_cred_id_t cred; 224 gss_name_t target = GSS_C_NO_NAME; 225 int i, optidx = 0; 226 OM_uint32 flag; 227 gss_OID type; 228 gss_buffer_t acquire_name_buffer = GSS_C_NO_BUFFER; 229 gss_buffer_desc acquire_name_buffer_desc = { 0, NULL }; 230 int export_name = 0; 231 uint8_t *decoded_name = NULL; 232 233 setprogname(argv[0]); 234 if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) 235 usage(1); 236 237 if (help_flag) 238 usage (0); 239 240 if(version_flag){ 241 print_version(NULL); 242 exit(0); 243 } 244 245 argc -= optidx; 246 247 if (argc != 0) 248 usage(1); 249 250 if (acquire_type) { 251 if (strcasecmp(acquire_type, "both") == 0) 252 flag = GSS_C_BOTH; 253 else if (strcasecmp(acquire_type, "accept") == 0) 254 flag = GSS_C_ACCEPT; 255 else if (strcasecmp(acquire_type, "initiate") == 0) 256 flag = GSS_C_INITIATE; 257 else 258 errx(1, "unknown type %s", acquire_type); 259 } else 260 flag = GSS_C_INITIATE; 261 262 if (no_ui_flag) 263 flag |= GSS_C_CRED_NO_UI; 264 265 if (name_type) { 266 if (strcasecmp("hostbased-service", name_type) == 0) 267 type = GSS_C_NT_HOSTBASED_SERVICE; 268 else if (strcasecmp("user-name", name_type) == 0) 269 type = GSS_C_NT_USER_NAME; 270 else if (strcasecmp("krb5-principal-name", name_type) == 0) 271 type = GSS_KRB5_NT_PRINCIPAL_NAME; 272 else if (strcasecmp("krb5-principal-name-referral", name_type) == 0) 273 type = GSS_KRB5_NT_PRINCIPAL_NAME_REFERRAL; 274 else if (strcasecmp("anonymous", name_type) == 0) { 275 type = GSS_C_NT_ANONYMOUS; 276 acquire_name_buffer = &acquire_name_buffer_desc; 277 } else if (strcasecmp("export-name", name_type) == 0) { 278 type = GSS_C_NT_EXPORT_NAME; 279 export_name = 1; 280 } else 281 errx(1, "unknown name type %s", name_type); 282 } else 283 type = GSS_C_NT_HOSTBASED_SERVICE; 284 285 if (ccache) { 286 maj_stat = gss_krb5_ccache_name(&min_stat, ccache, NULL); 287 if (GSS_ERROR(maj_stat)) 288 errx(1, "gss_krb5_ccache_name %s", 289 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 290 } 291 292 if (kerberos_flag) 293 mechoid = GSS_KRB5_MECHANISM; 294 295 if (mech_type) 296 mechoid = gss_name_to_oid(mech_type); 297 298 if (cred_type) { 299 credoid = gss_name_to_oid(cred_type); 300 if (credoid == NULL) 301 errx(1, "failed to find cred type %s", cred_type); 302 303 maj_stat = gss_create_empty_oid_set(&min_stat, &oidset); 304 if (maj_stat != GSS_S_COMPLETE) 305 errx(1, "gss_create_empty_oid_set: %s", 306 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 307 308 maj_stat = gss_add_oid_set_member(&min_stat, credoid, &oidset); 309 if (maj_stat != GSS_S_COMPLETE) 310 errx(1, "gss_add_oid_set_member: %s", 311 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 312 } 313 314 if (target_name) { 315 gss_buffer_desc name; 316 317 name.value = target_name; 318 name.length = strlen(target_name); 319 maj_stat = gss_import_name(&min_stat, &name, 320 GSS_C_NT_HOSTBASED_SERVICE, &target); 321 if (maj_stat != GSS_S_COMPLETE) 322 errx(1, "gss_import_name: %s", 323 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 324 } 325 326 if (acquire_name) { 327 acquire_name_buffer = &acquire_name_buffer_desc; 328 329 if (export_name) { 330 int len; 331 332 decoded_name = emalloc(strlen(acquire_name)); 333 len = base64_decode(acquire_name, decoded_name); 334 if (len < 0) 335 abort(); 336 337 acquire_name_buffer->value = decoded_name; 338 acquire_name_buffer->length = len; 339 } else { 340 acquire_name_buffer->value = acquire_name; 341 acquire_name_buffer->length = strlen(acquire_name); 342 } 343 } 344 345 isc_flags = GSS_C_MUTUAL_FLAG; 346 if (anonymous_flag) 347 isc_flags |= GSS_C_ANON_FLAG; 348 349 for (i = 0; i < num_loops; i++) { 350 351 cred = acquire_cred_service(acquire_name_buffer, type, oidset, flag); 352 353 if (credoid) { 354 int j; 355 356 for (j = 0; j < 10; j++) 357 test_add(credoid, flag, cred); 358 } 359 360 if (enctype) { 361 int32_t enctypelist = enctype; 362 363 maj_stat = gss_krb5_set_allowable_enctypes(&min_stat, cred, 364 1, &enctypelist); 365 if (maj_stat) 366 errx(1, "gss_krb5_set_allowable_enctypes: %s", 367 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 368 } 369 370 if (target) { 371 gss_ctx_id_t context = GSS_C_NO_CONTEXT; 372 gss_buffer_desc out; 373 374 out.length = 0; 375 out.value = NULL; 376 377 maj_stat = gss_init_sec_context(&min_stat, 378 cred, &context, 379 target, rk_UNCONST(mechoid), 380 isc_flags, 0, NULL, 381 GSS_C_NO_BUFFER, NULL, 382 &out, NULL, NULL); 383 if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED) 384 errx(1, "init_sec_context failed: %s", 385 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 386 387 gss_release_buffer(&min_stat, &out); 388 gss_delete_sec_context(&min_stat, &context, NULL); 389 } 390 gss_release_cred(&min_stat, &cred); 391 } 392 393 cred = acquire_cred_service(acquire_name_buffer, type, NULL, flag); 394 if (cred) 395 gss_release_cred(&min_stat, &cred); 396 397 if (decoded_name) 398 free(decoded_name); 399 400 return 0; 401} 402