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>
119 #define _(String) gettext (String)
120 #define gettext_noop(String) String
121 #define N_(String) gettext_noop (String)
123 /* Long parameters only */
126 OPTION_REQUEST
= 300,
129 OPTION_WRITE_AP_REQUEST_FILE
,
130 OPTION_WRITE_AUTHENTICATOR_FILE
,
131 OPTION_WRITE_REQUEST_FILE
,
132 OPTION_WRITE_RESPONSE_FILE
,
133 OPTION_READ_REQUEST_FILE
,
134 OPTION_READ_RESPONSE_FILE
,
140 OPTION_TICKET_GRANTER
,
143 OPTION_CRYPTO_ENCRYPT
,
144 OPTION_CRYPTO_DECRYPT
,
145 OPTION_CRYPTO_ALGORITHM
,
146 OPTION_CRYPTO_KEY_VERSION
,
147 OPTION_CRYPTO_KEY_USAGE
,
148 OPTION_CRYPTO_KEY_VALUE
,
149 OPTION_CRYPTO_READ_KEY_FILE
,
150 OPTION_CRYPTO_WRITE_KEY_FILE
,
151 OPTION_CRYPTO_READ_DATA_FILE
,
152 OPTION_CRYPTO_WRITE_DATA_FILE
,
153 OPTION_CRYPTO_RANDOM
,
154 OPTION_CRYPTO_PARAMETER
,
155 OPTION_CRYPTO_PASSWORD
,
158 OPTION_CRYPTO_GENERATE_KEY
,
159 OPTION_VERBOSE_LIBRARY
,
170 OPTION_WRITE_TICKET_FILE
173 #define TYPE_TEXT_NAME "text"
174 #define TYPE_DER_NAME "der"
175 #define TYPE_HEX_NAME "hex"
176 #define TYPE_BASE64_NAME "base64"
177 #define TYPE_BINARY_NAME "binary"
181 int silent
, verbose
, verbose_library
;
186 char *ticketwritefile
;
202 char *renew_till_str
;
223 const char *program_name
= PACKAGE
;
224 const char *argp_program_version
= PACKAGE_STRING
;
225 const char *argp_program_bug_address
= PACKAGE_BUGREPORT
;
228 crypto (Shishi
* handle
, struct arguments arg
)
233 size_t inlen
, outlen
;
237 if (arg
.cname
== NULL
)
238 arg
.cname
= shishi_principal_default (handle
);
240 if (arg
.realm
== NULL
)
241 arg
.realm
= shishi_realm_default (handle
);
243 if (arg
.salt
== NULL
)
245 arg
.salt
= malloc (strlen (arg
.realm
) + strlen (arg
.cname
) + 1);
247 return SHISHI_MALLOC_ERROR
;
248 strcpy (arg
.salt
, arg
.realm
);
249 strcat (arg
.salt
, arg
.cname
);
252 rc
= shishi_key (handle
, &key
);
255 shishi_error_printf (handle
, _("Cannot create key: %s"),
256 shishi_strerror (rc
));
260 shishi_key_type_set (key
, arg
.algorithm
);
261 shishi_key_version_set (key
, arg
.kvno
);
262 shishi_key_principal_set (key
, arg
.cname
);
263 shishi_key_realm_set (key
, arg
.realm
);
267 rc
= shishi_string_to_key (handle
, arg
.algorithm
,
269 strlen (arg
.password
),
271 strlen (arg
.salt
), arg
.parameter
, key
);
274 shishi_error_printf (handle
, _("Error in string2key"));
279 else if (arg
.keyvalue
)
281 rc
= shishi_key_from_base64 (handle
, arg
.algorithm
, arg
.keyvalue
, &key
);
284 fprintf (stderr
, _("Could not create key: %s\n"),
285 shishi_strerror (rc
));
293 rc
= shishi_randomize (handle
, buf
,
294 shishi_cipher_randomlen (arg
.algorithm
));
298 shishi_random_to_key (handle
, arg
.algorithm
,
299 buf
, shishi_cipher_randomlen (arg
.algorithm
),
302 else if (arg
.readkeyfile
)
304 key
= shishi_keys_for_server_in_file (handle
, arg
.readkeyfile
,
307 shishi_key_from_file (handle
, arg
.writekeyfile
, arg
.algorithm
, key
,
308 keylen
, arg
.kvno
, arg
.cname
, arg
.realm
);
313 fprintf (stderr
, _("Could not find key: %s\n"),
314 shishi_strerror_details (handle
));
320 fprintf (stderr
, "Nothing to do.\n");
324 if (shishi_key_type (key
) == SHISHI_NULL
&& !arg
.silent
)
326 "warning: using %s is silly, consider using --algorithm.\n",
327 shishi_cipher_name (arg
.algorithm
));
330 ((arg
.password
|| arg
.random
|| arg
.keyvalue
) &&
331 !(arg
.encrypt_p
|| arg
.decrypt_p
)))
333 shishi_key_print (handle
, stdout
, key
);
338 if (arg
.encrypt_p
|| arg
.decrypt_p
)
342 infh
= fopen (arg
.inputfile
, "r");
345 shishi_error_printf (handle
, _("`%s': %s\n"),
346 arg
.inputfile
, strerror (errno
));
347 return SHISHI_FOPEN_ERROR
;
355 outfh
= fopen (arg
.outputfile
, "w");
358 shishi_error_printf (handle
, _("`%s': %s\n"),
359 arg
.inputfile
, strerror (errno
));
360 return SHISHI_FOPEN_ERROR
;
366 outlen
= fread (out
, sizeof (out
[0]),
367 sizeof (out
) / sizeof (out
[0]), infh
);
370 fprintf (stderr
, _("Error reading `%s'\n"), arg
.inputfile
);
374 printf (_("Read %d bytes...\n"), outlen
);
377 rc
= shishi_encrypt (handle
, key
, arg
.keyusage
,
378 out
, outlen
, &in
, &inlen
);
380 rc
= shishi_decrypt (handle
, key
, arg
.keyusage
,
381 in
, inlen
, &out
, &outlen
);
384 shishi_error_printf (handle
, _("Error ciphering\n"));
388 if (arg
.outputtype
== SHISHI_FILETYPE_HEX
)
390 for (i
= 0; i
< inlen
; i
++)
393 fprintf (outfh
, "\n");
394 fprintf (outfh
, "%02x ", in
[i
]);
396 fprintf (outfh
, "\n");
398 else if (arg
.outputtype
== SHISHI_FILETYPE_BINARY
)
400 i
= fwrite (in
, sizeof (in
[0]), inlen
, outfh
);
403 fprintf (stderr
, _("Short write (%d < %d)...\n"), i
, inlen
);
406 printf (_("Wrote %d bytes...\n"), inlen
);
414 shishi_error_printf (handle
, _("`%s': %s\n"),
415 arg
.outputfile
, strerror (errno
));
416 return SHISHI_FCLOSE_ERROR
;
425 shishi_error_printf (handle
, _("`%s': %s\n"),
426 arg
.inputfile
, strerror (errno
));
427 return SHISHI_FCLOSE_ERROR
;
433 if (arg
.writekeyfile
)
435 shishi_key_to_file (handle
, arg
.writekeyfile
, key
);
442 parse_filename (char *arg
, int *type
, char **var
)
444 if (strncasecmp (arg
, TYPE_TEXT_NAME
",", strlen (TYPE_TEXT_NAME
",")) == 0)
446 (*type
) = SHISHI_FILETYPE_TEXT
;
447 arg
+= strlen (TYPE_TEXT_NAME
",");
449 else if (strncasecmp (arg
, TYPE_DER_NAME
",", strlen (TYPE_DER_NAME
",")) ==
452 (*type
) = SHISHI_FILETYPE_DER
;
453 arg
+= strlen (TYPE_DER_NAME
",");
455 else if (strncasecmp (arg
, TYPE_HEX_NAME
",", strlen (TYPE_HEX_NAME
",")) ==
458 (*type
) = SHISHI_FILETYPE_HEX
;
459 arg
+= strlen (TYPE_HEX_NAME
",");
461 else if (strncasecmp (arg
, TYPE_BASE64_NAME
",",
462 strlen (TYPE_BASE64_NAME
",")) == 0)
464 (*type
) = SHISHI_FILETYPE_BASE64
;
465 arg
+= strlen (TYPE_BASE64_NAME
",");
467 else if (strncasecmp (arg
, TYPE_BINARY_NAME
",",
468 strlen (TYPE_BINARY_NAME
",")) == 0)
470 (*type
) = SHISHI_FILETYPE_BINARY
;
471 arg
+= strlen (TYPE_BINARY_NAME
",");
479 parse_opt (int key
, char *arg
, struct argp_state
*state
)
481 struct arguments
*arguments
= state
->input
;
486 arguments
->silent
= 1;
490 arguments
->verbose
= 1;
493 case OPTION_VERBOSE_LIBRARY
:
494 arguments
->verbose_library
= 1;
498 arguments
->lib_options
= arg
;
501 case OPTION_WRITE_TICKET_FILE
:
502 arguments
->ticketwritefile
= strdup (arg
);
506 arguments
->etypes
= strdup (arg
);
509 case OPTION_CFG_SYSTEM
:
510 arguments
->systemcfgfile
= strdup (arg
);
513 case OPTION_CFG_USER
:
514 arguments
->usercfgfile
= strdup (arg
);
518 arguments
->ticketfile
= strdup (arg
);
521 case OPTION_CRYPTO_ALGORITHM
:
522 if (arguments
->command
!= OPTION_CRYPTO
)
523 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
524 state
->argv
[state
->next
- 1]);
525 arguments
->algorithm
= shishi_cipher_parse (arg
);
526 if (arguments
->algorithm
== -1)
527 argp_error (state
, _("Unknown encryption type in `%s'"),
528 state
->argv
[state
->next
- 1]);
531 case OPTION_CRYPTO_ENCRYPT
:
532 if (arguments
->command
!= OPTION_CRYPTO
)
533 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
534 state
->argv
[state
->next
- 1]);
535 if (arguments
->decrypt_p
)
536 argp_error (state
, _("Cannot both encrypt and decrypt."));
537 arguments
->encrypt_p
= 1;
540 case OPTION_CRYPTO_DECRYPT
:
541 if (arguments
->command
!= OPTION_CRYPTO
)
542 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
543 state
->argv
[state
->next
- 1]);
544 if (arguments
->encrypt_p
)
545 argp_error (state
, _("Cannot both encrypt and decrypt."));
546 arguments
->decrypt_p
= 1;
549 case OPTION_CRYPTO_KEY_VALUE
:
550 arguments
->keyvalue
= strdup (arg
);
553 case OPTION_CRYPTO_KEY_USAGE
:
554 if (arguments
->command
!= OPTION_CRYPTO
)
555 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
556 state
->argv
[state
->next
- 1]);
557 arguments
->keyusage
= atoi (arg
);
560 case OPTION_CRYPTO_KEY_VERSION
:
561 if (arguments
->command
!= OPTION_CRYPTO
)
562 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
563 state
->argv
[state
->next
- 1]);
564 arguments
->kvno
= atoi (arg
);
567 case OPTION_CRYPTO_PARAMETER
:
568 if (arguments
->command
!= OPTION_CRYPTO
)
569 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
570 state
->argv
[state
->next
- 1]);
571 arguments
->parameter
= strdup (arg
);
574 case OPTION_CRYPTO_PASSWORD
:
575 arguments
->password
= strdup (arg
);
578 case OPTION_CRYPTO_RANDOM
:
579 if (arguments
->command
!= OPTION_CRYPTO
)
580 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
581 state
->argv
[state
->next
- 1]);
582 arguments
->random
= 1;
585 case OPTION_CRYPTO_READ_DATA_FILE
:
586 if (arguments
->command
!= OPTION_CRYPTO
)
587 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
588 state
->argv
[state
->next
- 1]);
589 parse_filename (arg
, &arguments
->inputtype
, &arguments
->inputfile
);
590 if (arguments
->inputtype
== SHISHI_FILETYPE_TEXT
||
591 arguments
->inputtype
== SHISHI_FILETYPE_DER
)
592 arguments
->inputtype
= SHISHI_FILETYPE_BINARY
;
595 case OPTION_CRYPTO_READ_KEY_FILE
:
596 if (arguments
->command
!= OPTION_CRYPTO
)
597 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
598 state
->argv
[state
->next
- 1]);
599 arguments
->readkeyfile
= strdup (arg
);
602 case OPTION_CRYPTO_SALT
:
603 if (arguments
->command
!= OPTION_CRYPTO
)
604 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
605 state
->argv
[state
->next
- 1]);
606 arguments
->salt
= 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
);
636 arguments
->realm
= strdup (arg
);
641 arguments
->renew
= 1;
644 case OPTION_RENEW_TILL
:
645 arguments
->renew_till_str
= strdup (arg
);
648 case OPTION_RENEWABLE
:
649 arguments
->renewable
= 1;
653 case OPTION_STARTTIME
:
654 arguments
->starttime
= get_date (arg
, NULL
);
655 if (arguments
->starttime
== -1)
656 argp_error (state
, _("invalid --starttime date `%s'"), arg
);
659 case OPTION_SERVER_NAME
:
660 arguments
->sname
= strdup (arg
);
663 case OPTION_FORCE_AS
:
664 arguments
->forceas_p
= 1;
667 case OPTION_FORCE_TGS
:
668 arguments
->forcetgs_p
= 1;
671 case OPTION_TICKET_GRANTER
:
672 arguments
->tgtname
= strdup (arg
);
676 arguments
->command
= OPTION_CRYPTO
;
681 arguments
->command
= OPTION_LIST
;
686 arguments
->command
= OPTION_DESTROY
;
690 if (arguments
->client
)
691 argp_error (state
, _("Too many arguments: `%s'"), arg
);
693 arguments
->client
= arg
;
697 return ARGP_ERR_UNKNOWN
;
703 static struct argp_option options
[] = {
705 {0, 0, 0, 0, "If no command is given, Shishi try to make sure you have a "
706 "ticket granting ticket for the default realm, and then display it."},
708 {"client-name", OPTION_CLIENT_NAME
, "NAME", 0,
709 "Client name. Default is login username. Only for AS.", 10},
711 {"destroy", 'd', 0, 0,
712 "Destroy tickets in local cache, subject to --server-name limiting."},
714 {"encryption-type", 'E', "ETYPE,[ETYPE...]", 0,
715 "Encryption types to use. ETYPE is either registered name or integer."},
717 {"force-as", OPTION_FORCE_AS
, 0, 0,
718 "Force AS mode. Default is to use TGS iff a TGT is found."},
720 {"force-tgs", OPTION_FORCE_TGS
, 0, 0,
721 "Force TGS mode. Default is to use TGS iff a TGT is found."},
723 {"endtime", 'e', "STRING", 0,
724 "Specify when ticket validity should expire. The time syntax may be "
725 "relative (to the start time), such as \"20 hours\", or absolute, "
726 "such as \"2001-02-03 04:05:06 CET\". The default is 8 hours after "
730 "List tickets in local cache, subject to --server-name limiting."},
733 "Renew ticket. Use --server-name to specify ticket, default is the "
734 "most recent renewable ticket granting ticket for the default realm."},
736 {"renewable", OPTION_RENEWABLE
, 0, 0,
737 "Get a renewable ticket."},
739 {"renew-till", OPTION_RENEW_TILL
, "STRING", 0,
740 "Specify renewable life of ticket. Implies --renewable. Accepts same "
741 "time syntax as --endtime. If --renewable is specified, the default is 1 "
742 "week after the start time."},
744 {"realm", OPTION_REALM
, "REALM", 0,
745 "Realm of server. Default is DNS domain of local host. For AS, this also "
746 "indicates realm of client."},
748 {"server", OPTION_SERVER
, "[FAMILY:]ADDRESS:SERVICE/TYPE", 0,
749 "Send all requests to HOST instead of using normal logic to locate "
750 "KDC addresses (discouraged)."},
752 {"server-name", OPTION_SERVER_NAME
, "NAME", 0,
753 "Server name. Default is \"krbtgt/REALM\" where REALM is server "
754 "realm (see --realm)."},
756 {"starttime", 's', "STRING", 0,
757 "Specify when ticket should start to be valid. Accepts same time syntax "
758 "as --endtime. The default is to become valid immediately."},
760 {"ticket-granter", OPTION_TICKET_GRANTER
, "NAME", 0,
761 "Service name in ticket to use for authenticating request. Only for TGS. "
762 "Defaults to \"krbtgt/REALM@REALM\" where REALM is server "
763 "realm (see --realm)."},
765 {"key-value", OPTION_CRYPTO_KEY_VALUE
, "KEY", 0,
766 "Cipher key to decrypt response (discouraged)."},
768 {"password", OPTION_CRYPTO_PASSWORD
, "PASSWORD", 0,
769 "Password to decrypt response (discouraged). Only for AS."},
771 /************** CRYPTO */
774 "Options for low-level cryptography (CRYPTO-OPTIONS):", 100},
776 {"algorithm", OPTION_CRYPTO_ALGORITHM
, "ALGORITHM", 0,
777 "Cipher algorithm, expressed either as the etype integer or "
778 "the registered name."},
780 {"client-name", OPTION_CLIENT_NAME
, "NAME", 0,
781 "Username. Default is login name."},
783 {"decrypt", OPTION_CRYPTO_DECRYPT
, 0, 0,
786 {"encrypt", OPTION_CRYPTO_ENCRYPT
, 0, 0,
789 {"key-usage", OPTION_CRYPTO_KEY_USAGE
, "KEYUSAGE", 0,
790 "Encrypt or decrypt using specified key usage. Default is 0, which "
791 "means no key derivation are performed."},
793 {"key-value", OPTION_CRYPTO_KEY_VALUE
, "KEY", 0,
794 "Base64 encoded key value."},
796 {"key-version", OPTION_CRYPTO_KEY_VERSION
, "INTEGER", 0,
797 "Version number of key."},
799 {"password", OPTION_CRYPTO_PASSWORD
, "PASSWORD", 0,
800 "Password used to generate key. --client-name and --realm also modify "
801 "the computed key value."},
803 {"random", OPTION_CRYPTO_RANDOM
, 0, 0,
804 "Generate key from random data."},
806 {"read-key-file", OPTION_CRYPTO_READ_KEY_FILE
, "FILE", 0,
807 "Read cipher key from FILE"},
809 {"read-data-file", OPTION_CRYPTO_READ_DATA_FILE
, "[TYPE,]FILE", 0,
810 "Read data from FILE in TYPE, BASE64, HEX or BINARY (default)."},
812 {"realm", OPTION_REALM
, "REALM", 0,
813 "Realm of principal. Defaults to DNS domain of local host. "},
815 {"salt", OPTION_CRYPTO_SALT
, "SALT", 0,
816 "Salt to use when --password is specified. Defaults to using the"
817 "username (--client-name) and realm (--realm)."},
819 {"parameter", OPTION_CRYPTO_PARAMETER
, "STRING", 0,
820 "String-to-key parameter to use when --password is specified. This data "
821 "is specific for each encryption algorithm and rarely needed."},
823 {"write-key-file", OPTION_CRYPTO_WRITE_KEY_FILE
, "FILE", 0,
824 "Append cipher key to FILE"},
826 {"write-data-file", OPTION_CRYPTO_WRITE_DATA_FILE
, "[TYPE,]FILE", 0,
827 "Write data to FILE in TYPE, BASE64, HEX or BINARY (default)."},
829 /************** OTHER */
831 {0, 0, 0, 0, "Other options:", 200},
833 {"verbose", 'v', 0, 0,
834 "Produce verbose output.",},
836 {"verbose-library", OPTION_VERBOSE_LIBRARY
, 0, 0,
837 "Produce verbose output in the library.",},
840 "Don't produce any output."},
842 {"silent", 0, 0, OPTION_ALIAS
},
844 {"system-configuration-file", OPTION_CFG_SYSTEM
, "FILE", 0,
845 "Read system wide configuration from file. Default is " SYSTEMCFGFILE
848 {"configuration-file", OPTION_CFG_USER
, "FILE", 0,
849 "Read user configuration from file. Default is ~/.shishi/config."},
851 {"library-options", 'o', "STRING", 0,
852 "Parse STRING as a configuration file statement."},
854 {"ticket-file", 'c', "FILE", 0,
855 "Read tickets from FILE. Default is $HOME/.shishi/tickets."},
857 {"ticket-write-file", OPTION_WRITE_TICKET_FILE
, "FILE", 0,
858 "Write tickets to FILE. Default is to write them back to ticket file."},
860 {"NAME", 0, 0, OPTION_DOC
| OPTION_NO_USAGE
,
861 "Set client name and realm from NAME. The --client-name and --realm can "
862 "be used to override part of NAME."},
864 /************** EXAMPLES */
866 {0, 0, 0, 0, "Examples:", 300},
868 {"shishi", 0, 0, OPTION_DOC
| OPTION_NO_USAGE
,
869 "Get a ticket granting ticket from the default KDC server for the "
870 "default user and realm."},
872 {"shishi jas/admin@ACCOUNTING", 0, 0, OPTION_DOC
| OPTION_NO_USAGE
,
873 "Get a ticket for jas/admin in the ACCOUNTING realm."},
875 {"shishi --list --server-name=krbtgt/JOSEFSSON.ORG@JOSEFSSON.ORG",
876 0, 0, OPTION_DOC
| OPTION_NO_USAGE
,
877 "List tickets for the Ticket Granting Service in the JOSEFSSON.ORG realm."},
882 static struct argp argp
= {
885 "[NAME] [OPTION...]\n"
886 "--list [--server-name=NAME]\n"
887 "--destroy [--server-name=NAME]\n"
888 "--crypto [CRYPTO-OPTION...]\n",
889 "Shishi -- A Kerberos 5 implementation"
893 main (int argc
, char *argv
[])
895 struct arguments arg
;
899 setlocale (LC_ALL
, "");
900 bindtextdomain (PACKAGE
, LOCALEDIR
);
901 textdomain (PACKAGE
);
903 memset (&arg
, 0, sizeof (arg
));
904 argp_parse (&argp
, argc
, argv
, ARGP_IN_ORDER
, 0, &arg
);
906 rc
= shishi_init_with_paths (&handle
, arg
.ticketfile
,
907 arg
.systemcfgfile
, arg
.usercfgfile
);
908 if (rc
== SHISHI_HANDLE_ERROR
)
909 error (1, 0, "Internal error: could not initialize shishi\n");
911 rc
= shishi_cfg_clientkdcetype_set (handle
, arg
.etypes
);
913 error (1, 0, "Could not set encryption types: %s\n", shishi_strerror (rc
));
917 rc
= shishi_parse_name (handle
, arg
.client
,
918 (char **) (arg
.cname
? NULL
: &arg
.cname
),
919 (char **) (arg
.realm
? NULL
: &arg
.realm
));
922 error (1, 0, "Could not parse principal \"%s\": %s\n", arg
.client
,
923 shishi_strerror (rc
));
926 rc
= shishi_cfg (handle
, arg
.lib_options
);
928 error (1, 0, "Could not read library options: %s\n", shishi_strerror (rc
));
930 if (arg
.verbose_library
)
932 rc
= shishi_cfg (handle
, "verbose");
934 error (1, 0, "Could not make library verbose: %s\n",
935 shishi_strerror (rc
));
939 arg
.starttime
= time(NULL
);
943 arg
.endtime
= get_date (arg
.endtime_str
, &arg
.starttime
);
944 if (arg
.endtime
== -1)
945 error (1, 0, _("invalid --endtime date `%s'"), arg
.endtime_str
);
948 if (arg
.renew_till_str
)
950 arg
.renew_till
= get_date (arg
.renew_till_str
, &arg
.starttime
);
951 if (arg
.renew_till
== -1)
952 error (1, 0, _("invalid --renew-till date `%s'"), arg
.renew_till_str
);
956 shishi_principal_default_set (handle
, arg
.cname
);
959 shishi_realm_default_set (handle
, arg
.realm
);
963 asprintf (&arg
.tgtname
, "krbtgt/%s", shishi_realm_default (handle
));
964 if (arg
.tgtname
== NULL
)
965 error (1, 0, "Could not allocate TGT name.");
974 printf (_("Tickets in `%s':\n"), shishi_tkts_default_file (handle
));
976 rc
= shishi_tkts_print_for_service (shishi_tkts_default (handle
),
979 fprintf (stderr
, "Could not list tickets: %s", shishi_strerror (rc
));
985 for (i
= 0; i
< shishi_tkts_size (shishi_tkts_default (handle
)); i
++)
988 !shishi_tkt_server_p (shishi_tkts_nth
989 (shishi_tkts_default (handle
),
995 printf ("Removing ticket:\n");
996 shishi_tkt_pretty_print (shishi_tkts_nth
998 (handle
), i
), stdout
);
1001 rc
= shishi_tkts_remove (shishi_tkts_default (handle
), i
);
1002 if (rc
!= SHISHI_OK
)
1003 fprintf (stderr
, "Could not destroy ticket %d:\n%s\n", i
,
1004 shishi_strerror (rc
));
1009 printf ("No tickets removed.\n");
1010 else if (removed
== 1)
1011 printf ("1 ticket removed.\n");
1013 printf ("%d tickets removed.\n", removed
);
1019 rc
= crypto (handle
, arg
);
1020 if (rc
!= SHISHI_OK
)
1021 fprintf (stderr
, "Operation failed:\n%s\n%s\n",
1022 shishi_strerror (rc
), shishi_strerror_details (handle
));
1028 Shishi_tkts_hint hint
;
1030 memset (&hint
, 0, sizeof (hint
));
1031 hint
.client
= (char *) arg
.cname
;
1032 hint
.server
= (char *) (arg
.sname
? arg
.sname
: arg
.tgtname
);
1033 hint
.starttime
= arg
.starttime
;
1034 hint
.starttime
= arg
.endtime
;
1035 hint
.renew_till
= arg
.renew_till
;
1036 hint
.renewable
= arg
.renewable
;
1038 tkt
= shishi_tkts_get (shishi_tkts_default (handle
), &hint
);
1041 printf ("Could not get ticket for `%s'.\n",
1042 arg
.tgtname
? arg
.tgtname
: arg
.cname
);
1047 rc
= shishi_tkt_pretty_print (tkt
, stdout
);
1048 if (rc
!= SHISHI_OK
)
1049 fprintf (stderr
, "Pretty printing ticket failed:\n%s\n%s\n",
1050 shishi_strerror (rc
), shishi_strerror_details (handle
));
1056 shishi_tkts_expire (shishi_tkts_default (handle
));
1058 if (arg
.ticketwritefile
)
1059 shishi_tkts_default_file_set (handle
, arg
.ticketwritefile
);
1061 shishi_done (handle
);
1063 return rc
== SHISHI_OK
? 0 : 1;