Annotation of embedaddon/ipsec-tools/src/racoon/gssapi.c, revision 1.1
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
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>