1 /* $NetBSD: gssapi.c,v 1.6 2015/05/19 15:16:00 christos 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 if (iph1->rmconf == NULL) {
196 plog(LLV_ERROR, LOCATION, NULL, "no remote config\n");
197 return -1;
198 }
199
200 gps = racoon_calloc(1, sizeof (struct gssapi_ph1_state));
201 if (gps == NULL) {
202 plog(LLV_ERROR, LOCATION, NULL, "racoon_calloc failed\n");
203 return -1;
204 }
205 gps->gss_context = GSS_C_NO_CONTEXT;
206 gps->gss_cred = GSS_C_NO_CREDENTIAL;
207
208 gssapi_set_state(iph1, gps);
209
210 if (iph1->rmconf->proposal->gssid != NULL) {
211 id_token.length = iph1->rmconf->proposal->gssid->l;
212 id_token.value = iph1->rmconf->proposal->gssid->v;
213 maj_stat = gss_import_name(&min_stat, &id_token, GSS_C_NO_OID,
214 &princ);
215 if (GSS_ERROR(maj_stat)) {
216 gssapi_error(min_stat, LOCATION, "import name\n");
217 gssapi_free_state(iph1);
218 return -1;
219 }
220 } else
221 gssapi_get_default_name(iph1, 0, &princ);
222
223 maj_stat = gss_canonicalize_name(&min_stat, princ, GSS_C_NO_OID,
224 &canon_princ);
225 if (GSS_ERROR(maj_stat)) {
226 gssapi_error(min_stat, LOCATION, "canonicalize name\n");
227 maj_stat = gss_release_name(&min_stat, &princ);
228 if (GSS_ERROR(maj_stat))
229 gssapi_error(min_stat, LOCATION, "release princ\n");
230 gssapi_free_state(iph1);
231 return -1;
232 }
233 maj_stat = gss_release_name(&min_stat, &princ);
234 if (GSS_ERROR(maj_stat))
235 gssapi_error(min_stat, LOCATION, "release princ\n");
236
237 maj_stat = gss_export_name(&min_stat, canon_princ, cred);
238 if (GSS_ERROR(maj_stat)) {
239 gssapi_error(min_stat, LOCATION, "export name\n");
240 maj_stat = gss_release_name(&min_stat, &canon_princ);
241 if (GSS_ERROR(maj_stat))
242 gssapi_error(min_stat, LOCATION,
243 "release canon_princ\n");
244 gssapi_free_state(iph1);
245 return -1;
246 }
247
248 #if 0
249 /*
250 * XXXJRT Did this debug message ever work? This is a GSS name
251 * blob at this point.
252 */
253 plog(LLV_DEBUG, LOCATION, NULL, "will try to acquire '%.*s' creds\n",
254 cred->length, cred->value);
255 #endif
256
257 maj_stat = gss_release_buffer(&min_stat, cred);
258 if (GSS_ERROR(maj_stat))
259 gssapi_error(min_stat, LOCATION, "release cred buffer\n");
260
261 maj_stat = gss_acquire_cred(&min_stat, canon_princ, GSS_C_INDEFINITE,
262 GSS_C_NO_OID_SET, GSS_C_BOTH, &gps->gss_cred, NULL, NULL);
263 if (GSS_ERROR(maj_stat)) {
264 gssapi_error(min_stat, LOCATION, "acquire cred\n");
265 maj_stat = gss_release_name(&min_stat, &canon_princ);
266 if (GSS_ERROR(maj_stat))
267 gssapi_error(min_stat, LOCATION,
268 "release canon_princ\n");
269 gssapi_free_state(iph1);
270 return -1;
271 }
272 maj_stat = gss_release_name(&min_stat, &canon_princ);
273 if (GSS_ERROR(maj_stat))
274 gssapi_error(min_stat, LOCATION, "release canon_princ\n");
275
276 return 0;
277 }
278
279 int
gssapi_get_itoken(struct ph1handle * iph1,int * lenp)280 gssapi_get_itoken(struct ph1handle *iph1, int *lenp)
281 {
282 struct gssapi_ph1_state *gps;
283 gss_buffer_desc empty, name_token;
284 gss_buffer_t itoken, rtoken, dummy;
285 OM_uint32 maj_stat, min_stat;
286 gss_name_t partner;
287
288 if (gssapi_get_state(iph1) == NULL && gssapi_init(iph1) < 0)
289 return -1;
290
291 gps = gssapi_get_state(iph1);
292
293 empty.length = 0;
294 empty.value = NULL;
295 dummy = ∅
296
297 if (iph1->approval != NULL && iph1->approval->gssid != NULL) {
298 plog(LLV_DEBUG, LOCATION, NULL,
299 "using provided service '%.*s'\n",
300 (int)iph1->approval->gssid->l, iph1->approval->gssid->v);
301 name_token.length = iph1->approval->gssid->l;
302 name_token.value = iph1->approval->gssid->v;
303 maj_stat = gss_import_name(&min_stat, &name_token,
304 GSS_C_NO_OID, &partner);
305 if (GSS_ERROR(maj_stat)) {
306 gssapi_error(min_stat, LOCATION, "import of %.*s\n",
307 name_token.length, name_token.value);
308 return -1;
309 }
310 } else
311 if (gssapi_get_default_name(iph1, 1, &partner) < 0)
312 return -1;
313
314 rtoken = gps->gsscnt_p == 0 ? dummy : &gps->gss_p[gps->gsscnt_p - 1];
315 itoken = &gps->gss[gps->gsscnt];
316
317 gps->gss_status = gss_init_sec_context(&min_stat, gps->gss_cred,
318 &gps->gss_context, partner, GSS_C_NO_OID,
319 GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG |
320 GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG,
321 0, GSS_C_NO_CHANNEL_BINDINGS, rtoken, NULL,
322 itoken, NULL, NULL);
323
324 if (GSS_ERROR(gps->gss_status)) {
325 gssapi_error(min_stat, LOCATION, "init_sec_context\n");
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 return -1;
330 }
331 maj_stat = gss_release_name(&min_stat, &partner);
332 if (GSS_ERROR(maj_stat))
333 gssapi_error(min_stat, LOCATION, "release name\n");
334
335 plog(LLV_DEBUG, LOCATION, NULL, "gss_init_sec_context status %x\n",
336 gps->gss_status);
337
338 if (lenp)
339 *lenp = itoken->length;
340
341 if (itoken->length != 0)
342 gps->gsscnt++;
343
344 return 0;
345 }
346
347 /*
348 * Call gss_accept_context, with token just read from the wire.
349 */
350 int
gssapi_get_rtoken(struct ph1handle * iph1,int * lenp)351 gssapi_get_rtoken(struct ph1handle *iph1, int *lenp)
352 {
353 struct gssapi_ph1_state *gps;
354 gss_buffer_desc name_token;
355 gss_buffer_t itoken, rtoken;
356 OM_uint32 min_stat, maj_stat;
357 gss_name_t client_name;
358
359 if (gssapi_get_state(iph1) == NULL && gssapi_init(iph1) < 0)
360 return -1;
361
362 gps = gssapi_get_state(iph1);
363
364 rtoken = &gps->gss_p[gps->gsscnt_p - 1];
365 itoken = &gps->gss[gps->gsscnt];
366
367 gps->gss_status = gss_accept_sec_context(&min_stat, &gps->gss_context,
368 gps->gss_cred, rtoken, GSS_C_NO_CHANNEL_BINDINGS, &client_name,
369 NULL, itoken, NULL, NULL, NULL);
370
371 if (GSS_ERROR(gps->gss_status)) {
372 gssapi_error(min_stat, LOCATION, "accept_sec_context\n");
373 return -1;
374 }
375
376 maj_stat = gss_display_name(&min_stat, client_name, &name_token, NULL);
377 if (GSS_ERROR(maj_stat)) {
378 gssapi_error(min_stat, LOCATION, "gss_display_name\n");
379 maj_stat = gss_release_name(&min_stat, &client_name);
380 if (GSS_ERROR(maj_stat))
381 gssapi_error(min_stat, LOCATION,
382 "release client_name\n");
383 return -1;
384 }
385 maj_stat = gss_release_name(&min_stat, &client_name);
386 if (GSS_ERROR(maj_stat))
387 gssapi_error(min_stat, LOCATION, "release client_name\n");
388
389 plog(LLV_DEBUG, LOCATION, NULL,
390 "gss_accept_sec_context: other side is %s\n",
391 (char *)name_token.value);
392 maj_stat = gss_release_buffer(&min_stat, &name_token);
393 if (GSS_ERROR(maj_stat))
394 gssapi_error(min_stat, LOCATION, "release name buffer\n");
395
396 if (itoken->length != 0)
397 gps->gsscnt++;
398
399 if (lenp)
400 *lenp = itoken->length;
401
402 return 0;
403 }
404
405 int
gssapi_save_received_token(struct ph1handle * iph1,vchar_t * token)406 gssapi_save_received_token(struct ph1handle *iph1, vchar_t *token)
407 {
408 struct gssapi_ph1_state *gps;
409 gss_buffer_t gsstoken;
410 int ret;
411
412 if (gssapi_get_state(iph1) == NULL && gssapi_init(iph1) < 0)
413 return -1;
414
415 gps = gssapi_get_state(iph1);
416
417 gsstoken = &gps->gss_p[gps->gsscnt_p];
418
419 ret = gssapi_vm2gssbuf(token, gsstoken);
420 if (ret < 0)
421 return ret;
422 gps->gsscnt_p++;
423
424 return 0;
425 }
426
427 int
gssapi_get_token_to_send(struct ph1handle * iph1,vchar_t ** token)428 gssapi_get_token_to_send(struct ph1handle *iph1, vchar_t **token)
429 {
430 struct gssapi_ph1_state *gps;
431 gss_buffer_t gsstoken;
432 int ret;
433
434 gps = gssapi_get_state(iph1);
435 if (gps == NULL) {
436 plog(LLV_ERROR, LOCATION, NULL,
437 "gssapi not yet initialized?\n");
438 return -1;
439 }
440 gsstoken = &gps->gss[gps->gsscnt - 1];
441 ret = gssapi_gss2vmbuf(gsstoken, token);
442 if (ret < 0)
443 return ret;
444
445 return 0;
446 }
447
448 int
gssapi_get_itokens(struct ph1handle * iph1,vchar_t ** tokens)449 gssapi_get_itokens(struct ph1handle *iph1, vchar_t **tokens)
450 {
451 struct gssapi_ph1_state *gps;
452 int len, i;
453 vchar_t *toks;
454 char *p;
455
456 gps = gssapi_get_state(iph1);
457 if (gps == NULL) {
458 plog(LLV_ERROR, LOCATION, NULL,
459 "gssapi not yet initialized?\n");
460 return -1;
461 }
462
463 for (i = len = 0; i < gps->gsscnt; i++)
464 len += gps->gss[i].length;
465
466 toks = vmalloc(len);
467 if (toks == 0)
468 return -1;
469 p = (char *)toks->v;
470 for (i = 0; i < gps->gsscnt; i++) {
471 memcpy(p, gps->gss[i].value, gps->gss[i].length);
472 p += gps->gss[i].length;
473 }
474
475 *tokens = toks;
476
477 plog(LLV_DEBUG, LOCATION, NULL,
478 "%d itokens of length %zu\n", gps->gsscnt, (*tokens)->l);
479
480 return 0;
481 }
482
483 int
gssapi_get_rtokens(struct ph1handle * iph1,vchar_t ** tokens)484 gssapi_get_rtokens(struct ph1handle *iph1, vchar_t **tokens)
485 {
486 struct gssapi_ph1_state *gps;
487 int len, i;
488 vchar_t *toks;
489 char *p;
490
491 gps = gssapi_get_state(iph1);
492 if (gps == NULL) {
493 plog(LLV_ERROR, LOCATION, NULL,
494 "gssapi not yet initialized?\n");
495 return -1;
496 }
497
498 if (gssapi_more_tokens(iph1)) {
499 plog(LLV_ERROR, LOCATION, NULL,
500 "gssapi roundtrips not complete\n");
501 return -1;
502 }
503
504 for (i = len = 0; i < gps->gsscnt_p; i++)
505 len += gps->gss_p[i].length;
506
507 toks = vmalloc(len);
508 if (toks == 0)
509 return -1;
510 p = (char *)toks->v;
511 for (i = 0; i < gps->gsscnt_p; i++) {
512 memcpy(p, gps->gss_p[i].value, gps->gss_p[i].length);
513 p += gps->gss_p[i].length;
514 }
515
516 *tokens = toks;
517
518 return 0;
519 }
520
521 vchar_t *
gssapi_wraphash(struct ph1handle * iph1)522 gssapi_wraphash(struct ph1handle *iph1)
523 {
524 struct gssapi_ph1_state *gps;
525 OM_uint32 maj_stat, min_stat;
526 gss_buffer_desc hash_in_buf, hash_out_buf;
527 gss_buffer_t hash_in = &hash_in_buf, hash_out = &hash_out_buf;
528 vchar_t *outbuf;
529
530 gps = gssapi_get_state(iph1);
531 if (gps == NULL) {
532 plog(LLV_ERROR, LOCATION, NULL,
533 "gssapi not yet initialized?\n");
534 return NULL;
535 }
536
537 if (gssapi_more_tokens(iph1)) {
538 plog(LLV_ERROR, LOCATION, NULL,
539 "gssapi roundtrips not complete\n");
540 return NULL;
541 }
542
543 if (gssapi_vm2gssbuf(iph1->hash, hash_in) < 0) {
544 plog(LLV_ERROR, LOCATION, NULL, "vm2gssbuf failed\n");
545 return NULL;
546 }
547
548 maj_stat = gss_wrap(&min_stat, gps->gss_context, 1, GSS_C_QOP_DEFAULT,
549 hash_in, NULL, hash_out);
550 if (GSS_ERROR(maj_stat)) {
551 gssapi_error(min_stat, LOCATION, "wrapping hash value\n");
552 maj_stat = gss_release_buffer(&min_stat, hash_in);
553 if (GSS_ERROR(maj_stat))
554 gssapi_error(min_stat, LOCATION,
555 "release hash_in buffer\n");
556 return NULL;
557 }
558
559 plog(LLV_DEBUG, LOCATION, NULL, "wrapped HASH, ilen %zu olen %zu\n",
560 hash_in->length, hash_out->length);
561
562 maj_stat = gss_release_buffer(&min_stat, hash_in);
563 if (GSS_ERROR(maj_stat))
564 gssapi_error(min_stat, LOCATION, "release hash_in buffer\n");
565
566 if (gssapi_gss2vmbuf(hash_out, &outbuf) < 0) {
567 plog(LLV_ERROR, LOCATION, NULL, "gss2vmbuf failed\n");
568 maj_stat = gss_release_buffer(&min_stat, hash_out);
569 if (GSS_ERROR(maj_stat))
570 gssapi_error(min_stat, LOCATION,
571 "release hash_out buffer\n");
572 return NULL;
573 }
574 maj_stat = gss_release_buffer(&min_stat, hash_out);
575 if (GSS_ERROR(maj_stat))
576 gssapi_error(min_stat, LOCATION, "release hash_out buffer\n");
577
578 return outbuf;
579 }
580
581 vchar_t *
gssapi_unwraphash(struct ph1handle * iph1)582 gssapi_unwraphash(struct ph1handle *iph1)
583 {
584 struct gssapi_ph1_state *gps;
585 OM_uint32 maj_stat, min_stat;
586 gss_buffer_desc hashbuf, hash_outbuf;
587 gss_buffer_t hash_in = &hashbuf, hash_out = &hash_outbuf;
588 vchar_t *outbuf;
589
590 gps = gssapi_get_state(iph1);
591 if (gps == NULL) {
592 plog(LLV_ERROR, LOCATION, NULL,
593 "gssapi not yet initialized?\n");
594 return NULL;
595 }
596
597
598 hashbuf.length = ntohs(iph1->pl_hash->h.len) - sizeof(*iph1->pl_hash);
599 hashbuf.value = (char *)(iph1->pl_hash + 1);
600
601 plog(LLV_DEBUG, LOCATION, NULL, "unwrapping HASH of len %zu\n",
602 hashbuf.length);
603
604 maj_stat = gss_unwrap(&min_stat, gps->gss_context, hash_in, hash_out,
605 NULL, NULL);
606 if (GSS_ERROR(maj_stat)) {
607 gssapi_error(min_stat, LOCATION, "unwrapping hash value\n");
608 return NULL;
609 }
610
611 if (gssapi_gss2vmbuf(hash_out, &outbuf) < 0) {
612 plog(LLV_ERROR, LOCATION, NULL, "gss2vmbuf failed\n");
613 maj_stat = gss_release_buffer(&min_stat, hash_out);
614 if (GSS_ERROR(maj_stat))
615 gssapi_error(min_stat, LOCATION,
616 "release hash_out buffer\n");
617 return NULL;
618 }
619 maj_stat = gss_release_buffer(&min_stat, hash_out);
620 if (GSS_ERROR(maj_stat))
621 gssapi_error(min_stat, LOCATION, "release hash_out buffer\n");
622
623 return outbuf;
624 }
625
626 void
gssapi_set_id_sent(struct ph1handle * iph1)627 gssapi_set_id_sent(struct ph1handle *iph1)
628 {
629 struct gssapi_ph1_state *gps;
630
631 gps = gssapi_get_state(iph1);
632
633 gps->gss_flags |= GSSFLAG_ID_SENT;
634 }
635
636 int
gssapi_id_sent(struct ph1handle * iph1)637 gssapi_id_sent(struct ph1handle *iph1)
638 {
639 struct gssapi_ph1_state *gps;
640
641 gps = gssapi_get_state(iph1);
642
643 return (gps->gss_flags & GSSFLAG_ID_SENT) != 0;
644 }
645
646 void
gssapi_set_id_rcvd(struct ph1handle * iph1)647 gssapi_set_id_rcvd(struct ph1handle *iph1)
648 {
649 struct gssapi_ph1_state *gps;
650
651 gps = gssapi_get_state(iph1);
652
653 gps->gss_flags |= GSSFLAG_ID_RCVD;
654 }
655
656 int
gssapi_id_rcvd(struct ph1handle * iph1)657 gssapi_id_rcvd(struct ph1handle *iph1)
658 {
659 struct gssapi_ph1_state *gps;
660
661 gps = gssapi_get_state(iph1);
662
663 return (gps->gss_flags & GSSFLAG_ID_RCVD) != 0;
664 }
665
666 void
gssapi_free_state(struct ph1handle * iph1)667 gssapi_free_state(struct ph1handle *iph1)
668 {
669 struct gssapi_ph1_state *gps;
670 OM_uint32 maj_stat, min_stat;
671
672 gps = gssapi_get_state(iph1);
673
674 if (gps == NULL)
675 return;
676
677 gssapi_set_state(iph1, NULL);
678
679 if (gps->gss_cred != GSS_C_NO_CREDENTIAL) {
680 maj_stat = gss_release_cred(&min_stat, &gps->gss_cred);
681 if (GSS_ERROR(maj_stat))
682 gssapi_error(min_stat, LOCATION,
683 "releasing credentials\n");
684 }
685 racoon_free(gps);
686 }
687
688 vchar_t *
gssapi_get_id(struct ph1handle * iph1)689 gssapi_get_id(struct ph1handle *iph1)
690 {
691 gss_buffer_desc id_buffer;
692 gss_buffer_t id = &id_buffer;
693 gss_name_t defname, canon_name;
694 OM_uint32 min_stat, maj_stat;
695 vchar_t *vmbuf;
696
697 if (iph1->rmconf->proposal->gssid != NULL)
698 return (vdup(iph1->rmconf->proposal->gssid));
699
700 if (gssapi_get_default_name(iph1, 0, &defname) < 0)
701 return NULL;
702
703 maj_stat = gss_canonicalize_name(&min_stat, defname, GSS_C_NO_OID,
704 &canon_name);
705 if (GSS_ERROR(maj_stat)) {
706 gssapi_error(min_stat, LOCATION, "canonicalize name\n");
707 maj_stat = gss_release_name(&min_stat, &defname);
708 if (GSS_ERROR(maj_stat))
709 gssapi_error(min_stat, LOCATION,
710 "release default name\n");
711 return NULL;
712 }
713 maj_stat = gss_release_name(&min_stat, &defname);
714 if (GSS_ERROR(maj_stat))
715 gssapi_error(min_stat, LOCATION, "release default name\n");
716
717 maj_stat = gss_export_name(&min_stat, canon_name, id);
718 if (GSS_ERROR(maj_stat)) {
719 gssapi_error(min_stat, LOCATION, "export name\n");
720 maj_stat = gss_release_name(&min_stat, &canon_name);
721 if (GSS_ERROR(maj_stat))
722 gssapi_error(min_stat, LOCATION,
723 "release canonical name\n");
724 return NULL;
725 }
726 maj_stat = gss_release_name(&min_stat, &canon_name);
727 if (GSS_ERROR(maj_stat))
728 gssapi_error(min_stat, LOCATION, "release canonical name\n");
729
730 #if 0
731 /*
732 * XXXJRT Did this debug message ever work? This is a GSS name
733 * blob at this point.
734 */
735 plog(LLV_DEBUG, LOCATION, NULL, "will try to acquire '%.*s' creds\n",
736 id->length, id->value);
737 #endif
738
739 if (gssapi_gss2vmbuf(id, &vmbuf) < 0) {
740 plog(LLV_ERROR, LOCATION, NULL, "gss2vmbuf failed\n");
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 return NULL;
745 }
746 maj_stat = gss_release_buffer(&min_stat, id);
747 if (GSS_ERROR(maj_stat))
748 gssapi_error(min_stat, LOCATION, "release id buffer\n");
749
750 return vmbuf;
751 }
752 #else
753 int __gssapi_dUmMy;
754 #endif
755