1/* 2 * Copyright (c) 2006 Kungliga Tekniska Högskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Portions Copyright (c) 2009 - 2010 Apple Inc. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * 3. Neither the name of KTH nor the names of its contributors may be 20 * used to endorse or promote products derived from this software without 21 * specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY 24 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE 27 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 30 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 31 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 32 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 33 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 */ 35 36#include <config.h> 37 38#include <stdio.h> 39#include <gssapi.h> 40#include <gssapi_krb5.h> 41#include <gssapi_spnego.h> 42#include <gssapi_ntlm.h> 43#include <gssapi_oid.h> 44#include <gssapi_spi.h> 45#include <heim-ipc.h> 46#include <err.h> 47#include <roken.h> 48#include <getarg.h> 49#include <rtbl.h> 50#include <hex.h> 51#include <gss-commands.h> 52#include <krb5.h> 53#ifdef __APPLE__ 54#include <heimcred.h> 55#endif 56#include <parse_time.h> 57 58#include "crypto-headers.h" 59 60static void usage (int ret) __attribute__((noreturn)); 61 62 63static int version_flag = 0; 64static int help_flag = 0; 65 66static struct getargs args[] = { 67 {"version", 0, arg_flag, &version_flag, "print version", NULL }, 68 {"help", 0, arg_flag, &help_flag, NULL, NULL } 69}; 70 71static void 72usage (int ret) 73{ 74 arg_printusage (args, sizeof(args)/sizeof(*args), 75 NULL, "service@host"); 76 exit (ret); 77} 78 79#define COL_DESC "Description" 80#define COL_ENABLED "Enabled" 81#define COL_EXPIRE "Expire" 82#define COL_MECH "Mech" 83#define COL_NAME "Name" 84#define COL_OID "OID" 85#define COL_OPTION "Option" 86#define COL_SASL "SASL" 87#define COL_VALUE "Value" 88#define COL_UUID "UUID" 89 90int 91supported_mechanisms(struct supported_mechanisms_options *opt, int argc, char **argv) 92{ 93 OM_uint32 maj_stat, min_stat; 94 gss_OID_set mechs; 95 rtbl_t ct; 96 size_t i; 97 98 maj_stat = gss_indicate_mechs(&min_stat, &mechs); 99 if (maj_stat != GSS_S_COMPLETE) 100 errx(1, "gss_indicate_mechs failed"); 101 102 printf("Supported mechanisms:\n"); 103 104 ct = rtbl_create(); 105 if (ct == NULL) 106 errx(1, "rtbl_create"); 107 108 rtbl_set_separator(ct, " "); 109 rtbl_add_column(ct, COL_OID, 0); 110 rtbl_add_column(ct, COL_NAME, 0); 111 rtbl_add_column(ct, COL_SASL, 0); 112 if (opt->options_flag) { 113 rtbl_add_column(ct, COL_OPTION, 0); 114 rtbl_add_column(ct, COL_ENABLED, 0); 115 } 116 117 for (i = 0; i < mechs->count; i++) { 118 gss_buffer_desc str; 119 const char *name = NULL; 120 121 maj_stat = gss_oid_to_str(&min_stat, &mechs->elements[i], &str); 122 if (maj_stat != GSS_S_COMPLETE) 123 errx(1, "gss_oid_to_str failed"); 124 125 rtbl_add_column_entryv(ct, COL_OID, "%.*s", 126 (int)str.length, (char *)str.value); 127 gss_release_buffer(&min_stat, &str); 128 129 name = gss_oid_to_name(&mechs->elements[i]); 130 if (name) 131 rtbl_add_column_entry(ct, COL_NAME, name); 132 else 133 rtbl_add_column_entry(ct, COL_NAME, ""); 134 135 maj_stat = gss_inquire_saslname_for_mech(&min_stat, &mechs->elements[i], &str, NULL, NULL); 136 if (maj_stat != GSS_S_COMPLETE) 137 errx(1, "gss_inquire_saslname_for_mech failed"); 138 rtbl_add_column_entryv(ct, COL_SASL, "%.*s", 139 (int)str.length, (char *)str.value); 140 gss_release_buffer(&min_stat, &str); 141 142 if (opt->options_flag) { 143 gss_OID_set options = GSS_C_NO_OID_SET; 144 gss_buffer_desc oname; 145 size_t n; 146 int ena; 147 148 gss_mo_list(&mechs->elements[i], &options); 149 150 rtbl_add_column_entry(ct, COL_OPTION, ""); 151 rtbl_add_column_entry(ct, COL_ENABLED, ""); 152 153 for (n = 0; options && n < options->count; n++) { 154 maj_stat = gss_mo_name(&mechs->elements[i], &options->elements[n], &oname); 155 if (maj_stat != GSS_S_COMPLETE) 156 continue; 157 158 rtbl_add_column_entry(ct, COL_OID, ""); 159 rtbl_add_column_entry(ct, COL_NAME, ""); 160 rtbl_add_column_entry(ct, COL_SASL, ""); 161 162 ena = gss_mo_get(&mechs->elements[i], &options->elements[n], NULL); 163 164 rtbl_add_column_entryv(ct, COL_OPTION, "%.*s", (int)oname.length, (char *)oname.value); 165 rtbl_add_column_entry(ct, COL_ENABLED, ena ? "yes" : "no"); 166 gss_release_buffer(&min_stat, &oname); 167 } 168 } 169 } 170 gss_release_oid_set(&min_stat, &mechs); 171 172 rtbl_format(ct, stdout); 173 rtbl_destroy(ct); 174 175 return 0; 176} 177 178int 179acquire_credential(struct acquire_credential_options *opt, int argc, char **argv) 180{ 181 char password[512]; 182 OM_uint32 maj_stat, min_stat; 183 gss_const_OID mech = NULL; 184 gss_OID nametype = GSS_C_NT_USER_NAME; 185 gss_name_t name = GSS_C_NO_NAME; 186 gss_buffer_desc buffer; 187 gss_cred_id_t cred = GSS_C_NO_CREDENTIAL; 188 CFMutableDictionaryRef attributes; 189 CFStringRef pw; 190 CFErrorRef error = NULL; 191 192 /* 193 * mech 194 */ 195 196 attributes = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 197 &kCFTypeDictionaryKeyCallBacks, 198 &kCFTypeDictionaryValueCallBacks); 199 if (attributes == NULL) 200 errx(1, "out of memory"); 201 202 if (opt->mech_string) { 203 mech = gss_name_to_oid(opt->mech_string); 204 if (mech == NULL) 205 errx(1, "No such mech: %s", opt->mech_string); 206 } else { 207 mech = GSS_KRB5_MECHANISM; 208 } 209 210 /* 211 * user 212 */ 213 214 if (opt->user_string == NULL && argc < 1) 215 errx(1, "no user string"); 216 217 if (opt->user_string) { 218 buffer.value = rk_UNCONST(opt->user_string); 219 buffer.length = strlen(opt->user_string); 220 } else { 221 buffer.value = argv[0]; 222 buffer.length = strlen(argv[0]); 223 } 224 225 maj_stat = gss_import_name(&min_stat, &buffer, nametype, &name); 226 if (maj_stat) 227 errx(1, "failed to import name"); 228 229 230 if (opt->certificate_persistant_string) { 231 size_t slen = strlen(opt->certificate_persistant_string); 232 CFMutableDataRef data = CFDataCreateMutable(NULL, slen); 233 ssize_t dlen; 234 235 CFDataSetLength(data, strlen); 236 237 dlen = hex_decode(opt->certificate_persistant_string, 238 CFDataGetMutableBytePtr(data), 239 slen); 240 if (dlen < 0) 241 errx(1, "failed to hex decode reference"); 242 243 CFDataSetLength(data, dlen); 244 245 CFDictionarySetValue(attributes, kGSSICCertificate, data); 246 CFRelease(data); 247 248 } else { 249 250 /* 251 * password 252 */ 253 254 if (UI_UTIL_read_pw_string(password, sizeof(password), 255 "Password: ", 0) != 0) 256 errx(1, "failed reading password"); 257 258 pw = CFStringCreateWithCString(kCFAllocatorDefault, password, kCFStringEncodingUTF8); 259 CFDictionarySetValue(attributes, kGSSICPassword, pw); 260 CFRelease(pw); 261 } 262 263 if (opt->validate_flag) 264 CFDictionarySetValue(attributes, kGSSICVerifyCredential, kCFBooleanTrue); 265 if (opt->kdc_hostname_string) { 266 CFStringRef hn = CFStringCreateWithCString(NULL, opt->kdc_hostname_string, kCFStringEncodingUTF8); 267 if (hn == NULL) 268 errx(1, "CFStringCreateWithCString"); 269 CFDictionarySetValue(attributes, kGSSICLKDCHostname, hn); 270 CFRelease(hn); 271 } 272 273 maj_stat = gss_aapl_initial_cred(name, 274 mech, 275 attributes, 276 &cred, 277 &error); 278 if (maj_stat != GSS_S_COMPLETE) { 279 char *msg = NULL; 280 if (error) { 281 CFStringRef m; 282 m = CFErrorCopyDescription(error); 283 if (m) { 284 msg = rk_cfstring2cstring(m); 285 CFRelease(m); 286 } 287 } 288 errx(1, "gss_aapl_initial_cred: %s: %d", 289 msg ? msg : "", (int)maj_stat); 290 } 291 gss_release_cred(&min_stat, &cred); 292 gss_release_name(&min_stat, &name); 293 294 CFRelease(attributes); 295 296 if (error) 297 CFRelease(error); 298 299 return 0; 300} 301 302 303struct print_cred { 304 rtbl_t t; 305}; 306 307static void 308print_cred(void *ctx, gss_const_OID oid, gss_cred_id_t cred) 309{ 310 struct print_cred *pc = ctx; 311 gss_buffer_set_t data_set; 312 OM_uint32 major, junk; 313 gss_buffer_desc buffer; 314 gss_name_t name; 315 const char *str; 316 OM_uint32 expire; 317 318 if (cred == NULL) 319 return; 320 321 major = gss_inquire_cred(&junk, cred, NULL, &expire, NULL, NULL); 322 if (major == GSS_S_CREDENTIALS_EXPIRED) 323 expire = 0; 324 else if (major) 325 goto out; 326 major = gss_inquire_cred_by_mech(&junk, cred, (gss_OID)oid, &name, NULL, NULL, NULL); 327 if (major) goto out; 328 major = gss_display_name(&junk, name, &buffer, NULL); 329 gss_release_name(&junk, &name); 330 if (major) goto out; 331 332 rtbl_add_column_entryv(pc->t, COL_NAME, "%.*s", 333 (int)buffer.length, (char *)buffer.value); 334 335 gss_release_buffer(&junk, &buffer); 336 337 str = gss_oid_to_name(oid); 338 if (str) 339 rtbl_add_column_entry(pc->t, COL_MECH, str); 340 341 if (expire == GSS_C_INDEFINITE) 342 rtbl_add_column_entryv(pc->t, COL_EXPIRE, "never"); 343 else if (expire == 0) 344 rtbl_add_column_entryv(pc->t, COL_EXPIRE, "expired"); 345 else { 346 char life[80]; 347 unparse_time_approx(expire, life, sizeof(life)); 348 rtbl_add_column_entry(pc->t, COL_EXPIRE, life); 349 } 350 351 major = gss_inquire_cred_by_oid(&junk, cred, GSS_C_NT_UUID, &data_set); 352 if (major == GSS_S_COMPLETE && data_set->count == 1) 353 rtbl_add_column_entryv(pc->t, COL_UUID, "%.*s\n", (int)data_set->elements[0].length, (const char *)data_set->elements[0].value); 354 else 355 rtbl_add_column_entry(pc->t, COL_UUID, ""); 356 357 gss_release_buffer_set(&junk, &data_set); 358 359 out: 360 gss_release_cred(&junk, &cred); 361} 362 363static void 364diag_cred(void *ctx, gss_const_OID oid, gss_cred_id_t cred) 365{ 366 const char *delim = "----------------"; 367 gss_buffer_set_t data_set; 368 gss_buffer_desc buffer; 369 OM_uint32 major, junk; 370 gss_name_t name; 371 const char *mech; 372 size_t n; 373 374 if (cred == NULL) 375 return; 376 377 major = gss_inquire_cred_by_mech(&junk, cred, (gss_OID)oid, &name, NULL, NULL, NULL); 378 if (major) 379 return; 380 381 major = gss_display_name(&junk, name, &buffer, NULL); 382 gss_release_name(&junk, &name); 383 if (major) 384 return; 385 386 mech = gss_oid_to_name(oid); 387 388 printf("@GSSCred\n%s\n%s: %.*s\n", 389 delim, 390 mech ? mech : "<unknown-mech>", 391 (int)buffer.length, buffer.value); 392 gss_release_buffer(&junk, &buffer); 393 394 major = gss_inquire_cred_by_oid(&junk, cred, GSS_C_CRED_DIAG, &data_set); 395 if (major) 396 return; 397 398 for (n = 0; n < data_set->count; n++) 399 printf("%s\n%.*s\n", delim, (int)data_set->elements[n].length, data_set->elements[n].value); 400 401 printf("%s\n", delim); 402 403 gss_release_buffer_set(&junk, &data_set); 404 405 major = gss_inquire_cred_by_oid(&junk, cred, GSS_C_NT_UUID, &data_set); 406 if (major == GSS_S_COMPLETE || data_set->count == 1) { 407 printf("UUID: %.*s\n", (int)data_set->elements[0].length, (const char *)data_set->elements[0].value); 408 printf("%s\n", delim); 409 } 410 gss_release_buffer_set(&junk, &data_set); 411 412 413} 414 415 416 417int 418list_credentials(struct list_credentials_options *opt, int argc, char **argv) 419{ 420 struct print_cred pc; 421 gss_const_OID mech = NULL; 422 423 if (opt->mech_string) { 424 mech = gss_name_to_oid(opt->mech_string); 425 if (mech == NULL) 426 errx(1, "No such mech: %s", opt->mech_string); 427 } 428 429 if (opt->verbose_flag) { 430 431 gss_iter_creds_f(NULL, 0, mech, NULL, diag_cred); 432 433 } else { 434 435 pc.t = rtbl_create(); 436 if (pc.t == NULL) 437 errx(1, "rtbl_create"); 438 439 rtbl_set_separator(pc.t, " "); 440 rtbl_add_column(pc.t, COL_NAME, 0); 441 rtbl_add_column(pc.t, COL_EXPIRE, 0); 442 rtbl_add_column(pc.t, COL_MECH, 0); 443 rtbl_add_column(pc.t, COL_UUID, 0); 444 445 gss_iter_creds_f(NULL, 0, mech, &pc, print_cred); 446 447 rtbl_format(pc.t, stdout); 448 rtbl_destroy(pc.t); 449 } 450 451 return 0; 452} 453 454static gss_cred_id_t 455acquire_cred(const char *name_string, gss_const_OID mech, gss_const_OID nametype) 456{ 457 OM_uint32 maj_stat, min_stat; 458 gss_OID_set mechset = NULL; 459 gss_cred_id_t cred = NULL; 460 gss_buffer_desc buffer; 461 gss_name_t name; 462 463 buffer.value = rk_UNCONST(name_string); 464 buffer.length = strlen(name_string); 465 466 maj_stat = gss_import_name(&min_stat, &buffer, nametype, &name); 467 if (maj_stat) 468 errx(1, "failed to import name"); 469 470 if (mech) { 471 gss_create_empty_oid_set(&min_stat, &mechset); 472 gss_add_oid_set_member(&min_stat, mech, &mechset); 473 } 474 475 maj_stat = gss_acquire_cred(&min_stat, name, GSS_C_INDEFINITE, 476 mechset, GSS_C_INITIATE, 477 &cred, NULL, NULL); 478 gss_release_name(&min_stat, &name); 479 gss_release_oid_set(&min_stat, &mechset); 480 if (maj_stat || cred == NULL) 481 errx(1, "acquire_cred failed"); 482 483 return cred; 484} 485 486static void 487destroy_cred(void *arg1, gss_const_OID oid, gss_cred_id_t cred) 488{ 489 gss_destroy_cred(NULL, &cred); 490} 491 492int 493destroy(struct destroy_options *opt, int argc, char **argv) 494{ 495 gss_const_OID mech = NULL; 496 497 if (opt->mech_string) { 498 mech = gss_name_to_oid(opt->mech_string); 499 if (mech == NULL) 500 errx(1, "No such mech: %s", opt->mech_string); 501 } 502 503 if (opt->all_flag) { 504 gss_iter_creds_f(NULL, 0, mech, NULL, destroy_cred); 505 } else { 506 gss_cred_id_t cred; 507 508 if (argc < 1) { 509 printf("%s: missing name\n", getprogname()); 510 return 1; 511 } 512 513 cred = acquire_cred(argv[0], mech, GSS_C_NT_USER_NAME); 514 515 gss_destroy_cred(NULL, &cred); 516 517 } 518 519 return 0; 520} 521 522/* 523 * 524 */ 525 526static int 527common_hold(OM_uint32 (*func)(OM_uint32 *, gss_cred_id_t), 528 const char *mech_string, int argc, char **argv) 529{ 530 OM_uint32 min_stat, maj_stat; 531 gss_const_OID mech = GSS_C_NO_OID; 532 gss_cred_id_t cred; 533 534 if (argc < 1) { 535 printf("missing username to (un)hold\n"); 536 return 1; 537 } 538 539 if (mech_string) { 540 mech = gss_name_to_oid(mech_string); 541 if (mech == NULL) 542 errx(1, "No such mech: %s", mech_string); 543 } 544 545 cred = acquire_cred(argv[0], mech, GSS_C_NT_USER_NAME); 546 547 maj_stat = func(&min_stat, cred); 548 if (maj_stat != GSS_S_COMPLETE) 549 errx(1, "(un)hold failed"); 550 551 gss_release_cred(&min_stat, &cred); 552 553 return 0; 554} 555 556int 557hold(struct hold_options *opt, int argc, char **argv) 558{ 559 return common_hold(gss_cred_hold, opt->mech_string, argc, argv); 560} 561 562int 563unhold(struct unhold_options *opt, int argc, char **argv) 564{ 565 return common_hold(gss_cred_unhold, opt->mech_string, argc, argv); 566} 567 568int 569get_label(struct get_label_options *opt, int argc, char **argv) 570{ 571 OM_uint32 min_stat, maj_stat; 572 gss_const_OID mech = GSS_C_NO_OID; 573 gss_cred_id_t cred; 574 gss_buffer_desc buf; 575 576 if (opt->mech_string) { 577 mech = gss_name_to_oid(opt->mech_string); 578 if (mech == NULL) 579 errx(1, "No such mech: %s", opt->mech_string); 580 } 581 582 cred = acquire_cred(argv[0], mech, GSS_C_NT_USER_NAME); 583 584 maj_stat = gss_cred_label_get(&min_stat, cred, argv[1], &buf); 585 if (maj_stat != GSS_S_COMPLETE) 586 errx(1, "label get failed"); 587 588 printf("value: %.*s\n", (int)buf.length, (char *)buf.value); 589 590 gss_release_buffer(&min_stat, &buf); 591 gss_release_cred(&min_stat, &cred); 592 593 return 0; 594} 595 596int 597set_label(struct set_label_options *opt, int argc, char **argv) 598{ 599 OM_uint32 min_stat, maj_stat; 600 gss_const_OID mech = GSS_C_NO_OID; 601 gss_cred_id_t cred; 602 gss_buffer_desc buf; 603 gss_buffer_t bufp = NULL; 604 605 if (opt->mech_string) { 606 mech = gss_name_to_oid(opt->mech_string); 607 if (mech == NULL) 608 errx(1, "No such mech: %s", opt->mech_string); 609 } 610 611 cred = acquire_cred(argv[0], mech, GSS_C_NT_USER_NAME); 612 613 if (argc > 2) { 614 buf.value = argv[2]; 615 buf.length = strlen(argv[2]); 616 bufp = &buf; 617 } 618 619 maj_stat = gss_cred_label_set(&min_stat, cred, argv[1], bufp); 620 if (maj_stat != GSS_S_COMPLETE) 621 errx(1, "label get failed"); 622 623 gss_release_cred(&min_stat, &cred); 624 625 return 0; 626} 627 628/* 629 * 630 */ 631 632static void 633print_mech_attr(const char *mechname, gss_const_OID mech, gss_OID_set set) 634{ 635 gss_buffer_desc name, desc; 636 OM_uint32 major, minor; 637 rtbl_t ct; 638 size_t n; 639 640 ct = rtbl_create(); 641 if (ct == NULL) 642 errx(1, "rtbl_create"); 643 644 rtbl_set_separator(ct, " "); 645 rtbl_add_column(ct, COL_OID, 0); 646 rtbl_add_column(ct, COL_DESC, 0); 647 if (mech) 648 rtbl_add_column(ct, COL_VALUE, 0); 649 650 for (n = 0; n < set->count; n++) { 651 major = gss_display_mech_attr(&minor, &set->elements[n], &name, &desc, NULL); 652 if (major) 653 continue; 654 655 rtbl_add_column_entryv(ct, COL_OID, "%.*s", 656 (int)name.length, (char *)name.value); 657 rtbl_add_column_entryv(ct, COL_DESC, "%.*s", 658 (int)desc.length, (char *)desc.value); 659 if (mech) { 660 gss_buffer_desc value; 661 662 if (gss_mo_get(mech, &set->elements[n], &value) != 0) 663 value.length = 0; 664 665 if (value.length) 666 rtbl_add_column_entryv(ct, COL_VALUE, "%.*s", 667 (int)value.length, (char *)value.value); 668 else 669 rtbl_add_column_entryv(ct, COL_VALUE, "<>"); 670 gss_release_buffer(&minor, &value); 671 } 672 673 gss_release_buffer(&minor, &name); 674 gss_release_buffer(&minor, &desc); 675 } 676 677 printf("attributes for: %s\n", mechname); 678 rtbl_format(ct, stdout); 679 rtbl_destroy(ct); 680} 681 682int 683attrs_for_mech(struct attrs_for_mech_options *opt, int argc, char **argv) 684{ 685 gss_OID_set mech_attr = NULL, known_mech_attrs = NULL; 686 gss_const_OID mech = GSS_C_NO_OID; 687 OM_uint32 major, minor; 688 689 if (opt->mech_string) { 690 mech = gss_name_to_oid(opt->mech_string); 691 if (mech == NULL) 692 errx(1, "mech %s is unknown", opt->mech_string); 693 } 694 695 major = gss_inquire_attrs_for_mech(&minor, 696 mech, 697 &mech_attr, 698 &known_mech_attrs); 699 if (major) 700 errx(1, "gss_inquire_attrs_for_mech"); 701 702 if (mech) 703 print_mech_attr(opt->mech_string, mech, mech_attr); 704 705 if (opt->all_flag) 706 print_mech_attr("all mechs", NULL, known_mech_attrs); 707 708 gss_release_oid_set(&minor, &mech_attr); 709 gss_release_oid_set(&minor, &known_mech_attrs); 710 711 return 0; 712} 713 714int 715display_status(struct display_status_options *opt, int argc, char **argv) 716{ 717 int status_type = GSS_C_GSS_CODE; 718 gss_const_OID mech = GSS_C_NO_OID; 719 720 if (opt->minor_status_flag) 721 status_type = GSS_C_MECH_CODE; 722 723 if (opt->mech_string) { 724 mech = gss_name_to_oid(opt->mech_string); 725 if (mech == NULL) 726 errx(1, "mech %s is unknown", opt->mech_string); 727 } 728 729 for (;argc; argc--, argv++) { 730 OM_uint32 ret, new_stat, msg_ctx; 731 gss_buffer_desc status_string; 732 long num; 733 734 num = atol(argv[0]); 735 if (num == 0) { 736 warnx("failed to parse %s as a number", argv[0]); 737 continue; 738 } 739 740 msg_ctx = 0; 741 do { 742 ret = gss_display_status(&new_stat, 743 (OM_uint32)num, 744 status_type, 745 (gss_OID)mech, 746 &msg_ctx, 747 &status_string); 748 if (!GSS_ERROR(ret)) { 749 printf("%s: %.*s\n", argv[0], 750 (int)status_string.length, 751 (char *)status_string.value); 752 gss_release_buffer(&new_stat, &status_string); 753 } 754 } while (!GSS_ERROR(ret) && msg_ctx != 0); 755 756 } 757 return 0; 758} 759 760/* 761 * 762 */ 763 764int 765credentials_status(struct credentials_status_options *opt, int argc, char **argv) 766{ 767#ifdef __APPLE__ 768 CFDictionaryRef status = HeimCredCopyStatus(NULL); 769 if (status) { 770 CFDataRef data = CFPropertyListCreateData(NULL, status, kCFPropertyListXMLFormat_v1_0, 0, NULL); 771 CFRelease(status); 772 if (data == NULL) 773 return 1; 774 printf("%.*s\n", (int)CFDataGetLength(data), CFDataGetBytePtr(data)); 775 CFRelease(data); 776 } else { 777 printf("no credentials to dump\n"); 778 return 1; 779 } 780#endif 781 return 0; 782} 783 784/* 785 * 786 */ 787 788int 789help(void *opt, int argc, char **argv) 790{ 791 sl_slc_help(commands, argc, argv); 792 return 0; 793} 794 795int 796main(int argc, char **argv) 797{ 798 int optidx = 0; 799 800 setprogname(argv[0]); 801 if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) 802 usage(1); 803 804 if (help_flag) 805 usage (0); 806 807 if(version_flag){ 808 print_version(NULL); 809 exit(0); 810 } 811 812 argc -= optidx; 813 argv += optidx; 814 815 if (argc == 0) { 816 help(NULL, argc, argv); 817 return 1; 818 } 819 820 return sl_command (commands, argc, argv); 821} 822