1 /* $NetBSD: gssapi.c,v 1.6 2015/05/19 15:16:00 christos Exp $ */ 2 3 /* $KAME: gssapi.c,v 1.19 2001/04/03 15:51:55 thorpej Exp $ */ 4 5 /* 6 * Copyright 2000 Wasabi Systems, Inc. 7 * All rights reserved. 8 * 9 * This software was written by Frank van der Linden of Wasabi Systems 10 * for Zembu Labs, Inc. http://www.zembu.com/ 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. The name of Wasabi Systems, Inc. may not be used to endorse 21 * or promote products derived from this software without specific prior 22 * written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 26 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 27 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 28 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34 * POSSIBILITY OF SUCH DAMAGE. 35 */ 36 37 #include "config.h" 38 39 #ifdef HAVE_GSSAPI 40 41 #include <sys/types.h> 42 #include <sys/queue.h> 43 #include <sys/socket.h> 44 #include <netdb.h> 45 #include <unistd.h> 46 47 #include <stdlib.h> 48 #include <string.h> 49 #include <errno.h> 50 51 #include "var.h" 52 #include "misc.h" 53 #include "vmbuf.h" 54 #include "plog.h" 55 #include "sockmisc.h" 56 #include "schedule.h" 57 #include "debug.h" 58 59 #include "localconf.h" 60 #include "remoteconf.h" 61 #include "isakmp_var.h" 62 #include "isakmp.h" 63 #include "oakley.h" 64 #include "handler.h" 65 #include "ipsec_doi.h" 66 #include "crypto_openssl.h" 67 #include "pfkey.h" 68 #include "isakmp_ident.h" 69 #include "isakmp_inf.h" 70 #include "vendorid.h" 71 #include "gcmalloc.h" 72 73 #include "gssapi.h" 74 75 static void 76 gssapi_error(OM_uint32 status_code, const char *where, 77 const char *fmt, ...) 78 { 79 OM_uint32 message_context, maj_stat, min_stat; 80 gss_buffer_desc status_string; 81 va_list ap; 82 83 va_start(ap, fmt); 84 plogv(LLV_ERROR, where, NULL, fmt, ap); 85 va_end(ap); 86 87 message_context = 0; 88 89 do { 90 maj_stat = gss_display_status(&min_stat, status_code, 91 GSS_C_MECH_CODE, GSS_C_NO_OID, &message_context, 92 &status_string); 93 if (GSS_ERROR(maj_stat)) 94 plog(LLV_ERROR, LOCATION, NULL, 95 "UNABLE TO GET GSSAPI ERROR CODE\n"); 96 else { 97 plog(LLV_ERROR, where, NULL, 98 "%s\n", (char *)status_string.value); 99 gss_release_buffer(&min_stat, &status_string); 100 } 101 } while (message_context != 0); 102 } 103 104 /* 105 * vmbufs and gss_buffer_descs are really just the same on NetBSD, but 106 * this is to be portable. 107 */ 108 static int 109 gssapi_vm2gssbuf(vchar_t *vmbuf, gss_buffer_t gsstoken) 110 { 111 112 gsstoken->value = racoon_malloc(vmbuf->l); 113 if (gsstoken->value == NULL) 114 return -1; 115 memcpy(gsstoken->value, vmbuf->v, vmbuf->l); 116 gsstoken->length = vmbuf->l; 117 118 return 0; 119 } 120 121 static int 122 gssapi_gss2vmbuf(gss_buffer_t gsstoken, vchar_t **vmbuf) 123 { 124 125 *vmbuf = vmalloc(gsstoken->length); 126 if (*vmbuf == NULL) 127 return -1; 128 memcpy((*vmbuf)->v, gsstoken->value, gsstoken->length); 129 (*vmbuf)->l = gsstoken->length; 130 131 return 0; 132 } 133 134 vchar_t * 135 gssapi_get_default_gss_id(void) 136 { 137 char name[NI_MAXHOST]; 138 vchar_t *gssid; 139 140 if (gethostname(name, sizeof(name)) != 0) { 141 plog(LLV_ERROR, LOCATION, NULL, "gethostname failed: %s\n", 142 strerror(errno)); 143 return (NULL); 144 } 145 name[sizeof(name) - 1] = '\0'; 146 147 gssid = racoon_malloc(sizeof(*gssid)); 148 gssid->l = asprintf(&gssid->v, "%s/%s", GSSAPI_DEF_NAME, name); 149 150 return (gssid); 151 } 152 153 static int 154 gssapi_get_default_name(struct ph1handle *iph1, int remote, gss_name_t *service) 155 { 156 char name[NI_MAXHOST]; 157 struct sockaddr *sa; 158 char* buf = NULL; 159 gss_buffer_desc name_token; 160 OM_uint32 min_stat, maj_stat; 161 162 sa = remote ? iph1->remote : iph1->local; 163 164 if (getnameinfo(sa, sysdep_sa_len(sa), name, NI_MAXHOST, NULL, 0, 0) != 0) 165 return -1; 166 167 name_token.length = asprintf(&buf, "%s@%s", GSSAPI_DEF_NAME, name); 168 name_token.value = buf; 169 170 maj_stat = gss_import_name(&min_stat, &name_token, 171 GSS_C_NT_HOSTBASED_SERVICE, service); 172 if (GSS_ERROR(maj_stat)) { 173 gssapi_error(min_stat, LOCATION, "import name\n"); 174 maj_stat = gss_release_buffer(&min_stat, &name_token); 175 if (GSS_ERROR(maj_stat)) 176 gssapi_error(min_stat, LOCATION, "release name_token"); 177 return -1; 178 } 179 maj_stat = gss_release_buffer(&min_stat, &name_token); 180 if (GSS_ERROR(maj_stat)) 181 gssapi_error(min_stat, LOCATION, "release name_token"); 182 183 return 0; 184 } 185 186 static int 187 gssapi_init(struct ph1handle *iph1) 188 { 189 struct gssapi_ph1_state *gps; 190 gss_buffer_desc id_token, cred_token; 191 gss_buffer_t cred = &cred_token; 192 gss_name_t princ, canon_princ; 193 OM_uint32 maj_stat, min_stat; 194 195 if (iph1->rmconf == NULL) { 196 plog(LLV_ERROR, LOCATION, NULL, "no remote config\n"); 197 return -1; 198 } 199 200 gps = racoon_calloc(1, sizeof (struct gssapi_ph1_state)); 201 if (gps == NULL) { 202 plog(LLV_ERROR, LOCATION, NULL, "racoon_calloc failed\n"); 203 return -1; 204 } 205 gps->gss_context = GSS_C_NO_CONTEXT; 206 gps->gss_cred = GSS_C_NO_CREDENTIAL; 207 208 gssapi_set_state(iph1, gps); 209 210 if (iph1->rmconf->proposal->gssid != NULL) { 211 id_token.length = iph1->rmconf->proposal->gssid->l; 212 id_token.value = iph1->rmconf->proposal->gssid->v; 213 maj_stat = gss_import_name(&min_stat, &id_token, GSS_C_NO_OID, 214 &princ); 215 if (GSS_ERROR(maj_stat)) { 216 gssapi_error(min_stat, LOCATION, "import name\n"); 217 gssapi_free_state(iph1); 218 return -1; 219 } 220 } else 221 gssapi_get_default_name(iph1, 0, &princ); 222 223 maj_stat = gss_canonicalize_name(&min_stat, princ, GSS_C_NO_OID, 224 &canon_princ); 225 if (GSS_ERROR(maj_stat)) { 226 gssapi_error(min_stat, LOCATION, "canonicalize name\n"); 227 maj_stat = gss_release_name(&min_stat, &princ); 228 if (GSS_ERROR(maj_stat)) 229 gssapi_error(min_stat, LOCATION, "release princ\n"); 230 gssapi_free_state(iph1); 231 return -1; 232 } 233 maj_stat = gss_release_name(&min_stat, &princ); 234 if (GSS_ERROR(maj_stat)) 235 gssapi_error(min_stat, LOCATION, "release princ\n"); 236 237 maj_stat = gss_export_name(&min_stat, canon_princ, cred); 238 if (GSS_ERROR(maj_stat)) { 239 gssapi_error(min_stat, LOCATION, "export name\n"); 240 maj_stat = gss_release_name(&min_stat, &canon_princ); 241 if (GSS_ERROR(maj_stat)) 242 gssapi_error(min_stat, LOCATION, 243 "release canon_princ\n"); 244 gssapi_free_state(iph1); 245 return -1; 246 } 247 248 #if 0 249 /* 250 * XXXJRT Did this debug message ever work? This is a GSS name 251 * blob at this point. 252 */ 253 plog(LLV_DEBUG, LOCATION, NULL, "will try to acquire '%.*s' creds\n", 254 cred->length, cred->value); 255 #endif 256 257 maj_stat = gss_release_buffer(&min_stat, cred); 258 if (GSS_ERROR(maj_stat)) 259 gssapi_error(min_stat, LOCATION, "release cred buffer\n"); 260 261 maj_stat = gss_acquire_cred(&min_stat, canon_princ, GSS_C_INDEFINITE, 262 GSS_C_NO_OID_SET, GSS_C_BOTH, &gps->gss_cred, NULL, NULL); 263 if (GSS_ERROR(maj_stat)) { 264 gssapi_error(min_stat, LOCATION, "acquire cred\n"); 265 maj_stat = gss_release_name(&min_stat, &canon_princ); 266 if (GSS_ERROR(maj_stat)) 267 gssapi_error(min_stat, LOCATION, 268 "release canon_princ\n"); 269 gssapi_free_state(iph1); 270 return -1; 271 } 272 maj_stat = gss_release_name(&min_stat, &canon_princ); 273 if (GSS_ERROR(maj_stat)) 274 gssapi_error(min_stat, LOCATION, "release canon_princ\n"); 275 276 return 0; 277 } 278 279 int 280 gssapi_get_itoken(struct ph1handle *iph1, int *lenp) 281 { 282 struct gssapi_ph1_state *gps; 283 gss_buffer_desc empty, name_token; 284 gss_buffer_t itoken, rtoken, dummy; 285 OM_uint32 maj_stat, min_stat; 286 gss_name_t partner; 287 288 if (gssapi_get_state(iph1) == NULL && gssapi_init(iph1) < 0) 289 return -1; 290 291 gps = gssapi_get_state(iph1); 292 293 empty.length = 0; 294 empty.value = NULL; 295 dummy = ∅ 296 297 if (iph1->approval != NULL && iph1->approval->gssid != NULL) { 298 plog(LLV_DEBUG, LOCATION, NULL, 299 "using provided service '%.*s'\n", 300 (int)iph1->approval->gssid->l, iph1->approval->gssid->v); 301 name_token.length = iph1->approval->gssid->l; 302 name_token.value = iph1->approval->gssid->v; 303 maj_stat = gss_import_name(&min_stat, &name_token, 304 GSS_C_NO_OID, &partner); 305 if (GSS_ERROR(maj_stat)) { 306 gssapi_error(min_stat, LOCATION, "import of %.*s\n", 307 name_token.length, name_token.value); 308 return -1; 309 } 310 } else 311 if (gssapi_get_default_name(iph1, 1, &partner) < 0) 312 return -1; 313 314 rtoken = gps->gsscnt_p == 0 ? dummy : &gps->gss_p[gps->gsscnt_p - 1]; 315 itoken = &gps->gss[gps->gsscnt]; 316 317 gps->gss_status = gss_init_sec_context(&min_stat, gps->gss_cred, 318 &gps->gss_context, partner, GSS_C_NO_OID, 319 GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG | 320 GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG, 321 0, GSS_C_NO_CHANNEL_BINDINGS, rtoken, NULL, 322 itoken, NULL, NULL); 323 324 if (GSS_ERROR(gps->gss_status)) { 325 gssapi_error(min_stat, LOCATION, "init_sec_context\n"); 326 maj_stat = gss_release_name(&min_stat, &partner); 327 if (GSS_ERROR(maj_stat)) 328 gssapi_error(min_stat, LOCATION, "release name\n"); 329 return -1; 330 } 331 maj_stat = gss_release_name(&min_stat, &partner); 332 if (GSS_ERROR(maj_stat)) 333 gssapi_error(min_stat, LOCATION, "release name\n"); 334 335 plog(LLV_DEBUG, LOCATION, NULL, "gss_init_sec_context status %x\n", 336 gps->gss_status); 337 338 if (lenp) 339 *lenp = itoken->length; 340 341 if (itoken->length != 0) 342 gps->gsscnt++; 343 344 return 0; 345 } 346 347 /* 348 * Call gss_accept_context, with token just read from the wire. 349 */ 350 int 351 gssapi_get_rtoken(struct ph1handle *iph1, int *lenp) 352 { 353 struct gssapi_ph1_state *gps; 354 gss_buffer_desc name_token; 355 gss_buffer_t itoken, rtoken; 356 OM_uint32 min_stat, maj_stat; 357 gss_name_t client_name; 358 359 if (gssapi_get_state(iph1) == NULL && gssapi_init(iph1) < 0) 360 return -1; 361 362 gps = gssapi_get_state(iph1); 363 364 rtoken = &gps->gss_p[gps->gsscnt_p - 1]; 365 itoken = &gps->gss[gps->gsscnt]; 366 367 gps->gss_status = gss_accept_sec_context(&min_stat, &gps->gss_context, 368 gps->gss_cred, rtoken, GSS_C_NO_CHANNEL_BINDINGS, &client_name, 369 NULL, itoken, NULL, NULL, NULL); 370 371 if (GSS_ERROR(gps->gss_status)) { 372 gssapi_error(min_stat, LOCATION, "accept_sec_context\n"); 373 return -1; 374 } 375 376 maj_stat = gss_display_name(&min_stat, client_name, &name_token, NULL); 377 if (GSS_ERROR(maj_stat)) { 378 gssapi_error(min_stat, LOCATION, "gss_display_name\n"); 379 maj_stat = gss_release_name(&min_stat, &client_name); 380 if (GSS_ERROR(maj_stat)) 381 gssapi_error(min_stat, LOCATION, 382 "release client_name\n"); 383 return -1; 384 } 385 maj_stat = gss_release_name(&min_stat, &client_name); 386 if (GSS_ERROR(maj_stat)) 387 gssapi_error(min_stat, LOCATION, "release client_name\n"); 388 389 plog(LLV_DEBUG, LOCATION, NULL, 390 "gss_accept_sec_context: other side is %s\n", 391 (char *)name_token.value); 392 maj_stat = gss_release_buffer(&min_stat, &name_token); 393 if (GSS_ERROR(maj_stat)) 394 gssapi_error(min_stat, LOCATION, "release name buffer\n"); 395 396 if (itoken->length != 0) 397 gps->gsscnt++; 398 399 if (lenp) 400 *lenp = itoken->length; 401 402 return 0; 403 } 404 405 int 406 gssapi_save_received_token(struct ph1handle *iph1, vchar_t *token) 407 { 408 struct gssapi_ph1_state *gps; 409 gss_buffer_t gsstoken; 410 int ret; 411 412 if (gssapi_get_state(iph1) == NULL && gssapi_init(iph1) < 0) 413 return -1; 414 415 gps = gssapi_get_state(iph1); 416 417 gsstoken = &gps->gss_p[gps->gsscnt_p]; 418 419 ret = gssapi_vm2gssbuf(token, gsstoken); 420 if (ret < 0) 421 return ret; 422 gps->gsscnt_p++; 423 424 return 0; 425 } 426 427 int 428 gssapi_get_token_to_send(struct ph1handle *iph1, vchar_t **token) 429 { 430 struct gssapi_ph1_state *gps; 431 gss_buffer_t gsstoken; 432 int ret; 433 434 gps = gssapi_get_state(iph1); 435 if (gps == NULL) { 436 plog(LLV_ERROR, LOCATION, NULL, 437 "gssapi not yet initialized?\n"); 438 return -1; 439 } 440 gsstoken = &gps->gss[gps->gsscnt - 1]; 441 ret = gssapi_gss2vmbuf(gsstoken, token); 442 if (ret < 0) 443 return ret; 444 445 return 0; 446 } 447 448 int 449 gssapi_get_itokens(struct ph1handle *iph1, vchar_t **tokens) 450 { 451 struct gssapi_ph1_state *gps; 452 int len, i; 453 vchar_t *toks; 454 char *p; 455 456 gps = gssapi_get_state(iph1); 457 if (gps == NULL) { 458 plog(LLV_ERROR, LOCATION, NULL, 459 "gssapi not yet initialized?\n"); 460 return -1; 461 } 462 463 for (i = len = 0; i < gps->gsscnt; i++) 464 len += gps->gss[i].length; 465 466 toks = vmalloc(len); 467 if (toks == 0) 468 return -1; 469 p = (char *)toks->v; 470 for (i = 0; i < gps->gsscnt; i++) { 471 memcpy(p, gps->gss[i].value, gps->gss[i].length); 472 p += gps->gss[i].length; 473 } 474 475 *tokens = toks; 476 477 plog(LLV_DEBUG, LOCATION, NULL, 478 "%d itokens of length %zu\n", gps->gsscnt, (*tokens)->l); 479 480 return 0; 481 } 482 483 int 484 gssapi_get_rtokens(struct ph1handle *iph1, vchar_t **tokens) 485 { 486 struct gssapi_ph1_state *gps; 487 int len, i; 488 vchar_t *toks; 489 char *p; 490 491 gps = gssapi_get_state(iph1); 492 if (gps == NULL) { 493 plog(LLV_ERROR, LOCATION, NULL, 494 "gssapi not yet initialized?\n"); 495 return -1; 496 } 497 498 if (gssapi_more_tokens(iph1)) { 499 plog(LLV_ERROR, LOCATION, NULL, 500 "gssapi roundtrips not complete\n"); 501 return -1; 502 } 503 504 for (i = len = 0; i < gps->gsscnt_p; i++) 505 len += gps->gss_p[i].length; 506 507 toks = vmalloc(len); 508 if (toks == 0) 509 return -1; 510 p = (char *)toks->v; 511 for (i = 0; i < gps->gsscnt_p; i++) { 512 memcpy(p, gps->gss_p[i].value, gps->gss_p[i].length); 513 p += gps->gss_p[i].length; 514 } 515 516 *tokens = toks; 517 518 return 0; 519 } 520 521 vchar_t * 522 gssapi_wraphash(struct ph1handle *iph1) 523 { 524 struct gssapi_ph1_state *gps; 525 OM_uint32 maj_stat, min_stat; 526 gss_buffer_desc hash_in_buf, hash_out_buf; 527 gss_buffer_t hash_in = &hash_in_buf, hash_out = &hash_out_buf; 528 vchar_t *outbuf; 529 530 gps = gssapi_get_state(iph1); 531 if (gps == NULL) { 532 plog(LLV_ERROR, LOCATION, NULL, 533 "gssapi not yet initialized?\n"); 534 return NULL; 535 } 536 537 if (gssapi_more_tokens(iph1)) { 538 plog(LLV_ERROR, LOCATION, NULL, 539 "gssapi roundtrips not complete\n"); 540 return NULL; 541 } 542 543 if (gssapi_vm2gssbuf(iph1->hash, hash_in) < 0) { 544 plog(LLV_ERROR, LOCATION, NULL, "vm2gssbuf failed\n"); 545 return NULL; 546 } 547 548 maj_stat = gss_wrap(&min_stat, gps->gss_context, 1, GSS_C_QOP_DEFAULT, 549 hash_in, NULL, hash_out); 550 if (GSS_ERROR(maj_stat)) { 551 gssapi_error(min_stat, LOCATION, "wrapping hash value\n"); 552 maj_stat = gss_release_buffer(&min_stat, hash_in); 553 if (GSS_ERROR(maj_stat)) 554 gssapi_error(min_stat, LOCATION, 555 "release hash_in buffer\n"); 556 return NULL; 557 } 558 559 plog(LLV_DEBUG, LOCATION, NULL, "wrapped HASH, ilen %zu olen %zu\n", 560 hash_in->length, hash_out->length); 561 562 maj_stat = gss_release_buffer(&min_stat, hash_in); 563 if (GSS_ERROR(maj_stat)) 564 gssapi_error(min_stat, LOCATION, "release hash_in buffer\n"); 565 566 if (gssapi_gss2vmbuf(hash_out, &outbuf) < 0) { 567 plog(LLV_ERROR, LOCATION, NULL, "gss2vmbuf failed\n"); 568 maj_stat = gss_release_buffer(&min_stat, hash_out); 569 if (GSS_ERROR(maj_stat)) 570 gssapi_error(min_stat, LOCATION, 571 "release hash_out buffer\n"); 572 return NULL; 573 } 574 maj_stat = gss_release_buffer(&min_stat, hash_out); 575 if (GSS_ERROR(maj_stat)) 576 gssapi_error(min_stat, LOCATION, "release hash_out buffer\n"); 577 578 return outbuf; 579 } 580 581 vchar_t * 582 gssapi_unwraphash(struct ph1handle *iph1) 583 { 584 struct gssapi_ph1_state *gps; 585 OM_uint32 maj_stat, min_stat; 586 gss_buffer_desc hashbuf, hash_outbuf; 587 gss_buffer_t hash_in = &hashbuf, hash_out = &hash_outbuf; 588 vchar_t *outbuf; 589 590 gps = gssapi_get_state(iph1); 591 if (gps == NULL) { 592 plog(LLV_ERROR, LOCATION, NULL, 593 "gssapi not yet initialized?\n"); 594 return NULL; 595 } 596 597 598 hashbuf.length = ntohs(iph1->pl_hash->h.len) - sizeof(*iph1->pl_hash); 599 hashbuf.value = (char *)(iph1->pl_hash + 1); 600 601 plog(LLV_DEBUG, LOCATION, NULL, "unwrapping HASH of len %zu\n", 602 hashbuf.length); 603 604 maj_stat = gss_unwrap(&min_stat, gps->gss_context, hash_in, hash_out, 605 NULL, NULL); 606 if (GSS_ERROR(maj_stat)) { 607 gssapi_error(min_stat, LOCATION, "unwrapping hash value\n"); 608 return NULL; 609 } 610 611 if (gssapi_gss2vmbuf(hash_out, &outbuf) < 0) { 612 plog(LLV_ERROR, LOCATION, NULL, "gss2vmbuf failed\n"); 613 maj_stat = gss_release_buffer(&min_stat, hash_out); 614 if (GSS_ERROR(maj_stat)) 615 gssapi_error(min_stat, LOCATION, 616 "release hash_out buffer\n"); 617 return NULL; 618 } 619 maj_stat = gss_release_buffer(&min_stat, hash_out); 620 if (GSS_ERROR(maj_stat)) 621 gssapi_error(min_stat, LOCATION, "release hash_out buffer\n"); 622 623 return outbuf; 624 } 625 626 void 627 gssapi_set_id_sent(struct ph1handle *iph1) 628 { 629 struct gssapi_ph1_state *gps; 630 631 gps = gssapi_get_state(iph1); 632 633 gps->gss_flags |= GSSFLAG_ID_SENT; 634 } 635 636 int 637 gssapi_id_sent(struct ph1handle *iph1) 638 { 639 struct gssapi_ph1_state *gps; 640 641 gps = gssapi_get_state(iph1); 642 643 return (gps->gss_flags & GSSFLAG_ID_SENT) != 0; 644 } 645 646 void 647 gssapi_set_id_rcvd(struct ph1handle *iph1) 648 { 649 struct gssapi_ph1_state *gps; 650 651 gps = gssapi_get_state(iph1); 652 653 gps->gss_flags |= GSSFLAG_ID_RCVD; 654 } 655 656 int 657 gssapi_id_rcvd(struct ph1handle *iph1) 658 { 659 struct gssapi_ph1_state *gps; 660 661 gps = gssapi_get_state(iph1); 662 663 return (gps->gss_flags & GSSFLAG_ID_RCVD) != 0; 664 } 665 666 void 667 gssapi_free_state(struct ph1handle *iph1) 668 { 669 struct gssapi_ph1_state *gps; 670 OM_uint32 maj_stat, min_stat; 671 672 gps = gssapi_get_state(iph1); 673 674 if (gps == NULL) 675 return; 676 677 gssapi_set_state(iph1, NULL); 678 679 if (gps->gss_cred != GSS_C_NO_CREDENTIAL) { 680 maj_stat = gss_release_cred(&min_stat, &gps->gss_cred); 681 if (GSS_ERROR(maj_stat)) 682 gssapi_error(min_stat, LOCATION, 683 "releasing credentials\n"); 684 } 685 racoon_free(gps); 686 } 687 688 vchar_t * 689 gssapi_get_id(struct ph1handle *iph1) 690 { 691 gss_buffer_desc id_buffer; 692 gss_buffer_t id = &id_buffer; 693 gss_name_t defname, canon_name; 694 OM_uint32 min_stat, maj_stat; 695 vchar_t *vmbuf; 696 697 if (iph1->rmconf->proposal->gssid != NULL) 698 return (vdup(iph1->rmconf->proposal->gssid)); 699 700 if (gssapi_get_default_name(iph1, 0, &defname) < 0) 701 return NULL; 702 703 maj_stat = gss_canonicalize_name(&min_stat, defname, GSS_C_NO_OID, 704 &canon_name); 705 if (GSS_ERROR(maj_stat)) { 706 gssapi_error(min_stat, LOCATION, "canonicalize name\n"); 707 maj_stat = gss_release_name(&min_stat, &defname); 708 if (GSS_ERROR(maj_stat)) 709 gssapi_error(min_stat, LOCATION, 710 "release default name\n"); 711 return NULL; 712 } 713 maj_stat = gss_release_name(&min_stat, &defname); 714 if (GSS_ERROR(maj_stat)) 715 gssapi_error(min_stat, LOCATION, "release default name\n"); 716 717 maj_stat = gss_export_name(&min_stat, canon_name, id); 718 if (GSS_ERROR(maj_stat)) { 719 gssapi_error(min_stat, LOCATION, "export name\n"); 720 maj_stat = gss_release_name(&min_stat, &canon_name); 721 if (GSS_ERROR(maj_stat)) 722 gssapi_error(min_stat, LOCATION, 723 "release canonical name\n"); 724 return NULL; 725 } 726 maj_stat = gss_release_name(&min_stat, &canon_name); 727 if (GSS_ERROR(maj_stat)) 728 gssapi_error(min_stat, LOCATION, "release canonical name\n"); 729 730 #if 0 731 /* 732 * XXXJRT Did this debug message ever work? This is a GSS name 733 * blob at this point. 734 */ 735 plog(LLV_DEBUG, LOCATION, NULL, "will try to acquire '%.*s' creds\n", 736 id->length, id->value); 737 #endif 738 739 if (gssapi_gss2vmbuf(id, &vmbuf) < 0) { 740 plog(LLV_ERROR, LOCATION, NULL, "gss2vmbuf failed\n"); 741 maj_stat = gss_release_buffer(&min_stat, id); 742 if (GSS_ERROR(maj_stat)) 743 gssapi_error(min_stat, LOCATION, "release id buffer\n"); 744 return NULL; 745 } 746 maj_stat = gss_release_buffer(&min_stat, id); 747 if (GSS_ERROR(maj_stat)) 748 gssapi_error(min_stat, LOCATION, "release id buffer\n"); 749 750 return vmbuf; 751 } 752 #else 753 int __gssapi_dUmMy; 754 #endif 755