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