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
gssapi_error(OM_uint32 status_code,const char * where,const char * fmt,...)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
gssapi_vm2gssbuf(vchar_t * vmbuf,gss_buffer_t gsstoken)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
gssapi_gss2vmbuf(gss_buffer_t gsstoken,vchar_t ** vmbuf)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 *
gssapi_get_default_gss_id(void)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
gssapi_get_default_name(struct ph1handle * iph1,int remote,gss_name_t * service)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
gssapi_init(struct ph1handle * iph1)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
gssapi_get_itoken(struct ph1handle * iph1,int * lenp)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
gssapi_get_rtoken(struct ph1handle * iph1,int * lenp)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
gssapi_save_received_token(struct ph1handle * iph1,vchar_t * token)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
gssapi_get_token_to_send(struct ph1handle * iph1,vchar_t ** token)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
gssapi_get_itokens(struct ph1handle * iph1,vchar_t ** tokens)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
gssapi_get_rtokens(struct ph1handle * iph1,vchar_t ** tokens)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 *
gssapi_wraphash(struct ph1handle * iph1)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 *
gssapi_unwraphash(struct ph1handle * iph1)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
gssapi_set_id_sent(struct ph1handle * iph1)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
gssapi_id_sent(struct ph1handle * iph1)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
gssapi_set_id_rcvd(struct ph1handle * iph1)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
gssapi_id_rcvd(struct ph1handle * iph1)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
gssapi_free_state(struct ph1handle * iph1)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 *
gssapi_get_id(struct ph1handle * iph1)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