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>
120 #define _(String) gettext (String)
121 #define gettext_noop(String) String
122 #define N_(String) gettext_noop (String)
124 /* Long parameters only */
127 OPTION_REQUEST
= 300,
130 OPTION_WRITE_AP_REQUEST_FILE
,
131 OPTION_WRITE_AUTHENTICATOR_FILE
,
132 OPTION_WRITE_REQUEST_FILE
,
133 OPTION_WRITE_RESPONSE_FILE
,
134 OPTION_READ_REQUEST_FILE
,
135 OPTION_READ_RESPONSE_FILE
,
141 OPTION_TICKET_GRANTER
,
144 OPTION_CRYPTO_ENCRYPT
,
145 OPTION_CRYPTO_DECRYPT
,
146 OPTION_CRYPTO_ALGORITHM
,
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
,
159 OPTION_CRYPTO_GENERATE_KEY
,
160 OPTION_VERBOSE_LIBRARY
,
171 OPTION_WRITE_TICKET_FILE
174 #define TYPE_TEXT_NAME "text"
175 #define TYPE_DER_NAME "der"
176 #define TYPE_HEX_NAME "hex"
177 #define TYPE_BASE64_NAME "base64"
178 #define TYPE_BINARY_NAME "binary"
182 int silent
, verbose
, verbose_library
;
187 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 if (arg
.cname
== NULL
)
234 arg
.cname
= shishi_principal_default (handle
);
236 if (arg
.realm
== NULL
)
237 arg
.realm
= shishi_realm_default (handle
);
239 if (arg
.salt
== NULL
)
241 arg
.salt
= malloc (strlen (arg
.realm
) + strlen (arg
.cname
) + 1);
243 return SHISHI_MALLOC_ERROR
;
244 strcpy (arg
.salt
, arg
.realm
);
245 strcat (arg
.salt
, arg
.cname
);
248 rc
= shishi_key (handle
, &key
);
251 shishi_error_printf (handle
, _("Cannot create key: %s"),
252 shishi_strerror (rc
));
256 shishi_key_type_set (key
, arg
.algorithm
);
257 shishi_key_version_set (key
, arg
.kvno
);
258 shishi_key_principal_set (key
, arg
.cname
);
259 shishi_key_realm_set (key
, arg
.realm
);
263 rc
= shishi_string_to_key (handle
, arg
.algorithm
,
265 strlen (arg
.password
),
267 strlen (arg
.salt
), arg
.parameter
, key
);
270 shishi_error_printf (handle
, _("Error in string2key"));
275 else if (arg
.keyvalue
)
277 rc
= shishi_key_from_base64 (handle
, arg
.algorithm
, arg
.keyvalue
, &key
);
280 fprintf (stderr
, _("Could not create key: %s\n"),
281 shishi_strerror (rc
));
289 rc
= shishi_randomize (handle
, buf
,
290 shishi_cipher_randomlen (arg
.algorithm
));
294 shishi_random_to_key (handle
, arg
.algorithm
,
295 buf
, shishi_cipher_randomlen (arg
.algorithm
),
298 else if (arg
.readkeyfile
)
300 key
= shishi_keys_for_server_in_file (handle
, arg
.readkeyfile
,
303 shishi_key_from_file (handle
, arg
.writekeyfile
, arg
.algorithm
, key
,
304 keylen
, arg
.kvno
, arg
.cname
, arg
.realm
);
309 fprintf (stderr
, _("Could not find key: %s\n"),
310 shishi_strerror_details (handle
));
316 fprintf (stderr
, "Nothing to do.\n");
320 if (shishi_key_type (key
) == SHISHI_NULL
&& !arg
.silent
)
322 "warning: using %s is silly, consider using --algorithm.\n",
323 shishi_cipher_name (arg
.algorithm
));
326 ((arg
.password
|| arg
.random
|| arg
.keyvalue
) &&
327 !(arg
.encrypt_p
|| arg
.decrypt_p
)))
329 shishi_key_print (handle
, stdout
, key
);
334 if (arg
.encrypt_p
|| arg
.decrypt_p
)
338 infh
= fopen (arg
.inputfile
, "r");
341 shishi_error_printf (handle
, _("`%s': %s\n"),
342 arg
.inputfile
, strerror (errno
));
343 return SHISHI_FOPEN_ERROR
;
351 outfh
= fopen (arg
.outputfile
, "w");
354 shishi_error_printf (handle
, _("`%s': %s\n"),
355 arg
.inputfile
, strerror (errno
));
356 return SHISHI_FOPEN_ERROR
;
362 outlen
= fread (out
, sizeof (out
[0]),
363 sizeof (out
) / sizeof (out
[0]), infh
);
366 fprintf (stderr
, _("Error reading `%s'\n"), arg
.inputfile
);
370 printf (_("Read %d bytes...\n"), outlen
);
373 rc
= shishi_encrypt (handle
, key
, arg
.keyusage
,
374 out
, outlen
, &in
, &inlen
);
376 rc
= shishi_decrypt (handle
, key
, arg
.keyusage
,
377 in
, inlen
, &out
, &outlen
);
380 shishi_error_printf (handle
, _("Error ciphering\n"));
384 if (arg
.outputtype
== SHISHI_FILETYPE_HEX
)
386 for (i
= 0; i
< inlen
; i
++)
389 fprintf (outfh
, "\n");
390 fprintf (outfh
, "%02x ", in
[i
]);
392 fprintf (outfh
, "\n");
394 else if (arg
.outputtype
== SHISHI_FILETYPE_BINARY
)
396 i
= fwrite (in
, sizeof (in
[0]), inlen
, outfh
);
399 fprintf (stderr
, _("Short write (%d < %d)...\n"), i
, inlen
);
402 printf (_("Wrote %d bytes...\n"), inlen
);
410 shishi_error_printf (handle
, _("`%s': %s\n"),
411 arg
.outputfile
, strerror (errno
));
412 return SHISHI_FCLOSE_ERROR
;
421 shishi_error_printf (handle
, _("`%s': %s\n"),
422 arg
.inputfile
, strerror (errno
));
423 return SHISHI_FCLOSE_ERROR
;
429 if (arg
.writekeyfile
)
431 shishi_key_to_file (handle
, arg
.writekeyfile
, key
);
438 parse_filename (char *arg
, int *type
, char **var
)
440 if (strncasecmp (arg
, TYPE_TEXT_NAME
",", strlen (TYPE_TEXT_NAME
",")) == 0)
442 (*type
) = SHISHI_FILETYPE_TEXT
;
443 arg
+= strlen (TYPE_TEXT_NAME
",");
445 else if (strncasecmp (arg
, TYPE_DER_NAME
",", strlen (TYPE_DER_NAME
",")) ==
448 (*type
) = SHISHI_FILETYPE_DER
;
449 arg
+= strlen (TYPE_DER_NAME
",");
451 else if (strncasecmp (arg
, TYPE_HEX_NAME
",", strlen (TYPE_HEX_NAME
",")) ==
454 (*type
) = SHISHI_FILETYPE_HEX
;
455 arg
+= strlen (TYPE_HEX_NAME
",");
457 else if (strncasecmp (arg
, TYPE_BASE64_NAME
",",
458 strlen (TYPE_BASE64_NAME
",")) == 0)
460 (*type
) = SHISHI_FILETYPE_BASE64
;
461 arg
+= strlen (TYPE_BASE64_NAME
",");
463 else if (strncasecmp (arg
, TYPE_BINARY_NAME
",",
464 strlen (TYPE_BINARY_NAME
",")) == 0)
466 (*type
) = SHISHI_FILETYPE_BINARY
;
467 arg
+= strlen (TYPE_BINARY_NAME
",");
475 parse_opt (int key
, char *arg
, struct argp_state
*state
)
477 struct arguments
*arguments
= state
->input
;
482 arguments
->silent
= 1;
486 arguments
->verbose
= 1;
489 case OPTION_VERBOSE_LIBRARY
:
490 arguments
->verbose_library
= 1;
494 arguments
->lib_options
= arg
;
497 case OPTION_WRITE_TICKET_FILE
:
498 arguments
->ticketwritefile
= strdup (arg
);
502 arguments
->etypes
= strdup (arg
);
505 case OPTION_CFG_SYSTEM
:
506 arguments
->systemcfgfile
= strdup (arg
);
509 case OPTION_CFG_USER
:
510 arguments
->usercfgfile
= strdup (arg
);
514 arguments
->ticketfile
= strdup (arg
);
517 case OPTION_CRYPTO_ALGORITHM
:
518 if (arguments
->command
!= OPTION_CRYPTO
)
519 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
520 state
->argv
[state
->next
- 1]);
521 arguments
->algorithm
= shishi_cipher_parse (arg
);
522 if (arguments
->algorithm
== -1)
523 argp_error (state
, _("Unknown encryption type in `%s'"),
524 state
->argv
[state
->next
- 1]);
527 case OPTION_CRYPTO_ENCRYPT
:
528 if (arguments
->command
!= OPTION_CRYPTO
)
529 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
530 state
->argv
[state
->next
- 1]);
531 if (arguments
->decrypt_p
)
532 argp_error (state
, _("Cannot both encrypt and decrypt."));
533 arguments
->encrypt_p
= 1;
536 case OPTION_CRYPTO_DECRYPT
:
537 if (arguments
->command
!= OPTION_CRYPTO
)
538 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
539 state
->argv
[state
->next
- 1]);
540 if (arguments
->encrypt_p
)
541 argp_error (state
, _("Cannot both encrypt and decrypt."));
542 arguments
->decrypt_p
= 1;
545 case OPTION_CRYPTO_KEY_VALUE
:
546 arguments
->keyvalue
= strdup (arg
);
549 case OPTION_CRYPTO_KEY_USAGE
:
550 if (arguments
->command
!= OPTION_CRYPTO
)
551 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
552 state
->argv
[state
->next
- 1]);
553 arguments
->keyusage
= atoi (arg
);
556 case OPTION_CRYPTO_KEY_VERSION
:
557 if (arguments
->command
!= OPTION_CRYPTO
)
558 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
559 state
->argv
[state
->next
- 1]);
560 arguments
->kvno
= atoi (arg
);
563 case OPTION_CRYPTO_PARAMETER
:
564 if (arguments
->command
!= OPTION_CRYPTO
)
565 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
566 state
->argv
[state
->next
- 1]);
567 arguments
->parameter
= strdup (arg
);
570 case OPTION_CRYPTO_PASSWORD
:
571 arguments
->password
= strdup (arg
);
574 case OPTION_CRYPTO_RANDOM
:
575 if (arguments
->command
!= OPTION_CRYPTO
)
576 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
577 state
->argv
[state
->next
- 1]);
578 arguments
->random
= 1;
581 case OPTION_CRYPTO_READ_DATA_FILE
:
582 if (arguments
->command
!= OPTION_CRYPTO
)
583 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
584 state
->argv
[state
->next
- 1]);
585 parse_filename (arg
, &arguments
->inputtype
, &arguments
->inputfile
);
586 if (arguments
->inputtype
== SHISHI_FILETYPE_TEXT
||
587 arguments
->inputtype
== SHISHI_FILETYPE_DER
)
588 arguments
->inputtype
= SHISHI_FILETYPE_BINARY
;
591 case OPTION_CRYPTO_READ_KEY_FILE
:
592 if (arguments
->command
!= OPTION_CRYPTO
)
593 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
594 state
->argv
[state
->next
- 1]);
595 arguments
->readkeyfile
= strdup (arg
);
598 case OPTION_CRYPTO_SALT
:
599 if (arguments
->command
!= OPTION_CRYPTO
)
600 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
601 state
->argv
[state
->next
- 1]);
602 arguments
->salt
= strdup (arg
);
605 case OPTION_CRYPTO_WRITE_DATA_FILE
:
606 if (arguments
->command
!= OPTION_CRYPTO
)
607 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
608 state
->argv
[state
->next
- 1]);
609 parse_filename (arg
, &arguments
->outputtype
, &arguments
->outputfile
);
610 if (arguments
->outputtype
== SHISHI_FILETYPE_TEXT
||
611 arguments
->outputtype
== SHISHI_FILETYPE_DER
)
612 arguments
->outputtype
= SHISHI_FILETYPE_BINARY
;
615 case OPTION_CRYPTO_WRITE_KEY_FILE
:
616 if (arguments
->command
!= OPTION_CRYPTO
)
617 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
618 state
->argv
[state
->next
- 1]);
619 arguments
->writekeyfile
= strdup (arg
);
622 case OPTION_CLIENT_NAME
:
623 arguments
->cname
= strdup (arg
);
628 arguments
->endtime_str
= strdup (arg
);
632 arguments
->realm
= strdup (arg
);
637 arguments
->command
= OPTION_RENEW
;
640 case OPTION_RENEW_TILL
:
641 arguments
->renew_till_str
= strdup (arg
);
644 case OPTION_RENEWABLE
:
645 arguments
->renewable
= 1;
649 case OPTION_STARTTIME
:
650 arguments
->starttime
= get_date (arg
, NULL
);
651 if (arguments
->starttime
== -1)
652 argp_error (state
, _("invalid --starttime date `%s'"), arg
);
655 case OPTION_SERVER_NAME
:
656 arguments
->sname
= strdup (arg
);
659 case OPTION_FORCE_AS
:
660 arguments
->forceas_p
= 1;
663 case OPTION_FORCE_TGS
:
664 arguments
->forcetgs_p
= 1;
667 case OPTION_TICKET_GRANTER
:
668 arguments
->tgtname
= strdup (arg
);
672 arguments
->command
= OPTION_CRYPTO
;
677 arguments
->command
= OPTION_LIST
;
682 arguments
->command
= OPTION_DESTROY
;
686 if (arguments
->client
)
687 argp_error (state
, _("Too many arguments: `%s'"), arg
);
689 arguments
->client
= arg
;
693 return ARGP_ERR_UNKNOWN
;
699 static struct argp_option options
[] = {
701 {0, 0, 0, 0, "If no command is given, Shishi try to make sure you have a "
702 "ticket granting ticket for the default realm, and then display it."},
704 {"client-name", OPTION_CLIENT_NAME
, "NAME", 0,
705 "Client name. Default is login username. Only for AS.", 10},
707 {"destroy", 'd', 0, 0,
708 "Destroy tickets in local cache, subject to --server-name limiting."},
710 {"encryption-type", 'E', "ETYPE,[ETYPE...]", 0,
711 "Encryption types to use. ETYPE is either registered name or integer."},
713 {"force-as", OPTION_FORCE_AS
, 0, 0,
714 "Force AS mode. Default is to use TGS iff a TGT is found."},
716 {"force-tgs", OPTION_FORCE_TGS
, 0, 0,
717 "Force TGS mode. Default is to use TGS iff a TGT is found."},
719 {"endtime", 'e', "STRING", 0,
720 "Specify when ticket validity should expire. The time syntax may be "
721 "relative (to the start time), such as \"20 hours\", or absolute, "
722 "such as \"2001-02-03 04:05:06 CET\". The default is 8 hours after "
726 "List tickets in local cache, subject to --server-name limiting."},
729 "Renew ticket. Use --server-name to specify ticket, default is the "
730 "most recent renewable ticket granting ticket for the default realm."},
732 {"renewable", OPTION_RENEWABLE
, 0, 0,
733 "Get a renewable ticket."},
735 {"renew-till", OPTION_RENEW_TILL
, "STRING", 0,
736 "Specify renewable life of ticket. Implies --renewable. Accepts same "
737 "time syntax as --endtime. If --renewable is specified, the default is 1 "
738 "week after the start time."},
740 {"realm", OPTION_REALM
, "REALM", 0,
741 "Realm of server. Default is DNS domain of local host. For AS, this also "
742 "indicates realm of client."},
744 {"server", OPTION_SERVER
, "[FAMILY:]ADDRESS:SERVICE/TYPE", 0,
745 "Send all requests to HOST instead of using normal logic to locate "
746 "KDC addresses (discouraged)."},
748 {"server-name", OPTION_SERVER_NAME
, "NAME", 0,
749 "Server name. Default is \"krbtgt/REALM\" where REALM is server "
750 "realm (see --realm)."},
752 {"starttime", 's', "STRING", 0,
753 "Specify when ticket should start to be valid. Accepts same time syntax "
754 "as --endtime. The default is to become valid immediately."},
756 {"ticket-granter", OPTION_TICKET_GRANTER
, "NAME", 0,
757 "Service name in ticket to use for authenticating request. Only for TGS. "
758 "Defaults to \"krbtgt/REALM@REALM\" where REALM is server "
759 "realm (see --realm)."},
761 {"key-value", OPTION_CRYPTO_KEY_VALUE
, "KEY", 0,
762 "Cipher key to decrypt response (discouraged)."},
764 {"password", OPTION_CRYPTO_PASSWORD
, "PASSWORD", 0,
765 "Password to decrypt response (discouraged). Only for AS."},
767 /************** CRYPTO */
770 "Options for low-level cryptography (CRYPTO-OPTIONS):", 100},
772 {"algorithm", OPTION_CRYPTO_ALGORITHM
, "ALGORITHM", 0,
773 "Cipher algorithm, expressed either as the etype integer or "
774 "the registered name."},
776 {"client-name", OPTION_CLIENT_NAME
, "NAME", 0,
777 "Username. Default is login name."},
779 {"decrypt", OPTION_CRYPTO_DECRYPT
, 0, 0,
782 {"encrypt", OPTION_CRYPTO_ENCRYPT
, 0, 0,
785 {"key-usage", OPTION_CRYPTO_KEY_USAGE
, "KEYUSAGE", 0,
786 "Encrypt or decrypt using specified key usage. Default is 0, which "
787 "means no key derivation are performed."},
789 {"key-value", OPTION_CRYPTO_KEY_VALUE
, "KEY", 0,
790 "Base64 encoded key value."},
792 {"key-version", OPTION_CRYPTO_KEY_VERSION
, "INTEGER", 0,
793 "Version number of key."},
795 {"password", OPTION_CRYPTO_PASSWORD
, "PASSWORD", 0,
796 "Password used to generate key. --client-name and --realm also modify "
797 "the computed key value."},
799 {"random", OPTION_CRYPTO_RANDOM
, 0, 0,
800 "Generate key from random data."},
802 {"read-key-file", OPTION_CRYPTO_READ_KEY_FILE
, "FILE", 0,
803 "Read cipher key from FILE"},
805 {"read-data-file", OPTION_CRYPTO_READ_DATA_FILE
, "[TYPE,]FILE", 0,
806 "Read data from FILE in TYPE, BASE64, HEX or BINARY (default)."},
808 {"realm", OPTION_REALM
, "REALM", 0,
809 "Realm of principal. Defaults to DNS domain of local host. "},
811 {"salt", OPTION_CRYPTO_SALT
, "SALT", 0,
812 "Salt to use when --password is specified. Defaults to using the"
813 "username (--client-name) and realm (--realm)."},
815 {"parameter", OPTION_CRYPTO_PARAMETER
, "STRING", 0,
816 "String-to-key parameter to use when --password is specified. This data "
817 "is specific for each encryption algorithm and rarely needed."},
819 {"write-key-file", OPTION_CRYPTO_WRITE_KEY_FILE
, "FILE", 0,
820 "Append cipher key to FILE"},
822 {"write-data-file", OPTION_CRYPTO_WRITE_DATA_FILE
, "[TYPE,]FILE", 0,
823 "Write data to FILE in TYPE, BASE64, HEX or BINARY (default)."},
825 /************** OTHER */
827 {0, 0, 0, 0, "Other options:", 200},
829 {"verbose", 'v', 0, 0,
830 "Produce verbose output.",},
832 {"verbose-library", OPTION_VERBOSE_LIBRARY
, 0, 0,
833 "Produce verbose output in the library.",},
836 "Don't produce any output."},
838 {"silent", 0, 0, OPTION_ALIAS
},
840 {"system-configuration-file", OPTION_CFG_SYSTEM
, "FILE", 0,
841 "Read system wide configuration from file. Default is " SYSTEMCFGFILE
844 {"configuration-file", OPTION_CFG_USER
, "FILE", 0,
845 "Read user configuration from file. Default is ~/.shishi/config."},
847 {"library-options", 'o', "STRING", 0,
848 "Parse STRING as a configuration file statement."},
850 {"ticket-file", 'c', "FILE", 0,
851 "Read tickets from FILE. Default is $HOME/.shishi/tickets."},
853 {"ticket-write-file", OPTION_WRITE_TICKET_FILE
, "FILE", 0,
854 "Write tickets to FILE. Default is to write them back to ticket file."},
856 {"NAME", 0, 0, OPTION_DOC
| OPTION_NO_USAGE
,
857 "Set client name and realm from NAME. The --client-name and --realm can "
858 "be used to override part of NAME."},
860 /************** EXAMPLES */
862 {0, 0, 0, 0, "Examples:", 300},
864 {"shishi", 0, 0, OPTION_DOC
| OPTION_NO_USAGE
,
865 "Get a ticket granting ticket from the default KDC server for the "
866 "default user and realm."},
868 {"shishi jas/admin@ACCOUNTING", 0, 0, OPTION_DOC
| OPTION_NO_USAGE
,
869 "Get a ticket for jas/admin in the ACCOUNTING realm."},
871 {"shishi --list --server-name=krbtgt/JOSEFSSON.ORG@JOSEFSSON.ORG",
872 0, 0, OPTION_DOC
| OPTION_NO_USAGE
,
873 "List tickets for the Ticket Granting Service in the JOSEFSSON.ORG realm."},
878 static struct argp argp
= {
881 "[NAME] [OPTION...]\n"
882 "--list [--server-name=NAME]\n"
883 "--destroy [--server-name=NAME]\n"
884 "--crypto [CRYPTO-OPTION...]\n",
885 "Shishi -- A Kerberos 5 implementation"
889 main (int argc
, char *argv
[])
891 struct arguments arg
;
895 setlocale (LC_ALL
, "");
896 bindtextdomain (PACKAGE
, LOCALEDIR
);
897 textdomain (PACKAGE
);
899 memset (&arg
, 0, sizeof (arg
));
900 argp_parse (&argp
, argc
, argv
, ARGP_IN_ORDER
, 0, &arg
);
902 rc
= shishi_init_with_paths (&handle
, arg
.ticketfile
,
903 arg
.systemcfgfile
, arg
.usercfgfile
);
904 if (rc
== SHISHI_HANDLE_ERROR
)
905 error (1, 0, "Internal error: could not initialize shishi\n");
907 rc
= shishi_cfg_clientkdcetype_set (handle
, arg
.etypes
);
909 error (1, 0, "Could not set encryption types: %s\n", shishi_strerror (rc
));
913 rc
= shishi_parse_name (handle
, arg
.client
,
914 (char **) (arg
.cname
? NULL
: &arg
.cname
),
915 (char **) (arg
.realm
? NULL
: &arg
.realm
));
918 error (1, 0, "Could not parse principal \"%s\": %s\n", arg
.client
,
919 shishi_strerror (rc
));
922 rc
= shishi_cfg (handle
, arg
.lib_options
);
924 error (1, 0, "Could not read library options: %s\n", shishi_strerror (rc
));
926 if (arg
.verbose_library
)
928 rc
= shishi_cfg (handle
, "verbose");
930 error (1, 0, "Could not make library verbose: %s\n",
931 shishi_strerror (rc
));
935 arg
.starttime
= time(NULL
);
939 arg
.endtime
= get_date (arg
.endtime_str
, &arg
.starttime
);
940 if (arg
.endtime
== -1)
941 error (1, 0, _("invalid --endtime date `%s'"), arg
.endtime_str
);
944 if (arg
.renew_till_str
)
946 arg
.renew_till
= get_date (arg
.renew_till_str
, &arg
.starttime
);
947 if (arg
.renew_till
== -1)
948 error (1, 0, _("invalid --renew-till date `%s'"), arg
.renew_till_str
);
952 shishi_principal_default_set (handle
, arg
.cname
);
955 shishi_realm_default_set (handle
, arg
.realm
);
959 asprintf (&arg
.tgtname
, "krbtgt/%s", shishi_realm_default (handle
));
960 if (arg
.tgtname
== NULL
)
961 error (1, 0, "Could not allocate TGT name.");
970 printf (_("Tickets in `%s':\n"), shishi_tkts_default_file (handle
));
972 rc
= shishi_tkts_print_for_service (shishi_tkts_default (handle
),
975 fprintf (stderr
, "Could not list tickets: %s", shishi_strerror (rc
));
981 for (i
= 0; i
< shishi_tkts_size (shishi_tkts_default (handle
)); i
++)
984 !shishi_tkt_server_p (shishi_tkts_nth
985 (shishi_tkts_default (handle
),
991 printf ("Removing ticket:\n");
992 shishi_tkt_pretty_print (shishi_tkts_nth
994 (handle
), i
), stdout
);
997 rc
= shishi_tkts_remove (shishi_tkts_default (handle
), i
);
999 fprintf (stderr
, "Could not destroy ticket %d:\n%s\n", i
,
1000 shishi_strerror (rc
));
1005 printf ("No tickets removed.\n");
1006 else if (removed
== 1)
1007 printf ("1 ticket removed.\n");
1009 printf ("%d tickets removed.\n", removed
);
1015 rc
= crypto (handle
, arg
);
1016 if (rc
!= SHISHI_OK
)
1017 fprintf (stderr
, "Operation failed:\n%s\n%s\n",
1018 shishi_strerror (rc
), shishi_strerror_details (handle
));
1024 Shishi_tkts_hint hint
;
1027 /* This doesn't work */
1029 memset (&hint
, 0, sizeof (hint
));
1030 hint
.client
= (char *) arg
.cname
;
1031 hint
.server
= (char *) (arg
.sname
? arg
.sname
: arg
.tgtname
);
1032 hint
.starttime
= arg
.starttime
;
1033 hint
.endtime
= arg
.endtime
;
1034 hint
.renew_till
= arg
.renew_till
;
1035 hint
.renewable
= arg
.renewable
;
1037 tkt
= shishi_tkts_find (shishi_tkts_default (handle
), &hint
);
1040 printf ("Could not get ticket for `%s'.\n", hint
.server
);
1045 rc
= shishi_tkt_pretty_print (tkt
, stdout
);
1046 if (rc
!= SHISHI_OK
)
1047 fprintf (stderr
, "Pretty printing ticket failed:\n%s\n%s\n",
1048 shishi_strerror (rc
), shishi_strerror_details (handle
));
1051 /* Get ticket using TGT ... */
1052 rc
= shishi_tgs (handle
, &tgs
);
1053 shishi_tgs_tgtkt_set (tgs
, tkt
);
1054 if (rc
== SHISHI_OK
)
1055 rc
= shishi_tgs_set_server (tgs
, hint
.server
);
1056 rc
= shishi_kdcreq_options_add (handle
, shishi_tgs_req(tgs
),
1057 SHISHI_KDCOPTIONS_RENEWABLE
|
1058 SHISHI_KDCOPTIONS_RENEW
);
1059 if (rc
== SHISHI_OK
)
1060 rc
= shishi_asn1_write (handle
, shishi_tgs_req(tgs
),
1062 shishi_generalize_time
1063 (handle
, hint
.renew_till
),
1065 if (rc
== SHISHI_OK
)
1066 rc
= shishi_tgs_req_build (tgs
);
1067 if (rc
== SHISHI_OK
)
1068 rc
= shishi_tgs_sendrecv (tgs
);
1069 if (rc
== SHISHI_OK
)
1070 rc
= shishi_tgs_rep_process (tgs
);
1071 if (rc
!= SHISHI_OK
)
1073 printf ("TGS exchange failed: %s\n%s\n", shishi_strerror (rc
),
1074 shishi_strerror_details (handle
));
1075 if (rc
== SHISHI_GOT_KRBERROR
)
1076 shishi_krberror_pretty_print (handle
, stdout
,
1077 shishi_tgs_krberror (tgs
));
1081 tkt
= shishi_tgs_tkt (tgs
);
1084 printf ("No ticket in TGS-REP?!: %s\n",
1085 shishi_strerror_details (handle
));
1089 shishi_tkt_pretty_print (tkt
, stdout
);
1091 rc
= shishi_tkts_add (shishi_tkts_default (handle
), tkt
);
1092 if (rc
!= SHISHI_OK
)
1093 printf ("Could not add ticket: %s", shishi_strerror (rc
));
1100 Shishi_tkts_hint hint
;
1102 memset (&hint
, 0, sizeof (hint
));
1103 hint
.client
= (char *) arg
.cname
;
1104 hint
.server
= (char *) (arg
.sname
? arg
.sname
: arg
.tgtname
);
1105 hint
.starttime
= arg
.starttime
;
1106 hint
.endtime
= arg
.endtime
;
1107 hint
.renew_till
= arg
.renew_till
;
1108 hint
.renewable
= arg
.renewable
;
1110 tkt
= shishi_tkts_get (shishi_tkts_default (handle
), &hint
);
1113 printf ("Could not get ticket for `%s'.\n",
1114 arg
.tgtname
? arg
.tgtname
: arg
.cname
);
1119 rc
= shishi_tkt_pretty_print (tkt
, stdout
);
1120 if (rc
!= SHISHI_OK
)
1121 fprintf (stderr
, "Pretty printing ticket failed:\n%s\n%s\n",
1122 shishi_strerror (rc
), shishi_strerror_details (handle
));
1128 shishi_tkts_expire (shishi_tkts_default (handle
));
1130 if (arg
.ticketwritefile
)
1131 shishi_tkts_default_file_set (handle
, arg
.ticketwritefile
);
1133 shishi_done (handle
);
1135 return rc
== SHISHI_OK
? 0 : 1;