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
,
162 OPTION_VERBOSE_LIBRARY
,
172 OPTION_WRITE_TICKET_FILE
175 #define TYPE_TEXT_NAME "text"
176 #define TYPE_DER_NAME "der"
177 #define TYPE_HEX_NAME "hex"
178 #define TYPE_BASE64_NAME "base64"
179 #define TYPE_BINARY_NAME "binary"
183 int silent
, verbose
, verbose_library
;
188 char *ticketwritefile
;
205 char *renew_till_str
;
226 const char *program_name
= PACKAGE
;
227 const char *argp_program_version
= PACKAGE_STRING
;
228 const char *argp_program_bug_address
= PACKAGE_BUGREPORT
;
231 crypto (Shishi
* handle
, struct arguments arg
)
236 if (arg
.cname
== NULL
)
237 arg
.cname
= shishi_principal_default (handle
);
239 if (arg
.crealm
== NULL
)
240 arg
.crealm
= shishi_realm_default (handle
);
242 if (arg
.salt
== NULL
)
244 char *cname
, *tok
, *tokptr
;
246 cname
= xstrdup (arg
.cname
);
247 arg
.salt
= xstrdup (arg
.crealm
);
248 tok
= strtok_r (cname
, "/", &tokptr
);
252 xrealloc (arg
.salt
, strlen (arg
.salt
) + strlen (tok
) + 1);
253 strcat (arg
.salt
, tok
);
254 tok
= strtok_r (NULL
, "/", &tokptr
);
259 rc
= shishi_key (handle
, &key
);
262 shishi_error_printf (handle
, _("Cannot create key: %s"),
263 shishi_strerror (rc
));
267 shishi_key_type_set (key
, arg
.algorithm
);
268 shishi_key_version_set (key
, arg
.kvno
);
269 shishi_key_principal_set (key
, arg
.cname
);
270 shishi_key_realm_set (key
, arg
.crealm
);
274 rc
= shishi_string_to_key (handle
, arg
.algorithm
,
276 strlen (arg
.password
),
278 strlen (arg
.salt
), arg
.parameter
, key
);
281 shishi_error_printf (handle
, _("Error in string2key"));
286 else if (arg
.keyvalue
)
288 rc
= shishi_key_from_base64 (handle
, arg
.algorithm
, arg
.keyvalue
, &key
);
291 fprintf (stderr
, _("Could not create key: %s\n"),
292 shishi_strerror (rc
));
300 rc
= shishi_randomize (handle
, buf
,
301 shishi_cipher_randomlen (arg
.algorithm
));
305 shishi_random_to_key (handle
, arg
.algorithm
,
306 buf
, shishi_cipher_randomlen (arg
.algorithm
),
309 else if (arg
.readkeyfile
)
311 key
= shishi_keys_for_server_in_file (handle
, arg
.readkeyfile
,
314 shishi_key_from_file (handle
, arg
.writekeyfile
, arg
.algorithm
, key
,
315 keylen
, arg
.kvno
, arg
.cname
, arg
.realm
);
320 fprintf (stderr
, _("Could not find key: %s\n"),
321 shishi_error (handle
));
327 fprintf (stderr
, "Nothing to do.\n");
332 ((arg
.password
|| arg
.random
|| arg
.keyvalue
) &&
333 !(arg
.encrypt_p
|| arg
.decrypt_p
)))
335 shishi_key_print (handle
, stdout
, key
);
339 currently broken
if (arg
.encrypt_p
|| arg
.decrypt_p
)
343 infh
= fopen (arg
.inputfile
, "r");
346 shishi_error_printf (handle
, _("`%s': %s\n"),
347 arg
.inputfile
, strerror (errno
));
348 return SHISHI_FOPEN_ERROR
;
356 outfh
= fopen (arg
.outputfile
, "w");
359 shishi_error_printf (handle
, _("`%s': %s\n"),
360 arg
.inputfile
, strerror (errno
));
361 return SHISHI_FOPEN_ERROR
;
367 outlen
= fread (out
, sizeof (out
[0]),
368 sizeof (out
) / sizeof (out
[0]), infh
);
371 fprintf (stderr
, _("Error reading `%s'\n"), arg
.inputfile
);
375 printf (_("Read %d bytes...\n"), outlen
);
378 rc
= shishi_encrypt (handle
, key
, arg
.keyusage
,
379 out
, outlen
, &in
, &inlen
);
381 rc
= shishi_decrypt (handle
, key
, arg
.keyusage
,
382 in
, inlen
, &out
, &outlen
);
385 shishi_error_printf (handle
, _("Error ciphering\n"));
389 if (arg
.outputtype
== SHISHI_FILETYPE_HEX
)
391 for (i
= 0; i
< inlen
; i
++)
394 fprintf (outfh
, "\n");
395 fprintf (outfh
, "%02x ", in
[i
]);
397 fprintf (outfh
, "\n");
399 else if (arg
.outputtype
== SHISHI_FILETYPE_BINARY
)
401 i
= fwrite (in
, sizeof (in
[0]), inlen
, outfh
);
404 fprintf (stderr
, _("Short write (%d < %d)...\n"), i
, inlen
);
407 printf (_("Wrote %d bytes...\n"), inlen
);
415 shishi_error_printf (handle
, _("`%s': %s\n"),
416 arg
.outputfile
, strerror (errno
));
417 return SHISHI_FCLOSE_ERROR
;
426 shishi_error_printf (handle
, _("`%s': %s\n"),
427 arg
.inputfile
, strerror (errno
));
428 return SHISHI_FCLOSE_ERROR
;
434 if (arg
.writekeyfile
)
436 shishi_key_to_file (handle
, arg
.writekeyfile
, key
);
443 parse_filename (char *arg
, int *type
, char **var
)
445 if (strncasecmp (arg
, TYPE_TEXT_NAME
",", strlen (TYPE_TEXT_NAME
",")) == 0)
447 (*type
) = SHISHI_FILETYPE_TEXT
;
448 arg
+= strlen (TYPE_TEXT_NAME
",");
450 else if (strncasecmp (arg
, TYPE_DER_NAME
",", strlen (TYPE_DER_NAME
",")) ==
453 (*type
) = SHISHI_FILETYPE_DER
;
454 arg
+= strlen (TYPE_DER_NAME
",");
456 else if (strncasecmp (arg
, TYPE_HEX_NAME
",", strlen (TYPE_HEX_NAME
",")) ==
459 (*type
) = SHISHI_FILETYPE_HEX
;
460 arg
+= strlen (TYPE_HEX_NAME
",");
462 else if (strncasecmp (arg
, TYPE_BASE64_NAME
",",
463 strlen (TYPE_BASE64_NAME
",")) == 0)
465 (*type
) = SHISHI_FILETYPE_BASE64
;
466 arg
+= strlen (TYPE_BASE64_NAME
",");
468 else if (strncasecmp (arg
, TYPE_BINARY_NAME
",",
469 strlen (TYPE_BINARY_NAME
",")) == 0)
471 (*type
) = SHISHI_FILETYPE_BINARY
;
472 arg
+= strlen (TYPE_BINARY_NAME
",");
480 parse_opt (int key
, char *arg
, struct argp_state
*state
)
482 struct arguments
*arguments
= state
->input
;
487 arguments
->silent
= 1;
491 arguments
->verbose
= 1;
494 case OPTION_VERBOSE_LIBRARY
:
495 arguments
->verbose_library
= 1;
499 arguments
->lib_options
= arg
;
502 case OPTION_WRITE_TICKET_FILE
:
503 arguments
->ticketwritefile
= strdup (arg
);
507 arguments
->etypes
= strdup (arg
);
510 case OPTION_CFG_SYSTEM
:
511 arguments
->systemcfgfile
= strdup (arg
);
514 case OPTION_CFG_USER
:
515 arguments
->usercfgfile
= strdup (arg
);
519 arguments
->ticketfile
= strdup (arg
);
522 case OPTION_CRYPTO_ENCRYPT
:
523 arguments
->command
= OPTION_CRYPTO
;
524 if (arguments
->decrypt_p
)
525 argp_error (state
, _("Cannot both encrypt and decrypt."));
526 arguments
->encrypt_p
= 1;
529 case OPTION_CRYPTO_DECRYPT
:
530 arguments
->command
= OPTION_CRYPTO
;
531 if (arguments
->encrypt_p
)
532 argp_error (state
, _("Cannot both encrypt and decrypt."));
533 arguments
->decrypt_p
= 1;
536 case OPTION_CRYPTO_KEY_VALUE
:
537 arguments
->keyvalue
= strdup (arg
);
540 case OPTION_CRYPTO_KEY_USAGE
:
541 if (arguments
->command
!= OPTION_CRYPTO
)
542 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
543 state
->argv
[state
->next
- 1]);
544 arguments
->keyusage
= atoi (arg
);
547 case OPTION_CRYPTO_KEY_VERSION
:
548 if (arguments
->command
!= OPTION_CRYPTO
)
549 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
550 state
->argv
[state
->next
- 1]);
551 arguments
->kvno
= atoi (arg
);
554 case OPTION_CRYPTO_PARAMETER
:
555 if (arguments
->command
!= OPTION_CRYPTO
)
556 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
557 state
->argv
[state
->next
- 1]);
558 arguments
->parameter
= strdup (arg
);
561 case OPTION_CRYPTO_PASSWORD
:
562 arguments
->password
= strdup (arg
);
565 case OPTION_CRYPTO_RANDOM
:
566 if (arguments
->command
!= OPTION_CRYPTO
)
567 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
568 state
->argv
[state
->next
- 1]);
569 arguments
->random
= 1;
572 case OPTION_CRYPTO_READ_DATA_FILE
:
573 if (arguments
->command
!= OPTION_CRYPTO
)
574 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
575 state
->argv
[state
->next
- 1]);
576 parse_filename (arg
, &arguments
->inputtype
, &arguments
->inputfile
);
577 if (arguments
->inputtype
== SHISHI_FILETYPE_TEXT
||
578 arguments
->inputtype
== SHISHI_FILETYPE_DER
)
579 arguments
->inputtype
= SHISHI_FILETYPE_BINARY
;
582 case OPTION_CRYPTO_READ_KEY_FILE
:
583 if (arguments
->command
!= OPTION_CRYPTO
)
584 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
585 state
->argv
[state
->next
- 1]);
586 arguments
->readkeyfile
= strdup (arg
);
589 case OPTION_CRYPTO_SALT
:
590 if (arguments
->command
!= OPTION_CRYPTO
)
591 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
592 state
->argv
[state
->next
- 1]);
593 arguments
->salt
= strdup (arg
);
596 case OPTION_CRYPTO_STR2KEY
:
597 arguments
->command
= OPTION_CRYPTO
;
600 if (arguments
->password
)
601 argp_error (state
, _("Password specified twice."));
602 arguments
->password
= strdup (arg
);
606 case OPTION_CRYPTO_WRITE_DATA_FILE
:
607 if (arguments
->command
!= OPTION_CRYPTO
)
608 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
609 state
->argv
[state
->next
- 1]);
610 parse_filename (arg
, &arguments
->outputtype
, &arguments
->outputfile
);
611 if (arguments
->outputtype
== SHISHI_FILETYPE_TEXT
||
612 arguments
->outputtype
== SHISHI_FILETYPE_DER
)
613 arguments
->outputtype
= SHISHI_FILETYPE_BINARY
;
616 case OPTION_CRYPTO_WRITE_KEY_FILE
:
617 if (arguments
->command
!= OPTION_CRYPTO
)
618 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
619 state
->argv
[state
->next
- 1]);
620 arguments
->writekeyfile
= strdup (arg
);
623 case OPTION_CLIENT_NAME
:
624 arguments
->cname
= strdup (arg
);
629 arguments
->endtime_str
= strdup (arg
);
633 arguments
->crealm
= strdup (arg
);
638 arguments
->command
= OPTION_RENEW
;
641 case OPTION_RENEW_TILL
:
642 arguments
->renew_till_str
= strdup (arg
);
645 case OPTION_RENEWABLE
:
646 arguments
->renewable
= 1;
650 case OPTION_STARTTIME
:
651 arguments
->starttime
= get_date (arg
, NULL
);
652 if (arguments
->starttime
== -1)
653 argp_error (state
, _("invalid --starttime date `%s'"), arg
);
656 case OPTION_SERVER_NAME
:
657 arguments
->sname
= strdup (arg
);
660 case OPTION_FORCE_AS
:
661 arguments
->forceas_p
= 1;
664 case OPTION_FORCE_TGS
:
665 arguments
->forcetgs_p
= 1;
668 case OPTION_TICKET_GRANTER
:
669 arguments
->tgtname
= strdup (arg
);
674 arguments
->command
= OPTION_LIST
;
679 arguments
->command
= OPTION_DESTROY
;
683 if (arguments
->server
&& arguments
->client
)
684 argp_error (state
, _("Too many arguments: `%s'"), arg
);
685 if (arguments
->client
)
686 arguments
->server
= strdup (arg
);
688 arguments
->client
= strdup (arg
);
692 return ARGP_ERR_UNKNOWN
;
698 static struct argp_option options
[] = {
700 {0, 0, 0, 0, "If no command is given, Shishi try to make sure you have a "
701 "ticket granting ticket for the default realm, and then display it.", 0},
703 {"client-name", OPTION_CLIENT_NAME
, "NAME", 0,
704 "Client name. Default is login username.", 10},
706 {"destroy", 'd', 0, 0,
707 "Destroy tickets in local cache, subject to --client-name and "
708 "--server-name limiting.", 0},
710 {"encryption-type", 'E', "ETYPE,[ETYPE...]", 0,
711 "Encryption types to use. ETYPE is either registered name or integer.",
714 {"force-as", OPTION_FORCE_AS
, 0, 0,
715 "Force AS mode. Default is to use TGS iff a TGT is found.", 0},
717 {"force-tgs", OPTION_FORCE_TGS
, 0, 0,
718 "Force TGS mode. Default is to use TGS iff a TGT is found.", 0},
720 {"endtime", 'e', "STRING", 0,
721 "Specify when ticket validity should expire. The time syntax may be "
722 "relative (to the start time), such as \"20 hours\", or absolute, "
723 "such as \"2001-02-03 04:05:06 CET\". The default is 8 hours after "
724 "the start time.", 0},
727 "List tickets in local cache, subject to --server-name limiting.", 0},
730 "Renew ticket. Use --server-name to specify ticket, default is the "
731 "most recent renewable ticket granting ticket for the default realm.", 0},
733 {"renewable", OPTION_RENEWABLE
, 0, 0,
734 "Get a renewable ticket.", 0},
736 {"renew-till", OPTION_RENEW_TILL
, "STRING", 0,
737 "Specify renewable life of ticket. Implies --renewable. Accepts same "
738 "time syntax as --endtime. If --renewable is specified, the default is 1 "
739 "week after the start time.", 0},
741 {"realm", OPTION_REALM
, "REALM", 0,
742 "Realm of server. Default is DNS domain of local host. For AS, this also "
743 "indicates realm of client.", 0},
745 {"server", OPTION_SERVER
, "[FAMILY:]ADDRESS:SERVICE/TYPE", 0,
746 "Send all requests to HOST instead of using normal logic to locate "
747 "KDC addresses (discouraged).", 0},
749 {"server-name", OPTION_SERVER_NAME
, "NAME", 0,
750 "Server name. Default is \"krbtgt/REALM\" where REALM is server "
751 "realm (see --realm).", 0},
753 {"starttime", 's', "STRING", 0,
754 "Specify when ticket should start to be valid. Accepts same time syntax "
755 "as --endtime. The default is to become valid immediately.", 0},
757 {"ticket-granter", OPTION_TICKET_GRANTER
, "NAME", 0,
758 "Service name in ticket to use for authenticating request. Only for TGS. "
759 "Defaults to \"krbtgt/REALM@REALM\" where REALM is server "
760 "realm (see --realm).", 0},
762 {"key-value", OPTION_CRYPTO_KEY_VALUE
, "KEY", 0,
763 "Cipher key to decrypt response (discouraged).", 0},
766 /************** CRYPTO */
769 "Options for low-level cryptography (CRYPTO-OPTIONS):", 100},
771 {"client-name", OPTION_CLIENT_NAME
, "NAME", 0,
772 "Username. Default is login name.", 0},
774 {"decrypt", OPTION_CRYPTO_DECRYPT
, 0, 0,
777 {"encrypt", OPTION_CRYPTO_ENCRYPT
, 0, 0,
780 {"key-usage", OPTION_CRYPTO_KEY_USAGE
, "KEYUSAGE", 0,
781 "Encrypt or decrypt using specified key usage. Default is 0, which "
782 "means no key derivation are performed.", 0},
784 {"key-value", OPTION_CRYPTO_KEY_VALUE
, "KEY", 0,
785 "Base64 encoded key value.", 0},
787 {"key-version", OPTION_CRYPTO_KEY_VERSION
, "INTEGER", 0,
788 "Version number of key. Default is 0.", 0},
790 {"random", OPTION_CRYPTO_RANDOM
, 0, 0,
791 "Generate key from random data.", 0},
793 {"read-key-file", OPTION_CRYPTO_READ_KEY_FILE
, "FILE", 0,
794 "Read cipher key from FILE", 0},
796 {"read-data-file", OPTION_CRYPTO_READ_DATA_FILE
, "[TYPE,]FILE", 0,
797 "Read data from FILE in TYPE, BASE64, HEX or BINARY (default).", 0},
799 {"realm", OPTION_REALM
, "REALM", 0,
800 "Realm of principal. Defaults to DNS domain of local host. ", 0},
802 {"salt", OPTION_CRYPTO_SALT
, "SALT", 0,
803 "Salt to use for --string-to-key. Defaults to concatenation of "
804 "realm and (unwrapped) client name.", 0},
806 {"string-to-key", OPTION_CRYPTO_STR2KEY
, "[PASSWORD]", OPTION_ARG_OPTIONAL
,
807 "Convert password into Kerberos key. Note that --client-name, --realm, "
808 "and --salt influence the generated key.", 0},
810 {"parameter", OPTION_CRYPTO_PARAMETER
, "STRING", 0,
811 "String-to-key parameter. This data is specific for each encryption "
812 "algorithm and rarely needed.", 0},
814 {"write-key-file", OPTION_CRYPTO_WRITE_KEY_FILE
, "FILE", 0,
815 "Append cipher key to FILE", 0},
817 {"write-data-file", OPTION_CRYPTO_WRITE_DATA_FILE
, "[TYPE,]FILE", 0,
818 "Write data to FILE in TYPE, BASE64, HEX or BINARY (default).", 0},
820 /************** OTHER */
822 {0, 0, 0, 0, "Other options:", 200},
824 {"verbose", 'v', 0, 0,
825 "Produce verbose output.", 0},
827 {"verbose-library", OPTION_VERBOSE_LIBRARY
, 0, 0,
828 "Produce verbose output in the library.", 0},
831 "Don't produce any output.", 0},
833 {"silent", 0, 0, OPTION_ALIAS
,
836 {"system-configuration-file", OPTION_CFG_SYSTEM
, "FILE", 0,
837 "Read system wide configuration from file. Default is " SYSTEMCFGFILE
840 {"configuration-file", OPTION_CFG_USER
, "FILE", 0,
841 "Read user configuration from file. Default is ~/.shishi/config.", 0},
843 {"library-options", 'o', "STRING", 0,
844 "Parse STRING as a configuration file statement.", 0},
846 {"ticket-file", 'c', "FILE", 0,
847 "Read tickets from FILE. Default is $HOME/.shishi/tickets.", 0},
849 {"ticket-write-file", OPTION_WRITE_TICKET_FILE
, "FILE", 0,
850 "Write tickets to FILE. Default is to write them back to ticket file.",
853 {"CLIENT", 0, 0, OPTION_DOC
| OPTION_NO_USAGE
,
854 "Set client name and realm from NAME. The --client-name and --realm "
855 "parameters can be used to override part of NAME.", 0},
857 {"SERVER", 0, 0, OPTION_DOC
| OPTION_NO_USAGE
,
858 "Set server name and realm from NAME. The --server-name and "
859 "--server-realm parameters can be used to override part of SERVER.", 0},
861 /************** EXAMPLES */
863 {0, 0, 0, 0, "Examples:", 300},
865 {"shishi", 0, 0, OPTION_DOC
| OPTION_NO_USAGE
,
866 "Get a ticket granting ticket from the default KDC server for the "
867 "default user and realm.", 0},
869 {"shishi jas/admin@ACCOUNTING", 0, 0, OPTION_DOC
| OPTION_NO_USAGE
,
870 "Get a ticket for jas/admin in the ACCOUNTING realm.", 0},
872 {"shishi --list --server-name=krbtgt/JOSEFSSON.ORG@JOSEFSSON.ORG",
873 0, 0, OPTION_DOC
| OPTION_NO_USAGE
,
874 "List tickets for the Ticket Granting Service in the JOSEFSSON.ORG realm.",
877 {NULL
, 0, 0, 0, NULL
, 0}
880 static struct argp argp
= {
883 "[CLIENT [SERVER]] [OPTION...]\n"
884 "--list [CLIENT [SERVER]]\n"
885 "--destroy [CLIENT [SERVER]]\n"
886 "--string-to-key [CLIENT] [OPTION...]\n",
887 "Shishi -- A Kerberos 5 implementation",
894 main (int argc
, char *argv
[])
896 struct arguments arg
;
901 setlocale (LC_ALL
, "");
902 bindtextdomain (PACKAGE
, LOCALEDIR
);
903 textdomain (PACKAGE
);
905 memset (&arg
, 0, sizeof (arg
));
907 argp_parse (&argp
, argc
, argv
, ARGP_IN_ORDER
, 0, &arg
);
909 rc
= shishi_init_with_paths (&handle
, arg
.ticketfile
,
910 arg
.systemcfgfile
, arg
.usercfgfile
);
911 if (rc
== SHISHI_HANDLE_ERROR
)
912 error (1, 0, "Internal error: could not initialize shishi\n");
914 rc
= shishi_cfg_clientkdcetype_set (handle
, arg
.etypes
);
916 error (1, 0, "Could not set encryption types: %s\n",
917 shishi_strerror (rc
));
919 if (arg
.algorithm
== -1 && shishi_cfg_clientkdcetype (handle
, &etype
) > 0)
920 arg
.algorithm
= *etype
;
924 rc
= shishi_parse_name (handle
, arg
.client
,
925 (char **) (arg
.cname
? NULL
: &arg
.cname
),
926 (char **) (arg
.crealm
? NULL
: &arg
.crealm
));
929 error (1, 0, "Could not parse principal \"%s\": %s\n", arg
.client
,
930 shishi_strerror (rc
));
935 rc
= shishi_parse_name (handle
, arg
.server
,
936 (char **) (arg
.sname
? NULL
: &arg
.sname
),
937 (char **) (arg
.srealm
? NULL
: &arg
.srealm
));
940 error (1, 0, "Could not parse principal \"%s\": %s\n", arg
.server
,
941 shishi_strerror (rc
));
944 rc
= shishi_cfg (handle
, arg
.lib_options
);
946 error (1, 0, "Could not read library options: %s\n",
947 shishi_strerror (rc
));
949 if (arg
.verbose_library
)
951 rc
= shishi_cfg (handle
, "verbose");
953 error (1, 0, "Could not make library verbose: %s\n",
954 shishi_strerror (rc
));
958 arg
.starttime
= time (NULL
);
962 arg
.endtime
= get_date (arg
.endtime_str
, &arg
.starttime
);
963 if (arg
.endtime
== -1)
964 error (1, 0, _("invalid --endtime date `%s'"), arg
.endtime_str
);
967 if (arg
.renew_till_str
)
969 arg
.renew_till
= get_date (arg
.renew_till_str
, &arg
.starttime
);
970 if (arg
.renew_till
== -1)
971 error (1, 0, _("invalid --renew-till date `%s'"), arg
.renew_till_str
);
975 shishi_principal_default_set (handle
, arg
.cname
);
978 shishi_realm_default_set (handle
, arg
.crealm
);
982 asprintf (&arg
.tgtname
, "krbtgt/%s", shishi_realm_default (handle
));
983 if (arg
.tgtname
== NULL
)
984 error (1, 0, "Could not allocate TGT name.");
993 printf (_("Tickets in `%s':\n"), shishi_tkts_default_file (handle
));
995 rc
= shishi_tkts_print_for_service (shishi_tkts_default (handle
),
998 fprintf (stderr
, "Could not list tickets: %s", shishi_strerror (rc
));
1001 case OPTION_DESTROY
:
1004 for (i
= 0; i
< shishi_tkts_size (shishi_tkts_default (handle
)); i
++)
1007 !shishi_tkt_server_p (shishi_tkts_nth
1008 (shishi_tkts_default (handle
),
1014 printf ("Removing ticket:\n");
1015 shishi_tkt_pretty_print (shishi_tkts_nth
1016 (shishi_tkts_default
1017 (handle
), i
), stdout
);
1020 rc
= shishi_tkts_remove (shishi_tkts_default (handle
), i
);
1021 if (rc
!= SHISHI_OK
)
1022 fprintf (stderr
, "Could not destroy ticket %d:\n%s\n", i
,
1023 shishi_strerror (rc
));
1028 printf ("No tickets removed.\n");
1029 else if (removed
== 1)
1030 printf ("1 ticket removed.\n");
1032 printf ("%d tickets removed.\n", removed
);
1038 rc
= crypto (handle
, arg
);
1039 if (rc
!= SHISHI_OK
)
1040 fprintf (stderr
, "Operation failed:\n%s\n%s\n",
1041 shishi_strerror (rc
), shishi_error (handle
));
1047 Shishi_tkts_hint hint
;
1050 /* This doesn't work */
1052 memset (&hint
, 0, sizeof (hint
));
1053 hint
.client
= (char *) arg
.cname
;
1054 hint
.server
= (char *) (arg
.sname
? arg
.sname
: arg
.tgtname
);
1055 hint
.starttime
= arg
.starttime
;
1056 hint
.endtime
= arg
.endtime
;
1057 hint
.renew_till
= arg
.renew_till
;
1058 hint
.renewable
= arg
.renewable
;
1060 tkt
= shishi_tkts_find (shishi_tkts_default (handle
), &hint
);
1063 printf ("Could not get ticket for `%s'.\n", hint
.server
);
1068 rc
= shishi_tkt_pretty_print (tkt
, stdout
);
1069 if (rc
!= SHISHI_OK
)
1070 fprintf (stderr
, "Pretty printing ticket failed:\n%s\n%s\n",
1071 shishi_strerror (rc
),
1072 shishi_error (handle
));
1075 /* Get ticket using TGT ... */
1076 rc
= shishi_tgs (handle
, &tgs
);
1077 shishi_tgs_tgtkt_set (tgs
, tkt
);
1078 if (rc
== SHISHI_OK
)
1079 rc
= shishi_tgs_set_server (tgs
, hint
.server
);
1080 rc
= shishi_kdcreq_options_add (handle
, shishi_tgs_req (tgs
),
1081 SHISHI_KDCOPTIONS_RENEWABLE
|
1082 SHISHI_KDCOPTIONS_RENEW
);
1083 if (rc
== SHISHI_OK
)
1084 rc
= shishi_asn1_write (handle
, shishi_tgs_req (tgs
),
1086 shishi_generalize_time
1087 (handle
, hint
.renew_till
), 0);
1088 if (rc
== SHISHI_OK
)
1089 rc
= shishi_tgs_req_build (tgs
);
1090 if (rc
== SHISHI_OK
)
1091 rc
= shishi_tgs_sendrecv (tgs
);
1092 if (rc
== SHISHI_OK
)
1093 rc
= shishi_tgs_rep_process (tgs
);
1094 if (rc
!= SHISHI_OK
)
1096 printf ("TGS exchange failed: %s\n%s\n", shishi_strerror (rc
),
1097 shishi_error (handle
));
1098 if (rc
== SHISHI_GOT_KRBERROR
)
1099 shishi_krberror_pretty_print (handle
, stdout
,
1100 shishi_tgs_krberror (tgs
));
1104 tkt
= shishi_tgs_tkt (tgs
);
1107 printf ("No ticket in TGS-REP?!: %s\n",
1108 shishi_error (handle
));
1112 shishi_tkt_pretty_print (tkt
, stdout
);
1114 rc
= shishi_tkts_add (shishi_tkts_default (handle
), tkt
);
1115 if (rc
!= SHISHI_OK
)
1116 printf ("Could not add ticket: %s", shishi_strerror (rc
));
1123 Shishi_tkts_hint hint
;
1125 memset (&hint
, 0, sizeof (hint
));
1126 hint
.client
= (char *) arg
.cname
;
1127 hint
.server
= (char *) (arg
.sname
? arg
.sname
: arg
.tgtname
);
1128 hint
.starttime
= arg
.starttime
;
1129 hint
.endtime
= arg
.endtime
;
1130 hint
.renew_till
= arg
.renew_till
;
1131 hint
.renewable
= arg
.renewable
;
1133 tkt
= shishi_tkts_get (shishi_tkts_default (handle
), &hint
);
1136 printf ("Could not get ticket for `%s'.\n", hint
.server
);
1141 rc
= shishi_tkt_pretty_print (tkt
, stdout
);
1142 if (rc
!= SHISHI_OK
)
1143 fprintf (stderr
, "Pretty printing ticket failed:\n%s\n%s\n",
1144 shishi_strerror (rc
),
1145 shishi_error (handle
));
1151 shishi_tkts_expire (shishi_tkts_default (handle
));
1153 if (arg
.ticketwritefile
)
1154 shishi_tkts_default_file_set (handle
, arg
.ticketwritefile
);
1156 shishi_done (handle
);
1158 return rc
== SHISHI_OK
? 0 : 1;