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