kdc: check_authz free 'cprinc' on success
[heimdal.git] / appl / gssmask / gssmaestro.c
blob9ccf1de4088124662c26430f741c7f1e6a192cbc
1 /*
2 * Copyright (c) 2006 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of KTH nor the names of its contributors may be
18 * used to endorse or promote products derived from this software without
19 * specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY
22 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 #include <common.h>
35 RCSID("$Id$");
37 static FILE *logfile;
43 struct client {
44 char *name;
45 struct sockaddr *sa;
46 socklen_t salen;
47 krb5_storage *sock;
48 int32_t capabilities;
49 char *target_name;
50 char *moniker;
51 krb5_storage *logsock;
52 int have_log;
53 #ifdef ENABLE_PTHREAD_SUPPORT
54 pthread_t thr;
55 #else
56 pid_t child;
57 #endif
60 static struct client **clients;
61 static int num_clients;
63 static int
64 init_sec_context(struct client *client,
65 int32_t *hContext, int32_t *hCred,
66 int32_t flags,
67 const char *targetname,
68 const krb5_data *itoken, krb5_data *otoken)
70 int32_t val;
71 krb5_data_zero(otoken);
72 put32(client, eInitContext);
73 put32(client, *hContext);
74 put32(client, *hCred);
75 put32(client, flags);
76 putstring(client, targetname);
77 putdata(client, *itoken);
78 ret32(client, *hContext);
79 ret32(client, val);
80 retdata(client, *otoken);
81 return val;
84 static int
85 accept_sec_context(struct client *client,
86 int32_t *hContext,
87 int32_t flags,
88 const krb5_data *itoken,
89 krb5_data *otoken,
90 int32_t *hDelegCred)
92 int32_t val;
93 krb5_data_zero(otoken);
94 put32(client, eAcceptContext);
95 put32(client, *hContext);
96 put32(client, flags);
97 putdata(client, *itoken);
98 ret32(client, *hContext);
99 ret32(client, val);
100 retdata(client, *otoken);
101 ret32(client, *hDelegCred);
102 return val;
105 static int
106 acquire_cred(struct client *client,
107 const char *username,
108 const char *password,
109 int32_t flags,
110 int32_t *hCred)
112 int32_t val;
113 put32(client, eAcquireCreds);
114 putstring(client, username);
115 putstring(client, password);
116 put32(client, flags);
117 ret32(client, val);
118 ret32(client, *hCred);
119 return val;
122 static int
123 toast_resource(struct client *client,
124 int32_t hCred)
126 int32_t val;
127 put32(client, eToastResource);
128 put32(client, hCred);
129 ret32(client, val);
130 return val;
133 static int
134 goodbye(struct client *client)
136 put32(client, eGoodBye);
137 return GSMERR_OK;
140 static int
141 get_targetname(struct client *client,
142 char **target)
144 put32(client, eGetTargetName);
145 retstring(client, *target);
146 return GSMERR_OK;
149 static int32_t
150 encrypt_token(struct client *client, int32_t hContext, int32_t flags,
151 krb5_data *in, krb5_data *out)
153 int32_t val;
154 put32(client, eEncrypt);
155 put32(client, hContext);
156 put32(client, flags);
157 put32(client, 0);
158 putdata(client, *in);
159 ret32(client, val);
160 retdata(client, *out);
161 return val;
164 static int32_t
165 decrypt_token(struct client *client, int32_t hContext, int flags,
166 krb5_data *in, krb5_data *out)
168 int32_t val;
169 put32(client, eDecrypt);
170 put32(client, hContext);
171 put32(client, flags);
172 put32(client, 0);
173 putdata(client, *in);
174 ret32(client, val);
175 retdata(client, *out);
176 return val;
179 static int32_t
180 wrap_token_ext(struct client *client, int32_t hContext, int32_t flags,
181 int32_t bflags, krb5_data *header, krb5_data *in, krb5_data *trailer,
182 krb5_data *out)
184 int32_t val;
185 put32(client, eWrapExt);
186 put32(client, hContext);
187 put32(client, flags);
188 put32(client, bflags);
189 putdata(client, *header);
190 putdata(client, *in);
191 putdata(client, *trailer);
192 ret32(client, val);
193 retdata(client, *out);
194 return val;
197 static int32_t
198 unwrap_token_ext(struct client *client, int32_t hContext, int32_t flags,
199 int32_t bflags, krb5_data *header, krb5_data *in, krb5_data *trailer,
200 krb5_data *out)
202 int32_t val;
203 put32(client, eUnwrapExt);
204 put32(client, hContext);
205 put32(client, flags);
206 put32(client, bflags);
207 putdata(client, *header);
208 putdata(client, *in);
209 putdata(client, *trailer);
210 ret32(client, val);
211 retdata(client, *out);
212 return val;
215 static int32_t
216 get_mic(struct client *client, int32_t hContext,
217 krb5_data *in, krb5_data *mic)
219 int32_t val;
220 put32(client, eSign);
221 put32(client, hContext);
222 put32(client, 0);
223 put32(client, 0);
224 putdata(client, *in);
225 ret32(client, val);
226 retdata(client, *mic);
227 return val;
230 static int32_t
231 verify_mic(struct client *client, int32_t hContext,
232 krb5_data *in, krb5_data *mic)
234 int32_t val;
235 put32(client, eVerify);
236 put32(client, hContext);
237 put32(client, 0);
238 put32(client, 0);
239 putdata(client, *in);
240 putdata(client, *mic);
241 ret32(client, val);
242 return val;
246 static int32_t
247 get_version_capa(struct client *client,
248 int32_t *version, int32_t *capa,
249 char **version_str)
251 put32(client, eGetVersionAndCapabilities);
252 ret32(client, *version);
253 ret32(client, *capa);
254 retstring(client, *version_str);
255 return GSMERR_OK;
258 static int32_t
259 get_moniker(struct client *client,
260 char **moniker)
262 put32(client, eGetMoniker);
263 retstring(client, *moniker);
264 return GSMERR_OK;
267 static int
268 wait_log(struct client *c)
270 int32_t port;
271 struct sockaddr_storage sast;
272 socklen_t salen = sizeof(sast);
273 krb5_socket_t sock, sock2;
274 int ret;
276 memset(&sast, 0, sizeof(sast));
278 assert(sizeof(sast) >= c->salen);
280 sock = socket(c->sa->sa_family, SOCK_STREAM, 0);
281 if (sock == rk_INVALID_SOCKET)
282 err(1, "failed to build socket for %s's logging port", c->moniker);
284 sast.ss_family = c->sa->sa_family;
285 ret = bind(sock, (struct sockaddr *)&sast, c->salen);
286 if (ret < 0)
287 err(1, "failed to bind %s's logging port", c->moniker);
289 if (listen(sock, SOMAXCONN) < 0)
290 err(1, "failed to listen %s's logging port", c->moniker);
292 salen = sizeof(sast);
293 ret = getsockname(sock, (struct sockaddr *)&sast, &salen);
294 if (ret < 0)
295 err(1, "failed to get address of local socket for %s", c->moniker);
297 port = socket_get_port((struct sockaddr *)&sast);
299 put32(c, eSetLoggingSocket);
300 put32(c, ntohs(port));
302 salen = sizeof(sast);
303 sock2 = accept(sock, (struct sockaddr *)&sast, &salen);
304 if (sock2 == rk_INVALID_SOCKET)
305 err(1, "failed to accept local socket for %s", c->moniker);
306 rk_closesocket(sock);
308 return sock2;
314 static int
315 build_context(struct client *ipeer, struct client *apeer,
316 int32_t flags, int32_t hCred,
317 int32_t *iContext, int32_t *aContext, int32_t *hDelegCred)
319 int32_t val = GSMERR_ERROR, ic = 0, ac = 0, deleg = 0;
320 krb5_data itoken, otoken;
321 int iDone = 0, aDone = 0;
322 int step = 0;
323 int first_call = 0x80;
325 if (apeer->target_name == NULL)
326 errx(1, "apeer %s have no target name", apeer->name);
328 krb5_data_zero(&itoken);
330 while (!iDone || !aDone) {
332 if (iDone) {
333 warnx("iPeer already done, aPeer want extra rtt");
334 val = GSMERR_ERROR;
335 goto out;
338 val = init_sec_context(ipeer, &ic, &hCred, flags|first_call,
339 apeer->target_name, &itoken, &otoken);
340 step++;
341 switch(val) {
342 case GSMERR_OK:
343 iDone = 1;
344 if (aDone)
345 continue;
346 break;
347 case GSMERR_CONTINUE_NEEDED:
348 break;
349 default:
350 warnx("iPeer %s failed with %d (step %d)",
351 ipeer->name, (int)val, step);
352 goto out;
355 if (aDone) {
356 warnx("aPeer already done, iPeer want extra rtt");
357 val = GSMERR_ERROR;
358 goto out;
361 val = accept_sec_context(apeer, &ac, flags|first_call,
362 &otoken, &itoken, &deleg);
363 step++;
364 switch(val) {
365 case GSMERR_OK:
366 aDone = 1;
367 if (iDone)
368 continue;
369 break;
370 case GSMERR_CONTINUE_NEEDED:
371 break;
372 default:
373 warnx("aPeer %s failed with %d (step %d)",
374 apeer->name, (int)val, step);
375 val = GSMERR_ERROR;
376 goto out;
378 first_call = 0;
379 val = GSMERR_OK;
382 if (iContext == NULL || val != GSMERR_OK) {
383 if (ic)
384 toast_resource(ipeer, ic);
385 if (iContext)
386 *iContext = 0;
387 } else
388 *iContext = ic;
390 if (aContext == NULL || val != GSMERR_OK) {
391 if (ac)
392 toast_resource(apeer, ac);
393 if (aContext)
394 *aContext = 0;
395 } else
396 *aContext = ac;
398 if (hDelegCred == NULL || val != GSMERR_OK) {
399 if (deleg)
400 toast_resource(apeer, deleg);
401 if (hDelegCred)
402 *hDelegCred = 0;
403 } else
404 *hDelegCred = deleg;
406 out:
407 return val;
410 static void
411 test_mic(struct client *c1, int32_t hc1, struct client *c2, int32_t hc2)
413 krb5_data msg, mic;
414 int32_t val;
416 msg.data = "foo";
417 msg.length = 3;
419 krb5_data_zero(&mic);
421 val = get_mic(c1, hc1, &msg, &mic);
422 if (val)
423 errx(1, "get_mic failed to host: %s", c1->moniker);
424 val = verify_mic(c2, hc2, &msg, &mic);
425 if (val)
426 errx(1, "verify_mic failed to host: %s", c2->moniker);
428 krb5_data_free(&mic);
431 static int32_t
432 test_wrap(struct client *c1, int32_t hc1, struct client *c2, int32_t hc2,
433 int conf)
435 krb5_data msg, wrapped, out;
436 int32_t val;
438 msg.data = "foo";
439 msg.length = 3;
441 krb5_data_zero(&wrapped);
442 krb5_data_zero(&out);
444 val = encrypt_token(c1, hc1, conf, &msg, &wrapped);
445 if (val) {
446 warnx("encrypt_token failed to host: %s", c1->moniker);
447 return val;
449 val = decrypt_token(c2, hc2, conf, &wrapped, &out);
450 if (val) {
451 krb5_data_free(&wrapped);
452 warnx("decrypt_token failed to host: %s", c2->moniker);
453 return val;
456 if (msg.length != out.length) {
457 warnx("decrypted'ed token have wrong length (%lu != %lu)",
458 (unsigned long)msg.length, (unsigned long)out.length);
459 val = GSMERR_ERROR;
460 } else if (memcmp(msg.data, out.data, msg.length) != 0) {
461 warnx("decryptd'ed token have wrong data");
462 val = GSMERR_ERROR;
465 krb5_data_free(&wrapped);
466 krb5_data_free(&out);
467 return val;
470 static int32_t
471 test_wrap_ext(struct client *c1, int32_t hc1, struct client *c2, int32_t hc2,
472 int conf, int bflags)
474 krb5_data header, msg, trailer, wrapped, out;
475 int32_t val;
477 header.data = "header";
478 header.length = sizeof("header") - 1;
480 msg.data = "0123456789abcdef"; /* padded for most enctypes */
481 msg.length = sizeof("0123456789abcdef") - 1;
483 trailer.data = "trailer";
484 trailer.length = 7;
486 krb5_data_zero(&wrapped);
487 krb5_data_zero(&out);
489 val = wrap_token_ext(c1, hc1, conf, bflags, &header, &msg, &trailer, &wrapped);
490 if (val) {
491 warnx("encrypt_token failed to host: %s", c1->moniker);
492 return val;
494 val = unwrap_token_ext(c2, hc2, conf, bflags, &header, &wrapped, &trailer, &out);
495 if (val) {
496 krb5_data_free(&wrapped);
497 warnx("decrypt_token failed to host: %s", c2->moniker);
498 return val;
501 if (msg.length != out.length) {
502 warnx("decrypted'ed token have wrong length (%lu != %lu)",
503 (unsigned long)msg.length, (unsigned long)out.length);
504 val = GSMERR_ERROR;
505 } else if (memcmp(msg.data, out.data, msg.length) != 0) {
506 warnx("decryptd'ed token have wrong data");
507 val = GSMERR_ERROR;
510 krb5_data_free(&wrapped);
511 krb5_data_free(&out);
512 return val;
516 static int32_t
517 test_token(struct client *c1, int32_t hc1, struct client *c2, int32_t hc2, int wrap_ext)
519 int32_t val;
520 int i;
522 for (i = 0; i < 10; i++) {
523 /* mic */
524 test_mic(c1, hc1, c2, hc2);
525 test_mic(c2, hc2, c1, hc1);
527 /* wrap */
528 val = test_wrap(c1, hc1, c2, hc2, 0);
529 if (val) return val;
530 val = test_wrap(c2, hc2, c1, hc1, 0);
531 if (val) return val;
533 val = test_wrap(c1, hc1, c2, hc2, 1);
534 if (val) return val;
535 val = test_wrap(c2, hc2, c1, hc1, 1);
536 if (val) return val;
538 if (wrap_ext) {
539 /* wrap ext */
540 val = test_wrap_ext(c1, hc1, c2, hc2, 1, 0);
541 if (val) return val;
542 val = test_wrap_ext(c2, hc2, c1, hc1, 1, 0);
543 if (val) return val;
545 val = test_wrap_ext(c1, hc1, c2, hc2, 1, 1);
546 if (val) return val;
547 val = test_wrap_ext(c2, hc2, c1, hc1, 1, 1);
548 if (val) return val;
550 val = test_wrap_ext(c1, hc1, c2, hc2, 0, 0);
551 if (val) return val;
552 val = test_wrap_ext(c2, hc2, c1, hc1, 0, 0);
553 if (val) return val;
555 val = test_wrap_ext(c1, hc1, c2, hc2, 0, 1);
556 if (val) return val;
557 val = test_wrap_ext(c2, hc2, c1, hc1, 0, 1);
558 if (val) return val;
561 return GSMERR_OK;
564 static int
565 log_function(void *ptr)
567 struct client *c = ptr;
568 int32_t cmd, line;
569 char *file = NULL, *string = NULL;
571 while (1) {
572 if (krb5_ret_int32(c->logsock, &cmd))
573 goto out;
575 switch (cmd) {
576 case eLogSetMoniker:
577 if (krb5_ret_string(c->logsock, &file))
578 goto out;
579 break;
580 case eLogInfo:
581 case eLogFailure:
582 if (krb5_ret_string(c->logsock, &file))
583 goto out;
584 if (krb5_ret_int32(c->logsock, &line))
585 goto out;
586 if (krb5_ret_string(c->logsock, &string))
587 goto out;
588 printf("%s:%lu: %s\n",
589 file, (unsigned long)line, string);
590 fprintf(logfile, "%s:%lu: %s\n",
591 file, (unsigned long)line, string);
592 fflush(logfile);
593 if (krb5_store_int32(c->logsock, 0))
594 goto out;
595 break;
596 default:
597 errx(1, "client send bad log command: %d", (int)cmd);
600 out:
601 free(file);
602 free(string);
604 return 0;
607 static void
608 connect_client(const char *slave)
610 char *name, *port;
611 struct client *c = ecalloc(1, sizeof(*c));
612 struct addrinfo hints, *res0, *res;
613 int ret;
614 krb5_socket_t sock;
616 name = estrdup(slave);
617 port = strchr(name, ':');
618 if (port == NULL)
619 errx(1, "port missing from %s", name);
620 *port++ = 0;
622 c->name = estrdup(slave);
624 memset(&hints, 0, sizeof(hints));
625 hints.ai_family = PF_UNSPEC;
626 hints.ai_socktype = SOCK_STREAM;
628 ret = getaddrinfo(name, port, &hints, &res0);
629 if (ret)
630 errx(1, "error resolving %s", name);
632 for (res = res0, sock = rk_INVALID_SOCKET; res; res = res->ai_next) {
633 sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
634 if (sock == rk_INVALID_SOCKET)
635 continue;
636 if (connect(sock, res->ai_addr, res->ai_addrlen) < 0) {
637 rk_closesocket(sock);
638 sock = rk_INVALID_SOCKET;
639 continue;
641 c->sa = ecalloc(1, res->ai_addrlen);
642 memcpy(c->sa, res->ai_addr, res->ai_addrlen);
643 c->salen = res->ai_addrlen;
644 break; /* okay we got one */
646 if (sock == rk_INVALID_SOCKET)
647 err(1, "connect to host: %s", name);
648 freeaddrinfo(res0);
650 c->sock = krb5_storage_from_socket(sock);
651 rk_closesocket(sock);
652 if (c->sock == NULL)
653 errx(1, "krb5_storage_from_fd");
656 int32_t version;
657 char *str = NULL;
658 get_version_capa(c, &version, &c->capabilities, &str);
659 if (str) {
660 free(str);
662 if (c->capabilities & HAS_MONIKER)
663 get_moniker(c, &c->moniker);
664 else
665 c->moniker = c->name;
666 if (c->capabilities & ISSERVER)
667 get_targetname(c, &c->target_name);
670 if (logfile) {
671 printf("starting log socket to client %s\n", c->moniker);
673 sock = wait_log(c);
675 c->logsock = krb5_storage_from_socket(sock);
676 rk_closesocket(sock);
677 if (c->logsock == NULL)
678 errx(1, "failed to create log krb5_storage");
679 #ifdef ENABLE_PTHREAD_SUPPORT
680 pthread_create(&c->thr, NULL, log_function, c);
681 #else
682 c->child = fork();
683 if (c->child == -1)
684 errx(1, "failed to fork");
685 else if (c->child == 0) {
686 log_function(c);
687 fclose(logfile);
688 exit(0);
690 #endif
694 clients = erealloc(clients, (num_clients + 1) * sizeof(*clients));
696 clients[num_clients] = c;
697 num_clients++;
699 free(name);
702 static struct client *
703 get_client(const char *slave)
705 size_t i;
706 for (i = 0; i < num_clients; i++)
707 if (strcmp(slave, clients[i]->name) == 0)
708 return clients[i];
709 errx(1, "failed to find client %s", slave);
716 static int version_flag;
717 static int help_flag;
718 static int wrap_ext = 0;
719 static char *logfile_str;
720 static getarg_strings principals;
721 static getarg_strings slaves;
723 struct getargs args[] = {
724 { "principals", 0, arg_strings, &principals, "Test principal",
725 NULL },
726 { "slaves", 0, arg_strings, &slaves, "Slaves",
727 NULL },
728 { "log-file", 0, arg_string, &logfile_str, "Logfile",
729 NULL },
730 { "wrap-ext", 0, arg_flag, &wrap_ext, "test wrap extended",
731 NULL },
732 { "version", 0, arg_flag, &version_flag, "Print version",
733 NULL },
734 { "help", 0, arg_flag, &help_flag, NULL,
735 NULL }
738 static void
739 usage(int ret)
741 arg_printusage (args,
742 sizeof(args) / sizeof(args[0]),
743 NULL,
744 "");
745 exit (ret);
749 main(int argc, char **argv)
751 int optidx= 0;
752 char *user;
753 char *password;
754 char ***list, **p;
755 size_t num_list, i, j, k;
756 int failed = 0;
758 setprogname (argv[0]);
760 if (getarg (args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx))
761 usage (1);
763 if (help_flag)
764 usage (0);
766 if (version_flag) {
767 print_version (NULL);
768 return 0;
771 if (optidx != argc)
772 usage (1);
774 if (principals.num_strings == 0)
775 errx(1, "no principals");
777 user = estrdup(principals.strings[0]);
778 password = strchr(user, ':');
779 if (password == NULL)
780 errx(1, "password missing from %s", user);
781 *password++ = 0;
783 if (slaves.num_strings == 0)
784 errx(1, "no principals");
786 if (logfile_str) {
787 printf("open logfile %s\n", logfile_str);
788 logfile = fopen(logfile_str, "w+");
789 if (logfile == NULL)
790 err(1, "failed to open: %s", logfile_str);
797 list = permutate_all(&slaves, &num_list);
800 * Set up connection to all clients
803 printf("Connecting to slaves\n");
804 for (i = 0; i < slaves.num_strings; i++)
805 connect_client(slaves.strings[i]);
808 * Test acquire credentials
811 printf("Test acquire credentials\n");
812 for (i = 0; i < slaves.num_strings; i++) {
813 int32_t hCred, val;
815 val = acquire_cred(clients[i], user, password, 1, &hCred);
816 if (val != GSMERR_OK) {
817 warnx("Failed to acquire_cred on host %s: %d",
818 clients[i]->moniker, (int)val);
819 failed = 1;
820 } else
821 toast_resource(clients[i], hCred);
824 if (failed)
825 goto out;
828 * First test if all slaves can build context to them-self.
831 printf("Self context tests\n");
832 for (i = 0; i < num_clients; i++) {
833 int32_t hCred, val, delegCred;
834 int32_t clientC, serverC;
835 struct client *c = clients[i];
837 if (c->target_name == NULL)
838 continue;
840 printf("%s connects to self using %s\n",
841 c->moniker, c->target_name);
843 val = acquire_cred(c, user, password, 1, &hCred);
844 if (val != GSMERR_OK)
845 errx(1, "failed to acquire_cred: %d", (int)val);
847 val = build_context(c, c,
848 GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG|
849 GSS_C_INTEG_FLAG|GSS_C_CONF_FLAG|
850 GSS_C_DELEG_FLAG|GSS_C_MUTUAL_FLAG,
851 hCred, &clientC, &serverC, &delegCred);
852 if (val == GSMERR_OK) {
853 test_token(c, clientC, c, serverC, wrap_ext);
854 toast_resource(c, clientC);
855 toast_resource(c, serverC);
856 if (delegCred)
857 toast_resource(c, delegCred);
858 } else {
859 warnx("build_context failed: %d", (int)val);
865 val = build_context(c, c,
866 GSS_C_INTEG_FLAG|GSS_C_CONF_FLAG,
867 hCred, &clientC, &serverC, &delegCred);
868 if (val == GSMERR_OK) {
869 test_token(c, clientC, c, serverC, wrap_ext);
870 toast_resource(c, clientC);
871 toast_resource(c, serverC);
872 if (delegCred)
873 toast_resource(c, delegCred);
874 } else {
875 warnx("build_context failed: %d", (int)val);
878 toast_resource(c, hCred);
881 * Build contexts though all entries in each lists, including the
882 * step from the last entry to the first, ie treat the list as a
883 * circle.
885 * Only follow the delegated credential, but test "all"
886 * flags. (XXX only do deleg|mutual right now.
889 printf("\"All\" permutation tests\n");
891 for (i = 0; i < num_list; i++) {
892 int32_t hCred, val, delegCred = 0;
893 int32_t clientC = 0, serverC = 0;
894 struct client *client, *server;
896 p = list[i];
898 client = get_client(p[0]);
900 val = acquire_cred(client, user, password, 1, &hCred);
901 if (val != GSMERR_OK)
902 errx(1, "failed to acquire_cred: %d", (int)val);
904 for (j = 1; j < num_clients + 1; j++) {
905 server = get_client(p[j % num_clients]);
907 if (server->target_name == NULL)
908 break;
910 for (k = 1; k < j; k++)
911 printf("\t");
912 printf("%s -> %s\n", client->moniker, server->moniker);
914 val = build_context(client, server,
915 GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG|
916 GSS_C_INTEG_FLAG|GSS_C_CONF_FLAG|
917 GSS_C_DELEG_FLAG|GSS_C_MUTUAL_FLAG,
918 hCred, &clientC, &serverC, &delegCred);
919 if (val != GSMERR_OK) {
920 warnx("build_context failed: %d", (int)val);
921 break;
924 val = test_token(client, clientC, server, serverC, wrap_ext);
925 if (val)
926 break;
928 toast_resource(client, clientC);
929 toast_resource(server, serverC);
930 if (!delegCred) {
931 warnx("no delegated cred on %s", server->moniker);
932 break;
934 toast_resource(client, hCred);
935 hCred = delegCred;
936 client = server;
938 if (hCred)
939 toast_resource(client, hCred);
943 * Close all connections to clients
946 out:
947 printf("sending goodbye and waiting for log sockets\n");
948 for (i = 0; i < num_clients; i++) {
949 goodbye(clients[i]);
950 if (clients[i]->logsock) {
951 #ifdef ENABLE_PTHREAD_SUPPORT
952 pthread_join(&clients[i]->thr, NULL);
953 #else
954 waitpid(clients[i]->child, NULL, 0);
955 #endif
959 printf("done\n");
961 return 0;