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 2003 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /*
28 * Test client for gssd. This program is not shipped on the binary
29 * release.
30 */
31
32 #include <stdio.h>
33 #include <strings.h>
34 #include <ctype.h>
35 #include <stdlib.h>
36 #include <gssapi/gssapi.h>
37 #include <gssapi/gssapi_ext.h>
38 #include "gssd.h"
39 #include <rpc/rpc.h>
40
41 #define _KERNEL
42 #include <gssapi/gssapi.h>
43 #undef _KERNEL
44
45 int gss_major_code;
46 int gss_minor_code;
47
48 int init_sec_context_phase = 0;
49 int accept_sec_context_phase = 0;
50
51 gss_ctx_id_t initiator_context_handle;
52 gss_ctx_id_t acceptor_context_handle;
53 gss_cred_id_t acceptor_credentials;
54 gss_buffer_desc init_token_buffer;
55 gss_buffer_desc accept_token_buffer;
56 gss_buffer_desc delete_token_buffer;
57 gss_buffer_desc message_buffer;
58 gss_buffer_desc msg_token;
59
60 #define LOOP_COUNTER 100
61 #define GSS_KRB5_MECH_OID "1.2.840.113554.1.2.2"
62 #define GSS_DUMMY_MECH_OID "1.3.6.1.4.1.42.2.26.1.2"
63 #ifdef _KERNEL
64 #define OCTAL_MACRO "%03o."
65 #define MALLOC(n) kmem_alloc((n), KM_SLEEP)
66 #define CALLOC(n, s) kmem_zalloc((n)*(s), KM_SLEEP)
67 #define FREE(x, n) kmem_free((x), (n))
68 #define memcpy(dst, src, n) bcopy((src), (dst), (n))
69 #define fprintf(s, m) printf(m)
70 #define isspace(s) ((s) == ' ' || (s) == '\t' || (s) == '\n' || \
71 (s) == '\r' || (s) == '\v' || (s) == '\f')
72
strdup(const char * s)73 static char *strdup(const char *s)
74 {
75 int len = strlen(s);
76 char *new = MALLOC(len+1);
77 strcpy(new, s);
78 return (new);
79 }
80
81 #else /* !_KERNEL */
82 #define OCTAL_MACRO "%03.3o."
83 #define MALLOC(n) malloc(n)
84 #define CALLOC(n, s) calloc((n), (s))
85 #define FREE(x, n) free(x)
86 #endif /* _KERNEL */
87
88 static gss_OID gss_str2oid(char *);
89 static char * gss_oid2str(gss_OID);
90 static void instructs();
91 static void usage();
92 static int parse_input_line(char *, int *, char ***);
93 extern uid_t getuid();
94
95 static void _gss_init_sec_context(int, char **);
96 static void _gss_acquire_cred(int, char **);
97 static void _gss_add_cred(int, char **);
98 static void _gss_sign(int, char **);
99 static void _gss_release_cred(int, char **);
100 static void _gss_accept_sec_context(int, char **);
101 static void _gss_process_context_token(int, char **);
102 static void _gss_delete_sec_context(int, char **);
103 static void _gss_context_time(int, char **);
104 static void _gss_verify(int, char **);
105 static void _gss_seal(int, char **);
106 static void _gss_unseal(int, char **);
107 static void _gss_display_status(int, char **);
108 static void _gss_indicate_mechs(int, char **);
109 static void _gss_inquire_cred(int, char **);
110 static void _gssd_expname_to_unix_cred(int, char **);
111 static void _gssd_name_to_unix_cred(int, char **);
112 static void _gssd_get_group_info(int, char **);
113
114 static int do_gssdtest(char *buf);
115
116
117 #ifndef _KERNEL
read_line(char * buf,int size)118 static int read_line(char *buf, int size)
119 {
120 int len;
121
122 /* read the next line. If cntl-d, return with zero char count */
123 printf(gettext("\n> "));
124
125 if (fgets(buf, size, stdin) == NULL)
126 return (0);
127
128 len = strlen(buf);
129 buf[--len] = '\0';
130 return (len);
131 }
132
133 int
main()134 main()
135 {
136 char buf[512];
137 int len, ret;
138
139 /* Print out usage and instructions to start off the session */
140
141 instructs();
142 usage();
143
144 /*
145 * Loop, repeatedly calling parse_input_line() to get the
146 * next line and parse it into argc and argv. Act on the
147 * arguements found on the line.
148 */
149
150 do {
151 len = read_line(buf, 512);
152 if (len)
153 ret = do_gssdtest(buf);
154 } while (len && !ret);
155
156 return (0);
157 }
158 #endif /* !_KERNEL */
159
160 static int
do_gssdtest(char * buf)161 do_gssdtest(char *buf)
162 {
163 int argc, seal_argc;
164 int i;
165 char **argv, **argv_array;
166
167 char *cmd;
168 char *seal_ini_array [] = { "initiator", " Hello"};
169 char *seal_acc_array [] = { "acceptor", " Hello"};
170 char *unseal_acc_array [] = {"acceptor"};
171 char *unseal_ini_array [] = {"initiator"};
172 char *delet_acc_array [] = {"acceptor"};
173 char *delet_ini_array [] = {"initiator"};
174
175 argv = 0;
176
177 if (parse_input_line(buf, &argc, &argv) == 0) {
178 printf(gettext("\n"));
179 return (1);
180 }
181
182 if (argc == 0) {
183 usage();
184 /*LINTED*/
185 FREE(argv_array, (argc+1)*sizeof (char *));
186 return (0);
187 }
188
189 /*
190 * remember argv_array address, which is memory calloc'd by
191 * parse_input_line, so it can be free'd at the end of the loop.
192 */
193
194 argv_array = argv;
195
196 cmd = argv[0];
197
198 argc--;
199 argv++;
200
201 if (strcmp(cmd, "gss_loop") == 0 ||
202 strcmp(cmd, "loop") == 0) {
203
204 if (argc < 1) {
205 usage();
206 FREE(argv_array, (argc+2) * sizeof (char *));
207 return (0);
208 }
209 for (i = 0; i < LOOP_COUNTER; i++) {
210 printf(gettext("Loop Count is %d \n"), i);
211 /*
212 * if (i > 53)
213 * printf ("Loop counter is greater than 55\n");
214 */
215 _gss_acquire_cred(argc, argv);
216 _gss_init_sec_context(argc, argv);
217 _gss_accept_sec_context(0, argv);
218 _gss_init_sec_context(argc, argv);
219
220 seal_argc = 2;
221 _gss_seal(seal_argc, seal_ini_array);
222 seal_argc = 1;
223 _gss_unseal(seal_argc, unseal_acc_array);
224 seal_argc = 2;
225 _gss_seal(seal_argc, seal_acc_array);
226 seal_argc = 1;
227 _gss_unseal(seal_argc, unseal_ini_array);
228 seal_argc = 2;
229 _gss_sign(seal_argc, seal_ini_array);
230 seal_argc = 1;
231 _gss_verify(seal_argc, unseal_acc_array);
232 seal_argc = 2;
233 _gss_sign(seal_argc, seal_acc_array);
234 seal_argc = 1;
235 _gss_verify(seal_argc, unseal_ini_array);
236 _gss_delete_sec_context(argc, delet_acc_array);
237 _gss_delete_sec_context(argc, delet_ini_array);
238 }
239 }
240 if (strcmp(cmd, "gss_all") == 0 ||
241 strcmp(cmd, "all") == 0) {
242 _gss_acquire_cred(argc, argv);
243 _gss_init_sec_context(argc, argv);
244 _gss_accept_sec_context(0, argv);
245 _gss_init_sec_context(argc, argv);
246
247 seal_argc = 2;
248 _gss_seal(seal_argc, seal_acc_array);
249 seal_argc = 1;
250 _gss_unseal(seal_argc, unseal_ini_array);
251 seal_argc = 2;
252 _gss_seal(seal_argc, seal_ini_array);
253 seal_argc = 1;
254 _gss_unseal(seal_argc, unseal_acc_array);
255 seal_argc = 2;
256 _gss_sign(seal_argc, seal_ini_array);
257 seal_argc = 1;
258 _gss_verify(seal_argc, unseal_acc_array);
259 seal_argc = 2;
260 _gss_sign(seal_argc, seal_acc_array);
261 seal_argc = 1;
262 _gss_verify(seal_argc, unseal_ini_array);
263
264 }
265 if (strcmp(cmd, "gss_acquire_cred") == 0 ||
266 strcmp(cmd, "acquire") == 0) {
267 _gss_acquire_cred(argc, argv);
268 if (argc == 1)
269 _gss_add_cred(argc, argv);
270 }
271
272 else if (strcmp(cmd, "gss_release_cred") == 0 ||
273 strcmp(cmd, "release") == 0)
274 _gss_release_cred(argc, argv);
275 else if (strcmp(cmd, "gss_init_sec_context") == 0 ||
276 strcmp(cmd, "init") == 0)
277 _gss_init_sec_context(argc, argv);
278 else if (strcmp(cmd, "gss_accept_sec_context") == 0 ||
279 strcmp(cmd, "accept") == 0)
280 _gss_accept_sec_context(argc, argv);
281 else if (strcmp(cmd, "gss_process_context_token") == 0 ||
282 strcmp(cmd, "process") == 0)
283 _gss_process_context_token(argc, argv);
284 else if (strcmp(cmd, "gss_delete_sec_context") == 0 ||
285 strcmp(cmd, "delete") == 0)
286 _gss_delete_sec_context(argc, argv);
287 else if (strcmp(cmd, "gss_context_time") == 0 ||
288 strcmp(cmd, "time") == 0)
289 _gss_context_time(argc, argv);
290 else if (strcmp(cmd, "gss_sign") == 0 ||
291 strcmp(cmd, "sign") == 0)
292 _gss_sign(argc, argv);
293 else if (strcmp(cmd, "gss_verify") == 0 ||
294 strcmp(cmd, "verify") == 0)
295 _gss_verify(argc, argv);
296 else if (strcmp(cmd, "gss_seal") == 0 ||
297 strcmp(cmd, "seal") == 0)
298 _gss_seal(argc, argv);
299 else if (strcmp(cmd, "gss_unseal") == 0 ||
300 strcmp(cmd, "unseal") == 0)
301 _gss_unseal(argc, argv);
302 else if (strcmp(cmd, "gss_display_status") == 0||
303 strcmp(cmd, "status") == 0)
304 _gss_display_status(argc, argv);
305 else if (strcmp(cmd, "gss_indicate_mechs") == 0 ||
306 strcmp(cmd, "indicate") == 0)
307 _gss_indicate_mechs(argc, argv);
308 else if (strcmp(cmd, "gss_inquire_cred") == 0 ||
309 strcmp(cmd, "inquire") == 0)
310 _gss_inquire_cred(argc, argv);
311 else if (strcmp(cmd, "expname2unixcred") == 0 ||
312 strcmp(cmd, "gsscred_expname_to_unix_cred") == 0)
313 _gssd_expname_to_unix_cred(argc, argv);
314 else if (strcmp(cmd, "name2unixcred") == 0 ||
315 strcmp(cmd, "gsscred_name_to_unix_cred") == 0)
316 _gssd_name_to_unix_cred(argc, argv);
317 else if (strcmp(cmd, "grpinfo") == 0 ||
318 strcmp(cmd, "gss_get_group_info") == 0)
319 _gssd_get_group_info(argc, argv);
320 else if (strcmp(cmd, "exit") == 0) {
321 printf(gettext("\n"));
322 FREE(argv_array, (argc+2) * sizeof (char *));
323 return (1);
324 } else
325 usage();
326
327 /* free argv array */
328
329 FREE(argv_array, (argc+2) * sizeof (char *));
330 return (0);
331 }
332
333 static void
_gss_acquire_cred(argc,argv)334 _gss_acquire_cred(argc, argv)
335 int argc;
336 char **argv;
337 {
338
339 OM_UINT32 status, minor_status;
340 gss_buffer_desc name;
341 gss_name_t desired_name = (gss_name_t) 0;
342 OM_uint32 time_req;
343 gss_OID_set_desc desired_mechs_desc;
344 gss_OID_set desired_mechs = &desired_mechs_desc;
345 int cred_usage;
346 gss_OID_set actual_mechs = GSS_C_NULL_OID_SET;
347 gss_OID_set inquire_mechs = GSS_C_NULL_OID_SET;
348 OM_UINT32 time_rec;
349 char * string;
350 char * inq_string;
351 uid_t uid;
352 gss_OID mech_type;
353
354 /*
355 * First set up the command line independent input arguments.
356 */
357
358 time_req = (OM_uint32) 0;
359 cred_usage = GSS_C_ACCEPT;
360 uid = getuid();
361
362 /* Parse the command line for the variable input arguments */
363
364 if (argc == 0) {
365 usage();
366 return;
367 }
368
369 /*
370 * Get the name of the principal.
371 */
372
373 name.length = strlen(argv[0])+1;
374 name.value = argv[0];
375
376 /*
377 * Now convert the string given by the first argument into internal
378 * form suitable for input to gss_acquire_cred()
379 */
380
381 if ((status = gss_import_name(&minor_status, &name,
382 (gss_OID)GSS_C_NT_HOSTBASED_SERVICE, &desired_name))
383 != GSS_S_COMPLETE) {
384 printf(gettext(
385 "could not parse desired name: err (octal) %o (%s)\n"),
386 status, gettext("gss_acquire_cred error"));
387 return;
388 }
389
390 argc--;
391 argv++;
392
393 /*
394 * The next argument is an OID in dotted decimal form.
395 */
396
397 if (argc == 0) {
398 printf(gettext("Assuming Kerberos V5 as the mechanism\n"));
399 printf(gettext(
400 "The mech OID 1.2.840.113554.1.2.2 will be used\n"));
401 mech_type = gss_str2oid((char *)GSS_KRB5_MECH_OID);
402 } else
403 mech_type = gss_str2oid(argv[0]);
404
405 if (mech_type == 0 || mech_type->length == 0) {
406 printf(gettext("improperly formated mechanism OID\n"));
407 return;
408 }
409
410 /*
411 * set up desired_mechs so it points to mech_type.
412 */
413
414 desired_mechs = (gss_OID_set) MALLOC(sizeof (gss_OID_desc));
415
416 desired_mechs->count = 1;
417 desired_mechs->elements = mech_type;
418
419 status = kgss_acquire_cred(
420 &minor_status,
421 desired_name,
422 time_req,
423 desired_mechs,
424 cred_usage,
425 &acceptor_credentials,
426 &actual_mechs,
427 &time_rec,
428 uid);
429
430 /* store major and minor status for gss_display_status() call */
431
432 gss_major_code = status;
433 gss_minor_code = minor_status;
434
435 if (status == GSS_S_COMPLETE) {
436 /* process returned values */
437
438 printf(gettext("\nacquire succeeded\n\n"));
439
440 /*
441 * print out the actual mechs returned NB: Since only one
442 * mechanism is specified in desired_mechs, only one
443 * can be returned in actual_mechs. Consequently,
444 * actual_mechs->elements points to an array of only one
445 * element.
446 */
447
448 if ((string = gss_oid2str(actual_mechs->elements)) == 0) {
449 printf(gettext("actual mechs == NULL\n\n"));
450 } else {
451 printf(gettext("actual mechs = %s\n\n"), string);
452 FREE(string, (actual_mechs->elements->length+1)*4+1);
453 }
454
455 if (cred_usage == GSS_C_BOTH)
456 printf(gettext("GSS_C_BOTH\n\n"));
457
458 if (cred_usage == GSS_C_INITIATE)
459 printf(gettext("GSS_C_INITIATE\n\n"));
460
461 if (cred_usage == GSS_C_ACCEPT)
462 printf(gettext("GSS_C_ACCEPT\n\n"));
463 status = kgss_inquire_cred(
464 &minor_status,
465 acceptor_credentials,
466 NULL,
467 &time_req,
468 &cred_usage,
469 &inquire_mechs,
470 uid);
471
472 if (status != GSS_S_COMPLETE)
473 printf(gettext("server ret err (octal) %o (%s)\n"),
474 status, gettext("gss_inquire_cred error"));
475 else {
476 if ((inq_string =
477 gss_oid2str(inquire_mechs->elements)) == 0) {
478 printf(gettext
479 ("mechs from inquire == NULL\n\n"));
480 } else {
481 printf(gettext
482 ("mechs from inquiry = %s\n\n"),
483 inq_string);
484 FREE(inq_string,
485 (inquire_mechs->elements->length+1)*4+1);
486 }
487 printf(gettext("inquire_cred successful \n\n"));
488 }
489
490 } else {
491 printf(gettext("server ret err (octal) %o (%s)\n"),
492 status, gettext("gss_acquire_cred error"));
493 }
494
495 /* free allocated memory */
496
497 /* actual mechs is allocated by clnt_stubs. Release it here */
498 if (actual_mechs != GSS_C_NULL_OID_SET)
499 gss_release_oid_set_and_oids(&minor_status, &actual_mechs);
500 if (inquire_mechs != GSS_C_NULL_OID_SET)
501 gss_release_oid_set_and_oids(&minor_status, &inquire_mechs);
502
503 gss_release_name(&minor_status, &desired_name);
504
505 /* mech_type and desired_mechs are allocated above. Release it here */
506
507 FREE(mech_type->elements, mech_type->length);
508 FREE(mech_type, sizeof (gss_OID_desc));
509 FREE(desired_mechs, sizeof (gss_OID_desc));
510 }
511
512 static void
_gss_add_cred(argc,argv)513 _gss_add_cred(argc, argv)
514 int argc;
515 char **argv;
516 {
517
518 OM_UINT32 status, minor_status;
519 gss_buffer_desc name;
520 gss_name_t desired_name = (gss_name_t) 0;
521 OM_uint32 time_req;
522 OM_uint32 initiator_time_req;
523 OM_uint32 acceptor_time_req;
524 int cred_usage;
525 gss_OID_set actual_mechs = GSS_C_NULL_OID_SET;
526 gss_OID_set inquire_mechs = GSS_C_NULL_OID_SET;
527 char * string;
528 uid_t uid;
529 gss_OID mech_type;
530 int i;
531
532 /*
533 * First set up the command line independent input arguments.
534 */
535
536 initiator_time_req = (OM_uint32) 0;
537 acceptor_time_req = (OM_uint32) 0;
538 cred_usage = GSS_C_ACCEPT;
539 uid = getuid();
540
541 /* Parse the command line for the variable input arguments */
542
543 if (argc == 0) {
544 usage();
545 return;
546 }
547
548 /*
549 * Get the name of the principal.
550 */
551
552 name.length = strlen(argv[0])+1;
553 name.value = argv[0];
554
555 /*
556 * Now convert the string given by the first argument into internal
557 * form suitable for input to gss_acquire_cred()
558 */
559
560 if ((status = gss_import_name(&minor_status, &name,
561 (gss_OID)GSS_C_NT_HOSTBASED_SERVICE, &desired_name))
562 != GSS_S_COMPLETE) {
563 printf(gettext(
564 "could not parse desired name: err (octal) %o (%s)\n"),
565 status, gettext("gss_acquire_cred error"));
566 return;
567 }
568
569 argc--;
570 argv++;
571
572 /*
573 * The next argument is an OID in dotted decimal form.
574 */
575
576 if (argc == 0) {
577 printf(gettext("Assuming dummy as the mechanism\n"));
578 printf(gettext(
579 "The mech OID 1.3.6.1.4.1.42.2.26.1.2 will be used\n"));
580 mech_type = gss_str2oid((char *)GSS_DUMMY_MECH_OID);
581 } else
582 mech_type = gss_str2oid(argv[0]);
583
584 if (mech_type == 0 || mech_type->length == 0) {
585 printf(gettext("improperly formated mechanism OID\n"));
586 return;
587 }
588
589 /*
590 * set up desired_mechs so it points to mech_type.
591 */
592
593 status = kgss_add_cred(
594 &minor_status,
595 acceptor_credentials,
596 desired_name,
597 mech_type,
598 cred_usage,
599 initiator_time_req,
600 acceptor_time_req,
601 &actual_mechs,
602 NULL,
603 NULL,
604 uid);
605
606 /* store major and minor status for gss_display_status() call */
607
608 gss_major_code = status;
609 gss_minor_code = minor_status;
610 if (status == GSS_S_COMPLETE) {
611 /* process returned values */
612
613 printf(gettext("\nadd succeeded\n\n"));
614 if (actual_mechs) {
615 for (i = 0; i < actual_mechs->count; i++) {
616 if ((string =
617 gss_oid2str
618 (&actual_mechs->elements[i])) == 0) {
619 printf(gettext
620 ("actual mechs == NULL\n\n"));
621 } else {
622 printf(gettext
623 ("actual mechs = %s\n\n"), string);
624 FREE(string,
625 (actual_mechs->elements->length+1)*4+1);
626 }
627 }
628 }
629 /*
630 * Try adding the cred again for the same mech
631 * We should get GSS_S_DUPLICATE_ELEMENT
632 * if not return an error
633 */
634 status = kgss_add_cred(
635 &minor_status,
636 acceptor_credentials,
637 desired_name,
638 mech_type,
639 cred_usage,
640 initiator_time_req,
641 acceptor_time_req,
642 NULL, /* &actual_mechs, */
643 NULL,
644 NULL,
645 uid);
646 if (status != GSS_S_DUPLICATE_ELEMENT) {
647 printf(gettext("Expected duplicate element, Got "
648 " (octal) %o (%s)\n"),
649 status, gettext("gss_add_cred error"));
650 }
651 status = kgss_inquire_cred(
652 &minor_status,
653 acceptor_credentials,
654 NULL,
655 &time_req,
656 &cred_usage,
657 &inquire_mechs,
658 uid);
659
660 if (status != GSS_S_COMPLETE)
661 printf(gettext("server ret err (octal) %o (%s)\n"),
662 status, gettext("gss_inquire_cred error"));
663 else {
664 for (i = 0; i < inquire_mechs->count; i++) {
665 if ((string =
666 gss_oid2str
667 (&inquire_mechs->elements[i])) == 0) {
668 printf(gettext
669 ("inquire_mechs mechs == NULL\n\n"));
670 } else {
671 printf(gettext
672 ("inquire_cred mechs = %s\n\n"),
673 string);
674 FREE(string,
675 (inquire_mechs->elements->length+1)*4
676 +1);
677 }
678 }
679 printf(gettext("inquire_cred successful \n\n"));
680 }
681
682 } else {
683 printf(gettext("server ret err (octal) %o (%s)\n"),
684 status, gettext("gss_acquire_cred error"));
685 }
686
687 /* Let us do inquire_cred_by_mech for both mechanisms */
688 status = kgss_inquire_cred_by_mech(
689 &minor_status,
690 acceptor_credentials,
691 mech_type,
692 uid);
693 if (status != GSS_S_COMPLETE)
694 printf(gettext("server ret err (octal) %o (%s)\n"),
695 status, gettext("gss_inquire_cred_by_mech"));
696 else
697 printf(gettext("gss_inquire_cred_by_mech successful"));
698
699
700 FREE(mech_type->elements, mech_type->length);
701 FREE(mech_type, sizeof (gss_OID_desc));
702 mech_type = gss_str2oid((char *)GSS_KRB5_MECH_OID);
703 status = kgss_inquire_cred_by_mech(
704 &minor_status,
705 acceptor_credentials,
706 mech_type,
707 uid);
708 if (status != GSS_S_COMPLETE)
709 printf(gettext("server ret err (octal) %o (%s)\n"),
710 status, gettext
711 ("gss_inquire_cred_by_mech for dummy mech error"));
712
713 /* free allocated memory */
714
715 /* actual mechs is allocated by clnt_stubs. Release it here */
716 if (actual_mechs != GSS_C_NULL_OID_SET)
717 gss_release_oid_set_and_oids(&minor_status, &actual_mechs);
718 if (inquire_mechs != GSS_C_NULL_OID_SET)
719 gss_release_oid_set_and_oids(&minor_status, &inquire_mechs);
720
721 gss_release_name(&minor_status, &desired_name);
722
723 /* mech_type and desired_mechs are allocated above. Release it here */
724
725 FREE(mech_type->elements, mech_type->length);
726 FREE(mech_type, sizeof (gss_OID_desc));
727 }
728
729 /*ARGSUSED*/
730 static void
_gss_release_cred(argc,argv)731 _gss_release_cred(argc, argv)
732 int argc;
733 char **argv;
734 {
735 OM_UINT32 status;
736 OM_UINT32 minor_status;
737 uid_t uid;
738
739 /* set up input arguments here */
740
741 if (argc != 0) {
742 usage();
743 return;
744 }
745
746 uid = getuid();
747
748 status = kgss_release_cred(
749 &minor_status,
750 &acceptor_credentials,
751 uid);
752
753 /* store major and minor status for gss_display_status() call */
754
755 gss_major_code = status;
756 gss_minor_code = minor_status;
757
758 if (status == GSS_S_COMPLETE) {
759 printf(gettext("\nrelease succeeded\n\n"));
760 } else {
761 printf(gettext("server ret err (octal) %o (%s)\n"),
762 status, gettext("gss_release_cred error"));
763 }
764 }
765
766 static void
_gss_init_sec_context(argc,argv)767 _gss_init_sec_context(argc, argv)
768 int argc;
769 char **argv;
770 {
771
772 OM_uint32 status;
773
774 OM_uint32 minor_status;
775 gss_cred_id_t claimant_cred_handle;
776 gss_name_t target_name = (gss_name_t) 0;
777 gss_OID mech_type = (gss_OID) 0;
778 int req_flags;
779 OM_uint32 time_req;
780 gss_channel_bindings_t input_chan_bindings;
781 gss_buffer_t input_token;
782 gss_buffer_desc context_token;
783 gss_OID actual_mech_type;
784 int ret_flags;
785 OM_uint32 time_rec;
786 uid_t uid;
787 char * string;
788 gss_buffer_desc name;
789
790 /*
791 * If this is the first phase of the context establishment,
792 * clear initiator_context_handle and indicate next phase.
793 */
794
795 if (init_sec_context_phase == 0) {
796 initiator_context_handle = GSS_C_NO_CONTEXT;
797 input_token = GSS_C_NO_BUFFER;
798 init_sec_context_phase = 1;
799 } else
800 input_token = &init_token_buffer;
801
802 /*
803 * First set up the non-variable command line independent input
804 * arguments
805 */
806
807 claimant_cred_handle = GSS_C_NO_CREDENTIAL;
808
809 req_flags = GSS_C_MUTUAL_FLAG;
810 time_req = (OM_uint32) 0;
811 input_chan_bindings = GSS_C_NO_CHANNEL_BINDINGS;
812 uid = getuid();
813
814 /* Now parse the command line for the remaining input arguments */
815
816 if (argc == 0) {
817 usage();
818 return;
819 }
820
821 /*
822 * Get the name of the target.
823 */
824
825 name.length = strlen(argv[0])+1;
826 name.value = argv[0];
827
828 /*
829 * Now convert the string given by the first argument into a target
830 * name suitable for input to gss_init_sec_context()
831 */
832
833 if ((status = gss_import_name(&minor_status, &name,
834 /* GSS_C_NULL_OID, &target_name)) */
835 (gss_OID)GSS_C_NT_HOSTBASED_SERVICE, &target_name))
836 != GSS_S_COMPLETE) {
837 printf(gettext(
838 "could not parse target name: err (octal) %o (%s)\n"),
839 status,
840 gettext("gss_init_sec_context error"));
841 if (input_token != GSS_C_NO_BUFFER)
842 gss_release_buffer(&minor_status, &init_token_buffer);
843 init_sec_context_phase = 0;
844 return;
845 }
846
847 argc--;
848 argv++;
849
850 if (argc == 0) {
851 printf(gettext("Assuming Kerberos V5 as the mechanism\n"));
852 printf(gettext(
853 "The mech OID 1.2.840.113554.1.2.2 will be used\n"));
854 mech_type = gss_str2oid((char *)GSS_KRB5_MECH_OID);
855 } else {
856 mech_type = gss_str2oid(argv[0]);
857 }
858
859 if (mech_type == 0 || mech_type->length == 0) {
860 printf(gettext("improperly formated mechanism OID\n"));
861 if (input_token != GSS_C_NO_BUFFER)
862 gss_release_buffer(&minor_status, &init_token_buffer);
863 init_sec_context_phase = 0;
864 return;
865 }
866
867 /* call kgss_init_sec_context */
868
869 status = kgss_init_sec_context(&minor_status,
870 claimant_cred_handle,
871 &initiator_context_handle,
872 target_name,
873 mech_type,
874 req_flags,
875 time_req,
876 input_chan_bindings,
877 input_token,
878 &actual_mech_type,
879 &accept_token_buffer,
880 &ret_flags,
881 &time_rec,
882 uid);
883
884 /* store major and minor status for gss_display_status() call */
885 gss_major_code = status;
886 gss_minor_code = minor_status;
887
888 if (status != GSS_S_COMPLETE &&
889 status != GSS_S_CONTINUE_NEEDED) {
890
891 printf(gettext("server ret err (octal) %o (%s)\n"),
892 status, "gss_init_sec_context error");
893 init_sec_context_phase = 0;
894 if (status == GSS_S_NO_CRED)
895 printf(gettext(" : no credentials"));
896 if (input_token != GSS_C_NO_BUFFER)
897 gss_release_buffer(&minor_status, &init_token_buffer);
898 if (status != GSS_S_FAILURE && minor_status != 0xffffffff)
899 status = kgss_delete_sec_context(&minor_status,
900 &initiator_context_handle,
901 &msg_token);
902 return;
903
904 } else if (status == GSS_S_COMPLETE) {
905
906 /* process returned values */
907
908 printf(gettext("\ninit succeeded\n\n"));
909
910 /* print out the actual mechanism type */
911
912 if ((string = gss_oid2str(actual_mech_type)) == 0) {
913
914 printf(gettext(
915 "gssapi internal err : actual "
916 "mech type null\n"));
917 init_sec_context_phase = 0;
918 if (input_token != GSS_C_NO_BUFFER)
919 gss_release_buffer(&minor_status,
920 &init_token_buffer);
921 gss_release_buffer(&minor_status, &accept_token_buffer);
922 status = kgss_delete_sec_context(&minor_status,
923 &initiator_context_handle,
924 &msg_token);
925 return;
926 } else {
927 printf(gettext("actual mech type = %s\n\n"), string);
928 FREE(string, (actual_mech_type->length+1)*4+1);
929 }
930
931 /* print out value of ret_flags and time_req */
932
933 if (ret_flags & GSS_C_DELEG_FLAG)
934 printf(gettext("GSS_C_DELEG_FLAG = True\n"));
935 else
936 printf(gettext("GSS_C_DELEG_FLAG = False\n"));
937
938 if (ret_flags & GSS_C_MUTUAL_FLAG)
939 printf(gettext("GSS_C_MUTUAL_FLAG = True\n"));
940 else
941 printf(gettext("GSS_C_MUTUAL_FLAG = False\n"));
942
943 if (ret_flags & GSS_C_REPLAY_FLAG)
944 printf(gettext("GSS_C_REPLAY_FLAG = True\n"));
945 else
946 printf(gettext("GSS_C_REPLAY_FLAG = False\n"));
947
948 if (ret_flags & GSS_C_SEQUENCE_FLAG)
949 printf(gettext("GSS_C_SEQUENCE_FLAG = True\n"));
950 else
951 printf(gettext("GSS_C_SEQUENCE_FLAG = False\n"));
952
953 if (ret_flags & GSS_C_CONF_FLAG)
954 printf(gettext("GSS_C_CONF_FLAG = True\n"));
955 else
956 printf(gettext("GSS_C_CONF_FLAG = False\n"));
957
958 if (ret_flags & GSS_C_INTEG_FLAG)
959 printf(gettext("GSS_C_INTEG_FLAG = True\n\n"));
960 else
961 printf(gettext("GSS_C_INTEG_FLAG = False\n\n"));
962
963 printf(gettext("time_req = %u seconds\n\n"), time_rec);
964
965 /* free allocated memory */
966
967 FREE(mech_type->elements, mech_type->length);
968 FREE(mech_type, sizeof (gss_OID_desc));
969
970 /* these two were malloc'd by kgss_init_sec_context() */
971
972 FREE(actual_mech_type->elements, actual_mech_type->length);
973 FREE(actual_mech_type, sizeof (gss_OID_desc));
974
975 gss_release_name(&minor_status, &target_name);
976
977 if (input_token != GSS_C_NO_BUFFER)
978 gss_release_buffer(&minor_status, &init_token_buffer);
979
980 /*
981 * if status == GSS_S_COMPLETE, reset the phase to 0 and
982 * release token in accept_token_buffer
983 */
984
985 init_sec_context_phase = 0;
986 /* Save and restore the context */
987 status = kgss_export_sec_context(&minor_status,
988 &initiator_context_handle,
989 &context_token);
990 if (status != GSS_S_COMPLETE) {
991 printf(gettext("server ret err (octal) %o (%s)\n"),
992 status, gettext("gss_export_sec_context_error"));
993 return;
994 }
995 status = kgss_import_sec_context(&minor_status,
996 &context_token,
997 &initiator_context_handle);
998 if (status != GSS_S_COMPLETE) {
999 printf(gettext("server ret err (octal) %o (%s)\n"),
1000 status, gettext("gss_import_sec_context_error"));
1001 return;
1002 }
1003 (void) gss_release_buffer(&minor_status, &context_token);
1004
1005 /* gss_export & gss_import secxc_context worked, return */
1006 printf(gettext("\nexport and import of contexts succeeded\n"));
1007 printf(gettext("\ninit completed"));
1008
1009 } else {
1010 printf(gettext("\nfirst phase of init succeeded"));
1011 printf(gettext("\ninit must be called again\n\n"));
1012 }
1013
1014 }
1015
1016 /*ARGSUSED*/
1017 static void
_gss_accept_sec_context(argc,argv)1018 _gss_accept_sec_context(argc, argv)
1019 int argc;
1020 char **argv;
1021 {
1022 OM_UINT32 status;
1023
1024 OM_uint32 minor_status;
1025 gss_channel_bindings_t input_chan_bindings;
1026 gss_OID mech_type;
1027 int ret_flags;
1028 OM_uint32 time_rec;
1029 gss_cred_id_t delegated_cred_handle;
1030 uid_t uid;
1031 char *string;
1032 gss_buffer_desc src_name, src_name_string;
1033 gss_buffer_desc output_token;
1034 gss_name_t gss_name;
1035 gss_buffer_desc context_token;
1036
1037 /*
1038 * If this is the first phase of the context establishment,
1039 * clear acceptor_context_handle and indicate next phase.
1040 */
1041
1042 if (accept_sec_context_phase == 0) {
1043 acceptor_context_handle = GSS_C_NO_CONTEXT;
1044 accept_sec_context_phase = 1;
1045 }
1046
1047 /* Now set up the other command line independent input arguments */
1048
1049 input_chan_bindings = GSS_C_NO_CHANNEL_BINDINGS;
1050
1051 uid = (uid_t) getuid();
1052
1053 if (argc != 0) {
1054 usage();
1055 return;
1056 }
1057
1058 status = kgss_accept_sec_context(&minor_status,
1059 &acceptor_context_handle,
1060 acceptor_credentials,
1061 &accept_token_buffer,
1062 input_chan_bindings,
1063 &src_name,
1064 &mech_type,
1065 &init_token_buffer,
1066 &ret_flags,
1067 &time_rec,
1068 &delegated_cred_handle,
1069 uid);
1070
1071 /* store major and minor status for gss_display_status() call */
1072
1073 gss_major_code = status;
1074 gss_minor_code = minor_status;
1075
1076 if (status != GSS_S_COMPLETE && status != GSS_S_CONTINUE_NEEDED) {
1077 printf(gettext("server ret err (octal) %o (%s)\n"),
1078 status, gettext("gss_accept_sec_context error"));
1079 gss_release_buffer(&minor_status, &accept_token_buffer);
1080 return;
1081 } else if (status == GSS_S_COMPLETE) {
1082
1083 /* process returned values */
1084
1085 printf(gettext("\naccept succeeded\n\n"));
1086
1087 /*
1088 * convert the exported name returned in src_name into
1089 * a string and print it.
1090 */
1091 if ((status = gss_import_name(&minor_status, &src_name,
1092 (gss_OID) GSS_C_NT_EXPORT_NAME, &gss_name))
1093 != GSS_S_COMPLETE) {
1094 printf(gettext(
1095 "could not import src name 0x%x\n"), status);
1096 accept_sec_context_phase = 0;
1097 status = kgss_delete_sec_context(&minor_status,
1098 &acceptor_context_handle,
1099 &output_token);
1100 gss_release_buffer(&minor_status, &accept_token_buffer);
1101 if (status == GSS_S_CONTINUE_NEEDED)
1102 gss_release_buffer(&minor_status,
1103 &init_token_buffer);
1104 gss_release_buffer(&minor_status, &src_name);
1105 return;
1106 }
1107
1108 memset(&src_name_string, 0, sizeof (src_name_string));
1109 if ((status = gss_display_name(&minor_status, gss_name,
1110 &src_name_string, NULL)) != GSS_S_COMPLETE) {
1111 printf(gettext("could not display src name: "
1112 "err (octal) %o (%s)\n"), status,
1113 "gss_init_sec_context error");
1114 accept_sec_context_phase = 0;
1115 status = kgss_delete_sec_context(&minor_status,
1116 &acceptor_context_handle,
1117 &output_token);
1118 gss_release_buffer(&minor_status, &accept_token_buffer);
1119 if (status == GSS_S_CONTINUE_NEEDED)
1120 gss_release_buffer(&minor_status,
1121 &init_token_buffer);
1122 gss_release_buffer(&minor_status, &src_name);
1123 return;
1124 }
1125 printf(gettext("src name = %s\n"), src_name_string.value);
1126 gss_release_name(&minor_status, &gss_name);
1127 gss_release_buffer(&minor_status, &src_name_string);
1128 gss_release_buffer(&minor_status, &src_name);
1129
1130 /* print out the mechanism type */
1131
1132 if ((string = gss_oid2str(mech_type)) == 0) {
1133
1134 printf(gettext(
1135 "gssapi internal err :"
1136 " actual mech type null\n"));
1137 accept_sec_context_phase = 0;
1138 status = kgss_delete_sec_context(&minor_status,
1139 &acceptor_context_handle,
1140 &output_token);
1141 gss_release_buffer(&minor_status, &accept_token_buffer);
1142 if (status == GSS_S_CONTINUE_NEEDED)
1143 gss_release_buffer(&minor_status,
1144 &init_token_buffer);
1145 return;
1146 } else {
1147
1148 printf(gettext("actual mech type = %s\n\n"), string);
1149 FREE(string, (mech_type->length+1)*4+1);
1150 }
1151
1152 /* Save and restore the context */
1153 status = kgss_export_sec_context(&minor_status,
1154 &initiator_context_handle,
1155 &context_token);
1156 if (status != GSS_S_COMPLETE) {
1157 printf(gettext("server ret err (octal) %o (%s)\n"),
1158 status, gettext("gss_export_sec_context_error"));
1159 return;
1160 }
1161 status = kgss_import_sec_context(&minor_status,
1162 &context_token,
1163 &initiator_context_handle);
1164 if (status != GSS_S_COMPLETE) {
1165 printf(gettext("server ret err (octal) %o (%s)\n"),
1166 status, gettext("gss_import_sec_context_error"));
1167 return;
1168 }
1169 (void) gss_release_buffer(&minor_status, &context_token);
1170
1171 /* gss_export & gss_import secxc_context worked, return */
1172
1173 /* print out value of ret_flags and time_req */
1174
1175 if (ret_flags & GSS_C_DELEG_FLAG)
1176 printf(gettext("GSS_C_DELEG_FLAG = True\n"));
1177 else
1178 printf(gettext("GSS_C_DELEG_FLAG = False\n"));
1179
1180 if (ret_flags & GSS_C_MUTUAL_FLAG)
1181 printf(gettext("GSS_C_MUTUAL_FLAG = True\n"));
1182 else
1183 printf(gettext("GSS_C_MUTUAL_FLAG = False\n"));
1184
1185 if (ret_flags & GSS_C_REPLAY_FLAG)
1186 printf(gettext("GSS_C_REPLAY_FLAG = True\n"));
1187 else
1188 printf(gettext("GSS_C_REPLAY_FLAG = False\n"));
1189
1190 if (ret_flags & GSS_C_SEQUENCE_FLAG)
1191 printf(gettext("GSS_C_SEQUENCE_FLAG = True\n"));
1192 else
1193 printf(gettext("GSS_C_SEQUENCE_FLAG = False\n"));
1194
1195 if (ret_flags & GSS_C_CONF_FLAG)
1196 printf(gettext("GSS_C_CONF_FLAG = True\n"));
1197 else
1198 printf(gettext("GSS_C_CONF_FLAG = False\n"));
1199
1200 if (ret_flags & GSS_C_INTEG_FLAG)
1201 printf(gettext("GSS_C_INTEG_FLAG = True\n\n"));
1202 else
1203 printf(gettext("GSS_C_INTEG_FLAG = False\n\n"));
1204
1205 printf(gettext("time_rec = %d seconds\n\n"), time_rec);
1206
1207 /* free allocated memory */
1208
1209 printf(gettext("\nexport and import of contexts succeeded\n"));
1210
1211 FREE(mech_type->elements, mech_type->length);
1212 FREE(mech_type, sizeof (gss_OID_desc));
1213 } else {
1214 printf(gettext("\nfirst phase of accept succeeded"));
1215 printf(gettext("\naccept must be called again\n\n"));
1216 }
1217
1218
1219 /* free the input token in accept_token_buffer */
1220 gss_release_buffer(&minor_status, &accept_token_buffer);
1221
1222 /* if status == GSS_S_COMPLETE, reset the phase to 0 */
1223
1224 if (status == GSS_S_COMPLETE)
1225 accept_sec_context_phase = 0;
1226
1227 /* gss_accept_sec_context worked, return */
1228 }
1229
1230 void
_gss_process_context_token(argc,argv)1231 _gss_process_context_token(argc, argv)
1232 int argc;
1233 char **argv;
1234 {
1235 OM_UINT32 status;
1236
1237 gss_ctx_id_t context_handle;
1238 OM_uint32 minor_status;
1239 uid_t uid;
1240
1241 uid = (uid_t) getuid();
1242
1243 /* parse the command line to determine the variable input argument */
1244
1245 if (argc == 0) {
1246 usage();
1247 return;
1248 }
1249
1250 if (strcmp(argv[0], "initiator") == 0)
1251 context_handle = initiator_context_handle;
1252 else if (strcmp(argv[0], "acceptor") == 0)
1253 context_handle = acceptor_context_handle;
1254 else {
1255 printf(gettext(
1256 "must specify either \"initiator\" or \"acceptor\"\n"));
1257 return;
1258 }
1259
1260 argc--;
1261 argv++;
1262
1263 if (argc != 0) {
1264 usage();
1265 return;
1266 }
1267
1268 status = kgss_process_context_token(&minor_status,
1269 context_handle,
1270 delete_token_buffer,
1271 uid);
1272
1273 /* store major and minor status for gss_display_status() call */
1274
1275 gss_major_code = status;
1276 gss_minor_code = minor_status;
1277
1278 if (status != GSS_S_COMPLETE) {
1279 printf(gettext("server ret err (octal) %o (%s)\n"),
1280 status, gettext("gss_process_context_token error"));
1281 return;
1282
1283 } else {
1284 printf(gettext("\nprocess succeeded\n\n"));
1285 return;
1286 }
1287 }
1288
1289 static void
_gss_delete_sec_context(argc,argv)1290 _gss_delete_sec_context(argc, argv)
1291 int argc;
1292 char **argv;
1293 {
1294 OM_UINT32 status;
1295 gss_ctx_id_t *context_handle;
1296 OM_uint32 minor_status;
1297 uid_t uid;
1298
1299 uid = (uid_t) getuid();
1300
1301 /* parse the command line to determine the variable input argument */
1302
1303 if (argc == 0) {
1304 usage();
1305 return;
1306 }
1307
1308 if (strcmp(argv[0], "initiator") == 0) {
1309 context_handle = &initiator_context_handle;
1310 } else if (strcmp(argv[0], "acceptor") == 0) {
1311 context_handle = &acceptor_context_handle;
1312 } else {
1313 printf(gettext(
1314 "must specify either \"initiator\" or \"acceptor\"\n"));
1315 return;
1316 }
1317
1318 argc--;
1319 argv++;
1320
1321 if (argc != 0) {
1322 usage();
1323 return;
1324 }
1325
1326
1327 status = kgss_delete_sec_context(&minor_status,
1328 context_handle,
1329 &delete_token_buffer);
1330
1331
1332 /* store major and minor status for gss_display_status() call */
1333
1334 gss_major_code = status;
1335 gss_minor_code = minor_status;
1336
1337 if (status != GSS_S_COMPLETE) {
1338
1339 printf(gettext("server ret err (octal) %o (%s)\n"),
1340 status, gettext("gss_delete_sec_context error"));
1341 return;
1342
1343 } else {
1344 printf(gettext("\ndelete succeeded\n\n"));
1345 return;
1346 }
1347 }
1348
1349 /*ARGSUSED*/
1350 static void
_gss_context_time(argc,argv)1351 _gss_context_time(argc, argv)
1352 int argc;
1353 char **argv;
1354 {
1355 /*
1356 * set up input arguments here
1357 * this function is unimplemented. Call usage() and return
1358 */
1359
1360 printf(gettext("\nunimplemented function"));
1361 }
1362
1363 static void
_gss_sign(argc,argv)1364 _gss_sign(argc, argv)
1365 int argc;
1366 char **argv;
1367 {
1368 OM_UINT32 status;
1369 OM_uint32 minor_status;
1370 gss_ctx_id_t context_handle;
1371 int qop_req;
1372 uid_t uid;
1373
1374 uid = (uid_t) getuid();
1375
1376 /* specify the default quality of protection */
1377
1378 qop_req = GSS_C_QOP_DEFAULT;
1379
1380 /* set up the arguments specified in the input parameters */
1381
1382 if (argc == 0) {
1383 usage();
1384 return;
1385 }
1386
1387
1388 if (strcmp(argv[0], "initiator") == 0)
1389 context_handle = initiator_context_handle;
1390 else if (strcmp(argv[0], "acceptor") == 0)
1391 context_handle = acceptor_context_handle;
1392 else {
1393 printf(gettext(
1394 "must specify either \"initiator\" or \"acceptor\"\n"));
1395 return;
1396 }
1397
1398 argc--;
1399 argv++;
1400
1401 if (argc == 0) {
1402 usage();
1403 return;
1404 }
1405
1406 message_buffer.length = strlen(argv[0])+1;
1407 message_buffer.value = (void *) MALLOC(message_buffer.length);
1408 strcpy(message_buffer.value, argv[0]);
1409
1410 argc--;
1411 argv++;
1412
1413 if (argc != 0) {
1414 usage();
1415 return;
1416 }
1417
1418 status = kgss_sign(&minor_status,
1419 context_handle,
1420 qop_req,
1421 &message_buffer,
1422 &msg_token,
1423 uid);
1424
1425 /* store major and minor status for gss_display_status() call */
1426
1427 gss_major_code = status;
1428 gss_minor_code = minor_status;
1429
1430 if (status != GSS_S_COMPLETE) {
1431 printf(gettext("server ret err (octal) %o (%s)\n"),
1432 status, gettext("gss_sign error"));
1433 return;
1434
1435 } else {
1436 printf(gettext("\nsign succeeded\n\n"));
1437 return;
1438 }
1439 }
1440
1441 static void
_gss_verify(argc,argv)1442 _gss_verify(argc, argv)
1443 int argc;
1444 char **argv;
1445 {
1446 OM_UINT32 status, minor_status;
1447 gss_ctx_id_t context_handle;
1448 int qop_state;
1449 uid_t uid;
1450
1451 uid = (uid_t) getuid();
1452
1453 /* set up the arguments specified in the input parameters */
1454
1455 if (argc == 0) {
1456 usage();
1457 return;
1458 }
1459
1460
1461 if (strcmp(argv[0], "initiator") == 0)
1462 context_handle = initiator_context_handle;
1463 else if (strcmp(argv[0], "acceptor") == 0)
1464 context_handle = acceptor_context_handle;
1465 else {
1466 printf(gettext(
1467 "must specify either \"initiator\" or \"acceptor\"\n"));
1468 return;
1469 }
1470
1471 argc--;
1472 argv++;
1473
1474 if (argc != 0) {
1475 usage();
1476 return;
1477 }
1478
1479 status = kgss_verify(&minor_status,
1480 context_handle,
1481 &message_buffer,
1482 &msg_token,
1483 &qop_state,
1484 uid);
1485
1486 /* store major and minor status for gss_display_status() call */
1487
1488 gss_major_code = status;
1489 gss_minor_code = minor_status;
1490
1491 if (status != GSS_S_COMPLETE) {
1492 printf(gettext("server ret err (octal) %o (%s)\n"),
1493 status, gettext("gss_verify error"));
1494 return;
1495 } else {
1496
1497 /* print out the verified message */
1498
1499 printf(gettext(
1500 "verified message = \"%s\"\n\n"), message_buffer.value);
1501
1502 /* print out the quality of protection returned */
1503
1504 printf(gettext("quality of protection = %d \n\n"), qop_state);
1505
1506 /* free the message buffer and message token and return */
1507
1508 gss_release_buffer(&minor_status, &message_buffer);
1509 gss_release_buffer(&minor_status, &msg_token);
1510
1511 return;
1512 }
1513 }
1514
1515 static void
_gss_seal(argc,argv)1516 _gss_seal(argc, argv)
1517 int argc;
1518 char **argv;
1519 {
1520 OM_UINT32 status;
1521
1522 OM_uint32 minor_status;
1523 gss_ctx_id_t context_handle;
1524 int conf_req_flag;
1525 int qop_req;
1526 gss_buffer_desc input_message_buffer;
1527 int conf_state;
1528 uid_t uid;
1529
1530 uid = (uid_t) getuid();
1531
1532 /*
1533 * specify the default confidentiality requested (both integrity
1534 * and confidentiality) and quality of protection
1535 */
1536
1537 conf_req_flag = 1;
1538 qop_req = GSS_C_QOP_DEFAULT;
1539
1540 /* set up the arguments specified in the input parameters */
1541
1542 if (argc == 0) {
1543 usage();
1544 return;
1545 }
1546
1547
1548 if (strcmp(argv[0], "initiator") == 0)
1549 context_handle = initiator_context_handle;
1550 else if (strcmp(argv[0], "acceptor") == 0)
1551 context_handle = acceptor_context_handle;
1552 else {
1553 printf(gettext(
1554 "must specify either \"initiator\" or \"acceptor\"\n"));
1555 return;
1556 }
1557
1558 argc--;
1559 argv++;
1560
1561 if (argc == 0) {
1562 usage();
1563 return;
1564 }
1565
1566
1567 input_message_buffer.length = strlen(argv[0])+1;
1568 input_message_buffer.value =
1569 (void *) MALLOC(input_message_buffer.length);
1570 strcpy(input_message_buffer.value, argv[0]);
1571
1572 argc--;
1573 argv++;
1574
1575 if (argc != 0) {
1576 usage();
1577 return;
1578 }
1579
1580 status = kgss_seal(&minor_status,
1581 context_handle,
1582 conf_req_flag,
1583 qop_req,
1584 &input_message_buffer,
1585 &conf_state,
1586 &message_buffer,
1587 uid);
1588
1589 /* store major and minor status for gss_display_status() call */
1590
1591 gss_major_code = status;
1592 gss_minor_code = minor_status;
1593
1594 /* free the inputmessage buffer */
1595
1596 gss_release_buffer(&minor_status, &input_message_buffer);
1597
1598 if (status != GSS_S_COMPLETE) {
1599 printf(gettext("server ret err (octal) %o (%s)\n"),
1600 status, gettext("gss_seal error"));
1601 return;
1602 } else {
1603 printf(gettext("\nseal succeeded\n\n"));
1604 return;
1605 }
1606 }
1607
1608 static void
_gss_unseal(argc,argv)1609 _gss_unseal(argc, argv)
1610 int argc;
1611 char **argv;
1612 {
1613 OM_UINT32 status;
1614
1615 OM_uint32 minor_status;
1616 gss_ctx_id_t context_handle;
1617 gss_buffer_desc output_message_buffer;
1618 int conf_state;
1619 int qop_state;
1620 uid_t uid;
1621
1622 uid = (uid_t) getuid();
1623
1624 /* set up the arguments specified in the input parameters */
1625
1626 if (argc == 0) {
1627 usage();
1628 return;
1629 }
1630
1631
1632 if (strcmp(argv[0], "initiator") == 0)
1633 context_handle = initiator_context_handle;
1634 else if (strcmp(argv[0], "acceptor") == 0)
1635 context_handle = acceptor_context_handle;
1636 else {
1637 printf(gettext(
1638 "must specify either \"initiator\" or \"acceptor\"\n"));
1639 return;
1640 }
1641
1642 argc--;
1643 argv++;
1644
1645 if (argc != 0) {
1646 usage();
1647 return;
1648 }
1649
1650 status = kgss_unseal(&minor_status,
1651 context_handle,
1652 &message_buffer,
1653 &output_message_buffer,
1654 &conf_state,
1655 &qop_state,
1656 uid);
1657
1658 /* store major and minor status for gss_display_status() call */
1659
1660 gss_major_code = status;
1661 gss_minor_code = minor_status;
1662
1663 if (status == GSS_S_COMPLETE) {
1664 printf(gettext("\nunseal succeeded\n\n"));
1665 printf(gettext("unsealed message = \"%s\"\n\n"),
1666 output_message_buffer.value);
1667 if (conf_state)
1668 printf(gettext("confidentiality and integrity used\n"));
1669 else
1670 printf(gettext("only integrity used\n"));
1671 printf(gettext("quality of protection = %d\n\n"), qop_state);
1672 gss_release_buffer(&minor_status, &output_message_buffer);
1673 } else {
1674 printf(gettext("server ret err (octal) %o (%s)\n"),
1675 status, gettext("gss_unseal error"));
1676 }
1677
1678 /* free the message buffer and return */
1679
1680 gss_release_buffer(&minor_status, &message_buffer);
1681 }
1682
1683 static void
_gss_display_status(argc,argv)1684 _gss_display_status(argc, argv)
1685 int argc;
1686 char **argv;
1687 {
1688 OM_UINT32 status;
1689 OM_uint32 minor_status;
1690 int status_type;
1691 int status_value;
1692 gss_OID mech_type = (gss_OID) 0;
1693 int message_context;
1694 gss_buffer_desc status_string;
1695 uid_t uid;
1696
1697 uid = (uid_t) getuid();
1698
1699 /* initialize message context to zero */
1700
1701 message_context = 0;
1702
1703 if (argc == 0) {
1704 printf(gettext("Assuming Kerberos V5 as the mechanism\n"));
1705 printf(gettext(
1706 "The mech OID 1.2.840.113554.1.2.2 will be used\n"));
1707 mech_type = gss_str2oid((char *)GSS_KRB5_MECH_OID);
1708 } else
1709 mech_type = gss_str2oid(argv[0]);
1710
1711 if (mech_type == 0 || mech_type->length == 0) {
1712 printf(gettext("improperly formated mechanism OID\n"));
1713 return;
1714 }
1715
1716 /* Is this call for the major or minor status? */
1717
1718 if (strcmp(argv[0], "major") == 0) {
1719 status_type = GSS_C_GSS_CODE;
1720 status_value = gss_major_code;
1721 } else if (strcmp(argv[0], "minor") == 0) {
1722 status_type = GSS_C_MECH_CODE;
1723 status_value = gss_minor_code;
1724 } else {
1725 printf(gettext("must specify either \"major\" or \"minor\"\n"));
1726 return;
1727 }
1728
1729 argc--;
1730 argv++;
1731
1732 if (argc != 0) {
1733 usage();
1734 return;
1735 }
1736
1737 status = kgss_display_status(&minor_status,
1738 status_value,
1739 status_type,
1740 mech_type,
1741 &message_context,
1742 &status_string,
1743 uid);
1744
1745 if (status == GSS_S_COMPLETE) {
1746 printf(gettext("status =\n %s\n\n"), status_string.value);
1747 } else if (status == GSS_S_BAD_MECH) {
1748 printf(gettext("invalide mechanism OID\n\n"));
1749 } else {
1750 printf(gettext("server ret err (octal) %o (%s)\n"),
1751 status, gettext("gss_display_status error"));
1752 }
1753 }
1754
1755 /*ARGSUSED*/
1756 static void
_gss_indicate_mechs(argc,argv)1757 _gss_indicate_mechs(argc, argv)
1758 int argc;
1759 char **argv;
1760 {
1761 OM_UINT32 status;
1762 OM_UINT32 minor_status;
1763 gss_OID_set oid_set = GSS_C_NULL_OID_SET;
1764 uid_t uid;
1765
1766 uid = (uid_t) getuid();
1767
1768 /* set up input arguments here */
1769
1770 if (argc != 0) {
1771 usage();
1772 return;
1773 }
1774
1775 status = kgss_indicate_mechs(&minor_status, &oid_set, uid);
1776
1777 if (status == GSS_S_COMPLETE) {
1778 int i;
1779 char *string;
1780
1781 printf(gettext("%d supported mechanism%s%s\n"), oid_set->count,
1782 (oid_set->count == 1) ? "" : "s",
1783 (oid_set->count > 0) ? ":" : "");
1784
1785 for (i = 0; i < oid_set->count; i++) {
1786 string = gss_oid2str(&oid_set->elements[i]);
1787 printf(gettext("\t%s\n"), string);
1788 FREE(string, ((oid_set->elements[i].length+1)*4)+1);
1789 }
1790 printf("\n");
1791
1792 } else {
1793 printf(gettext("server ret err (octal) %o (%s)\n"),
1794 status, gettext("gss_indicate_mechs error"));
1795 }
1796
1797 if (oid_set)
1798 gss_release_oid_set_and_oids(&minor_status, &oid_set);
1799 }
1800
1801 /*ARGSUSED*/
1802 static void
_gss_inquire_cred(argc,argv)1803 _gss_inquire_cred(argc, argv)
1804 int argc;
1805 char **argv;
1806 {
1807 /* set up input arguments here */
1808
1809 if (argc != 0) {
1810 usage();
1811 return;
1812 }
1813
1814
1815 /* this function is unimplemented. Call usage() and return */
1816
1817 printf(gettext("\nUnsupported function"));
1818 }
1819
1820 static char hexChars[] = "0123456789ABCDEF";
1821
1822 static void
_gssd_expname_to_unix_cred(argc,argv)1823 _gssd_expname_to_unix_cred(argc, argv)
1824 int argc;
1825 char **argv;
1826 {
1827 OM_uint32 major;
1828 gss_buffer_desc expName;
1829 char krb5_root_name[] = "040100092A864886F712010202000000"
1830 "25000A2A864886F71201020101726F6F744053554E534F46"
1831 "542E454E472E53554E2E434F4D00";
1832 unsigned char *byteStr, *hexStr;
1833 uid_t uidOut, uidIn;
1834 gid_t *gids, gidOut;
1835 int gidsLen, i, newLen;
1836
1837 /* set up the arguments */
1838 uidIn = (uid_t) getuid();
1839
1840 if (argc < 1) {
1841 printf(gettext(
1842 "Using principal name of root for krberos_v5\n"));
1843 expName.value = (void*)krb5_root_name;
1844 expName.length = strlen(krb5_root_name);
1845 } else {
1846 expName.value = (void*)argv[0];
1847 expName.length = strlen(argv[0]);
1848 }
1849
1850 /* convert the name from hex to byte... */
1851 hexStr = (unsigned char *)expName.value;
1852 newLen = expName.length/2;
1853 byteStr = (unsigned char *)MALLOC(newLen+1);
1854 expName.value = (char *)byteStr;
1855 for (i = 0; i < expName.length; i += 2) {
1856 *byteStr = (strchr(hexChars, *hexStr++) - hexChars) << 4;
1857 *byteStr += (strchr(hexChars, *hexStr++) - hexChars);
1858 byteStr++;
1859 }
1860 expName.length = newLen;
1861
1862 major = kgsscred_expname_to_unix_cred(&expName, &uidOut, &gidOut,
1863 &gids, &gidsLen, uidIn);
1864
1865 FREE(expName.value, newLen);
1866
1867 if (major == GSS_S_COMPLETE) {
1868 printf(gettext("uid = <%d>\tgid = <%d>\t"), uidOut, gidOut);
1869 if (gidsLen > 0)
1870 printf(gettext(" %d gids <"), gidsLen);
1871 else
1872 printf(gettext(
1873 " no supplementary group information\n"));
1874 for (i = 0; i < gidsLen; i++)
1875 printf(" %d ", gids[i]);
1876 if (gidsLen > 0) {
1877 printf(">\n");
1878 FREE(gids, gidsLen * sizeof (gid_t));
1879 }
1880 } else {
1881 printf(gettext("server ret err (octal) %o (%s)\n"),
1882 major, gettext("gsscred_expname_to_unix_cred"));
1883 }
1884 }
1885
1886 static void
_gssd_name_to_unix_cred(argc,argv)1887 _gssd_name_to_unix_cred(argc, argv)
1888 int argc;
1889 char **argv;
1890 {
1891 OM_uint32 major, minor;
1892 gss_name_t gssName;
1893 gss_buffer_desc gssBuf = GSS_C_EMPTY_BUFFER;
1894 int gidsLen, i;
1895 gid_t *gids, gidOut;
1896 uid_t uidOut, uid;
1897 char defaultPrincipal[] = "root";
1898 gss_OID mechType, nameType;
1899
1900 uid = getuid();
1901
1902 /* optional argument 1 - contains principal name */
1903 if (argc > 0) {
1904 gssBuf.value = (void *)argv[0];
1905 gssBuf.length = strlen((char *)argv[0]);
1906 } else {
1907 gssBuf.value = (void *)defaultPrincipal;
1908 gssBuf.length = strlen(defaultPrincipal);
1909 }
1910 printf(gettext(
1911 "Using <%s> as the principal name.\n"), (char *)gssBuf.value);
1912
1913
1914 /* optional argument 2 - contains name oid */
1915 if (argc > 1)
1916 nameType = gss_str2oid((char *) argv[1]);
1917 else
1918 nameType = (gss_OID)GSS_C_NT_USER_NAME;
1919
1920 if (nameType == NULL || nameType->length == 0) {
1921 printf(gettext("improperly formated name OID\n"));
1922 return;
1923 }
1924 printf(gettext("Principal name of type: <%s>.\n"),
1925 (argc > 1) ? argv[1] : "GSS_C_NT_USER_NAME");
1926
1927
1928 /* optional argument 3 - contains mech oid */
1929 if (argc > 2)
1930 mechType = gss_str2oid(argv[2]);
1931 else
1932 mechType = gss_str2oid((char *)GSS_KRB5_MECH_OID);
1933
1934 if (mechType == NULL || mechType->length == NULL) {
1935 FREE(nameType->elements, nameType->length);
1936 FREE(nameType, sizeof (gss_OID_desc));
1937 printf(gettext("improperly formated mech OID\n"));
1938 return;
1939 }
1940 printf(gettext("Mechanism oid: <%s>.\n"),
1941 (argc > 2) ? argv[2] :
1942 (char *)GSS_KRB5_MECH_OID "(Kerberos v5)");
1943
1944
1945 /* convert the name to internal format */
1946 if ((major = gss_import_name(&minor, &gssBuf,
1947 nameType, &gssName)) != GSS_S_COMPLETE) {
1948 printf(gettext("could not parse name: err (octal) %o (%s)\n"),
1949 major, "gss_import_name");
1950
1951 FREE(nameType->elements, nameType->length);
1952 FREE(nameType, sizeof (gss_OID_desc));
1953 return;
1954 }
1955
1956 major = kgsscred_name_to_unix_cred(gssName, mechType, &uidOut,
1957 &gidOut, &gids, &gidsLen, uid);
1958
1959 gss_release_name(&minor, &gssName);
1960 FREE(mechType->elements, mechType->length);
1961 FREE(mechType, sizeof (gss_OID_desc));
1962 if (argc > 1) {
1963 FREE(nameType->elements, nameType->length);
1964 FREE(nameType, sizeof (gss_OID_desc));
1965 }
1966
1967 if (major == GSS_S_COMPLETE) {
1968 printf("uid = <%d>\tgid = <%d>\t", uidOut, gidOut);
1969 if (gidsLen > 0)
1970 printf(gettext(" %d gids <"), gidsLen);
1971 else
1972 printf(gettext(
1973 " no supplementary group information\n"));
1974 for (i = 0; i < gidsLen; i++)
1975 printf(" %d ", gids[i]);
1976 if (gidsLen > 0) {
1977 printf(">\n");
1978 FREE(gids, gidsLen * sizeof (gid_t));
1979 }
1980 } else {
1981 printf(gettext("server ret err (octal) %o (%s)\n"),
1982 major, gettext("gsscred_name_to_unix_cred"));
1983 }
1984 }
1985
1986 static void
_gssd_get_group_info(argc,argv)1987 _gssd_get_group_info(argc, argv)
1988 int argc;
1989 char **argv;
1990 {
1991 OM_uint32 major;
1992 uid_t puid, uidIn;
1993 gid_t *gids, gidOut;
1994 int gidsLen, i;
1995
1996 /* set up the arguments */
1997 uidIn = (uid_t) getuid();
1998
1999 if (argc < 1)
2000 puid = 0;
2001 else
2002 puid = atol(argv[0]);
2003
2004 printf(gettext("Retrieving group info for uid of <%d>\n"), puid);
2005
2006 major = kgss_get_group_info(puid, &gidOut, &gids, &gidsLen, uidIn);
2007
2008 if (major == GSS_S_COMPLETE) {
2009 printf(gettext("group id = <%d>\t"), gidOut);
2010 if (gidsLen > 0)
2011 printf(gettext(" %d gids <"), gidsLen);
2012 else
2013 printf(gettext(
2014 " no supplementary group information\n"));
2015 for (i = 0; i < gidsLen; i++)
2016 printf(" %d ", gids[i]);
2017 if (gidsLen > 0) {
2018 printf(">\n");
2019 FREE(gids, gidsLen * sizeof (gid_t));
2020 }
2021 } else {
2022 printf(gettext("server ret err (octal) %o (%s)\n"),
2023 major, "gss_get_group_info");
2024 }
2025 }
2026
2027 static gss_OID
gss_str2oid(string)2028 gss_str2oid(string)
2029 char * string;
2030 {
2031 /*
2032 * a convenient wrapper routine for gss_str_to_oid
2033 * this can handle all valid oid strings.
2034 */
2035 OM_uint32 minor;
2036 gss_buffer_desc abuf;
2037 gss_OID oidOut;
2038
2039 abuf.value = (void*)string;
2040 abuf.length = strlen(string);
2041
2042 if (gss_str_to_oid(&minor, &abuf, &oidOut) != GSS_S_COMPLETE)
2043 return (NULL);
2044
2045 return (oidOut);
2046 }
2047
2048 static char *
gss_oid2str(oid)2049 gss_oid2str(oid)
2050 gss_OID oid;
2051 {
2052 /*
2053 * a convenient wrapper for gss_oid_to_str
2054 * this calls the GSS-API routine which should
2055 * be able to handle all types of oids.
2056 */
2057 OM_uint32 minor;
2058 gss_buffer_desc oidStr;
2059
2060 if (gss_oid_to_str(&minor, oid, &oidStr) != GSS_S_COMPLETE)
2061 return (NULL);
2062
2063 return ((char *)oidStr.value);
2064 } /* gss_oid2str */
2065
2066 static void
instructs()2067 instructs()
2068 {
2069 fprintf(stderr,
2070 gettext(
2071 "\nThis program must be run as root. Root must be installed on the KDC\n"
2072 "and exist in srvtab as root/<hostname>, where <hostname> is the machine on\n"
2073 "which the test runs. Before running gssdtest for Kerberos mechanism, the\n"
2074 "operator running as root must kinit as some other principal, e.g., test.\n"
2075 "There are two mechanisms avaialble: dummy and Kerberos(default).\n"
2076 "The OID for dummy mechanism is 1.3.6.1.4.1.42.2.26.1.2.\n"
2077 "The OID for Kerberos mechanism is 1.2.840.113554.1.2.2.\n"
2078 "The order of context establishment calls is important. First, acquire must"
2079 "\nbe called. This obtains the credentials used by accept. Acquire need\n"
2080 "only be called once, since the credentials it returns are used each time\n"
2081 "accept is called. Then init is called, followed by accept. Calling init\n"
2082 "twice without calling accept or calling these in a different order gives\n"
2083 "erroneous results and will cause memory leaks in the gssapi daemon. \n"
2084 "Finally, after calling init and accept, init must be called again to\n"
2085 "finish context establishment. So an example sequence (with data valid for\n"
2086 "the Kerberos mechanism and running on the machine \"elrond\" in the realm\n"
2087 "FOO.BAR.SUN.COM is :\n"));
2088 fprintf(stderr,
2089 gettext("\nacquire service@host 1.2.840.113554.1.2.2\n"
2090 "init service@host 1.2.840.113554.1.2.2\n"
2091 "accept\ninit service@host 1.2.840.113554.1.2.2\n"
2092 "\nAfter a context is established, sign, seal,\n"
2093 "verify and unseal may be called. Here are some examples\n"
2094 "for these routines : \n\n"
2095 "sign initiator ThisTestMessageIsForSigning\n"
2096 "verify acceptor\nseal initiator ThisTestMessageIsForSealing\n"
2097 "unseal acceptor\n\nEach input line is terminated by <cr>.\n"
2098 "The program is terminated by cntl-d\nor the command \"exit\""
2099 "\nfrom the prompt\n\n"));
2100 }
2101
2102 static void
usage()2103 usage()
2104 {
2105 fprintf(stderr,
2106 gettext(
2107 "\nusage:\t[acquire | gss_acquire_cred]"
2108 "desired_name mech_type\n"
2109 "\t[release | gss_release_cred]\n"
2110 "\t[init | gss_init_sec_context] target_name mech_type\n"
2111 "\t[accept | gss_accept_sec_context]\n"
2112 "\t[process | gss_process_context_token] initiator | acceptor\n"
2113 "\t[delete | gss_delete_sec_context] initiator | acceptor\n"
2114 "\t[time | gss_context_time] {not yet implemented}\n"
2115 "\t[sign | gss_sign] initiator | acceptor message-to-sign\n"
2116 "\t[verify | gss_verify] initiator | acceptor\n"
2117 "\t[seal | gss_seal] initiator | acceptor message-to-seal\n"
2118 "\t[unseal | gss_unseal] initiator | acceptor\n"
2119 "\t[status | gss_display_status] mech_type [major | minor] \n"
2120 "\t[indicate | gss_indicate_mechs]\n"
2121 "\t[inquire | gss_inquire_cred] {not yet implemented}\n"
2122 "\t[expname2unixcred | gsscred_expname_to_unix_cred]"
2123 " export-name\n"
2124 "\t[name2unixcred | gsscred_name_to_unix_cred] "
2125 "pname [name_type mech_type]\n"
2126 "\t[grpinfo | gss_get_group_info] uid\n"
2127 "\t[gss_all | all] desired_name\n"
2128 "\t[gss_loop | loop] desired_name\n"
2129 "\texit\n\n"));
2130 }
2131
2132 /* Copied from parse_argv(), then modified */
2133
2134 static int
parse_input_line(input_line,argc,argv)2135 parse_input_line(input_line, argc, argv)
2136 char *input_line;
2137 int * argc;
2138 char ***argv;
2139 {
2140 const char nil = '\0';
2141 char * chptr;
2142 int chr_cnt;
2143 int arg_cnt = 0;
2144 int ch_was_space = 1;
2145 int ch_is_space;
2146
2147 chr_cnt = strlen(input_line);
2148
2149 /* Count the arguments in the input_line string */
2150
2151 *argc = 1;
2152
2153 for (chptr = &input_line[0]; *chptr != nil; chptr++) {
2154 ch_is_space = isspace(*chptr);
2155 if (ch_is_space && !ch_was_space) {
2156 (*argc)++;
2157 }
2158 ch_was_space = ch_is_space;
2159 }
2160
2161 if (ch_was_space) {
2162 (*argc)--;
2163 } /* minus trailing spaces */
2164
2165 /* Now that we know how many args calloc the argv array */
2166
2167 *argv = (char **) CALLOC((*argc)+1, sizeof (char *));
2168 chptr = (char *) (&input_line[0]);
2169
2170 for (ch_was_space = 1; *chptr != nil; chptr++) {
2171 ch_is_space = isspace(*chptr);
2172 if (ch_is_space) {
2173 *chptr = nil; /* replace each space with nil */
2174 } else if (ch_was_space) { /* begining of word? */
2175 (*argv)[arg_cnt++] = chptr; /* new argument ? */
2176 }
2177
2178 ch_was_space = ch_is_space;
2179 }
2180
2181 return (chr_cnt);
2182 }
2183