1 /* shishi.c command line interface to shishi
2 * Copyright (C) 2002, 2003 Simon Josefsson
4 * This file is part of Shishi.
6 * Shishi is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * Shishi is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with Shishi; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
41 #if defined HAVE_DECL_H_ERRNO && !HAVE_DECL_H_ERRNO
42 /* extern int h_errno; */
49 #ifdef HAVE_SYS_TYPES_H
50 #include <sys/types.h>
53 #ifdef HAVE_SYS_SELECT_H
54 #include <sys/select.h>
57 #ifdef HAVE_SYS_SOCKET_H
58 #include <sys/socket.h>
61 #ifdef HAVE_SYS_IOCTL_H
62 #include <sys/ioctl.h>
70 # include <inttypes.h>
77 #if TIME_WITH_SYS_TIME
78 # include <sys/time.h>
82 # include <sys/time.h>
89 # if !STDC_HEADERS && HAVE_MEMORY_H
102 #ifdef HAVE_NETINET_IN_H
103 #include <netinet/in.h>
105 #ifdef HAVE_NETINET_IN6_H
106 #include <netinet/in6.h>
121 #define _(String) gettext (String)
122 #define gettext_noop(String) String
123 #define N_(String) gettext_noop (String)
125 /* Long parameters only */
128 OPTION_REQUEST
= 300,
131 OPTION_WRITE_AP_REQUEST_FILE
,
132 OPTION_WRITE_AUTHENTICATOR_FILE
,
133 OPTION_WRITE_REQUEST_FILE
,
134 OPTION_WRITE_RESPONSE_FILE
,
135 OPTION_READ_REQUEST_FILE
,
136 OPTION_READ_RESPONSE_FILE
,
142 OPTION_TICKET_GRANTER
,
145 OPTION_CRYPTO_ENCRYPT
,
146 OPTION_CRYPTO_DECRYPT
,
147 OPTION_CRYPTO_KEY_VERSION
,
148 OPTION_CRYPTO_KEY_USAGE
,
149 OPTION_CRYPTO_KEY_VALUE
,
150 OPTION_CRYPTO_READ_KEY_FILE
,
151 OPTION_CRYPTO_WRITE_KEY_FILE
,
152 OPTION_CRYPTO_READ_DATA_FILE
,
153 OPTION_CRYPTO_WRITE_DATA_FILE
,
154 OPTION_CRYPTO_RANDOM
,
155 OPTION_CRYPTO_PARAMETER
,
156 OPTION_CRYPTO_PASSWORD
,
158 OPTION_CRYPTO_STR2KEY
,
160 OPTION_CRYPTO_GENERATE_KEY
,
175 OPTION_WRITE_TICKET_FILE
178 #define TYPE_TEXT_NAME "text"
179 #define TYPE_DER_NAME "der"
180 #define TYPE_HEX_NAME "hex"
181 #define TYPE_BASE64_NAME "base64"
182 #define TYPE_BINARY_NAME "binary"
191 char *ticketwritefile
;
212 char *renew_till_str
;
233 const char *program_name
= PACKAGE
;
234 const char *argp_program_version
= PACKAGE_STRING
;
235 const char *argp_program_bug_address
= PACKAGE_BUGREPORT
;
238 crypto (Shishi
* handle
, struct arguments arg
)
243 if (arg
.cname
== NULL
)
244 arg
.cname
= shishi_principal_default (handle
);
246 if (arg
.crealm
== NULL
)
247 arg
.crealm
= shishi_realm_default (handle
);
249 if (arg
.salt
== NULL
)
251 char *cname
, *tok
, *tokptr
;
253 cname
= xstrdup (arg
.cname
);
254 arg
.salt
= xstrdup (arg
.crealm
);
255 tok
= strtok_r (cname
, "/", &tokptr
);
259 xrealloc (arg
.salt
, strlen (arg
.salt
) + strlen (tok
) + 1);
260 strcat (arg
.salt
, tok
);
261 tok
= strtok_r (NULL
, "/", &tokptr
);
266 rc
= shishi_key (handle
, &key
);
269 shishi_error_printf (handle
, _("Cannot create key: %s"),
270 shishi_strerror (rc
));
274 shishi_key_type_set (key
, arg
.algorithm
);
275 shishi_key_version_set (key
, arg
.kvno
);
276 shishi_key_principal_set (key
, arg
.cname
);
277 shishi_key_realm_set (key
, arg
.crealm
);
281 rc
= shishi_string_to_key (handle
, arg
.algorithm
,
283 strlen (arg
.password
),
285 strlen (arg
.salt
), arg
.parameter
, key
);
288 shishi_error_printf (handle
, _("Error in string2key"));
293 else if (arg
.keyvalue
)
295 rc
= shishi_key_from_base64 (handle
, arg
.algorithm
, arg
.keyvalue
, &key
);
298 fprintf (stderr
, _("Could not create key: %s\n"),
299 shishi_strerror (rc
));
307 rc
= shishi_randomize (handle
, buf
,
308 shishi_cipher_randomlen (arg
.algorithm
));
312 shishi_random_to_key (handle
, arg
.algorithm
,
313 buf
, shishi_cipher_randomlen (arg
.algorithm
),
316 else if (arg
.readkeyfile
)
318 key
= shishi_keys_for_server_in_file (handle
, arg
.readkeyfile
,
321 shishi_key_from_file (handle
, arg
.writekeyfile
, arg
.algorithm
, key
,
322 keylen
, arg
.kvno
, arg
.cname
, arg
.realm
);
327 fprintf (stderr
, _("Could not find key: %s\n"),
328 shishi_error (handle
));
334 fprintf (stderr
, "Nothing to do.\n");
339 ((arg
.password
|| arg
.random
|| arg
.keyvalue
) &&
340 !(arg
.encrypt_p
|| arg
.decrypt_p
)))
342 shishi_key_print (handle
, stdout
, key
);
346 currently broken
if (arg
.encrypt_p
|| arg
.decrypt_p
)
350 infh
= fopen (arg
.inputfile
, "r");
353 shishi_error_printf (handle
, _("`%s': %s\n"),
354 arg
.inputfile
, strerror (errno
));
355 return SHISHI_FOPEN_ERROR
;
363 outfh
= fopen (arg
.outputfile
, "w");
366 shishi_error_printf (handle
, _("`%s': %s\n"),
367 arg
.inputfile
, strerror (errno
));
368 return SHISHI_FOPEN_ERROR
;
374 outlen
= fread (out
, sizeof (out
[0]),
375 sizeof (out
) / sizeof (out
[0]), infh
);
378 fprintf (stderr
, _("Error reading `%s'\n"), arg
.inputfile
);
382 printf (_("Read %d bytes...\n"), outlen
);
385 rc
= shishi_encrypt (handle
, key
, arg
.keyusage
,
386 out
, outlen
, &in
, &inlen
);
388 rc
= shishi_decrypt (handle
, key
, arg
.keyusage
,
389 in
, inlen
, &out
, &outlen
);
392 shishi_error_printf (handle
, _("Error ciphering\n"));
396 if (arg
.outputtype
== SHISHI_FILETYPE_HEX
)
398 for (i
= 0; i
< inlen
; i
++)
401 fprintf (outfh
, "\n");
402 fprintf (outfh
, "%02x ", in
[i
]);
404 fprintf (outfh
, "\n");
406 else if (arg
.outputtype
== SHISHI_FILETYPE_BINARY
)
408 i
= fwrite (in
, sizeof (in
[0]), inlen
, outfh
);
411 fprintf (stderr
, _("Short write (%d < %d)...\n"), i
, inlen
);
414 printf (_("Wrote %d bytes...\n"), inlen
);
422 shishi_error_printf (handle
, _("`%s': %s\n"),
423 arg
.outputfile
, strerror (errno
));
424 return SHISHI_FCLOSE_ERROR
;
433 shishi_error_printf (handle
, _("`%s': %s\n"),
434 arg
.inputfile
, strerror (errno
));
435 return SHISHI_FCLOSE_ERROR
;
441 if (arg
.writekeyfile
)
443 shishi_key_to_file (handle
, arg
.writekeyfile
, key
);
450 parse_filename (char *arg
, int *type
, char **var
)
452 if (strncasecmp (arg
, TYPE_TEXT_NAME
",", strlen (TYPE_TEXT_NAME
",")) == 0)
454 (*type
) = SHISHI_FILETYPE_TEXT
;
455 arg
+= strlen (TYPE_TEXT_NAME
",");
457 else if (strncasecmp (arg
, TYPE_DER_NAME
",", strlen (TYPE_DER_NAME
",")) ==
460 (*type
) = SHISHI_FILETYPE_DER
;
461 arg
+= strlen (TYPE_DER_NAME
",");
463 else if (strncasecmp (arg
, TYPE_HEX_NAME
",", strlen (TYPE_HEX_NAME
",")) ==
466 (*type
) = SHISHI_FILETYPE_HEX
;
467 arg
+= strlen (TYPE_HEX_NAME
",");
469 else if (strncasecmp (arg
, TYPE_BASE64_NAME
",",
470 strlen (TYPE_BASE64_NAME
",")) == 0)
472 (*type
) = SHISHI_FILETYPE_BASE64
;
473 arg
+= strlen (TYPE_BASE64_NAME
",");
475 else if (strncasecmp (arg
, TYPE_BINARY_NAME
",",
476 strlen (TYPE_BINARY_NAME
",")) == 0)
478 (*type
) = SHISHI_FILETYPE_BINARY
;
479 arg
+= strlen (TYPE_BINARY_NAME
",");
487 parse_opt (int key
, char *arg
, struct argp_state
*state
)
489 struct arguments
*arguments
= state
->input
;
494 arguments
->silent
= 1;
498 arguments
->verbose
++;
502 arguments
->lib_options
= arg
;
505 case OPTION_WRITE_TICKET_FILE
:
506 arguments
->ticketwritefile
= strdup (arg
);
510 arguments
->etypes
= strdup (arg
);
513 case OPTION_CFG_SYSTEM
:
514 arguments
->systemcfgfile
= strdup (arg
);
517 case OPTION_CFG_USER
:
518 arguments
->usercfgfile
= strdup (arg
);
522 arguments
->ticketfile
= strdup (arg
);
525 case OPTION_CRYPTO_ENCRYPT
:
526 arguments
->command
= OPTION_CRYPTO
;
527 if (arguments
->decrypt_p
)
528 argp_error (state
, _("Cannot both encrypt and decrypt."));
529 arguments
->encrypt_p
= 1;
532 case OPTION_CRYPTO_DECRYPT
:
533 arguments
->command
= OPTION_CRYPTO
;
534 if (arguments
->encrypt_p
)
535 argp_error (state
, _("Cannot both encrypt and decrypt."));
536 arguments
->decrypt_p
= 1;
539 case OPTION_CRYPTO_KEY_VALUE
:
540 arguments
->keyvalue
= strdup (arg
);
543 case OPTION_CRYPTO_KEY_USAGE
:
544 if (arguments
->command
!= OPTION_CRYPTO
)
545 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
546 state
->argv
[state
->next
- 1]);
547 arguments
->keyusage
= atoi (arg
);
550 case OPTION_CRYPTO_KEY_VERSION
:
551 if (arguments
->command
!= OPTION_CRYPTO
)
552 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
553 state
->argv
[state
->next
- 1]);
554 arguments
->kvno
= atoi (arg
);
557 case OPTION_CRYPTO_PARAMETER
:
558 if (arguments
->command
!= OPTION_CRYPTO
)
559 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
560 state
->argv
[state
->next
- 1]);
561 arguments
->parameter
= strdup (arg
);
564 case OPTION_CRYPTO_PASSWORD
:
565 arguments
->password
= strdup (arg
);
568 case OPTION_CRYPTO_RANDOM
:
569 if (arguments
->command
!= OPTION_CRYPTO
)
570 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
571 state
->argv
[state
->next
- 1]);
572 arguments
->random
= 1;
575 case OPTION_CRYPTO_READ_DATA_FILE
:
576 if (arguments
->command
!= OPTION_CRYPTO
)
577 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
578 state
->argv
[state
->next
- 1]);
579 parse_filename (arg
, &arguments
->inputtype
, &arguments
->inputfile
);
580 if (arguments
->inputtype
== SHISHI_FILETYPE_TEXT
||
581 arguments
->inputtype
== SHISHI_FILETYPE_DER
)
582 arguments
->inputtype
= SHISHI_FILETYPE_BINARY
;
585 case OPTION_CRYPTO_READ_KEY_FILE
:
586 if (arguments
->command
!= OPTION_CRYPTO
)
587 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
588 state
->argv
[state
->next
- 1]);
589 arguments
->readkeyfile
= strdup (arg
);
592 case OPTION_CRYPTO_SALT
:
593 if (arguments
->command
!= OPTION_CRYPTO
)
594 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
595 state
->argv
[state
->next
- 1]);
596 arguments
->salt
= strdup (arg
);
599 case OPTION_CRYPTO_STR2KEY
:
600 arguments
->command
= OPTION_CRYPTO
;
603 if (arguments
->password
)
604 argp_error (state
, _("Password specified twice."));
605 arguments
->password
= strdup (arg
);
609 case OPTION_CRYPTO_WRITE_DATA_FILE
:
610 if (arguments
->command
!= OPTION_CRYPTO
)
611 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
612 state
->argv
[state
->next
- 1]);
613 parse_filename (arg
, &arguments
->outputtype
, &arguments
->outputfile
);
614 if (arguments
->outputtype
== SHISHI_FILETYPE_TEXT
||
615 arguments
->outputtype
== SHISHI_FILETYPE_DER
)
616 arguments
->outputtype
= SHISHI_FILETYPE_BINARY
;
619 case OPTION_CRYPTO_WRITE_KEY_FILE
:
620 if (arguments
->command
!= OPTION_CRYPTO
)
621 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
622 state
->argv
[state
->next
- 1]);
623 arguments
->writekeyfile
= strdup (arg
);
626 case OPTION_CLIENT_NAME
:
627 arguments
->cname
= strdup (arg
);
632 arguments
->endtime_str
= strdup (arg
);
635 case OPTION_FORWARDABLE
:
636 arguments
->forwardable
= 1;
639 case OPTION_FORWARDED
:
640 arguments
->forwarded
= 1;
643 case OPTION_PROXIABLE
:
644 arguments
->proxiable
= 1;
648 arguments
->proxy
= 1;
652 arguments
->crealm
= strdup (arg
);
657 arguments
->command
= OPTION_RENEW
;
660 case OPTION_RENEW_TILL
:
661 arguments
->renew_till_str
= strdup (arg
);
664 case OPTION_RENEWABLE
:
665 arguments
->renewable
= 1;
669 case OPTION_STARTTIME
:
670 arguments
->starttime
= get_date (arg
, NULL
);
671 if (arguments
->starttime
== -1)
672 argp_error (state
, _("invalid --starttime date `%s'"), arg
);
675 case OPTION_SERVER_NAME
:
676 arguments
->sname
= strdup (arg
);
679 case OPTION_FORCE_AS
:
680 arguments
->forceas_p
= 1;
683 case OPTION_FORCE_TGS
:
684 arguments
->forcetgs_p
= 1;
687 case OPTION_TICKET_GRANTER
:
688 arguments
->tgtname
= strdup (arg
);
693 arguments
->command
= OPTION_LIST
;
698 arguments
->command
= OPTION_DESTROY
;
702 if (arguments
->server
&& arguments
->client
)
703 argp_error (state
, _("Too many arguments: `%s'"), arg
);
704 if (arguments
->client
)
705 arguments
->server
= strdup (arg
);
707 arguments
->client
= strdup (arg
);
711 return ARGP_ERR_UNKNOWN
;
717 static struct argp_option options
[] = {
719 {0, 0, 0, 0, "If no command is given, Shishi try to make sure you have a "
720 "ticket granting ticket for the default realm, and then display it.", 0},
722 {"client-name", OPTION_CLIENT_NAME
, "NAME", 0,
723 "Client name. Default is login username.", 10},
725 {"destroy", 'd', 0, 0,
726 "Destroy tickets in local cache, subject to --client-name and "
727 "--server-name limiting.", 0},
729 {"encryption-type", 'E', "ETYPE,[ETYPE...]", 0,
730 "Encryption types to use. ETYPE is either registered name or integer.",
733 {"force-as", OPTION_FORCE_AS
, 0, 0,
734 "Force AS mode. Default is to use TGS iff a TGT is found.", 0},
736 {"force-tgs", OPTION_FORCE_TGS
, 0, 0,
737 "Force TGS mode. Default is to use TGS iff a TGT is found.", 0},
739 {"endtime", 'e', "STRING", 0,
740 "Specify when ticket validity should expire. The time syntax may be "
741 "relative (to the start time), such as \"20 hours\", or absolute, "
742 "such as \"2001-02-03 04:05:06 CET\". The default is 8 hours after "
743 "the start time.", 0},
745 {"forwardable", OPTION_FORWARDABLE
, 0, 0,
746 "Get a forwardable ticket, i.e., one that can be used to get forwarded "
749 {"forwarded", OPTION_FORWARDED
, 0, 0,
750 "Get a forwarded ticket.", 0},
753 "List tickets in local cache, subject to --server-name limiting.", 0},
755 {"proxiable", OPTION_PROXIABLE
, 0, 0,
756 "Get a proxiable ticket, i.e., one that can be used to get proxy "
759 {"proxy", OPTION_PROXY
, 0, 0,
760 "Get a proxy ticket.", 0},
763 "Renew ticket. Use --server-name to specify ticket, default is the "
764 "most recent renewable ticket granting ticket for the default realm.", 0},
766 {"renewable", OPTION_RENEWABLE
, 0, 0,
767 "Get a renewable ticket.", 0},
769 {"renew-till", OPTION_RENEW_TILL
, "STRING", 0,
770 "Specify renewable life of ticket. Implies --renewable. Accepts same "
771 "time syntax as --endtime. If --renewable is specified, the default is 1 "
772 "week after the start time.", 0},
774 {"realm", OPTION_REALM
, "REALM", 0,
775 "Realm of server. Default is DNS domain of local host. For AS, this also "
776 "indicates realm of client.", 0},
778 {"server", OPTION_SERVER
, "[FAMILY:]ADDRESS:SERVICE/TYPE", 0,
779 "Send all requests to HOST instead of using normal logic to locate "
780 "KDC addresses (discouraged).", 0},
782 {"server-name", OPTION_SERVER_NAME
, "NAME", 0,
783 "Server name. Default is \"krbtgt/REALM\" where REALM is server "
784 "realm (see --realm).", 0},
786 {"starttime", 's', "STRING", 0,
787 "Specify when ticket should start to be valid. Accepts same time syntax "
788 "as --endtime. The default is to become valid immediately.", 0},
790 {"ticket-granter", OPTION_TICKET_GRANTER
, "NAME", 0,
791 "Service name in ticket to use for authenticating request. Only for TGS. "
792 "Defaults to \"krbtgt/REALM@REALM\" where REALM is server "
793 "realm (see --realm).", 0},
795 {"key-value", OPTION_CRYPTO_KEY_VALUE
, "KEY", 0,
796 "Cipher key to decrypt response (discouraged).", 0},
799 /************** CRYPTO */
802 "Options for low-level cryptography (CRYPTO-OPTIONS):", 100},
804 {"client-name", OPTION_CLIENT_NAME
, "NAME", 0,
805 "Username. Default is login name.", 0},
807 {"decrypt", OPTION_CRYPTO_DECRYPT
, 0, 0,
810 {"encrypt", OPTION_CRYPTO_ENCRYPT
, 0, 0,
813 {"key-usage", OPTION_CRYPTO_KEY_USAGE
, "KEYUSAGE", 0,
814 "Encrypt or decrypt using specified key usage. Default is 0, which "
815 "means no key derivation are performed.", 0},
817 {"key-value", OPTION_CRYPTO_KEY_VALUE
, "KEY", 0,
818 "Base64 encoded key value.", 0},
820 {"key-version", OPTION_CRYPTO_KEY_VERSION
, "INTEGER", 0,
821 "Version number of key. Default is 0.", 0},
823 {"random", OPTION_CRYPTO_RANDOM
, 0, 0,
824 "Generate key from random data.", 0},
826 {"read-key-file", OPTION_CRYPTO_READ_KEY_FILE
, "FILE", 0,
827 "Read cipher key from FILE", 0},
829 {"read-data-file", OPTION_CRYPTO_READ_DATA_FILE
, "[TYPE,]FILE", 0,
830 "Read data from FILE in TYPE, BASE64, HEX or BINARY (default).", 0},
832 {"realm", OPTION_REALM
, "REALM", 0,
833 "Realm of principal. Defaults to DNS domain of local host. ", 0},
835 {"salt", OPTION_CRYPTO_SALT
, "SALT", 0,
836 "Salt to use for --string-to-key. Defaults to concatenation of "
837 "realm and (unwrapped) client name.", 0},
839 {"string-to-key", OPTION_CRYPTO_STR2KEY
, "[PASSWORD]", OPTION_ARG_OPTIONAL
,
840 "Convert password into Kerberos key. Note that --client-name, --realm, "
841 "and --salt influence the generated key.", 0},
843 {"parameter", OPTION_CRYPTO_PARAMETER
, "STRING", 0,
844 "String-to-key parameter. This data is specific for each encryption "
845 "algorithm and rarely needed.", 0},
847 {"write-key-file", OPTION_CRYPTO_WRITE_KEY_FILE
, "FILE", 0,
848 "Append cipher key to FILE", 0},
850 {"write-data-file", OPTION_CRYPTO_WRITE_DATA_FILE
, "[TYPE,]FILE", 0,
851 "Write data to FILE in TYPE, BASE64, HEX or BINARY (default).", 0},
853 /************** OTHER */
855 {0, 0, 0, 0, "Other options:", 200},
857 {"verbose", 'v', 0, 0,
858 "Produce verbose output. Use multiple times to increase amount of "
859 "verbose output.", 0},
862 "Don't produce any output.", 0},
864 {"silent", 0, 0, OPTION_ALIAS
,
867 {"system-configuration-file", OPTION_CFG_SYSTEM
, "FILE", 0,
868 "Read system wide configuration from file. Default is " SYSTEMCFGFILE
871 {"configuration-file", OPTION_CFG_USER
, "FILE", 0,
872 "Read user configuration from file. Default is ~/.shishi/config.", 0},
874 {"library-options", 'o', "STRING", 0,
875 "Parse STRING as a configuration file statement.", 0},
877 {"ticket-file", 'c', "FILE", 0,
878 "Read tickets from FILE. Default is $HOME/.shishi/tickets.", 0},
880 {"ticket-write-file", OPTION_WRITE_TICKET_FILE
, "FILE", 0,
881 "Write tickets to FILE. Default is to write them back to ticket file.",
884 {"CLIENT", 0, 0, OPTION_DOC
| OPTION_NO_USAGE
,
885 "Set client name and realm from NAME. The --client-name and --realm "
886 "parameters can be used to override part of NAME.", 0},
888 {"SERVER", 0, 0, OPTION_DOC
| OPTION_NO_USAGE
,
889 "Set server name and realm from NAME. The --server-name and "
890 "--server-realm parameters can be used to override part of SERVER.", 0},
892 /************** EXAMPLES */
894 {0, 0, 0, 0, "Examples:", 300},
896 {"shishi", 0, 0, OPTION_DOC
| OPTION_NO_USAGE
,
897 "Get a ticket granting ticket from the default KDC server for the "
898 "default user and realm.", 0},
900 {"shishi jas/admin@ACCOUNTING", 0, 0, OPTION_DOC
| OPTION_NO_USAGE
,
901 "Get a ticket for jas/admin in the ACCOUNTING realm.", 0},
903 {"shishi --list --server-name=krbtgt/JOSEFSSON.ORG@JOSEFSSON.ORG",
904 0, 0, OPTION_DOC
| OPTION_NO_USAGE
,
905 "List tickets for the Ticket Granting Service in the JOSEFSSON.ORG realm.",
908 {NULL
, 0, 0, 0, NULL
, 0}
911 static struct argp argp
= {
914 "[CLIENT [SERVER]] [OPTION...]\n"
915 "--list [CLIENT [SERVER]]\n"
916 "--destroy [CLIENT [SERVER]]\n" "--string-to-key [CLIENT] [OPTION...]\n",
917 "Shishi -- A Kerberos 5 implementation",
924 main (int argc
, char *argv
[])
926 struct arguments arg
;
931 setlocale (LC_ALL
, "");
932 bindtextdomain (PACKAGE
, LOCALEDIR
);
933 textdomain (PACKAGE
);
935 memset (&arg
, 0, sizeof (arg
));
937 argp_parse (&argp
, argc
, argv
, ARGP_IN_ORDER
, 0, &arg
);
939 rc
= shishi_init_with_paths (&handle
, arg
.ticketfile
,
940 arg
.systemcfgfile
, arg
.usercfgfile
);
941 if (rc
== SHISHI_HANDLE_ERROR
)
942 error (1, 0, "Internal error: could not initialize shishi\n");
944 rc
= shishi_cfg_clientkdcetype_set (handle
, arg
.etypes
);
946 error (1, 0, "Could not set encryption types: %s\n",
947 shishi_strerror (rc
));
949 if (arg
.algorithm
== -1 && shishi_cfg_clientkdcetype (handle
, &etype
) > 0)
950 arg
.algorithm
= *etype
;
954 rc
= shishi_parse_name (handle
, arg
.client
,
955 (char **) (arg
.cname
? NULL
: &arg
.cname
),
956 (char **) (arg
.crealm
? NULL
: &arg
.crealm
));
959 error (1, 0, "Could not parse principal \"%s\": %s\n", arg
.client
,
960 shishi_strerror (rc
));
965 rc
= shishi_parse_name (handle
, arg
.server
,
966 (char **) (arg
.sname
? NULL
: &arg
.sname
),
967 (char **) (arg
.srealm
? NULL
: &arg
.srealm
));
970 error (1, 0, "Could not parse principal \"%s\": %s\n", arg
.server
,
971 shishi_strerror (rc
));
974 rc
= shishi_cfg (handle
, arg
.lib_options
);
976 error (1, 0, "Could not read library options: %s\n",
977 shishi_strerror (rc
));
981 rc
= shishi_cfg (handle
, "verbose");
983 error (1, 0, "Could not make library verbose: %s\n",
984 shishi_strerror (rc
));
989 rc
= shishi_cfg (handle
, "verbose-noice");
991 error (1, 0, "Could not make library verbose: %s\n",
992 shishi_strerror (rc
));
997 rc
= shishi_cfg (handle
, "verbose-asn1");
999 error (1, 0, "Could not make library verbose: %s\n",
1000 shishi_strerror (rc
));
1003 if (arg
.verbose
> 4)
1005 rc
= shishi_cfg (handle
, "verbose-crypto");
1006 if (rc
!= SHISHI_OK
)
1007 error (1, 0, "Could not make library verbose: %s\n",
1008 shishi_strerror (rc
));
1012 arg
.starttime
= time (NULL
);
1014 if (arg
.endtime_str
)
1016 arg
.endtime
= get_date (arg
.endtime_str
, &arg
.starttime
);
1017 if (arg
.endtime
== -1)
1018 error (1, 0, _("invalid --endtime date `%s'"), arg
.endtime_str
);
1021 if (arg
.renew_till_str
)
1023 arg
.renew_till
= get_date (arg
.renew_till_str
, &arg
.starttime
);
1024 if (arg
.renew_till
== -1)
1025 error (1, 0, _("invalid --renew-till date `%s'"), arg
.renew_till_str
);
1029 shishi_principal_default_set (handle
, arg
.cname
);
1032 shishi_realm_default_set (handle
, arg
.crealm
);
1036 asprintf (&arg
.tgtname
, "krbtgt/%s", shishi_realm_default (handle
));
1037 if (arg
.tgtname
== NULL
)
1038 error (1, 0, "Could not allocate TGT name.");
1043 switch (arg
.command
)
1047 printf (_("Tickets in `%s':\n"), shishi_tkts_default_file (handle
));
1049 rc
= shishi_tkts_print_for_service (shishi_tkts_default (handle
),
1051 if (rc
!= SHISHI_OK
)
1052 fprintf (stderr
, "Could not list tickets: %s", shishi_strerror (rc
));
1055 case OPTION_DESTROY
:
1058 for (i
= 0; i
< shishi_tkts_size (shishi_tkts_default (handle
)); i
++)
1061 !shishi_tkt_server_p (shishi_tkts_nth
1062 (shishi_tkts_default (handle
),
1068 printf ("Removing ticket:\n");
1069 shishi_tkt_pretty_print (shishi_tkts_nth
1070 (shishi_tkts_default
1071 (handle
), i
), stdout
);
1074 rc
= shishi_tkts_remove (shishi_tkts_default (handle
), i
);
1075 if (rc
!= SHISHI_OK
)
1076 fprintf (stderr
, "Could not destroy ticket %d:\n%s\n", i
,
1077 shishi_strerror (rc
));
1084 printf ("No tickets removed.\n");
1085 else if (removed
== 1)
1086 printf ("1 ticket removed.\n");
1088 printf ("%d tickets removed.\n", removed
);
1095 rc
= crypto (handle
, arg
);
1096 if (rc
!= SHISHI_OK
)
1097 fprintf (stderr
, "Operation failed:\n%s\n%s\n",
1098 shishi_strerror (rc
), shishi_error (handle
));
1104 Shishi_tkts_hint hint
;
1107 /* This doesn't work */
1109 memset (&hint
, 0, sizeof (hint
));
1110 hint
.client
= (char *) arg
.cname
;
1111 hint
.server
= (char *) (arg
.sname
? arg
.sname
: arg
.tgtname
);
1112 hint
.starttime
= arg
.starttime
;
1113 hint
.endtime
= arg
.endtime
;
1114 hint
.renew_till
= arg
.renew_till
;
1116 tkt
= shishi_tkts_find (shishi_tkts_default (handle
), &hint
);
1119 fprintf (stderr
, "Could not get ticket for `%s'.\n", hint
.server
);
1123 shishi_tkt_pretty_print (tkt
, stdout
);
1125 /* Get ticket using TGT ... */
1126 rc
= shishi_tgs (handle
, &tgs
);
1127 shishi_tgs_tgtkt_set (tgs
, tkt
);
1128 if (rc
== SHISHI_OK
)
1129 rc
= shishi_tgs_set_server (tgs
, hint
.server
);
1130 rc
= shishi_kdcreq_options_add (handle
, shishi_tgs_req (tgs
),
1131 SHISHI_KDCOPTIONS_RENEWABLE
|
1132 SHISHI_KDCOPTIONS_RENEW
);
1133 if (rc
== SHISHI_OK
)
1134 rc
= shishi_asn1_write (handle
, shishi_tgs_req (tgs
),
1136 shishi_generalize_time
1137 (handle
, hint
.renew_till
), 0);
1138 if (rc
== SHISHI_OK
)
1139 rc
= shishi_tgs_req_build (tgs
);
1140 if (rc
== SHISHI_OK
)
1141 rc
= shishi_tgs_sendrecv (tgs
);
1142 if (rc
== SHISHI_OK
)
1143 rc
= shishi_tgs_rep_process (tgs
);
1144 if (rc
!= SHISHI_OK
)
1146 fprintf (stderr
, "TGS exchange failed: %s\n%s\n",
1147 shishi_strerror (rc
),
1148 shishi_error (handle
));
1149 if (rc
== SHISHI_GOT_KRBERROR
)
1150 shishi_krberror_pretty_print (handle
, stdout
,
1151 shishi_tgs_krberror (tgs
));
1155 tkt
= shishi_tgs_tkt (tgs
);
1158 fprintf (stderr
, "No ticket in TGS-REP?!: %s\n",
1159 shishi_error (handle
));
1163 shishi_tkt_pretty_print (tkt
, stdout
);
1165 rc
= shishi_tkts_add (shishi_tkts_default (handle
), tkt
);
1166 if (rc
!= SHISHI_OK
)
1167 fprintf (stderr
, "Could not add ticket: %s", shishi_strerror (rc
));
1174 Shishi_tkts_hint hint
;
1176 memset (&hint
, 0, sizeof (hint
));
1177 hint
.client
= (char *) arg
.cname
;
1178 hint
.server
= (char *) (arg
.sname
? arg
.sname
: arg
.tgtname
);
1179 hint
.starttime
= arg
.starttime
;
1180 hint
.endtime
= arg
.endtime
;
1181 hint
.renew_till
= arg
.renew_till
;
1183 hint
.tktflags
|= SHISHI_TICKETFLAGS_RENEWABLE
;
1185 hint
.tktflags
|= SHISHI_TICKETFLAGS_PROXIABLE
;
1187 hint
.tktflags
|= SHISHI_TICKETFLAGS_PROXY
;
1188 if (arg
.forwardable
)
1189 hint
.tktflags
|= SHISHI_TICKETFLAGS_FORWARDABLE
;
1191 hint
.tktflags
|= SHISHI_TICKETFLAGS_FORWARDED
;
1193 tkt
= shishi_tkts_get (shishi_tkts_default (handle
), &hint
);
1196 fprintf (stderr
, "Could not get ticket for `%s'.\n", hint
.server
);
1200 shishi_tkt_pretty_print (tkt
, stdout
);
1205 shishi_tkts_expire (shishi_tkts_default (handle
));
1207 if (arg
.ticketwritefile
)
1208 shishi_tkts_default_file_set (handle
, arg
.ticketwritefile
);
1210 shishi_done (handle
);
1212 return rc
== SHISHI_OK
? 0 : 1;