Merge remote-tracking branch 'origin/master'
[unleashed/lotheac.git] / usr / src / cmd / gss / gssd / gssdtest.c
blob66fca4f8b0a76f47cdb37706488dbaece2b8df59
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
20 * CDDL HEADER END
23 * Copyright 2017 Gary Mills
24 * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
29 * Test client for gssd. This program is not shipped on the binary
30 * release.
33 #include <stdio.h>
34 #include <strings.h>
35 #include <ctype.h>
36 #include <stdlib.h>
37 #include <gssapi/gssapi.h>
38 #include <gssapi/gssapi_ext.h>
39 #include "gssd.h"
40 #include <rpc/rpc.h>
42 #define _KERNEL
43 #include <gssapi/gssapi.h>
44 #undef _KERNEL
46 int gss_major_code;
47 int gss_minor_code;
49 int init_sec_context_phase = 0;
50 int accept_sec_context_phase = 0;
52 gss_ctx_id_t initiator_context_handle;
53 gss_ctx_id_t acceptor_context_handle;
54 gss_cred_id_t acceptor_credentials;
55 gss_buffer_desc init_token_buffer;
56 gss_buffer_desc accept_token_buffer;
57 gss_buffer_desc delete_token_buffer;
58 gss_buffer_desc message_buffer;
59 gss_buffer_desc msg_token;
61 #define LOOP_COUNTER 100
62 #define GSS_KRB5_MECH_OID "1.2.840.113554.1.2.2"
63 #define GSS_DUMMY_MECH_OID "1.3.6.1.4.1.42.2.26.1.2"
64 #ifdef _KERNEL
65 #define OCTAL_MACRO "%03o."
66 #define MALLOC(n) kmem_alloc((n), KM_SLEEP)
67 #define CALLOC(n, s) kmem_zalloc((n)*(s), KM_SLEEP)
68 #define FREE(x, n) kmem_free((x), (n))
69 #define memcpy(dst, src, n) bcopy((src), (dst), (n))
70 #define fprintf(s, m) printf(m)
71 #define isspace(s) ((s) == ' ' || (s) == '\t' || (s) == '\n' || \
72 (s) == '\r' || (s) == '\v' || (s) == '\f')
74 static char *strdup(const char *s)
76 int len = strlen(s);
77 char *new = MALLOC(len+1);
78 strcpy(new, s);
79 return (new);
82 #else /* !_KERNEL */
83 #define OCTAL_MACRO "%03.3o."
84 #define MALLOC(n) malloc(n)
85 #define CALLOC(n, s) calloc((n), (s))
86 #define FREE(x, n) free(x)
87 #endif /* _KERNEL */
89 static gss_OID gss_str2oid(char *);
90 static char * gss_oid2str(gss_OID);
91 static void instructs();
92 static void usage();
93 static int parse_input_line(char *, int *, char ***);
94 extern uid_t getuid();
96 static void _gss_init_sec_context(int, char **);
97 static void _gss_acquire_cred(int, char **);
98 static void _gss_add_cred(int, char **);
99 static void _gss_sign(int, char **);
100 static void _gss_release_cred(int, char **);
101 static void _gss_accept_sec_context(int, char **);
102 static void _gss_process_context_token(int, char **);
103 static void _gss_delete_sec_context(int, char **);
104 static void _gss_context_time(int, char **);
105 static void _gss_verify(int, char **);
106 static void _gss_seal(int, char **);
107 static void _gss_unseal(int, char **);
108 static void _gss_display_status(int, char **);
109 static void _gss_indicate_mechs(int, char **);
110 static void _gss_inquire_cred(int, char **);
111 static void _gssd_expname_to_unix_cred(int, char **);
112 static void _gssd_name_to_unix_cred(int, char **);
113 static void _gssd_get_group_info(int, char **);
115 static int do_gssdtest(char *buf);
118 #ifndef _KERNEL
119 static int read_line(char *buf, int size)
121 int len;
123 /* read the next line. If cntl-d, return with zero char count */
124 printf(gettext("\n> "));
126 if (fgets(buf, size, stdin) == NULL)
127 return (0);
129 len = strlen(buf);
130 buf[--len] = '\0';
131 return (len);
135 main()
137 char buf[512];
138 int len, ret;
140 /* Print out usage and instructions to start off the session */
142 instructs();
143 usage();
146 * Loop, repeatedly calling parse_input_line() to get the
147 * next line and parse it into argc and argv. Act on the
148 * arguements found on the line.
151 do {
152 len = read_line(buf, 512);
153 if (len)
154 ret = do_gssdtest(buf);
155 } while (len && !ret);
157 return (0);
159 #endif /* !_KERNEL */
161 static int
162 do_gssdtest(char *buf)
164 int argc, seal_argc;
165 int i;
166 char **argv, **argv_array;
168 char *cmd;
169 char *seal_ini_array [] = { "initiator", " Hello"};
170 char *seal_acc_array [] = { "acceptor", " Hello"};
171 char *unseal_acc_array [] = {"acceptor"};
172 char *unseal_ini_array [] = {"initiator"};
173 char *delet_acc_array [] = {"acceptor"};
174 char *delet_ini_array [] = {"initiator"};
176 argv = 0;
178 if (parse_input_line(buf, &argc, &argv) == 0) {
179 printf(gettext("\n"));
180 return (1);
183 if (argc == 0) {
184 usage();
185 /*LINTED*/
186 FREE(argv_array, (argc+1)*sizeof (char *));
187 return (0);
191 * remember argv_array address, which is memory calloc'd by
192 * parse_input_line, so it can be free'd at the end of the loop.
195 argv_array = argv;
197 cmd = argv[0];
199 argc--;
200 argv++;
202 if (strcmp(cmd, "gss_loop") == 0 ||
203 strcmp(cmd, "loop") == 0) {
205 if (argc < 1) {
206 usage();
207 FREE(argv_array, (argc+2) * sizeof (char *));
208 return (0);
210 for (i = 0; i < LOOP_COUNTER; i++) {
211 printf(gettext("Loop Count is %d \n"), i);
213 * if (i > 53)
214 * printf ("Loop counter is greater than 55\n");
216 _gss_acquire_cred(argc, argv);
217 _gss_init_sec_context(argc, argv);
218 _gss_accept_sec_context(0, argv);
219 _gss_init_sec_context(argc, argv);
221 seal_argc = 2;
222 _gss_seal(seal_argc, seal_ini_array);
223 seal_argc = 1;
224 _gss_unseal(seal_argc, unseal_acc_array);
225 seal_argc = 2;
226 _gss_seal(seal_argc, seal_acc_array);
227 seal_argc = 1;
228 _gss_unseal(seal_argc, unseal_ini_array);
229 seal_argc = 2;
230 _gss_sign(seal_argc, seal_ini_array);
231 seal_argc = 1;
232 _gss_verify(seal_argc, unseal_acc_array);
233 seal_argc = 2;
234 _gss_sign(seal_argc, seal_acc_array);
235 seal_argc = 1;
236 _gss_verify(seal_argc, unseal_ini_array);
237 _gss_delete_sec_context(argc, delet_acc_array);
238 _gss_delete_sec_context(argc, delet_ini_array);
241 if (strcmp(cmd, "gss_all") == 0 ||
242 strcmp(cmd, "all") == 0) {
243 _gss_acquire_cred(argc, argv);
244 _gss_init_sec_context(argc, argv);
245 _gss_accept_sec_context(0, argv);
246 _gss_init_sec_context(argc, argv);
248 seal_argc = 2;
249 _gss_seal(seal_argc, seal_acc_array);
250 seal_argc = 1;
251 _gss_unseal(seal_argc, unseal_ini_array);
252 seal_argc = 2;
253 _gss_seal(seal_argc, seal_ini_array);
254 seal_argc = 1;
255 _gss_unseal(seal_argc, unseal_acc_array);
256 seal_argc = 2;
257 _gss_sign(seal_argc, seal_ini_array);
258 seal_argc = 1;
259 _gss_verify(seal_argc, unseal_acc_array);
260 seal_argc = 2;
261 _gss_sign(seal_argc, seal_acc_array);
262 seal_argc = 1;
263 _gss_verify(seal_argc, unseal_ini_array);
266 if (strcmp(cmd, "gss_acquire_cred") == 0 ||
267 strcmp(cmd, "acquire") == 0) {
268 _gss_acquire_cred(argc, argv);
269 if (argc == 1)
270 _gss_add_cred(argc, argv);
273 else if (strcmp(cmd, "gss_release_cred") == 0 ||
274 strcmp(cmd, "release") == 0)
275 _gss_release_cred(argc, argv);
276 else if (strcmp(cmd, "gss_init_sec_context") == 0 ||
277 strcmp(cmd, "init") == 0)
278 _gss_init_sec_context(argc, argv);
279 else if (strcmp(cmd, "gss_accept_sec_context") == 0 ||
280 strcmp(cmd, "accept") == 0)
281 _gss_accept_sec_context(argc, argv);
282 else if (strcmp(cmd, "gss_process_context_token") == 0 ||
283 strcmp(cmd, "process") == 0)
284 _gss_process_context_token(argc, argv);
285 else if (strcmp(cmd, "gss_delete_sec_context") == 0 ||
286 strcmp(cmd, "delete") == 0)
287 _gss_delete_sec_context(argc, argv);
288 else if (strcmp(cmd, "gss_context_time") == 0 ||
289 strcmp(cmd, "time") == 0)
290 _gss_context_time(argc, argv);
291 else if (strcmp(cmd, "gss_sign") == 0 ||
292 strcmp(cmd, "sign") == 0)
293 _gss_sign(argc, argv);
294 else if (strcmp(cmd, "gss_verify") == 0 ||
295 strcmp(cmd, "verify") == 0)
296 _gss_verify(argc, argv);
297 else if (strcmp(cmd, "gss_seal") == 0 ||
298 strcmp(cmd, "seal") == 0)
299 _gss_seal(argc, argv);
300 else if (strcmp(cmd, "gss_unseal") == 0 ||
301 strcmp(cmd, "unseal") == 0)
302 _gss_unseal(argc, argv);
303 else if (strcmp(cmd, "gss_display_status") == 0||
304 strcmp(cmd, "status") == 0)
305 _gss_display_status(argc, argv);
306 else if (strcmp(cmd, "gss_indicate_mechs") == 0 ||
307 strcmp(cmd, "indicate") == 0)
308 _gss_indicate_mechs(argc, argv);
309 else if (strcmp(cmd, "gss_inquire_cred") == 0 ||
310 strcmp(cmd, "inquire") == 0)
311 _gss_inquire_cred(argc, argv);
312 else if (strcmp(cmd, "expname2unixcred") == 0 ||
313 strcmp(cmd, "gsscred_expname_to_unix_cred") == 0)
314 _gssd_expname_to_unix_cred(argc, argv);
315 else if (strcmp(cmd, "name2unixcred") == 0 ||
316 strcmp(cmd, "gsscred_name_to_unix_cred") == 0)
317 _gssd_name_to_unix_cred(argc, argv);
318 else if (strcmp(cmd, "grpinfo") == 0 ||
319 strcmp(cmd, "gss_get_group_info") == 0)
320 _gssd_get_group_info(argc, argv);
321 else if (strcmp(cmd, "exit") == 0) {
322 printf(gettext("\n"));
323 FREE(argv_array, (argc+2) * sizeof (char *));
324 return (1);
325 } else
326 usage();
328 /* free argv array */
330 FREE(argv_array, (argc+2) * sizeof (char *));
331 return (0);
334 static void
335 _gss_acquire_cred(argc, argv)
336 int argc;
337 char **argv;
340 OM_UINT32 status, minor_status;
341 gss_buffer_desc name;
342 gss_name_t desired_name = (gss_name_t) 0;
343 OM_uint32 time_req;
344 gss_OID_set_desc desired_mechs_desc;
345 gss_OID_set desired_mechs = &desired_mechs_desc;
346 int cred_usage;
347 gss_OID_set actual_mechs = GSS_C_NULL_OID_SET;
348 gss_OID_set inquire_mechs = GSS_C_NULL_OID_SET;
349 OM_UINT32 time_rec;
350 char * string;
351 char * inq_string;
352 uid_t uid;
353 gss_OID mech_type;
356 * First set up the command line independent input arguments.
359 time_req = (OM_uint32) 0;
360 cred_usage = GSS_C_ACCEPT;
361 uid = getuid();
363 /* Parse the command line for the variable input arguments */
365 if (argc == 0) {
366 usage();
367 return;
371 * Get the name of the principal.
374 name.length = strlen(argv[0])+1;
375 name.value = argv[0];
378 * Now convert the string given by the first argument into internal
379 * form suitable for input to gss_acquire_cred()
382 if ((status = gss_import_name(&minor_status, &name,
383 (gss_OID)GSS_C_NT_HOSTBASED_SERVICE, &desired_name))
384 != GSS_S_COMPLETE) {
385 printf(gettext(
386 "could not parse desired name: err (octal) %o (%s)\n"),
387 status, gettext("gss_acquire_cred error"));
388 return;
391 argc--;
392 argv++;
395 * The next argument is an OID in dotted decimal form.
398 if (argc == 0) {
399 printf(gettext("Assuming Kerberos V5 as the mechanism\n"));
400 printf(gettext(
401 "The mech OID 1.2.840.113554.1.2.2 will be used\n"));
402 mech_type = gss_str2oid((char *)GSS_KRB5_MECH_OID);
403 } else
404 mech_type = gss_str2oid(argv[0]);
406 if (mech_type == 0 || mech_type->length == 0) {
407 printf(gettext("improperly formated mechanism OID\n"));
408 return;
412 * set up desired_mechs so it points to mech_type.
415 desired_mechs = (gss_OID_set) MALLOC(sizeof (gss_OID_desc));
417 desired_mechs->count = 1;
418 desired_mechs->elements = mech_type;
420 status = kgss_acquire_cred(
421 &minor_status,
422 desired_name,
423 time_req,
424 desired_mechs,
425 cred_usage,
426 &acceptor_credentials,
427 &actual_mechs,
428 &time_rec,
429 uid);
431 /* store major and minor status for gss_display_status() call */
433 gss_major_code = status;
434 gss_minor_code = minor_status;
436 if (status == GSS_S_COMPLETE) {
437 /* process returned values */
439 printf(gettext("\nacquire succeeded\n\n"));
442 * print out the actual mechs returned NB: Since only one
443 * mechanism is specified in desired_mechs, only one
444 * can be returned in actual_mechs. Consequently,
445 * actual_mechs->elements points to an array of only one
446 * element.
449 if ((string = gss_oid2str(actual_mechs->elements)) == 0) {
450 printf(gettext("actual mechs == NULL\n\n"));
451 } else {
452 printf(gettext("actual mechs = %s\n\n"), string);
453 FREE(string, (actual_mechs->elements->length+1)*4+1);
456 if (cred_usage == GSS_C_BOTH)
457 printf(gettext("GSS_C_BOTH\n\n"));
459 if (cred_usage == GSS_C_INITIATE)
460 printf(gettext("GSS_C_INITIATE\n\n"));
462 if (cred_usage == GSS_C_ACCEPT)
463 printf(gettext("GSS_C_ACCEPT\n\n"));
464 status = kgss_inquire_cred(
465 &minor_status,
466 acceptor_credentials,
467 NULL,
468 &time_req,
469 &cred_usage,
470 &inquire_mechs,
471 uid);
473 if (status != GSS_S_COMPLETE)
474 printf(gettext("server ret err (octal) %o (%s)\n"),
475 status, gettext("gss_inquire_cred error"));
476 else {
477 if ((inq_string =
478 gss_oid2str(inquire_mechs->elements)) == 0) {
479 printf(gettext
480 ("mechs from inquire == NULL\n\n"));
481 } else {
482 printf(gettext
483 ("mechs from inquiry = %s\n\n"),
484 inq_string);
485 FREE(inq_string,
486 (inquire_mechs->elements->length+1)*4+1);
488 printf(gettext("inquire_cred successful \n\n"));
491 } else {
492 printf(gettext("server ret err (octal) %o (%s)\n"),
493 status, gettext("gss_acquire_cred error"));
496 /* free allocated memory */
498 /* actual mechs is allocated by clnt_stubs. Release it here */
499 if (actual_mechs != GSS_C_NULL_OID_SET)
500 gss_release_oid_set_and_oids(&minor_status, &actual_mechs);
501 if (inquire_mechs != GSS_C_NULL_OID_SET)
502 gss_release_oid_set_and_oids(&minor_status, &inquire_mechs);
504 gss_release_name(&minor_status, &desired_name);
506 /* mech_type and desired_mechs are allocated above. Release it here */
508 FREE(mech_type->elements, mech_type->length);
509 FREE(mech_type, sizeof (gss_OID_desc));
510 FREE(desired_mechs, sizeof (gss_OID_desc));
513 static void
514 _gss_add_cred(argc, argv)
515 int argc;
516 char **argv;
519 OM_UINT32 status, minor_status;
520 gss_buffer_desc name;
521 gss_name_t desired_name = (gss_name_t) 0;
522 OM_uint32 time_req;
523 OM_uint32 initiator_time_req;
524 OM_uint32 acceptor_time_req;
525 int cred_usage;
526 gss_OID_set actual_mechs = GSS_C_NULL_OID_SET;
527 gss_OID_set inquire_mechs = GSS_C_NULL_OID_SET;
528 char * string;
529 uid_t uid;
530 gss_OID mech_type;
531 int i;
534 * First set up the command line independent input arguments.
537 initiator_time_req = (OM_uint32) 0;
538 acceptor_time_req = (OM_uint32) 0;
539 cred_usage = GSS_C_ACCEPT;
540 uid = getuid();
542 /* Parse the command line for the variable input arguments */
544 if (argc == 0) {
545 usage();
546 return;
550 * Get the name of the principal.
553 name.length = strlen(argv[0])+1;
554 name.value = argv[0];
557 * Now convert the string given by the first argument into internal
558 * form suitable for input to gss_acquire_cred()
561 if ((status = gss_import_name(&minor_status, &name,
562 (gss_OID)GSS_C_NT_HOSTBASED_SERVICE, &desired_name))
563 != GSS_S_COMPLETE) {
564 printf(gettext(
565 "could not parse desired name: err (octal) %o (%s)\n"),
566 status, gettext("gss_acquire_cred error"));
567 return;
570 argc--;
571 argv++;
574 * The next argument is an OID in dotted decimal form.
577 if (argc == 0) {
578 printf(gettext("Assuming dummy as the mechanism\n"));
579 printf(gettext(
580 "The mech OID 1.3.6.1.4.1.42.2.26.1.2 will be used\n"));
581 mech_type = gss_str2oid((char *)GSS_DUMMY_MECH_OID);
582 } else
583 mech_type = gss_str2oid(argv[0]);
585 if (mech_type == 0 || mech_type->length == 0) {
586 printf(gettext("improperly formated mechanism OID\n"));
587 return;
591 * set up desired_mechs so it points to mech_type.
594 status = kgss_add_cred(
595 &minor_status,
596 acceptor_credentials,
597 desired_name,
598 mech_type,
599 cred_usage,
600 initiator_time_req,
601 acceptor_time_req,
602 &actual_mechs,
603 NULL,
604 NULL,
605 uid);
607 /* store major and minor status for gss_display_status() call */
609 gss_major_code = status;
610 gss_minor_code = minor_status;
611 if (status == GSS_S_COMPLETE) {
612 /* process returned values */
614 printf(gettext("\nadd succeeded\n\n"));
615 if (actual_mechs) {
616 for (i = 0; i < actual_mechs->count; i++) {
617 if ((string =
618 gss_oid2str
619 (&actual_mechs->elements[i])) == 0) {
620 printf(gettext
621 ("actual mechs == NULL\n\n"));
622 } else {
623 printf(gettext
624 ("actual mechs = %s\n\n"), string);
625 FREE(string,
626 (actual_mechs->elements->length+1)*4+1);
631 * Try adding the cred again for the same mech
632 * We should get GSS_S_DUPLICATE_ELEMENT
633 * if not return an error
635 status = kgss_add_cred(
636 &minor_status,
637 acceptor_credentials,
638 desired_name,
639 mech_type,
640 cred_usage,
641 initiator_time_req,
642 acceptor_time_req,
643 NULL, /* &actual_mechs, */
644 NULL,
645 NULL,
646 uid);
647 if (status != GSS_S_DUPLICATE_ELEMENT) {
648 printf(gettext("Expected duplicate element, Got "
649 " (octal) %o (%s)\n"),
650 status, gettext("gss_add_cred error"));
652 status = kgss_inquire_cred(
653 &minor_status,
654 acceptor_credentials,
655 NULL,
656 &time_req,
657 &cred_usage,
658 &inquire_mechs,
659 uid);
661 if (status != GSS_S_COMPLETE)
662 printf(gettext("server ret err (octal) %o (%s)\n"),
663 status, gettext("gss_inquire_cred error"));
664 else {
665 for (i = 0; i < inquire_mechs->count; i++) {
666 if ((string =
667 gss_oid2str
668 (&inquire_mechs->elements[i])) == 0) {
669 printf(gettext
670 ("inquire_mechs mechs == NULL\n\n"));
671 } else {
672 printf(gettext
673 ("inquire_cred mechs = %s\n\n"),
674 string);
675 FREE(string,
676 (inquire_mechs->elements->length+1)*4
677 +1);
680 printf(gettext("inquire_cred successful \n\n"));
683 } else {
684 printf(gettext("server ret err (octal) %o (%s)\n"),
685 status, gettext("gss_acquire_cred error"));
688 /* Let us do inquire_cred_by_mech for both mechanisms */
689 status = kgss_inquire_cred_by_mech(
690 &minor_status,
691 acceptor_credentials,
692 mech_type,
693 uid);
694 if (status != GSS_S_COMPLETE)
695 printf(gettext("server ret err (octal) %o (%s)\n"),
696 status, gettext("gss_inquire_cred_by_mech"));
697 else
698 printf(gettext("gss_inquire_cred_by_mech successful"));
701 FREE(mech_type->elements, mech_type->length);
702 FREE(mech_type, sizeof (gss_OID_desc));
703 mech_type = gss_str2oid((char *)GSS_KRB5_MECH_OID);
704 status = kgss_inquire_cred_by_mech(
705 &minor_status,
706 acceptor_credentials,
707 mech_type,
708 uid);
709 if (status != GSS_S_COMPLETE)
710 printf(gettext("server ret err (octal) %o (%s)\n"),
711 status, gettext
712 ("gss_inquire_cred_by_mech for dummy mech error"));
714 /* free allocated memory */
716 /* actual mechs is allocated by clnt_stubs. Release it here */
717 if (actual_mechs != GSS_C_NULL_OID_SET)
718 gss_release_oid_set_and_oids(&minor_status, &actual_mechs);
719 if (inquire_mechs != GSS_C_NULL_OID_SET)
720 gss_release_oid_set_and_oids(&minor_status, &inquire_mechs);
722 gss_release_name(&minor_status, &desired_name);
724 /* mech_type and desired_mechs are allocated above. Release it here */
726 FREE(mech_type->elements, mech_type->length);
727 FREE(mech_type, sizeof (gss_OID_desc));
730 /*ARGSUSED*/
731 static void
732 _gss_release_cred(argc, argv)
733 int argc;
734 char **argv;
736 OM_UINT32 status;
737 OM_UINT32 minor_status;
738 uid_t uid;
740 /* set up input arguments here */
742 if (argc != 0) {
743 usage();
744 return;
747 uid = getuid();
749 status = kgss_release_cred(
750 &minor_status,
751 &acceptor_credentials,
752 uid);
754 /* store major and minor status for gss_display_status() call */
756 gss_major_code = status;
757 gss_minor_code = minor_status;
759 if (status == GSS_S_COMPLETE) {
760 printf(gettext("\nrelease succeeded\n\n"));
761 } else {
762 printf(gettext("server ret err (octal) %o (%s)\n"),
763 status, gettext("gss_release_cred error"));
767 static void
768 _gss_init_sec_context(argc, argv)
769 int argc;
770 char **argv;
773 OM_uint32 status;
775 OM_uint32 minor_status;
776 gss_cred_id_t claimant_cred_handle;
777 gss_name_t target_name = (gss_name_t) 0;
778 gss_OID mech_type = (gss_OID) 0;
779 int req_flags;
780 OM_uint32 time_req;
781 gss_channel_bindings_t input_chan_bindings;
782 gss_buffer_t input_token;
783 gss_buffer_desc context_token;
784 gss_OID actual_mech_type;
785 int ret_flags;
786 OM_uint32 time_rec;
787 uid_t uid;
788 char * string;
789 gss_buffer_desc name;
792 * If this is the first phase of the context establishment,
793 * clear initiator_context_handle and indicate next phase.
796 if (init_sec_context_phase == 0) {
797 initiator_context_handle = GSS_C_NO_CONTEXT;
798 input_token = GSS_C_NO_BUFFER;
799 init_sec_context_phase = 1;
800 } else
801 input_token = &init_token_buffer;
804 * First set up the non-variable command line independent input
805 * arguments
808 claimant_cred_handle = GSS_C_NO_CREDENTIAL;
810 req_flags = GSS_C_MUTUAL_FLAG;
811 time_req = (OM_uint32) 0;
812 input_chan_bindings = GSS_C_NO_CHANNEL_BINDINGS;
813 uid = getuid();
815 /* Now parse the command line for the remaining input arguments */
817 if (argc == 0) {
818 usage();
819 return;
823 * Get the name of the target.
826 name.length = strlen(argv[0])+1;
827 name.value = argv[0];
830 * Now convert the string given by the first argument into a target
831 * name suitable for input to gss_init_sec_context()
834 if ((status = gss_import_name(&minor_status, &name,
835 /* GSS_C_NULL_OID, &target_name)) */
836 (gss_OID)GSS_C_NT_HOSTBASED_SERVICE, &target_name))
837 != GSS_S_COMPLETE) {
838 printf(gettext(
839 "could not parse target name: err (octal) %o (%s)\n"),
840 status,
841 gettext("gss_init_sec_context error"));
842 if (input_token != GSS_C_NO_BUFFER)
843 gss_release_buffer(&minor_status, &init_token_buffer);
844 init_sec_context_phase = 0;
845 return;
848 argc--;
849 argv++;
851 if (argc == 0) {
852 printf(gettext("Assuming Kerberos V5 as the mechanism\n"));
853 printf(gettext(
854 "The mech OID 1.2.840.113554.1.2.2 will be used\n"));
855 mech_type = gss_str2oid((char *)GSS_KRB5_MECH_OID);
856 } else {
857 mech_type = gss_str2oid(argv[0]);
860 if (mech_type == 0 || mech_type->length == 0) {
861 printf(gettext("improperly formated mechanism OID\n"));
862 if (input_token != GSS_C_NO_BUFFER)
863 gss_release_buffer(&minor_status, &init_token_buffer);
864 init_sec_context_phase = 0;
865 return;
868 /* call kgss_init_sec_context */
870 status = kgss_init_sec_context(&minor_status,
871 claimant_cred_handle,
872 &initiator_context_handle,
873 target_name,
874 mech_type,
875 req_flags,
876 time_req,
877 input_chan_bindings,
878 input_token,
879 &actual_mech_type,
880 &accept_token_buffer,
881 &ret_flags,
882 &time_rec,
883 uid);
885 /* store major and minor status for gss_display_status() call */
886 gss_major_code = status;
887 gss_minor_code = minor_status;
889 if (status != GSS_S_COMPLETE &&
890 status != GSS_S_CONTINUE_NEEDED) {
892 printf(gettext("server ret err (octal) %o (%s)\n"),
893 status, "gss_init_sec_context error");
894 init_sec_context_phase = 0;
895 if (status == GSS_S_NO_CRED)
896 printf(gettext(" : no credentials"));
897 if (input_token != GSS_C_NO_BUFFER)
898 gss_release_buffer(&minor_status, &init_token_buffer);
899 if (status != GSS_S_FAILURE && minor_status != 0xffffffff)
900 status = kgss_delete_sec_context(&minor_status,
901 &initiator_context_handle,
902 &msg_token);
903 return;
905 } else if (status == GSS_S_COMPLETE) {
907 /* process returned values */
909 printf(gettext("\ninit succeeded\n\n"));
911 /* print out the actual mechanism type */
913 if ((string = gss_oid2str(actual_mech_type)) == 0) {
915 printf(gettext(
916 "gssapi internal err : actual "
917 "mech type null\n"));
918 init_sec_context_phase = 0;
919 if (input_token != GSS_C_NO_BUFFER)
920 gss_release_buffer(&minor_status,
921 &init_token_buffer);
922 gss_release_buffer(&minor_status, &accept_token_buffer);
923 status = kgss_delete_sec_context(&minor_status,
924 &initiator_context_handle,
925 &msg_token);
926 return;
927 } else {
928 printf(gettext("actual mech type = %s\n\n"), string);
929 FREE(string, (actual_mech_type->length+1)*4+1);
932 /* print out value of ret_flags and time_req */
934 if (ret_flags & GSS_C_DELEG_FLAG)
935 printf(gettext("GSS_C_DELEG_FLAG = True\n"));
936 else
937 printf(gettext("GSS_C_DELEG_FLAG = False\n"));
939 if (ret_flags & GSS_C_MUTUAL_FLAG)
940 printf(gettext("GSS_C_MUTUAL_FLAG = True\n"));
941 else
942 printf(gettext("GSS_C_MUTUAL_FLAG = False\n"));
944 if (ret_flags & GSS_C_REPLAY_FLAG)
945 printf(gettext("GSS_C_REPLAY_FLAG = True\n"));
946 else
947 printf(gettext("GSS_C_REPLAY_FLAG = False\n"));
949 if (ret_flags & GSS_C_SEQUENCE_FLAG)
950 printf(gettext("GSS_C_SEQUENCE_FLAG = True\n"));
951 else
952 printf(gettext("GSS_C_SEQUENCE_FLAG = False\n"));
954 if (ret_flags & GSS_C_CONF_FLAG)
955 printf(gettext("GSS_C_CONF_FLAG = True\n"));
956 else
957 printf(gettext("GSS_C_CONF_FLAG = False\n"));
959 if (ret_flags & GSS_C_INTEG_FLAG)
960 printf(gettext("GSS_C_INTEG_FLAG = True\n\n"));
961 else
962 printf(gettext("GSS_C_INTEG_FLAG = False\n\n"));
964 printf(gettext("time_req = %u seconds\n\n"), time_rec);
966 /* free allocated memory */
968 FREE(mech_type->elements, mech_type->length);
969 FREE(mech_type, sizeof (gss_OID_desc));
971 /* these two were malloc'd by kgss_init_sec_context() */
973 FREE(actual_mech_type->elements, actual_mech_type->length);
974 FREE(actual_mech_type, sizeof (gss_OID_desc));
976 gss_release_name(&minor_status, &target_name);
978 if (input_token != GSS_C_NO_BUFFER)
979 gss_release_buffer(&minor_status, &init_token_buffer);
982 * if status == GSS_S_COMPLETE, reset the phase to 0 and
983 * release token in accept_token_buffer
986 init_sec_context_phase = 0;
987 /* Save and restore the context */
988 status = kgss_export_sec_context(&minor_status,
989 &initiator_context_handle,
990 &context_token);
991 if (status != GSS_S_COMPLETE) {
992 printf(gettext("server ret err (octal) %o (%s)\n"),
993 status, gettext("gss_export_sec_context_error"));
994 return;
996 status = kgss_import_sec_context(&minor_status,
997 &context_token,
998 &initiator_context_handle);
999 if (status != GSS_S_COMPLETE) {
1000 printf(gettext("server ret err (octal) %o (%s)\n"),
1001 status, gettext("gss_import_sec_context_error"));
1002 return;
1004 (void) gss_release_buffer(&minor_status, &context_token);
1006 /* gss_export & gss_import secxc_context worked, return */
1007 printf(gettext("\nexport and import of contexts succeeded\n"));
1008 printf(gettext("\ninit completed"));
1010 } else {
1011 printf(gettext("\nfirst phase of init succeeded"));
1012 printf(gettext("\ninit must be called again\n\n"));
1017 /*ARGSUSED*/
1018 static void
1019 _gss_accept_sec_context(argc, argv)
1020 int argc;
1021 char **argv;
1023 OM_UINT32 status;
1025 OM_uint32 minor_status;
1026 gss_channel_bindings_t input_chan_bindings;
1027 gss_OID mech_type;
1028 int ret_flags;
1029 OM_uint32 time_rec;
1030 gss_cred_id_t delegated_cred_handle;
1031 uid_t uid;
1032 char *string;
1033 gss_buffer_desc src_name, src_name_string;
1034 gss_buffer_desc output_token;
1035 gss_name_t gss_name;
1036 gss_buffer_desc context_token;
1039 * If this is the first phase of the context establishment,
1040 * clear acceptor_context_handle and indicate next phase.
1043 if (accept_sec_context_phase == 0) {
1044 acceptor_context_handle = GSS_C_NO_CONTEXT;
1045 accept_sec_context_phase = 1;
1048 /* Now set up the other command line independent input arguments */
1050 input_chan_bindings = GSS_C_NO_CHANNEL_BINDINGS;
1052 uid = (uid_t) getuid();
1054 if (argc != 0) {
1055 usage();
1056 return;
1059 status = kgss_accept_sec_context(&minor_status,
1060 &acceptor_context_handle,
1061 acceptor_credentials,
1062 &accept_token_buffer,
1063 input_chan_bindings,
1064 &src_name,
1065 &mech_type,
1066 &init_token_buffer,
1067 &ret_flags,
1068 &time_rec,
1069 &delegated_cred_handle,
1070 uid);
1072 /* store major and minor status for gss_display_status() call */
1074 gss_major_code = status;
1075 gss_minor_code = minor_status;
1077 if (status != GSS_S_COMPLETE && status != GSS_S_CONTINUE_NEEDED) {
1078 printf(gettext("server ret err (octal) %o (%s)\n"),
1079 status, gettext("gss_accept_sec_context error"));
1080 gss_release_buffer(&minor_status, &accept_token_buffer);
1081 return;
1082 } else if (status == GSS_S_COMPLETE) {
1084 /* process returned values */
1086 printf(gettext("\naccept succeeded\n\n"));
1089 * convert the exported name returned in src_name into
1090 * a string and print it.
1092 if ((status = gss_import_name(&minor_status, &src_name,
1093 (gss_OID) GSS_C_NT_EXPORT_NAME, &gss_name))
1094 != GSS_S_COMPLETE) {
1095 printf(gettext(
1096 "could not import src name 0x%x\n"), status);
1097 accept_sec_context_phase = 0;
1098 status = kgss_delete_sec_context(&minor_status,
1099 &acceptor_context_handle,
1100 &output_token);
1101 gss_release_buffer(&minor_status, &accept_token_buffer);
1102 if (status == GSS_S_CONTINUE_NEEDED)
1103 gss_release_buffer(&minor_status,
1104 &init_token_buffer);
1105 gss_release_buffer(&minor_status, &src_name);
1106 return;
1109 memset(&src_name_string, 0, sizeof (src_name_string));
1110 if ((status = gss_display_name(&minor_status, gss_name,
1111 &src_name_string, NULL)) != GSS_S_COMPLETE) {
1112 printf(gettext("could not display src name: "
1113 "err (octal) %o (%s)\n"), status,
1114 "gss_init_sec_context error");
1115 accept_sec_context_phase = 0;
1116 status = kgss_delete_sec_context(&minor_status,
1117 &acceptor_context_handle,
1118 &output_token);
1119 gss_release_buffer(&minor_status, &accept_token_buffer);
1120 if (status == GSS_S_CONTINUE_NEEDED)
1121 gss_release_buffer(&minor_status,
1122 &init_token_buffer);
1123 gss_release_buffer(&minor_status, &src_name);
1124 return;
1126 printf(gettext("src name = %s\n"), src_name_string.value);
1127 gss_release_name(&minor_status, &gss_name);
1128 gss_release_buffer(&minor_status, &src_name_string);
1129 gss_release_buffer(&minor_status, &src_name);
1131 /* print out the mechanism type */
1133 if ((string = gss_oid2str(mech_type)) == 0) {
1135 printf(gettext(
1136 "gssapi internal err :"
1137 " actual mech type null\n"));
1138 accept_sec_context_phase = 0;
1139 status = kgss_delete_sec_context(&minor_status,
1140 &acceptor_context_handle,
1141 &output_token);
1142 gss_release_buffer(&minor_status, &accept_token_buffer);
1143 if (status == GSS_S_CONTINUE_NEEDED)
1144 gss_release_buffer(&minor_status,
1145 &init_token_buffer);
1146 return;
1147 } else {
1149 printf(gettext("actual mech type = %s\n\n"), string);
1150 FREE(string, (mech_type->length+1)*4+1);
1153 /* Save and restore the context */
1154 status = kgss_export_sec_context(&minor_status,
1155 &initiator_context_handle,
1156 &context_token);
1157 if (status != GSS_S_COMPLETE) {
1158 printf(gettext("server ret err (octal) %o (%s)\n"),
1159 status, gettext("gss_export_sec_context_error"));
1160 return;
1162 status = kgss_import_sec_context(&minor_status,
1163 &context_token,
1164 &initiator_context_handle);
1165 if (status != GSS_S_COMPLETE) {
1166 printf(gettext("server ret err (octal) %o (%s)\n"),
1167 status, gettext("gss_import_sec_context_error"));
1168 return;
1170 (void) gss_release_buffer(&minor_status, &context_token);
1172 /* gss_export & gss_import secxc_context worked, return */
1174 /* print out value of ret_flags and time_req */
1176 if (ret_flags & GSS_C_DELEG_FLAG)
1177 printf(gettext("GSS_C_DELEG_FLAG = True\n"));
1178 else
1179 printf(gettext("GSS_C_DELEG_FLAG = False\n"));
1181 if (ret_flags & GSS_C_MUTUAL_FLAG)
1182 printf(gettext("GSS_C_MUTUAL_FLAG = True\n"));
1183 else
1184 printf(gettext("GSS_C_MUTUAL_FLAG = False\n"));
1186 if (ret_flags & GSS_C_REPLAY_FLAG)
1187 printf(gettext("GSS_C_REPLAY_FLAG = True\n"));
1188 else
1189 printf(gettext("GSS_C_REPLAY_FLAG = False\n"));
1191 if (ret_flags & GSS_C_SEQUENCE_FLAG)
1192 printf(gettext("GSS_C_SEQUENCE_FLAG = True\n"));
1193 else
1194 printf(gettext("GSS_C_SEQUENCE_FLAG = False\n"));
1196 if (ret_flags & GSS_C_CONF_FLAG)
1197 printf(gettext("GSS_C_CONF_FLAG = True\n"));
1198 else
1199 printf(gettext("GSS_C_CONF_FLAG = False\n"));
1201 if (ret_flags & GSS_C_INTEG_FLAG)
1202 printf(gettext("GSS_C_INTEG_FLAG = True\n\n"));
1203 else
1204 printf(gettext("GSS_C_INTEG_FLAG = False\n\n"));
1206 printf(gettext("time_rec = %d seconds\n\n"), time_rec);
1208 /* free allocated memory */
1210 printf(gettext("\nexport and import of contexts succeeded\n"));
1212 FREE(mech_type->elements, mech_type->length);
1213 FREE(mech_type, sizeof (gss_OID_desc));
1214 } else {
1215 printf(gettext("\nfirst phase of accept succeeded"));
1216 printf(gettext("\naccept must be called again\n\n"));
1220 /* free the input token in accept_token_buffer */
1221 gss_release_buffer(&minor_status, &accept_token_buffer);
1223 /* if status == GSS_S_COMPLETE, reset the phase to 0 */
1225 if (status == GSS_S_COMPLETE)
1226 accept_sec_context_phase = 0;
1228 /* gss_accept_sec_context worked, return */
1231 void
1232 _gss_process_context_token(argc, argv)
1233 int argc;
1234 char **argv;
1236 OM_UINT32 status;
1238 gss_ctx_id_t context_handle;
1239 OM_uint32 minor_status;
1240 uid_t uid;
1242 uid = (uid_t) getuid();
1244 /* parse the command line to determine the variable input argument */
1246 if (argc == 0) {
1247 usage();
1248 return;
1251 if (strcmp(argv[0], "initiator") == 0)
1252 context_handle = initiator_context_handle;
1253 else if (strcmp(argv[0], "acceptor") == 0)
1254 context_handle = acceptor_context_handle;
1255 else {
1256 printf(gettext(
1257 "must specify either \"initiator\" or \"acceptor\"\n"));
1258 return;
1261 argc--;
1262 argv++;
1264 if (argc != 0) {
1265 usage();
1266 return;
1269 status = kgss_process_context_token(&minor_status,
1270 context_handle,
1271 delete_token_buffer,
1272 uid);
1274 /* store major and minor status for gss_display_status() call */
1276 gss_major_code = status;
1277 gss_minor_code = minor_status;
1279 if (status != GSS_S_COMPLETE) {
1280 printf(gettext("server ret err (octal) %o (%s)\n"),
1281 status, gettext("gss_process_context_token error"));
1282 return;
1284 } else {
1285 printf(gettext("\nprocess succeeded\n\n"));
1286 return;
1290 static void
1291 _gss_delete_sec_context(argc, argv)
1292 int argc;
1293 char **argv;
1295 OM_UINT32 status;
1296 gss_ctx_id_t *context_handle;
1297 OM_uint32 minor_status;
1300 /* parse the command line to determine the variable input argument */
1302 if (argc == 0) {
1303 usage();
1304 return;
1307 if (strcmp(argv[0], "initiator") == 0) {
1308 context_handle = &initiator_context_handle;
1309 } else if (strcmp(argv[0], "acceptor") == 0) {
1310 context_handle = &acceptor_context_handle;
1311 } else {
1312 printf(gettext(
1313 "must specify either \"initiator\" or \"acceptor\"\n"));
1314 return;
1317 argc--;
1318 argv++;
1320 if (argc != 0) {
1321 usage();
1322 return;
1326 status = kgss_delete_sec_context(&minor_status,
1327 context_handle,
1328 &delete_token_buffer);
1331 /* store major and minor status for gss_display_status() call */
1333 gss_major_code = status;
1334 gss_minor_code = minor_status;
1336 if (status != GSS_S_COMPLETE) {
1338 printf(gettext("server ret err (octal) %o (%s)\n"),
1339 status, gettext("gss_delete_sec_context error"));
1340 return;
1342 } else {
1343 printf(gettext("\ndelete succeeded\n\n"));
1344 return;
1348 /*ARGSUSED*/
1349 static void
1350 _gss_context_time(argc, argv)
1351 int argc;
1352 char **argv;
1355 * set up input arguments here
1356 * this function is unimplemented. Call usage() and return
1359 printf(gettext("\nunimplemented function"));
1362 static void
1363 _gss_sign(argc, argv)
1364 int argc;
1365 char **argv;
1367 OM_UINT32 status;
1368 OM_uint32 minor_status;
1369 gss_ctx_id_t context_handle;
1370 int qop_req;
1371 uid_t uid;
1373 uid = (uid_t) getuid();
1375 /* specify the default quality of protection */
1377 qop_req = GSS_C_QOP_DEFAULT;
1379 /* set up the arguments specified in the input parameters */
1381 if (argc == 0) {
1382 usage();
1383 return;
1387 if (strcmp(argv[0], "initiator") == 0)
1388 context_handle = initiator_context_handle;
1389 else if (strcmp(argv[0], "acceptor") == 0)
1390 context_handle = acceptor_context_handle;
1391 else {
1392 printf(gettext(
1393 "must specify either \"initiator\" or \"acceptor\"\n"));
1394 return;
1397 argc--;
1398 argv++;
1400 if (argc == 0) {
1401 usage();
1402 return;
1405 message_buffer.length = strlen(argv[0])+1;
1406 message_buffer.value = (void *) MALLOC(message_buffer.length);
1407 strcpy(message_buffer.value, argv[0]);
1409 argc--;
1410 argv++;
1412 if (argc != 0) {
1413 usage();
1414 return;
1417 status = kgss_sign(&minor_status,
1418 context_handle,
1419 qop_req,
1420 &message_buffer,
1421 &msg_token,
1422 uid);
1424 /* store major and minor status for gss_display_status() call */
1426 gss_major_code = status;
1427 gss_minor_code = minor_status;
1429 if (status != GSS_S_COMPLETE) {
1430 printf(gettext("server ret err (octal) %o (%s)\n"),
1431 status, gettext("gss_sign error"));
1432 return;
1434 } else {
1435 printf(gettext("\nsign succeeded\n\n"));
1436 return;
1440 static void
1441 _gss_verify(argc, argv)
1442 int argc;
1443 char **argv;
1445 OM_UINT32 status, minor_status;
1446 gss_ctx_id_t context_handle;
1447 int qop_state;
1448 uid_t uid;
1450 uid = (uid_t) getuid();
1452 /* set up the arguments specified in the input parameters */
1454 if (argc == 0) {
1455 usage();
1456 return;
1460 if (strcmp(argv[0], "initiator") == 0)
1461 context_handle = initiator_context_handle;
1462 else if (strcmp(argv[0], "acceptor") == 0)
1463 context_handle = acceptor_context_handle;
1464 else {
1465 printf(gettext(
1466 "must specify either \"initiator\" or \"acceptor\"\n"));
1467 return;
1470 argc--;
1471 argv++;
1473 if (argc != 0) {
1474 usage();
1475 return;
1478 status = kgss_verify(&minor_status,
1479 context_handle,
1480 &message_buffer,
1481 &msg_token,
1482 &qop_state,
1483 uid);
1485 /* store major and minor status for gss_display_status() call */
1487 gss_major_code = status;
1488 gss_minor_code = minor_status;
1490 if (status != GSS_S_COMPLETE) {
1491 printf(gettext("server ret err (octal) %o (%s)\n"),
1492 status, gettext("gss_verify error"));
1493 return;
1494 } else {
1496 /* print out the verified message */
1498 printf(gettext(
1499 "verified message = \"%s\"\n\n"), message_buffer.value);
1501 /* print out the quality of protection returned */
1503 printf(gettext("quality of protection = %d \n\n"), qop_state);
1505 /* free the message buffer and message token and return */
1507 gss_release_buffer(&minor_status, &message_buffer);
1508 gss_release_buffer(&minor_status, &msg_token);
1510 return;
1514 static void
1515 _gss_seal(argc, argv)
1516 int argc;
1517 char **argv;
1519 OM_UINT32 status;
1521 OM_uint32 minor_status;
1522 gss_ctx_id_t context_handle;
1523 int conf_req_flag;
1524 int qop_req;
1525 gss_buffer_desc input_message_buffer;
1526 int conf_state;
1527 uid_t uid;
1529 uid = (uid_t) getuid();
1532 * specify the default confidentiality requested (both integrity
1533 * and confidentiality) and quality of protection
1536 conf_req_flag = 1;
1537 qop_req = GSS_C_QOP_DEFAULT;
1539 /* set up the arguments specified in the input parameters */
1541 if (argc == 0) {
1542 usage();
1543 return;
1547 if (strcmp(argv[0], "initiator") == 0)
1548 context_handle = initiator_context_handle;
1549 else if (strcmp(argv[0], "acceptor") == 0)
1550 context_handle = acceptor_context_handle;
1551 else {
1552 printf(gettext(
1553 "must specify either \"initiator\" or \"acceptor\"\n"));
1554 return;
1557 argc--;
1558 argv++;
1560 if (argc == 0) {
1561 usage();
1562 return;
1566 input_message_buffer.length = strlen(argv[0])+1;
1567 input_message_buffer.value =
1568 (void *) MALLOC(input_message_buffer.length);
1569 strcpy(input_message_buffer.value, argv[0]);
1571 argc--;
1572 argv++;
1574 if (argc != 0) {
1575 usage();
1576 return;
1579 status = kgss_seal(&minor_status,
1580 context_handle,
1581 conf_req_flag,
1582 qop_req,
1583 &input_message_buffer,
1584 &conf_state,
1585 &message_buffer,
1586 uid);
1588 /* store major and minor status for gss_display_status() call */
1590 gss_major_code = status;
1591 gss_minor_code = minor_status;
1593 /* free the inputmessage buffer */
1595 gss_release_buffer(&minor_status, &input_message_buffer);
1597 if (status != GSS_S_COMPLETE) {
1598 printf(gettext("server ret err (octal) %o (%s)\n"),
1599 status, gettext("gss_seal error"));
1600 return;
1601 } else {
1602 printf(gettext("\nseal succeeded\n\n"));
1603 return;
1607 static void
1608 _gss_unseal(argc, argv)
1609 int argc;
1610 char **argv;
1612 OM_UINT32 status;
1614 OM_uint32 minor_status;
1615 gss_ctx_id_t context_handle;
1616 gss_buffer_desc output_message_buffer;
1617 int conf_state;
1618 int qop_state;
1619 uid_t uid;
1621 uid = (uid_t) getuid();
1623 /* set up the arguments specified in the input parameters */
1625 if (argc == 0) {
1626 usage();
1627 return;
1631 if (strcmp(argv[0], "initiator") == 0)
1632 context_handle = initiator_context_handle;
1633 else if (strcmp(argv[0], "acceptor") == 0)
1634 context_handle = acceptor_context_handle;
1635 else {
1636 printf(gettext(
1637 "must specify either \"initiator\" or \"acceptor\"\n"));
1638 return;
1641 argc--;
1642 argv++;
1644 if (argc != 0) {
1645 usage();
1646 return;
1649 status = kgss_unseal(&minor_status,
1650 context_handle,
1651 &message_buffer,
1652 &output_message_buffer,
1653 &conf_state,
1654 &qop_state,
1655 uid);
1657 /* store major and minor status for gss_display_status() call */
1659 gss_major_code = status;
1660 gss_minor_code = minor_status;
1662 if (status == GSS_S_COMPLETE) {
1663 printf(gettext("\nunseal succeeded\n\n"));
1664 printf(gettext("unsealed message = \"%s\"\n\n"),
1665 output_message_buffer.value);
1666 if (conf_state)
1667 printf(gettext("confidentiality and integrity used\n"));
1668 else
1669 printf(gettext("only integrity used\n"));
1670 printf(gettext("quality of protection = %d\n\n"), qop_state);
1671 gss_release_buffer(&minor_status, &output_message_buffer);
1672 } else {
1673 printf(gettext("server ret err (octal) %o (%s)\n"),
1674 status, gettext("gss_unseal error"));
1677 /* free the message buffer and return */
1679 gss_release_buffer(&minor_status, &message_buffer);
1682 static void
1683 _gss_display_status(argc, argv)
1684 int argc;
1685 char **argv;
1687 OM_UINT32 status;
1688 OM_uint32 minor_status;
1689 int status_type;
1690 int status_value;
1691 gss_OID mech_type = (gss_OID) 0;
1692 int message_context;
1693 gss_buffer_desc status_string;
1694 uid_t uid;
1696 uid = (uid_t) getuid();
1698 /* initialize message context to zero */
1700 message_context = 0;
1702 if (argc == 0) {
1703 printf(gettext("Assuming Kerberos V5 as the mechanism\n"));
1704 printf(gettext(
1705 "The mech OID 1.2.840.113554.1.2.2 will be used\n"));
1706 mech_type = gss_str2oid((char *)GSS_KRB5_MECH_OID);
1707 } else
1708 mech_type = gss_str2oid(argv[0]);
1710 if (mech_type == 0 || mech_type->length == 0) {
1711 printf(gettext("improperly formated mechanism OID\n"));
1712 return;
1715 /* Is this call for the major or minor status? */
1717 if (strcmp(argv[0], "major") == 0) {
1718 status_type = GSS_C_GSS_CODE;
1719 status_value = gss_major_code;
1720 } else if (strcmp(argv[0], "minor") == 0) {
1721 status_type = GSS_C_MECH_CODE;
1722 status_value = gss_minor_code;
1723 } else {
1724 printf(gettext("must specify either \"major\" or \"minor\"\n"));
1725 return;
1728 argc--;
1729 argv++;
1731 if (argc != 0) {
1732 usage();
1733 return;
1736 status = kgss_display_status(&minor_status,
1737 status_value,
1738 status_type,
1739 mech_type,
1740 &message_context,
1741 &status_string,
1742 uid);
1744 if (status == GSS_S_COMPLETE) {
1745 printf(gettext("status =\n %s\n\n"), status_string.value);
1746 } else if (status == GSS_S_BAD_MECH) {
1747 printf(gettext("invalide mechanism OID\n\n"));
1748 } else {
1749 printf(gettext("server ret err (octal) %o (%s)\n"),
1750 status, gettext("gss_display_status error"));
1754 /*ARGSUSED*/
1755 static void
1756 _gss_indicate_mechs(argc, argv)
1757 int argc;
1758 char **argv;
1760 OM_UINT32 status;
1761 OM_UINT32 minor_status;
1762 gss_OID_set oid_set = GSS_C_NULL_OID_SET;
1763 uid_t uid;
1765 uid = (uid_t) getuid();
1767 /* set up input arguments here */
1769 if (argc != 0) {
1770 usage();
1771 return;
1774 status = kgss_indicate_mechs(&minor_status, &oid_set, uid);
1776 if (status == GSS_S_COMPLETE) {
1777 int i;
1778 char *string;
1780 printf(gettext("%d supported mechanism%s%s\n"), oid_set->count,
1781 (oid_set->count == 1) ? "" : "s",
1782 (oid_set->count > 0) ? ":" : "");
1784 for (i = 0; i < oid_set->count; i++) {
1785 string = gss_oid2str(&oid_set->elements[i]);
1786 printf(gettext("\t%s\n"), string);
1787 FREE(string, ((oid_set->elements[i].length+1)*4)+1);
1789 printf("\n");
1791 } else {
1792 printf(gettext("server ret err (octal) %o (%s)\n"),
1793 status, gettext("gss_indicate_mechs error"));
1796 if (oid_set)
1797 gss_release_oid_set_and_oids(&minor_status, &oid_set);
1800 /*ARGSUSED*/
1801 static void
1802 _gss_inquire_cred(argc, argv)
1803 int argc;
1804 char **argv;
1806 /* set up input arguments here */
1808 if (argc != 0) {
1809 usage();
1810 return;
1814 /* this function is unimplemented. Call usage() and return */
1816 printf(gettext("\nUnsupported function"));
1819 static char hexChars[] = "0123456789ABCDEF";
1821 static void
1822 _gssd_expname_to_unix_cred(argc, argv)
1823 int argc;
1824 char **argv;
1826 OM_uint32 major;
1827 gss_buffer_desc expName;
1828 char krb5_root_name[] = "040100092A864886F712010202000000"
1829 "25000A2A864886F71201020101726F6F744053554E534F46"
1830 "542E454E472E53554E2E434F4D00";
1831 unsigned char *byteStr, *hexStr;
1832 uid_t uidOut, uidIn;
1833 gid_t *gids, gidOut;
1834 int gidsLen, i, newLen;
1836 /* set up the arguments */
1837 uidIn = (uid_t) getuid();
1839 if (argc < 1) {
1840 printf(gettext(
1841 "Using principal name of root for krberos_v5\n"));
1842 expName.value = (void*)krb5_root_name;
1843 expName.length = strlen(krb5_root_name);
1844 } else {
1845 expName.value = (void*)argv[0];
1846 expName.length = strlen(argv[0]);
1849 /* convert the name from hex to byte... */
1850 hexStr = (unsigned char *)expName.value;
1851 newLen = expName.length/2;
1852 byteStr = (unsigned char *)MALLOC(newLen+1);
1853 expName.value = (char *)byteStr;
1854 for (i = 0; i < expName.length; i += 2) {
1855 *byteStr = (strchr(hexChars, *hexStr++) - hexChars) << 4;
1856 *byteStr += (strchr(hexChars, *hexStr++) - hexChars);
1857 byteStr++;
1859 expName.length = newLen;
1861 major = kgsscred_expname_to_unix_cred(&expName, &uidOut, &gidOut,
1862 &gids, &gidsLen, uidIn);
1864 FREE(expName.value, newLen);
1866 if (major == GSS_S_COMPLETE) {
1867 printf(gettext("uid = <%d>\tgid = <%d>\t"), uidOut, gidOut);
1868 if (gidsLen > 0)
1869 printf(gettext(" %d gids <"), gidsLen);
1870 else
1871 printf(gettext(
1872 " no supplementary group information\n"));
1873 for (i = 0; i < gidsLen; i++)
1874 printf(" %d ", gids[i]);
1875 if (gidsLen > 0) {
1876 printf(">\n");
1877 FREE(gids, gidsLen * sizeof (gid_t));
1879 } else {
1880 printf(gettext("server ret err (octal) %o (%s)\n"),
1881 major, gettext("gsscred_expname_to_unix_cred"));
1885 static void
1886 _gssd_name_to_unix_cred(argc, argv)
1887 int argc;
1888 char **argv;
1890 OM_uint32 major, minor;
1891 gss_name_t gssName;
1892 gss_buffer_desc gssBuf = GSS_C_EMPTY_BUFFER;
1893 int gidsLen, i;
1894 gid_t *gids, gidOut;
1895 uid_t uidOut, uid;
1896 char defaultPrincipal[] = "root";
1897 gss_OID mechType, nameType;
1899 uid = getuid();
1901 /* optional argument 1 - contains principal name */
1902 if (argc > 0) {
1903 gssBuf.value = (void *)argv[0];
1904 gssBuf.length = strlen((char *)argv[0]);
1905 } else {
1906 gssBuf.value = (void *)defaultPrincipal;
1907 gssBuf.length = strlen(defaultPrincipal);
1909 printf(gettext(
1910 "Using <%s> as the principal name.\n"), (char *)gssBuf.value);
1913 /* optional argument 2 - contains name oid */
1914 if (argc > 1)
1915 nameType = gss_str2oid((char *) argv[1]);
1916 else
1917 nameType = (gss_OID)GSS_C_NT_USER_NAME;
1919 if (nameType == NULL || nameType->length == 0) {
1920 printf(gettext("improperly formated name OID\n"));
1921 return;
1923 printf(gettext("Principal name of type: <%s>.\n"),
1924 (argc > 1) ? argv[1] : "GSS_C_NT_USER_NAME");
1927 /* optional argument 3 - contains mech oid */
1928 if (argc > 2)
1929 mechType = gss_str2oid(argv[2]);
1930 else
1931 mechType = gss_str2oid((char *)GSS_KRB5_MECH_OID);
1933 if (mechType == NULL || mechType->length == 0) {
1934 FREE(nameType->elements, nameType->length);
1935 FREE(nameType, sizeof (gss_OID_desc));
1936 printf(gettext("improperly formated mech OID\n"));
1937 return;
1939 printf(gettext("Mechanism oid: <%s>.\n"),
1940 (argc > 2) ? argv[2] :
1941 (char *)GSS_KRB5_MECH_OID "(Kerberos v5)");
1944 /* convert the name to internal format */
1945 if ((major = gss_import_name(&minor, &gssBuf,
1946 nameType, &gssName)) != GSS_S_COMPLETE) {
1947 printf(gettext("could not parse name: err (octal) %o (%s)\n"),
1948 major, "gss_import_name");
1950 FREE(nameType->elements, nameType->length);
1951 FREE(nameType, sizeof (gss_OID_desc));
1952 return;
1955 major = kgsscred_name_to_unix_cred(gssName, mechType, &uidOut,
1956 &gidOut, &gids, &gidsLen, uid);
1958 gss_release_name(&minor, &gssName);
1959 FREE(mechType->elements, mechType->length);
1960 FREE(mechType, sizeof (gss_OID_desc));
1961 if (argc > 1) {
1962 FREE(nameType->elements, nameType->length);
1963 FREE(nameType, sizeof (gss_OID_desc));
1966 if (major == GSS_S_COMPLETE) {
1967 printf("uid = <%d>\tgid = <%d>\t", uidOut, gidOut);
1968 if (gidsLen > 0)
1969 printf(gettext(" %d gids <"), gidsLen);
1970 else
1971 printf(gettext(
1972 " no supplementary group information\n"));
1973 for (i = 0; i < gidsLen; i++)
1974 printf(" %d ", gids[i]);
1975 if (gidsLen > 0) {
1976 printf(">\n");
1977 FREE(gids, gidsLen * sizeof (gid_t));
1979 } else {
1980 printf(gettext("server ret err (octal) %o (%s)\n"),
1981 major, gettext("gsscred_name_to_unix_cred"));
1985 static void
1986 _gssd_get_group_info(argc, argv)
1987 int argc;
1988 char **argv;
1990 OM_uint32 major;
1991 uid_t puid, uidIn;
1992 gid_t *gids, gidOut;
1993 int gidsLen, i;
1995 /* set up the arguments */
1996 uidIn = (uid_t) getuid();
1998 if (argc < 1)
1999 puid = 0;
2000 else
2001 puid = atol(argv[0]);
2003 printf(gettext("Retrieving group info for uid of <%d>\n"), puid);
2005 major = kgss_get_group_info(puid, &gidOut, &gids, &gidsLen, uidIn);
2007 if (major == GSS_S_COMPLETE) {
2008 printf(gettext("group id = <%d>\t"), gidOut);
2009 if (gidsLen > 0)
2010 printf(gettext(" %d gids <"), gidsLen);
2011 else
2012 printf(gettext(
2013 " no supplementary group information\n"));
2014 for (i = 0; i < gidsLen; i++)
2015 printf(" %d ", gids[i]);
2016 if (gidsLen > 0) {
2017 printf(">\n");
2018 FREE(gids, gidsLen * sizeof (gid_t));
2020 } else {
2021 printf(gettext("server ret err (octal) %o (%s)\n"),
2022 major, "gss_get_group_info");
2026 static gss_OID
2027 gss_str2oid(string)
2028 char * string;
2031 * a convenient wrapper routine for gss_str_to_oid
2032 * this can handle all valid oid strings.
2034 OM_uint32 minor;
2035 gss_buffer_desc abuf;
2036 gss_OID oidOut;
2038 abuf.value = (void*)string;
2039 abuf.length = strlen(string);
2041 if (gss_str_to_oid(&minor, &abuf, &oidOut) != GSS_S_COMPLETE)
2042 return (NULL);
2044 return (oidOut);
2047 static char *
2048 gss_oid2str(oid)
2049 gss_OID oid;
2052 * a convenient wrapper for gss_oid_to_str
2053 * this calls the GSS-API routine which should
2054 * be able to handle all types of oids.
2056 OM_uint32 minor;
2057 gss_buffer_desc oidStr;
2059 if (gss_oid_to_str(&minor, oid, &oidStr) != GSS_S_COMPLETE)
2060 return (NULL);
2062 return ((char *)oidStr.value);
2063 } /* gss_oid2str */
2065 static void
2066 instructs()
2068 fprintf(stderr,
2069 gettext(
2070 "\nThis program must be run as root. Root must be installed on the KDC\n"
2071 "and exist in srvtab as root/<hostname>, where <hostname> is the machine on\n"
2072 "which the test runs. Before running gssdtest for Kerberos mechanism, the\n"
2073 "operator running as root must kinit as some other principal, e.g., test.\n"
2074 "There are two mechanisms avaialble: dummy and Kerberos(default).\n"
2075 "The OID for dummy mechanism is 1.3.6.1.4.1.42.2.26.1.2.\n"
2076 "The OID for Kerberos mechanism is 1.2.840.113554.1.2.2.\n"
2077 "The order of context establishment calls is important. First, acquire must"
2078 "\nbe called. This obtains the credentials used by accept. Acquire need\n"
2079 "only be called once, since the credentials it returns are used each time\n"
2080 "accept is called. Then init is called, followed by accept. Calling init\n"
2081 "twice without calling accept or calling these in a different order gives\n"
2082 "erroneous results and will cause memory leaks in the gssapi daemon. \n"
2083 "Finally, after calling init and accept, init must be called again to\n"
2084 "finish context establishment. So an example sequence (with data valid for\n"
2085 "the Kerberos mechanism and running on the machine \"elrond\" in the realm\n"
2086 "FOO.BAR.SUN.COM is :\n"));
2087 fprintf(stderr,
2088 gettext("\nacquire service@host 1.2.840.113554.1.2.2\n"
2089 "init service@host 1.2.840.113554.1.2.2\n"
2090 "accept\ninit service@host 1.2.840.113554.1.2.2\n"
2091 "\nAfter a context is established, sign, seal,\n"
2092 "verify and unseal may be called. Here are some examples\n"
2093 "for these routines : \n\n"
2094 "sign initiator ThisTestMessageIsForSigning\n"
2095 "verify acceptor\nseal initiator ThisTestMessageIsForSealing\n"
2096 "unseal acceptor\n\nEach input line is terminated by <cr>.\n"
2097 "The program is terminated by cntl-d\nor the command \"exit\""
2098 "\nfrom the prompt\n\n"));
2101 static void
2102 usage()
2104 fprintf(stderr,
2105 gettext(
2106 "\nusage:\t[acquire | gss_acquire_cred]"
2107 "desired_name mech_type\n"
2108 "\t[release | gss_release_cred]\n"
2109 "\t[init | gss_init_sec_context] target_name mech_type\n"
2110 "\t[accept | gss_accept_sec_context]\n"
2111 "\t[process | gss_process_context_token] initiator | acceptor\n"
2112 "\t[delete | gss_delete_sec_context] initiator | acceptor\n"
2113 "\t[time | gss_context_time] {not yet implemented}\n"
2114 "\t[sign | gss_sign] initiator | acceptor message-to-sign\n"
2115 "\t[verify | gss_verify] initiator | acceptor\n"
2116 "\t[seal | gss_seal] initiator | acceptor message-to-seal\n"
2117 "\t[unseal | gss_unseal] initiator | acceptor\n"
2118 "\t[status | gss_display_status] mech_type [major | minor] \n"
2119 "\t[indicate | gss_indicate_mechs]\n"
2120 "\t[inquire | gss_inquire_cred] {not yet implemented}\n"
2121 "\t[expname2unixcred | gsscred_expname_to_unix_cred]"
2122 " export-name\n"
2123 "\t[name2unixcred | gsscred_name_to_unix_cred] "
2124 "pname [name_type mech_type]\n"
2125 "\t[grpinfo | gss_get_group_info] uid\n"
2126 "\t[gss_all | all] desired_name\n"
2127 "\t[gss_loop | loop] desired_name\n"
2128 "\texit\n\n"));
2131 /* Copied from parse_argv(), then modified */
2133 static int
2134 parse_input_line(input_line, argc, argv)
2135 char *input_line;
2136 int * argc;
2137 char ***argv;
2139 const char nil = '\0';
2140 char * chptr;
2141 int chr_cnt;
2142 int arg_cnt = 0;
2143 int ch_was_space = 1;
2144 int ch_is_space;
2146 chr_cnt = strlen(input_line);
2148 /* Count the arguments in the input_line string */
2150 *argc = 1;
2152 for (chptr = &input_line[0]; *chptr != nil; chptr++) {
2153 ch_is_space = isspace(*chptr);
2154 if (ch_is_space && !ch_was_space) {
2155 (*argc)++;
2157 ch_was_space = ch_is_space;
2160 if (ch_was_space) {
2161 (*argc)--;
2162 } /* minus trailing spaces */
2164 /* Now that we know how many args calloc the argv array */
2166 *argv = (char **) CALLOC((*argc)+1, sizeof (char *));
2167 chptr = (char *) (&input_line[0]);
2169 for (ch_was_space = 1; *chptr != nil; chptr++) {
2170 ch_is_space = isspace(*chptr);
2171 if (ch_is_space) {
2172 *chptr = nil; /* replace each space with nil */
2173 } else if (ch_was_space) { /* begining of word? */
2174 (*argv)[arg_cnt++] = chptr; /* new argument ? */
2177 ch_was_space = ch_is_space;
2180 return (chr_cnt);