1 /*
2 * CDDL HEADER START
3 *
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.
8 *
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.
13 *
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]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 2017 Gary Mills
24 * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
26 */
27
28 /*
29 * Test client for gssd. This program is not shipped on the binary
30 * release.
31 */
32
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>
41
42 #define _KERNEL
43 #include <gssapi/gssapi.h>
44 #undef _KERNEL
45
46 int gss_major_code;
47 int gss_minor_code;
48
49 int init_sec_context_phase = 0;
50 int accept_sec_context_phase = 0;
51
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;
60
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')
73
strdup(const char * s)74 static char *strdup(const char *s)
75 {
76 int len = strlen(s);
77 char *new = MALLOC(len+1);
78 strcpy(new, s);
79 return (new);
80 }
81
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 */
88
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();
95
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 **);
114
115 static int do_gssdtest(char *buf);
116
117
118 #ifndef _KERNEL
read_line(char * buf,int size)119 static int read_line(char *buf, int size)
120 {
121 int len;
122
123 /* read the next line. If cntl-d, return with zero char count */
124 printf(gettext("\n> "));
125
126 if (fgets(buf, size, stdin) == NULL)
127 return (0);
128
129 len = strlen(buf);
130 buf[--len] = '\0';
131 return (len);
132 }
133
134 int
main()135 main()
136 {
137 char buf[512];
138 int len, ret;
139
140 /* Print out usage and instructions to start off the session */
141
142 instructs();
143 usage();
144
145 /*
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.
149 */
150
151 do {
152 len = read_line(buf, 512);
153 if (len)
154 ret = do_gssdtest(buf);
155 } while (len && !ret);
156
157 return (0);
158 }
159 #endif /* !_KERNEL */
160
161 static int
do_gssdtest(char * buf)162 do_gssdtest(char *buf)
163 {
164 int argc, seal_argc;
165 int i;
166 char **argv, **argv_array;
167
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"};
175
176 argv = 0;
177
178 if (parse_input_line(buf, &argc, &argv) == 0) {
179 printf(gettext("\n"));
180 return (1);
181 }
182
183 if (argc == 0) {
184 usage();
185 /*LINTED*/
186 FREE(argv_array, (argc+1)*sizeof (char *));
187 return (0);
188 }
189
190 /*
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.
193 */
194
195 argv_array = argv;
196
197 cmd = argv[0];
198
199 argc--;
200 argv++;
201
202 if (strcmp(cmd, "gss_loop") == 0 ||
203 strcmp(cmd, "loop") == 0) {
204
205 if (argc < 1) {
206 usage();
207 FREE(argv_array, (argc+2) * sizeof (char *));
208 return (0);
209 }
210 for (i = 0; i < LOOP_COUNTER; i++) {
211 printf(gettext("Loop Count is %d \n"), i);
212 /*
213 * if (i > 53)
214 * printf ("Loop counter is greater than 55\n");
215 */
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);
220
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);
239 }
240 }
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);
247
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);
264
265 }
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);
271 }
272
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();
327
328 /* free argv array */
329
330 FREE(argv_array, (argc+2) * sizeof (char *));
331 return (0);
332 }
333
334 static void
_gss_acquire_cred(argc,argv)335 _gss_acquire_cred(argc, argv)
336 int argc;
337 char **argv;
338 {
339
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;
354
355 /*
356 * First set up the command line independent input arguments.
357 */
358
359 time_req = (OM_uint32) 0;
360 cred_usage = GSS_C_ACCEPT;
361 uid = getuid();
362
363 /* Parse the command line for the variable input arguments */
364
365 if (argc == 0) {
366 usage();
367 return;
368 }
369
370 /*
371 * Get the name of the principal.
372 */
373
374 name.length = strlen(argv[0])+1;
375 name.value = argv[0];
376
377 /*
378 * Now convert the string given by the first argument into internal
379 * form suitable for input to gss_acquire_cred()
380 */
381
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;
389 }
390
391 argc--;
392 argv++;
393
394 /*
395 * The next argument is an OID in dotted decimal form.
396 */
397
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]);
405
406 if (mech_type == 0 || mech_type->length == 0) {
407 printf(gettext("improperly formated mechanism OID\n"));
408 return;
409 }
410
411 /*
412 * set up desired_mechs so it points to mech_type.
413 */
414
415 desired_mechs = (gss_OID_set) MALLOC(sizeof (gss_OID_desc));
416
417 desired_mechs->count = 1;
418 desired_mechs->elements = mech_type;
419
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);
430
431 /* store major and minor status for gss_display_status() call */
432
433 gss_major_code = status;
434 gss_minor_code = minor_status;
435
436 if (status == GSS_S_COMPLETE) {
437 /* process returned values */
438
439 printf(gettext("\nacquire succeeded\n\n"));
440
441 /*
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.
447 */
448
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);
454 }
455
456 if (cred_usage == GSS_C_BOTH)
457 printf(gettext("GSS_C_BOTH\n\n"));
458
459 if (cred_usage == GSS_C_INITIATE)
460 printf(gettext("GSS_C_INITIATE\n\n"));
461
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);
472
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);
487 }
488 printf(gettext("inquire_cred successful \n\n"));
489 }
490
491 } else {
492 printf(gettext("server ret err (octal) %o (%s)\n"),
493 status, gettext("gss_acquire_cred error"));
494 }
495
496 /* free allocated memory */
497
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);
503
504 gss_release_name(&minor_status, &desired_name);
505
506 /* mech_type and desired_mechs are allocated above. Release it here */
507
508 FREE(mech_type->elements, mech_type->length);
509 FREE(mech_type, sizeof (gss_OID_desc));
510 FREE(desired_mechs, sizeof (gss_OID_desc));
511 }
512
513 static void
_gss_add_cred(argc,argv)514 _gss_add_cred(argc, argv)
515 int argc;
516 char **argv;
517 {
518
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;
532
533 /*
534 * First set up the command line independent input arguments.
535 */
536
537 initiator_time_req = (OM_uint32) 0;
538 acceptor_time_req = (OM_uint32) 0;
539 cred_usage = GSS_C_ACCEPT;
540 uid = getuid();
541
542 /* Parse the command line for the variable input arguments */
543
544 if (argc == 0) {
545 usage();
546 return;
547 }
548
549 /*
550 * Get the name of the principal.
551 */
552
553 name.length = strlen(argv[0])+1;
554 name.value = argv[0];
555
556 /*
557 * Now convert the string given by the first argument into internal
558 * form suitable for input to gss_acquire_cred()
559 */
560
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;
568 }
569
570 argc--;
571 argv++;
572
573 /*
574 * The next argument is an OID in dotted decimal form.
575 */
576
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]);
584
585 if (mech_type == 0 || mech_type->length == 0) {
586 printf(gettext("improperly formated mechanism OID\n"));
587 return;
588 }
589
590 /*
591 * set up desired_mechs so it points to mech_type.
592 */
593
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);
606
607 /* store major and minor status for gss_display_status() call */
608
609 gss_major_code = status;
610 gss_minor_code = minor_status;
611 if (status == GSS_S_COMPLETE) {
612 /* process returned values */
613
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);
627 }
628 }
629 }
630 /*
631 * Try adding the cred again for the same mech
632 * We should get GSS_S_DUPLICATE_ELEMENT
633 * if not return an error
634 */
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"));
651 }
652 status = kgss_inquire_cred(
653 &minor_status,
654 acceptor_credentials,
655 NULL,
656 &time_req,
657 &cred_usage,
658 &inquire_mechs,
659 uid);
660
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);
678 }
679 }
680 printf(gettext("inquire_cred successful \n\n"));
681 }
682
683 } else {
684 printf(gettext("server ret err (octal) %o (%s)\n"),
685 status, gettext("gss_acquire_cred error"));
686 }
687
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"));
699
700
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"));
713
714 /* free allocated memory */
715
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);
721
722 gss_release_name(&minor_status, &desired_name);
723
724 /* mech_type and desired_mechs are allocated above. Release it here */
725
726 FREE(mech_type->elements, mech_type->length);
727 FREE(mech_type, sizeof (gss_OID_desc));
728 }
729
730 /*ARGSUSED*/
731 static void
_gss_release_cred(argc,argv)732 _gss_release_cred(argc, argv)
733 int argc;
734 char **argv;
735 {
736 OM_UINT32 status;
737 OM_UINT32 minor_status;
738 uid_t uid;
739
740 /* set up input arguments here */
741
742 if (argc != 0) {
743 usage();
744 return;
745 }
746
747 uid = getuid();
748
749 status = kgss_release_cred(
750 &minor_status,
751 &acceptor_credentials,
752 uid);
753
754 /* store major and minor status for gss_display_status() call */
755
756 gss_major_code = status;
757 gss_minor_code = minor_status;
758
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"));
764 }
765 }
766
767 static void
_gss_init_sec_context(argc,argv)768 _gss_init_sec_context(argc, argv)
769 int argc;
770 char **argv;
771 {
772
773 OM_uint32 status;
774
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;
790
791 /*
792 * If this is the first phase of the context establishment,
793 * clear initiator_context_handle and indicate next phase.
794 */
795
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;
802
803 /*
804 * First set up the non-variable command line independent input
805 * arguments
806 */
807
808 claimant_cred_handle = GSS_C_NO_CREDENTIAL;
809
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();
814
815 /* Now parse the command line for the remaining input arguments */
816
817 if (argc == 0) {
818 usage();
819 return;
820 }
821
822 /*
823 * Get the name of the target.
824 */
825
826 name.length = strlen(argv[0])+1;
827 name.value = argv[0];
828
829 /*
830 * Now convert the string given by the first argument into a target
831 * name suitable for input to gss_init_sec_context()
832 */
833
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;
846 }
847
848 argc--;
849 argv++;
850
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]);
858 }
859
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;
866 }
867
868 /* call kgss_init_sec_context */
869
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);
884
885 /* store major and minor status for gss_display_status() call */
886 gss_major_code = status;
887 gss_minor_code = minor_status;
888
889 if (status != GSS_S_COMPLETE &&
890 status != GSS_S_CONTINUE_NEEDED) {
891
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;
904
905 } else if (status == GSS_S_COMPLETE) {
906
907 /* process returned values */
908
909 printf(gettext("\ninit succeeded\n\n"));
910
911 /* print out the actual mechanism type */
912
913 if ((string = gss_oid2str(actual_mech_type)) == 0) {
914
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);
930 }
931
932 /* print out value of ret_flags and time_req */
933
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"));
938
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"));
943
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"));
948
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"));
953
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"));
958
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"));
963
964 printf(gettext("time_req = %u seconds\n\n"), time_rec);
965
966 /* free allocated memory */
967
968 FREE(mech_type->elements, mech_type->length);
969 FREE(mech_type, sizeof (gss_OID_desc));
970
971 /* these two were malloc'd by kgss_init_sec_context() */
972
973 FREE(actual_mech_type->elements, actual_mech_type->length);
974 FREE(actual_mech_type, sizeof (gss_OID_desc));
975
976 gss_release_name(&minor_status, &target_name);
977
978 if (input_token != GSS_C_NO_BUFFER)
979 gss_release_buffer(&minor_status, &init_token_buffer);
980
981 /*
982 * if status == GSS_S_COMPLETE, reset the phase to 0 and
983 * release token in accept_token_buffer
984 */
985
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;
995 }
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;
1003 }
1004 (void) gss_release_buffer(&minor_status, &context_token);
1005
1006 /* gss_export & gss_import secxc_context worked, return */
1007 printf(gettext("\nexport and import of contexts succeeded\n"));
1008 printf(gettext("\ninit completed"));
1009
1010 } else {
1011 printf(gettext("\nfirst phase of init succeeded"));
1012 printf(gettext("\ninit must be called again\n\n"));
1013 }
1014
1015 }
1016
1017 /*ARGSUSED*/
1018 static void
_gss_accept_sec_context(argc,argv)1019 _gss_accept_sec_context(argc, argv)
1020 int argc;
1021 char **argv;
1022 {
1023 OM_UINT32 status;
1024
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;
1037
1038 /*
1039 * If this is the first phase of the context establishment,
1040 * clear acceptor_context_handle and indicate next phase.
1041 */
1042
1043 if (accept_sec_context_phase == 0) {
1044 acceptor_context_handle = GSS_C_NO_CONTEXT;
1045 accept_sec_context_phase = 1;
1046 }
1047
1048 /* Now set up the other command line independent input arguments */
1049
1050 input_chan_bindings = GSS_C_NO_CHANNEL_BINDINGS;
1051
1052 uid = (uid_t) getuid();
1053
1054 if (argc != 0) {
1055 usage();
1056 return;
1057 }
1058
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);
1071
1072 /* store major and minor status for gss_display_status() call */
1073
1074 gss_major_code = status;
1075 gss_minor_code = minor_status;
1076
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) {
1083
1084 /* process returned values */
1085
1086 printf(gettext("\naccept succeeded\n\n"));
1087
1088 /*
1089 * convert the exported name returned in src_name into
1090 * a string and print it.
1091 */
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;
1107 }
1108
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;
1125 }
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);
1130
1131 /* print out the mechanism type */
1132
1133 if ((string = gss_oid2str(mech_type)) == 0) {
1134
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 {
1148
1149 printf(gettext("actual mech type = %s\n\n"), string);
1150 FREE(string, (mech_type->length+1)*4+1);
1151 }
1152
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;
1161 }
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;
1169 }
1170 (void) gss_release_buffer(&minor_status, &context_token);
1171
1172 /* gss_export & gss_import secxc_context worked, return */
1173
1174 /* print out value of ret_flags and time_req */
1175
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"));
1180
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"));
1185
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"));
1190
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"));
1195
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"));
1200
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"));
1205
1206 printf(gettext("time_rec = %d seconds\n\n"), time_rec);
1207
1208 /* free allocated memory */
1209
1210 printf(gettext("\nexport and import of contexts succeeded\n"));
1211
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"));
1217 }
1218
1219
1220 /* free the input token in accept_token_buffer */
1221 gss_release_buffer(&minor_status, &accept_token_buffer);
1222
1223 /* if status == GSS_S_COMPLETE, reset the phase to 0 */
1224
1225 if (status == GSS_S_COMPLETE)
1226 accept_sec_context_phase = 0;
1227
1228 /* gss_accept_sec_context worked, return */
1229 }
1230
1231 void
_gss_process_context_token(argc,argv)1232 _gss_process_context_token(argc, argv)
1233 int argc;
1234 char **argv;
1235 {
1236 OM_UINT32 status;
1237
1238 gss_ctx_id_t context_handle;
1239 OM_uint32 minor_status;
1240 uid_t uid;
1241
1242 uid = (uid_t) getuid();
1243
1244 /* parse the command line to determine the variable input argument */
1245
1246 if (argc == 0) {
1247 usage();
1248 return;
1249 }
1250
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;
1259 }
1260
1261 argc--;
1262 argv++;
1263
1264 if (argc != 0) {
1265 usage();
1266 return;
1267 }
1268
1269 status = kgss_process_context_token(&minor_status,
1270 context_handle,
1271 delete_token_buffer,
1272 uid);
1273
1274 /* store major and minor status for gss_display_status() call */
1275
1276 gss_major_code = status;
1277 gss_minor_code = minor_status;
1278
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;
1283
1284 } else {
1285 printf(gettext("\nprocess succeeded\n\n"));
1286 return;
1287 }
1288 }
1289
1290 static void
_gss_delete_sec_context(argc,argv)1291 _gss_delete_sec_context(argc, argv)
1292 int argc;
1293 char **argv;
1294 {
1295 OM_UINT32 status;
1296 gss_ctx_id_t *context_handle;
1297 OM_uint32 minor_status;
1298
1299
1300 /* parse the command line to determine the variable input argument */
1301
1302 if (argc == 0) {
1303 usage();
1304 return;
1305 }
1306
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;
1315 }
1316
1317 argc--;
1318 argv++;
1319
1320 if (argc != 0) {
1321 usage();
1322 return;
1323 }
1324
1325
1326 status = kgss_delete_sec_context(&minor_status,
1327 context_handle,
1328 &delete_token_buffer);
1329
1330
1331 /* store major and minor status for gss_display_status() call */
1332
1333 gss_major_code = status;
1334 gss_minor_code = minor_status;
1335
1336 if (status != GSS_S_COMPLETE) {
1337
1338 printf(gettext("server ret err (octal) %o (%s)\n"),
1339 status, gettext("gss_delete_sec_context error"));
1340 return;
1341
1342 } else {
1343 printf(gettext("\ndelete succeeded\n\n"));
1344 return;
1345 }
1346 }
1347
1348 /*ARGSUSED*/
1349 static void
_gss_context_time(argc,argv)1350 _gss_context_time(argc, argv)
1351 int argc;
1352 char **argv;
1353 {
1354 /*
1355 * set up input arguments here
1356 * this function is unimplemented. Call usage() and return
1357 */
1358
1359 printf(gettext("\nunimplemented function"));
1360 }
1361
1362 static void
_gss_sign(argc,argv)1363 _gss_sign(argc, argv)
1364 int argc;
1365 char **argv;
1366 {
1367 OM_UINT32 status;
1368 OM_uint32 minor_status;
1369 gss_ctx_id_t context_handle;
1370 int qop_req;
1371 uid_t uid;
1372
1373 uid = (uid_t) getuid();
1374
1375 /* specify the default quality of protection */
1376
1377 qop_req = GSS_C_QOP_DEFAULT;
1378
1379 /* set up the arguments specified in the input parameters */
1380
1381 if (argc == 0) {
1382 usage();
1383 return;
1384 }
1385
1386
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;
1395 }
1396
1397 argc--;
1398 argv++;
1399
1400 if (argc == 0) {
1401 usage();
1402 return;
1403 }
1404
1405 message_buffer.length = strlen(argv[0])+1;
1406 message_buffer.value = (void *) MALLOC(message_buffer.length);
1407 strcpy(message_buffer.value, argv[0]);
1408
1409 argc--;
1410 argv++;
1411
1412 if (argc != 0) {
1413 usage();
1414 return;
1415 }
1416
1417 status = kgss_sign(&minor_status,
1418 context_handle,
1419 qop_req,
1420 &message_buffer,
1421 &msg_token,
1422 uid);
1423
1424 /* store major and minor status for gss_display_status() call */
1425
1426 gss_major_code = status;
1427 gss_minor_code = minor_status;
1428
1429 if (status != GSS_S_COMPLETE) {
1430 printf(gettext("server ret err (octal) %o (%s)\n"),
1431 status, gettext("gss_sign error"));
1432 return;
1433
1434 } else {
1435 printf(gettext("\nsign succeeded\n\n"));
1436 return;
1437 }
1438 }
1439
1440 static void
_gss_verify(argc,argv)1441 _gss_verify(argc, argv)
1442 int argc;
1443 char **argv;
1444 {
1445 OM_UINT32 status, minor_status;
1446 gss_ctx_id_t context_handle;
1447 int qop_state;
1448 uid_t uid;
1449
1450 uid = (uid_t) getuid();
1451
1452 /* set up the arguments specified in the input parameters */
1453
1454 if (argc == 0) {
1455 usage();
1456 return;
1457 }
1458
1459
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;
1468 }
1469
1470 argc--;
1471 argv++;
1472
1473 if (argc != 0) {
1474 usage();
1475 return;
1476 }
1477
1478 status = kgss_verify(&minor_status,
1479 context_handle,
1480 &message_buffer,
1481 &msg_token,
1482 &qop_state,
1483 uid);
1484
1485 /* store major and minor status for gss_display_status() call */
1486
1487 gss_major_code = status;
1488 gss_minor_code = minor_status;
1489
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 {
1495
1496 /* print out the verified message */
1497
1498 printf(gettext(
1499 "verified message = \"%s\"\n\n"), message_buffer.value);
1500
1501 /* print out the quality of protection returned */
1502
1503 printf(gettext("quality of protection = %d \n\n"), qop_state);
1504
1505 /* free the message buffer and message token and return */
1506
1507 gss_release_buffer(&minor_status, &message_buffer);
1508 gss_release_buffer(&minor_status, &msg_token);
1509
1510 return;
1511 }
1512 }
1513
1514 static void
_gss_seal(argc,argv)1515 _gss_seal(argc, argv)
1516 int argc;
1517 char **argv;
1518 {
1519 OM_UINT32 status;
1520
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;
1528
1529 uid = (uid_t) getuid();
1530
1531 /*
1532 * specify the default confidentiality requested (both integrity
1533 * and confidentiality) and quality of protection
1534 */
1535
1536 conf_req_flag = 1;
1537 qop_req = GSS_C_QOP_DEFAULT;
1538
1539 /* set up the arguments specified in the input parameters */
1540
1541 if (argc == 0) {
1542 usage();
1543 return;
1544 }
1545
1546
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;
1555 }
1556
1557 argc--;
1558 argv++;
1559
1560 if (argc == 0) {
1561 usage();
1562 return;
1563 }
1564
1565
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]);
1570
1571 argc--;
1572 argv++;
1573
1574 if (argc != 0) {
1575 usage();
1576 return;
1577 }
1578
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);
1587
1588 /* store major and minor status for gss_display_status() call */
1589
1590 gss_major_code = status;
1591 gss_minor_code = minor_status;
1592
1593 /* free the inputmessage buffer */
1594
1595 gss_release_buffer(&minor_status, &input_message_buffer);
1596
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;
1604 }
1605 }
1606
1607 static void
_gss_unseal(argc,argv)1608 _gss_unseal(argc, argv)
1609 int argc;
1610 char **argv;
1611 {
1612 OM_UINT32 status;
1613
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;
1620
1621 uid = (uid_t) getuid();
1622
1623 /* set up the arguments specified in the input parameters */
1624
1625 if (argc == 0) {
1626 usage();
1627 return;
1628 }
1629
1630
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;
1639 }
1640
1641 argc--;
1642 argv++;
1643
1644 if (argc != 0) {
1645 usage();
1646 return;
1647 }
1648
1649 status = kgss_unseal(&minor_status,
1650 context_handle,
1651 &message_buffer,
1652 &output_message_buffer,
1653 &conf_state,
1654 &qop_state,
1655 uid);
1656
1657 /* store major and minor status for gss_display_status() call */
1658
1659 gss_major_code = status;
1660 gss_minor_code = minor_status;
1661
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"));
1675 }
1676
1677 /* free the message buffer and return */
1678
1679 gss_release_buffer(&minor_status, &message_buffer);
1680 }
1681
1682 static void
_gss_display_status(argc,argv)1683 _gss_display_status(argc, argv)
1684 int argc;
1685 char **argv;
1686 {
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;
1695
1696 uid = (uid_t) getuid();
1697
1698 /* initialize message context to zero */
1699
1700 message_context = 0;
1701
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]);
1709
1710 if (mech_type == 0 || mech_type->length == 0) {
1711 printf(gettext("improperly formated mechanism OID\n"));
1712 return;
1713 }
1714
1715 /* Is this call for the major or minor status? */
1716
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;
1726 }
1727
1728 argc--;
1729 argv++;
1730
1731 if (argc != 0) {
1732 usage();
1733 return;
1734 }
1735
1736 status = kgss_display_status(&minor_status,
1737 status_value,
1738 status_type,
1739 mech_type,
1740 &message_context,
1741 &status_string,
1742 uid);
1743
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"));
1751 }
1752 }
1753
1754 /*ARGSUSED*/
1755 static void
_gss_indicate_mechs(argc,argv)1756 _gss_indicate_mechs(argc, argv)
1757 int argc;
1758 char **argv;
1759 {
1760 OM_UINT32 status;
1761 OM_UINT32 minor_status;
1762 gss_OID_set oid_set = GSS_C_NULL_OID_SET;
1763 uid_t uid;
1764
1765 uid = (uid_t) getuid();
1766
1767 /* set up input arguments here */
1768
1769 if (argc != 0) {
1770 usage();
1771 return;
1772 }
1773
1774 status = kgss_indicate_mechs(&minor_status, &oid_set, uid);
1775
1776 if (status == GSS_S_COMPLETE) {
1777 int i;
1778 char *string;
1779
1780 printf(gettext("%d supported mechanism%s%s\n"), oid_set->count,
1781 (oid_set->count == 1) ? "" : "s",
1782 (oid_set->count > 0) ? ":" : "");
1783
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);
1788 }
1789 printf("\n");
1790
1791 } else {
1792 printf(gettext("server ret err (octal) %o (%s)\n"),
1793 status, gettext("gss_indicate_mechs error"));
1794 }
1795
1796 if (oid_set)
1797 gss_release_oid_set_and_oids(&minor_status, &oid_set);
1798 }
1799
1800 /*ARGSUSED*/
1801 static void
_gss_inquire_cred(argc,argv)1802 _gss_inquire_cred(argc, argv)
1803 int argc;
1804 char **argv;
1805 {
1806 /* set up input arguments here */
1807
1808 if (argc != 0) {
1809 usage();
1810 return;
1811 }
1812
1813
1814 /* this function is unimplemented. Call usage() and return */
1815
1816 printf(gettext("\nUnsupported function"));
1817 }
1818
1819 static char hexChars[] = "0123456789ABCDEF";
1820
1821 static void
_gssd_expname_to_unix_cred(argc,argv)1822 _gssd_expname_to_unix_cred(argc, argv)
1823 int argc;
1824 char **argv;
1825 {
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;
1835
1836 /* set up the arguments */
1837 uidIn = (uid_t) getuid();
1838
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]);
1847 }
1848
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++;
1858 }
1859 expName.length = newLen;
1860
1861 major = kgsscred_expname_to_unix_cred(&expName, &uidOut, &gidOut,
1862 &gids, &gidsLen, uidIn);
1863
1864 FREE(expName.value, newLen);
1865
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));
1878 }
1879 } else {
1880 printf(gettext("server ret err (octal) %o (%s)\n"),
1881 major, gettext("gsscred_expname_to_unix_cred"));
1882 }
1883 }
1884
1885 static void
_gssd_name_to_unix_cred(argc,argv)1886 _gssd_name_to_unix_cred(argc, argv)
1887 int argc;
1888 char **argv;
1889 {
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;
1898
1899 uid = getuid();
1900
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);
1908 }
1909 printf(gettext(
1910 "Using <%s> as the principal name.\n"), (char *)gssBuf.value);
1911
1912
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;
1918
1919 if (nameType == NULL || nameType->length == 0) {
1920 printf(gettext("improperly formated name OID\n"));
1921 return;
1922 }
1923 printf(gettext("Principal name of type: <%s>.\n"),
1924 (argc > 1) ? argv[1] : "GSS_C_NT_USER_NAME");
1925
1926
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);
1932
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;
1938 }
1939 printf(gettext("Mechanism oid: <%s>.\n"),
1940 (argc > 2) ? argv[2] :
1941 (char *)GSS_KRB5_MECH_OID "(Kerberos v5)");
1942
1943
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");
1949
1950 FREE(nameType->elements, nameType->length);
1951 FREE(nameType, sizeof (gss_OID_desc));
1952 return;
1953 }
1954
1955 major = kgsscred_name_to_unix_cred(gssName, mechType, &uidOut,
1956 &gidOut, &gids, &gidsLen, uid);
1957
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));
1964 }
1965
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));
1978 }
1979 } else {
1980 printf(gettext("server ret err (octal) %o (%s)\n"),
1981 major, gettext("gsscred_name_to_unix_cred"));
1982 }
1983 }
1984
1985 static void
_gssd_get_group_info(argc,argv)1986 _gssd_get_group_info(argc, argv)
1987 int argc;
1988 char **argv;
1989 {
1990 OM_uint32 major;
1991 uid_t puid, uidIn;
1992 gid_t *gids, gidOut;
1993 int gidsLen, i;
1994
1995 /* set up the arguments */
1996 uidIn = (uid_t) getuid();
1997
1998 if (argc < 1)
1999 puid = 0;
2000 else
2001 puid = atol(argv[0]);
2002
2003 printf(gettext("Retrieving group info for uid of <%d>\n"), puid);
2004
2005 major = kgss_get_group_info(puid, &gidOut, &gids, &gidsLen, uidIn);
2006
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));
2019 }
2020 } else {
2021 printf(gettext("server ret err (octal) %o (%s)\n"),
2022 major, "gss_get_group_info");
2023 }
2024 }
2025
2026 static gss_OID
gss_str2oid(string)2027 gss_str2oid(string)
2028 char * string;
2029 {
2030 /*
2031 * a convenient wrapper routine for gss_str_to_oid
2032 * this can handle all valid oid strings.
2033 */
2034 OM_uint32 minor;
2035 gss_buffer_desc abuf;
2036 gss_OID oidOut;
2037
2038 abuf.value = (void*)string;
2039 abuf.length = strlen(string);
2040
2041 if (gss_str_to_oid(&minor, &abuf, &oidOut) != GSS_S_COMPLETE)
2042 return (NULL);
2043
2044 return (oidOut);
2045 }
2046
2047 static char *
gss_oid2str(oid)2048 gss_oid2str(oid)
2049 gss_OID oid;
2050 {
2051 /*
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.
2055 */
2056 OM_uint32 minor;
2057 gss_buffer_desc oidStr;
2058
2059 if (gss_oid_to_str(&minor, oid, &oidStr) != GSS_S_COMPLETE)
2060 return (NULL);
2061
2062 return ((char *)oidStr.value);
2063 } /* gss_oid2str */
2064
2065 static void
instructs()2066 instructs()
2067 {
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"));
2099 }
2100
2101 static void
usage()2102 usage()
2103 {
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"));
2129 }
2130
2131 /* Copied from parse_argv(), then modified */
2132
2133 static int
parse_input_line(input_line,argc,argv)2134 parse_input_line(input_line, argc, argv)
2135 char *input_line;
2136 int * argc;
2137 char ***argv;
2138 {
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;
2145
2146 chr_cnt = strlen(input_line);
2147
2148 /* Count the arguments in the input_line string */
2149
2150 *argc = 1;
2151
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)++;
2156 }
2157 ch_was_space = ch_is_space;
2158 }
2159
2160 if (ch_was_space) {
2161 (*argc)--;
2162 } /* minus trailing spaces */
2163
2164 /* Now that we know how many args calloc the argv array */
2165
2166 *argv = (char **) CALLOC((*argc)+1, sizeof (char *));
2167 chptr = (char *) (&input_line[0]);
2168
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 ? */
2175 }
2176
2177 ch_was_space = ch_is_space;
2178 }
2179
2180 return (chr_cnt);
2181 }
2182