]> git.saurik.com Git - apple/ipsec.git/blob - ipsec-tools/racoon/gssapi.c
ipsec-93.13.tar.gz
[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 char* buf = NULL;
157 gss_buffer_desc name_token;
158 OM_uint32 min_stat, maj_stat;
159
160 sa = remote ? iph1->remote : iph1->local;
161
162 if (getnameinfo(sa, sysdep_sa_len(sa), name, NI_MAXHOST, NULL, 0, 0) != 0)
163 return -1;
164
165 name_token.length = asprintf(&buf, "%s@%s", GSSAPI_DEF_NAME, name);
166 name_token.value = buf;
167
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 = &empty;
289
290 if (iph1->approval != NULL && iph1->approval->gssid != NULL) {
291 plog(LLV_DEBUG, LOCATION, NULL,
292 "using provided service '%.*s'\n",
293 (int)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 %zu\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 %zu olen %zu\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 %zu\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