Return to gssapi.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / ipsec-tools / src / racoon |
1.1 ! misho 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