1 /* $NetBSD: gssapi.c,v 1.3 2005/11/21 14:20:29 manu 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 gss_buffer_desc name_token; 159 OM_uint32 min_stat, maj_stat; 160 161 sa = remote ? iph1->remote : iph1->local; 162 163 if (getnameinfo(sa, sysdep_sa_len(sa), name, NI_MAXHOST, NULL, 0, 0) != 0) 164 return -1; 165 166 name_token.length = asprintf((char **)&name_token.value, 167 "%s@%s", GSSAPI_DEF_NAME, name); 168 maj_stat = gss_import_name(&min_stat, &name_token, 169 GSS_C_NT_HOSTBASED_SERVICE, service); 170 if (GSS_ERROR(maj_stat)) { 171 gssapi_error(min_stat, LOCATION, "import name\n"); 172 maj_stat = gss_release_buffer(&min_stat, &name_token); 173 if (GSS_ERROR(maj_stat)) 174 gssapi_error(min_stat, LOCATION, "release name_token"); 175 return -1; 176 } 177 maj_stat = gss_release_buffer(&min_stat, &name_token); 178 if (GSS_ERROR(maj_stat)) 179 gssapi_error(min_stat, LOCATION, "release name_token"); 180 181 return 0; 182 } 183 184 static int 185 gssapi_init(struct ph1handle *iph1) 186 { 187 struct gssapi_ph1_state *gps; 188 gss_buffer_desc id_token, cred_token; 189 gss_buffer_t cred = &cred_token; 190 gss_name_t princ, canon_princ; 191 OM_uint32 maj_stat, min_stat; 192 193 gps = racoon_calloc(1, sizeof (struct gssapi_ph1_state)); 194 if (gps == NULL) { 195 plog(LLV_ERROR, LOCATION, NULL, "racoon_calloc failed\n"); 196 return -1; 197 } 198 gps->gss_context = GSS_C_NO_CONTEXT; 199 gps->gss_cred = GSS_C_NO_CREDENTIAL; 200 201 gssapi_set_state(iph1, gps); 202 203 if (iph1->rmconf->proposal->gssid != NULL) { 204 id_token.length = iph1->rmconf->proposal->gssid->l; 205 id_token.value = iph1->rmconf->proposal->gssid->v; 206 maj_stat = gss_import_name(&min_stat, &id_token, GSS_C_NO_OID, 207 &princ); 208 if (GSS_ERROR(maj_stat)) { 209 gssapi_error(min_stat, LOCATION, "import name\n"); 210 gssapi_free_state(iph1); 211 return -1; 212 } 213 } else 214 gssapi_get_default_name(iph1, 0, &princ); 215 216 maj_stat = gss_canonicalize_name(&min_stat, princ, GSS_C_NO_OID, 217 &canon_princ); 218 if (GSS_ERROR(maj_stat)) { 219 gssapi_error(min_stat, LOCATION, "canonicalize name\n"); 220 maj_stat = gss_release_name(&min_stat, &princ); 221 if (GSS_ERROR(maj_stat)) 222 gssapi_error(min_stat, LOCATION, "release princ\n"); 223 gssapi_free_state(iph1); 224 return -1; 225 } 226 maj_stat = gss_release_name(&min_stat, &princ); 227 if (GSS_ERROR(maj_stat)) 228 gssapi_error(min_stat, LOCATION, "release princ\n"); 229 230 maj_stat = gss_export_name(&min_stat, canon_princ, cred); 231 if (GSS_ERROR(maj_stat)) { 232 gssapi_error(min_stat, LOCATION, "export name\n"); 233 maj_stat = gss_release_name(&min_stat, &canon_princ); 234 if (GSS_ERROR(maj_stat)) 235 gssapi_error(min_stat, LOCATION, 236 "release canon_princ\n"); 237 gssapi_free_state(iph1); 238 return -1; 239 } 240 241 #if 0 242 /* 243 * XXXJRT Did this debug message ever work? This is a GSS name 244 * blob at this point. 245 */ 246 plog(LLV_DEBUG, LOCATION, NULL, "will try to acquire '%.*s' creds\n", 247 cred->length, cred->value); 248 #endif 249 250 maj_stat = gss_release_buffer(&min_stat, cred); 251 if (GSS_ERROR(maj_stat)) 252 gssapi_error(min_stat, LOCATION, "release cred buffer\n"); 253 254 maj_stat = gss_acquire_cred(&min_stat, canon_princ, GSS_C_INDEFINITE, 255 GSS_C_NO_OID_SET, GSS_C_BOTH, &gps->gss_cred, NULL, NULL); 256 if (GSS_ERROR(maj_stat)) { 257 gssapi_error(min_stat, LOCATION, "acquire cred\n"); 258 maj_stat = gss_release_name(&min_stat, &canon_princ); 259 if (GSS_ERROR(maj_stat)) 260 gssapi_error(min_stat, LOCATION, 261 "release canon_princ\n"); 262 gssapi_free_state(iph1); 263 return -1; 264 } 265 maj_stat = gss_release_name(&min_stat, &canon_princ); 266 if (GSS_ERROR(maj_stat)) 267 gssapi_error(min_stat, LOCATION, "release canon_princ\n"); 268 269 return 0; 270 } 271 272 int 273 gssapi_get_itoken(struct ph1handle *iph1, int *lenp) 274 { 275 struct gssapi_ph1_state *gps; 276 gss_buffer_desc empty, name_token; 277 gss_buffer_t itoken, rtoken, dummy; 278 OM_uint32 maj_stat, min_stat; 279 gss_name_t partner; 280 281 if (gssapi_get_state(iph1) == NULL && gssapi_init(iph1) < 0) 282 return -1; 283 284 gps = gssapi_get_state(iph1); 285 286 empty.length = 0; 287 empty.value = NULL; 288 dummy = ∅ 289 290 if (iph1->approval != NULL && iph1->approval->gssid != NULL) { 291 plog(LLV_DEBUG, LOCATION, NULL, 292 "using provided service '%.*s'\n", 293 iph1->approval->gssid->l, iph1->approval->gssid->v); 294 name_token.length = iph1->approval->gssid->l; 295 name_token.value = iph1->approval->gssid->v; 296 maj_stat = gss_import_name(&min_stat, &name_token, 297 GSS_C_NO_OID, &partner); 298 if (GSS_ERROR(maj_stat)) { 299 gssapi_error(min_stat, LOCATION, "import of %.*s\n", 300 name_token.length, name_token.value); 301 return -1; 302 } 303 } else 304 if (gssapi_get_default_name(iph1, 1, &partner) < 0) 305 return -1; 306 307 rtoken = gps->gsscnt_p == 0 ? dummy : &gps->gss_p[gps->gsscnt_p - 1]; 308 itoken = &gps->gss[gps->gsscnt]; 309 310 gps->gss_status = gss_init_sec_context(&min_stat, gps->gss_cred, 311 &gps->gss_context, partner, GSS_C_NO_OID, 312 GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG | 313 GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG, 314 0, GSS_C_NO_CHANNEL_BINDINGS, rtoken, NULL, 315 itoken, NULL, NULL); 316 317 if (GSS_ERROR(gps->gss_status)) { 318 gssapi_error(min_stat, LOCATION, "init_sec_context\n"); 319 maj_stat = gss_release_name(&min_stat, &partner); 320 if (GSS_ERROR(maj_stat)) 321 gssapi_error(min_stat, LOCATION, "release name\n"); 322 return -1; 323 } 324 maj_stat = gss_release_name(&min_stat, &partner); 325 if (GSS_ERROR(maj_stat)) 326 gssapi_error(min_stat, LOCATION, "release name\n"); 327 328 plog(LLV_DEBUG, LOCATION, NULL, "gss_init_sec_context status %x\n", 329 gps->gss_status); 330 331 if (lenp) 332 *lenp = itoken->length; 333 334 if (itoken->length != 0) 335 gps->gsscnt++; 336 337 return 0; 338 } 339 340 /* 341 * Call gss_accept_context, with token just read from the wire. 342 */ 343 int 344 gssapi_get_rtoken(struct ph1handle *iph1, int *lenp) 345 { 346 struct gssapi_ph1_state *gps; 347 gss_buffer_desc name_token; 348 gss_buffer_t itoken, rtoken; 349 OM_uint32 min_stat, maj_stat; 350 gss_name_t client_name; 351 352 if (gssapi_get_state(iph1) == NULL && gssapi_init(iph1) < 0) 353 return -1; 354 355 gps = gssapi_get_state(iph1); 356 357 rtoken = &gps->gss_p[gps->gsscnt_p - 1]; 358 itoken = &gps->gss[gps->gsscnt]; 359 360 gps->gss_status = gss_accept_sec_context(&min_stat, &gps->gss_context, 361 gps->gss_cred, rtoken, GSS_C_NO_CHANNEL_BINDINGS, &client_name, 362 NULL, itoken, NULL, NULL, NULL); 363 364 if (GSS_ERROR(gps->gss_status)) { 365 gssapi_error(min_stat, LOCATION, "accept_sec_context\n"); 366 return -1; 367 } 368 369 maj_stat = gss_display_name(&min_stat, client_name, &name_token, NULL); 370 if (GSS_ERROR(maj_stat)) { 371 gssapi_error(min_stat, LOCATION, "gss_display_name\n"); 372 maj_stat = gss_release_name(&min_stat, &client_name); 373 if (GSS_ERROR(maj_stat)) 374 gssapi_error(min_stat, LOCATION, 375 "release client_name\n"); 376 return -1; 377 } 378 maj_stat = gss_release_name(&min_stat, &client_name); 379 if (GSS_ERROR(maj_stat)) 380 gssapi_error(min_stat, LOCATION, "release client_name\n"); 381 382 plog(LLV_DEBUG, LOCATION, NULL, 383 "gss_accept_sec_context: other side is %s\n", 384 (char *)name_token.value); 385 maj_stat = gss_release_buffer(&min_stat, &name_token); 386 if (GSS_ERROR(maj_stat)) 387 gssapi_error(min_stat, LOCATION, "release name buffer\n"); 388 389 if (itoken->length != 0) 390 gps->gsscnt++; 391 392 if (lenp) 393 *lenp = itoken->length; 394 395 return 0; 396 } 397 398 int 399 gssapi_save_received_token(struct ph1handle *iph1, vchar_t *token) 400 { 401 struct gssapi_ph1_state *gps; 402 gss_buffer_t gsstoken; 403 int ret; 404 405 if (gssapi_get_state(iph1) == NULL && gssapi_init(iph1) < 0) 406 return -1; 407 408 gps = gssapi_get_state(iph1); 409 410 gsstoken = &gps->gss_p[gps->gsscnt_p]; 411 412 ret = gssapi_vm2gssbuf(token, gsstoken); 413 if (ret < 0) 414 return ret; 415 gps->gsscnt_p++; 416 417 return 0; 418 } 419 420 int 421 gssapi_get_token_to_send(struct ph1handle *iph1, vchar_t **token) 422 { 423 struct gssapi_ph1_state *gps; 424 gss_buffer_t gsstoken; 425 int ret; 426 427 gps = gssapi_get_state(iph1); 428 if (gps == NULL) { 429 plog(LLV_ERROR, LOCATION, NULL, 430 "gssapi not yet initialized?\n"); 431 return -1; 432 } 433 gsstoken = &gps->gss[gps->gsscnt - 1]; 434 ret = gssapi_gss2vmbuf(gsstoken, token); 435 if (ret < 0) 436 return ret; 437 438 return 0; 439 } 440 441 int 442 gssapi_get_itokens(struct ph1handle *iph1, vchar_t **tokens) 443 { 444 struct gssapi_ph1_state *gps; 445 int len, i; 446 vchar_t *toks; 447 char *p; 448 449 gps = gssapi_get_state(iph1); 450 if (gps == NULL) { 451 plog(LLV_ERROR, LOCATION, NULL, 452 "gssapi not yet initialized?\n"); 453 return -1; 454 } 455 456 for (i = len = 0; i < gps->gsscnt; i++) 457 len += gps->gss[i].length; 458 459 toks = vmalloc(len); 460 if (toks == 0) 461 return -1; 462 p = (char *)toks->v; 463 for (i = 0; i < gps->gsscnt; i++) { 464 memcpy(p, gps->gss[i].value, gps->gss[i].length); 465 p += gps->gss[i].length; 466 } 467 468 *tokens = toks; 469 470 plog(LLV_DEBUG, LOCATION, NULL, 471 "%d itokens of length %d\n", gps->gsscnt, (*tokens)->l); 472 473 return 0; 474 } 475 476 int 477 gssapi_get_rtokens(struct ph1handle *iph1, vchar_t **tokens) 478 { 479 struct gssapi_ph1_state *gps; 480 int len, i; 481 vchar_t *toks; 482 char *p; 483 484 gps = gssapi_get_state(iph1); 485 if (gps == NULL) { 486 plog(LLV_ERROR, LOCATION, NULL, 487 "gssapi not yet initialized?\n"); 488 return -1; 489 } 490 491 if (gssapi_more_tokens(iph1)) { 492 plog(LLV_ERROR, LOCATION, NULL, 493 "gssapi roundtrips not complete\n"); 494 return -1; 495 } 496 497 for (i = len = 0; i < gps->gsscnt_p; i++) 498 len += gps->gss_p[i].length; 499 500 toks = vmalloc(len); 501 if (toks == 0) 502 return -1; 503 p = (char *)toks->v; 504 for (i = 0; i < gps->gsscnt_p; i++) { 505 memcpy(p, gps->gss_p[i].value, gps->gss_p[i].length); 506 p += gps->gss_p[i].length; 507 } 508 509 *tokens = toks; 510 511 return 0; 512 } 513 514 vchar_t * 515 gssapi_wraphash(struct ph1handle *iph1) 516 { 517 struct gssapi_ph1_state *gps; 518 OM_uint32 maj_stat, min_stat; 519 gss_buffer_desc hash_in_buf, hash_out_buf; 520 gss_buffer_t hash_in = &hash_in_buf, hash_out = &hash_out_buf; 521 vchar_t *outbuf; 522 523 gps = gssapi_get_state(iph1); 524 if (gps == NULL) { 525 plog(LLV_ERROR, LOCATION, NULL, 526 "gssapi not yet initialized?\n"); 527 return NULL; 528 } 529 530 if (gssapi_more_tokens(iph1)) { 531 plog(LLV_ERROR, LOCATION, NULL, 532 "gssapi roundtrips not complete\n"); 533 return NULL; 534 } 535 536 if (gssapi_vm2gssbuf(iph1->hash, hash_in) < 0) { 537 plog(LLV_ERROR, LOCATION, NULL, "vm2gssbuf failed\n"); 538 return NULL; 539 } 540 541 maj_stat = gss_wrap(&min_stat, gps->gss_context, 1, GSS_C_QOP_DEFAULT, 542 hash_in, NULL, hash_out); 543 if (GSS_ERROR(maj_stat)) { 544 gssapi_error(min_stat, LOCATION, "wrapping hash value\n"); 545 maj_stat = gss_release_buffer(&min_stat, hash_in); 546 if (GSS_ERROR(maj_stat)) 547 gssapi_error(min_stat, LOCATION, 548 "release hash_in buffer\n"); 549 return NULL; 550 } 551 552 plog(LLV_DEBUG, LOCATION, NULL, "wrapped HASH, ilen %d olen %d\n", 553 hash_in->length, hash_out->length); 554 555 maj_stat = gss_release_buffer(&min_stat, hash_in); 556 if (GSS_ERROR(maj_stat)) 557 gssapi_error(min_stat, LOCATION, "release hash_in buffer\n"); 558 559 if (gssapi_gss2vmbuf(hash_out, &outbuf) < 0) { 560 plog(LLV_ERROR, LOCATION, NULL, "gss2vmbuf failed\n"); 561 maj_stat = gss_release_buffer(&min_stat, hash_out); 562 if (GSS_ERROR(maj_stat)) 563 gssapi_error(min_stat, LOCATION, 564 "release hash_out buffer\n"); 565 return NULL; 566 } 567 maj_stat = gss_release_buffer(&min_stat, hash_out); 568 if (GSS_ERROR(maj_stat)) 569 gssapi_error(min_stat, LOCATION, "release hash_out buffer\n"); 570 571 return outbuf; 572 } 573 574 vchar_t * 575 gssapi_unwraphash(struct ph1handle *iph1) 576 { 577 struct gssapi_ph1_state *gps; 578 OM_uint32 maj_stat, min_stat; 579 gss_buffer_desc hashbuf, hash_outbuf; 580 gss_buffer_t hash_in = &hashbuf, hash_out = &hash_outbuf; 581 vchar_t *outbuf; 582 583 gps = gssapi_get_state(iph1); 584 if (gps == NULL) { 585 plog(LLV_ERROR, LOCATION, NULL, 586 "gssapi not yet initialized?\n"); 587 return NULL; 588 } 589 590 591 hashbuf.length = ntohs(iph1->pl_hash->h.len) - sizeof(*iph1->pl_hash); 592 hashbuf.value = (char *)(iph1->pl_hash + 1); 593 594 plog(LLV_DEBUG, LOCATION, NULL, "unwrapping HASH of len %d\n", 595 hashbuf.length); 596 597 maj_stat = gss_unwrap(&min_stat, gps->gss_context, hash_in, hash_out, 598 NULL, NULL); 599 if (GSS_ERROR(maj_stat)) { 600 gssapi_error(min_stat, LOCATION, "unwrapping hash value\n"); 601 return NULL; 602 } 603 604 if (gssapi_gss2vmbuf(hash_out, &outbuf) < 0) { 605 plog(LLV_ERROR, LOCATION, NULL, "gss2vmbuf failed\n"); 606 maj_stat = gss_release_buffer(&min_stat, hash_out); 607 if (GSS_ERROR(maj_stat)) 608 gssapi_error(min_stat, LOCATION, 609 "release hash_out buffer\n"); 610 return NULL; 611 } 612 maj_stat = gss_release_buffer(&min_stat, hash_out); 613 if (GSS_ERROR(maj_stat)) 614 gssapi_error(min_stat, LOCATION, "release hash_out buffer\n"); 615 616 return outbuf; 617 } 618 619 void 620 gssapi_set_id_sent(struct ph1handle *iph1) 621 { 622 struct gssapi_ph1_state *gps; 623 624 gps = gssapi_get_state(iph1); 625 626 gps->gss_flags |= GSSFLAG_ID_SENT; 627 } 628 629 int 630 gssapi_id_sent(struct ph1handle *iph1) 631 { 632 struct gssapi_ph1_state *gps; 633 634 gps = gssapi_get_state(iph1); 635 636 return (gps->gss_flags & GSSFLAG_ID_SENT) != 0; 637 } 638 639 void 640 gssapi_set_id_rcvd(struct ph1handle *iph1) 641 { 642 struct gssapi_ph1_state *gps; 643 644 gps = gssapi_get_state(iph1); 645 646 gps->gss_flags |= GSSFLAG_ID_RCVD; 647 } 648 649 int 650 gssapi_id_rcvd(struct ph1handle *iph1) 651 { 652 struct gssapi_ph1_state *gps; 653 654 gps = gssapi_get_state(iph1); 655 656 return (gps->gss_flags & GSSFLAG_ID_RCVD) != 0; 657 } 658 659 void 660 gssapi_free_state(struct ph1handle *iph1) 661 { 662 struct gssapi_ph1_state *gps; 663 OM_uint32 maj_stat, min_stat; 664 665 gps = gssapi_get_state(iph1); 666 667 if (gps == NULL) 668 return; 669 670 gssapi_set_state(iph1, NULL); 671 672 if (gps->gss_cred != GSS_C_NO_CREDENTIAL) { 673 maj_stat = gss_release_cred(&min_stat, &gps->gss_cred); 674 if (GSS_ERROR(maj_stat)) 675 gssapi_error(min_stat, LOCATION, 676 "releasing credentials\n"); 677 } 678 racoon_free(gps); 679 } 680 681 vchar_t * 682 gssapi_get_id(struct ph1handle *iph1) 683 { 684 gss_buffer_desc id_buffer; 685 gss_buffer_t id = &id_buffer; 686 gss_name_t defname, canon_name; 687 OM_uint32 min_stat, maj_stat; 688 vchar_t *vmbuf; 689 690 if (iph1->rmconf->proposal->gssid != NULL) 691 return (vdup(iph1->rmconf->proposal->gssid)); 692 693 if (gssapi_get_default_name(iph1, 0, &defname) < 0) 694 return NULL; 695 696 maj_stat = gss_canonicalize_name(&min_stat, defname, GSS_C_NO_OID, 697 &canon_name); 698 if (GSS_ERROR(maj_stat)) { 699 gssapi_error(min_stat, LOCATION, "canonicalize name\n"); 700 maj_stat = gss_release_name(&min_stat, &defname); 701 if (GSS_ERROR(maj_stat)) 702 gssapi_error(min_stat, LOCATION, 703 "release default name\n"); 704 return NULL; 705 } 706 maj_stat = gss_release_name(&min_stat, &defname); 707 if (GSS_ERROR(maj_stat)) 708 gssapi_error(min_stat, LOCATION, "release default name\n"); 709 710 maj_stat = gss_export_name(&min_stat, canon_name, id); 711 if (GSS_ERROR(maj_stat)) { 712 gssapi_error(min_stat, LOCATION, "export name\n"); 713 maj_stat = gss_release_name(&min_stat, &canon_name); 714 if (GSS_ERROR(maj_stat)) 715 gssapi_error(min_stat, LOCATION, 716 "release canonical name\n"); 717 return NULL; 718 } 719 maj_stat = gss_release_name(&min_stat, &canon_name); 720 if (GSS_ERROR(maj_stat)) 721 gssapi_error(min_stat, LOCATION, "release canonical name\n"); 722 723 #if 0 724 /* 725 * XXXJRT Did this debug message ever work? This is a GSS name 726 * blob at this point. 727 */ 728 plog(LLV_DEBUG, LOCATION, NULL, "will try to acquire '%.*s' creds\n", 729 id->length, id->value); 730 #endif 731 732 if (gssapi_gss2vmbuf(id, &vmbuf) < 0) { 733 plog(LLV_ERROR, LOCATION, NULL, "gss2vmbuf failed\n"); 734 maj_stat = gss_release_buffer(&min_stat, id); 735 if (GSS_ERROR(maj_stat)) 736 gssapi_error(min_stat, LOCATION, "release id buffer\n"); 737 return NULL; 738 } 739 maj_stat = gss_release_buffer(&min_stat, id); 740 if (GSS_ERROR(maj_stat)) 741 gssapi_error(min_stat, LOCATION, "release id buffer\n"); 742 743 return vmbuf; 744 } 745 #else 746 int __gssapi_dUmMy; 747 #endif 748