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
25 const char *program_name
= PACKAGE
;
26 const char *argp_program_version
= PACKAGE_STRING
;
27 const char *argp_program_bug_address
= PACKAGE_BUGREPORT
;
30 parse_filename (char *arg
, int *type
, char **var
)
32 if (strncasecmp (arg
, TYPE_TEXT_NAME
",", strlen (TYPE_TEXT_NAME
",")) == 0)
34 (*type
) = SHISHI_FILETYPE_TEXT
;
35 arg
+= strlen (TYPE_TEXT_NAME
",");
37 else if (strncasecmp (arg
, TYPE_DER_NAME
",", strlen (TYPE_DER_NAME
",")) ==
40 (*type
) = SHISHI_FILETYPE_DER
;
41 arg
+= strlen (TYPE_DER_NAME
",");
43 else if (strncasecmp (arg
, TYPE_HEX_NAME
",", strlen (TYPE_HEX_NAME
",")) ==
46 (*type
) = SHISHI_FILETYPE_HEX
;
47 arg
+= strlen (TYPE_HEX_NAME
",");
49 else if (strncasecmp (arg
, TYPE_BASE64_NAME
",",
50 strlen (TYPE_BASE64_NAME
",")) == 0)
52 (*type
) = SHISHI_FILETYPE_BASE64
;
53 arg
+= strlen (TYPE_BASE64_NAME
",");
55 else if (strncasecmp (arg
, TYPE_BINARY_NAME
",",
56 strlen (TYPE_BINARY_NAME
",")) == 0)
58 (*type
) = SHISHI_FILETYPE_BINARY
;
59 arg
+= strlen (TYPE_BINARY_NAME
",");
67 parse_opt (int key
, char *arg
, struct argp_state
*state
)
69 struct arguments
*arguments
= state
->input
;
74 arguments
->silent
= 1;
78 arguments
->verbose
= 1;
81 case OPTION_VERBOSE_LIBRARY
:
82 arguments
->verbose_library
= 1;
86 arguments
->lib_options
= arg
;
90 arguments
->ticketwritefile
= strdup (arg
);
94 arguments
->etypes
= strdup (arg
);
98 arguments
->systemcfgfile
= strdup (arg
);
102 arguments
->usercfgfile
= strdup (arg
);
106 arguments
->ticketfile
= strdup (arg
);
111 case OPTION_CLIENT_AP_OPTIONS
:
117 arguments
->apoptions
= 0;
119 (val
= strtok_r (i
== 0 ? arg
: NULL
, ", \t\n\r", &ptrptr
)); i
++)
121 int option
= shishi_ap_string2option (val
);
123 fprintf (stderr
, "Ignoring unknown AP option: `%s'\n", val
);
124 arguments
->apoptions
|= option
;
131 case OPTION_CRYPTO_ALGORITHM
:
132 if (arguments
->command
!= COMMAND_CRYPTO
)
133 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
134 state
->argv
[state
->next
- 1]);
135 arguments
->algorithm
= shishi_cipher_parse (arg
);
136 if (arguments
->algorithm
== -1)
137 argp_error (state
, _("Unknown encryption type in `%s'"),
138 state
->argv
[state
->next
- 1]);
141 case OPTION_CRYPTO_ENCRYPT
:
142 if (arguments
->command
!= COMMAND_CRYPTO
)
143 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
144 state
->argv
[state
->next
- 1]);
145 if (arguments
->decrypt_p
)
146 argp_error (state
, _("Cannot both encrypt and decrypt."));
147 arguments
->encrypt_p
= 1;
150 case OPTION_CRYPTO_DECRYPT
:
151 if (arguments
->command
!= COMMAND_CRYPTO
)
152 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
153 state
->argv
[state
->next
- 1]);
154 if (arguments
->encrypt_p
)
155 argp_error (state
, _("Cannot both encrypt and decrypt."));
156 arguments
->decrypt_p
= 1;
159 case OPTION_CRYPTO_SALT
:
160 if (arguments
->command
!= COMMAND_CRYPTO
)
161 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
162 state
->argv
[state
->next
- 1]);
163 arguments
->salt
= strdup (arg
);
166 case OPTION_CRYPTO_PARAMETER
:
167 if (arguments
->command
!= COMMAND_CRYPTO
)
168 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
169 state
->argv
[state
->next
- 1]);
170 arguments
->parameter
= strdup (arg
);
173 case OPTION_AS_PASSWORD
:
174 case OPTION_CRYPTO_PASSWORD
:
175 case OPTION_KDC_PASSWORD
:
176 case OPTION_SERVER_PASSWORD
:
177 if (arguments
->command
!= COMMAND_CRYPTO
&&
178 arguments
->command
!= COMMAND_AS
&&
179 arguments
->command
!= COMMAND_KDC
&&
180 arguments
->command
!= COMMAND_SERVER
)
183 _("Option `%s' only valid with CRYPTO, KDC/AS/TGS and SERVER."),
184 state
->argv
[state
->next
- 1]);
185 arguments
->password
= strdup (arg
);
188 case OPTION_CRYPTO_RANDOM
:
189 if (arguments
->command
!= COMMAND_CRYPTO
)
190 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
191 state
->argv
[state
->next
- 1]);
192 arguments
->random
= 1;
195 case OPTION_CRYPTO_READ_DATA_FILE
:
196 if (arguments
->command
!= COMMAND_CRYPTO
)
197 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
198 state
->argv
[state
->next
- 1]);
199 parse_filename (arg
, &arguments
->inputtype
, &arguments
->inputfile
);
200 if (arguments
->inputtype
== SHISHI_FILETYPE_TEXT
||
201 arguments
->inputtype
== SHISHI_FILETYPE_DER
)
202 arguments
->inputtype
= SHISHI_FILETYPE_BINARY
;
205 case OPTION_CRYPTO_WRITE_DATA_FILE
:
206 if (arguments
->command
!= COMMAND_CRYPTO
)
207 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
208 state
->argv
[state
->next
- 1]);
209 parse_filename (arg
, &arguments
->outputtype
, &arguments
->outputfile
);
210 if (arguments
->outputtype
== SHISHI_FILETYPE_TEXT
||
211 arguments
->outputtype
== SHISHI_FILETYPE_DER
)
212 arguments
->outputtype
= SHISHI_FILETYPE_BINARY
;
215 case OPTION_CRYPTO_READ_KEY_FILE
:
216 if (arguments
->command
!= COMMAND_CRYPTO
)
217 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
218 state
->argv
[state
->next
- 1]);
219 arguments
->readkeyfile
= strdup (arg
);
222 case OPTION_CRYPTO_WRITE_KEY_FILE
:
223 if (arguments
->command
!= COMMAND_CRYPTO
)
224 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
225 state
->argv
[state
->next
- 1]);
226 arguments
->writekeyfile
= strdup (arg
);
231 case OPTION_AP_AUTHENTICATOR_READ_FILE
:
232 if (arguments
->command
!= COMMAND_AP
)
233 argp_error (state
, _("Option `%s' only valid with AP."),
234 state
->argv
[state
->next
- 1]);
235 parse_filename (arg
, &arguments
->authenticatorreadtype
,
236 &arguments
->authenticatorreadfile
);
239 case OPTION_AP_AUTHENTICATOR_DATA
:
240 if (arguments
->command
!= COMMAND_AP
)
241 argp_error (state
, _("Option `%s' only valid with AP."),
242 state
->argv
[state
->next
- 1]);
243 arguments
->authenticatordata
= strdup (arg
);
246 case OPTION_AP_AUTHENTICATOR_READ_DATA_FILE
:
247 if (arguments
->command
!= COMMAND_AP
)
248 argp_error (state
, _("Option `%s' only valid with AP."),
249 state
->argv
[state
->next
- 1]);
250 parse_filename (arg
, &arguments
->authenticatordatareadtype
,
251 &arguments
->authenticatordatareadfile
);
252 if (arguments
->authenticatordatareadtype
== SHISHI_FILETYPE_TEXT
||
253 arguments
->authenticatordatareadtype
== SHISHI_FILETYPE_DER
)
254 arguments
->authenticatordatareadtype
= SHISHI_FILETYPE_BINARY
;
257 case OPTION_AS_CLIENT_NAME
:
258 case OPTION_CRYPTO_CLIENT_NAME
:
259 case OPTION_KDC_CLIENT_NAME
:
260 case OPTION_SERVER_CLIENT_NAME
:
261 case OPTION_TGS_CLIENT_NAME
:
262 if (arguments
->command
!= COMMAND_CRYPTO
&&
263 arguments
->command
!= COMMAND_AS
&&
264 arguments
->command
!= COMMAND_KDC
&&
265 arguments
->command
!= COMMAND_TGS
&&
266 arguments
->command
!= COMMAND_SERVER
)
269 ("Option `%s' only valid with CRYPTO, KDC/AS/TGS "
270 "and SERVER."), state
->argv
[state
->next
- 1]);
271 arguments
->cname
= strdup (arg
);
275 case OPTION_AP_REALM
:
276 case OPTION_AS_REALM
:
277 case OPTION_CLIENT_REALM
:
278 case OPTION_CRYPTO_REALM
:
279 case OPTION_KDC_REALM
:
280 case OPTION_TGS_REALM
:
281 if (arguments
->command
!= COMMAND_AP
&&
282 arguments
->command
!= COMMAND_CLIENT
&&
283 arguments
->command
!= COMMAND_CRYPTO
&&
284 arguments
->command
!= COMMAND_AS
&&
285 arguments
->command
!= COMMAND_KDC
&&
286 arguments
->command
!= COMMAND_TGS
)
287 argp_error (state
, _("Option `%s' only valid with AP, CLIENT, CRYPTO "
289 state
->argv
[state
->next
- 1]);
290 arguments
->realm
= strdup (arg
);
293 case OPTION_CRYPTO_KEY_VALUE
:
294 case OPTION_KDC_KEY_VALUE
:
295 case OPTION_SERVER_KEY_VALUE
:
296 if (arguments
->command
!= COMMAND_CRYPTO
&&
297 arguments
->command
!= COMMAND_KDC
&&
298 arguments
->command
!= COMMAND_SERVER
)
300 _("Option `%s' only valid with CRYPTO and KDC/AS/TGS."),
301 state
->argv
[state
->next
- 1]);
302 arguments
->keyvalue
= strdup (arg
);
305 case OPTION_CRYPTO_KEY_USAGE
:
306 if (arguments
->command
!= COMMAND_CRYPTO
)
307 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
308 state
->argv
[state
->next
- 1]);
309 arguments
->keyusage
= atoi (arg
);
312 case OPTION_CRYPTO_KEY_VERSION
:
313 if (arguments
->command
!= COMMAND_CRYPTO
)
314 argp_error (state
, _("Option `%s' only valid with CRYPTO."),
315 state
->argv
[state
->next
- 1]);
316 arguments
->kvno
= atoi (arg
);
319 case OPTION_AP_SERVER_NAME
:
320 case OPTION_CLIENT_SERVER_NAME
:
321 case OPTION_KDC_SERVER_NAME
:
322 case OPTION_LIST_SERVER_NAME
:
323 case OPTION_SERVER_SERVER_NAME
:
324 case OPTION_TGS_SERVER_NAME
:
325 arguments
->sname
= strdup (arg
);
328 case OPTION_KDC_FORCE_AS
:
329 if (arguments
->command
!= COMMAND_KDC
)
330 argp_error (state
, _("Option `%s' only valid with KDC."),
331 state
->argv
[state
->next
- 1]);
332 arguments
->forceas_p
= 1;
335 case OPTION_KDC_FORCE_TGS
:
336 if (arguments
->command
!= COMMAND_KDC
)
337 argp_error (state
, _("Option `%s' only valid with KDC."),
338 state
->argv
[state
->next
- 1]);
339 arguments
->forcetgs_p
= 1;
342 case OPTION_KDC_TICKET_GRANTER
:
343 case OPTION_TGS_TICKET_GRANTER
:
344 if (arguments
->command
!= COMMAND_KDC
&&
345 arguments
->command
!= COMMAND_TGS
)
346 argp_error (state
, _("Option `%s' only valid with KDC/TGS."),
347 state
->argv
[state
->next
- 1]);
348 arguments
->tgtname
= strdup (arg
);
351 case OPTION_KDC_REQUEST
:
352 if (arguments
->command
!= COMMAND_KDC
)
353 argp_error (state
, _("Option `%s' only valid with KDC/AS/TGS."),
354 state
->argv
[state
->next
- 1]);
355 arguments
->request_p
= 1;
358 case OPTION_AP_REQUEST_WRITE_FILE
:
359 case OPTION_KDC_WRITE_AP_REQUEST_FILE
:
360 if (arguments
->command
!= COMMAND_KDC
&&
361 arguments
->command
!= COMMAND_AP
)
363 _("Option `%s' only valid with AP and KDC/AS/TGS."),
364 state
->argv
[state
->next
- 1]);
365 parse_filename (arg
, &arguments
->apreqwritetype
,
366 &arguments
->apreqwritefile
);
369 case OPTION_AP_AUTHENTICATOR_WRITE_FILE
:
370 case OPTION_KDC_WRITE_AUTHENTICATOR_FILE
:
371 if (arguments
->command
!= COMMAND_AP
||
372 arguments
->command
!= COMMAND_KDC
)
374 _("Option `%s' only valid with AP and KDC/AS/TGS."),
375 state
->argv
[state
->next
- 1]);
376 parse_filename (arg
, &arguments
->authenticatorwritetype
,
377 &arguments
->authenticatorwritefile
);
380 case OPTION_KDC_WRITE_REQUEST_FILE
:
381 if (arguments
->command
!= COMMAND_KDC
)
382 argp_error (state
, _("Option `%s' only valid with KDC/AS/TGS."),
383 state
->argv
[state
->next
- 1]);
384 parse_filename (arg
, &arguments
->kdcreqwritetype
,
385 &arguments
->kdcreqwritefile
);
388 case OPTION_KDC_READ_REQUEST_FILE
:
389 if (arguments
->command
!= COMMAND_KDC
)
390 argp_error (state
, _("Option `%s' only valid with KDC/AS/TGS."),
391 state
->argv
[state
->next
- 1]);
392 parse_filename (arg
, &arguments
->kdcreqreadtype
,
393 &arguments
->kdcreqreadfile
);
396 case OPTION_KDC_WRITE_RESPONSE_FILE
:
397 if (arguments
->command
!= COMMAND_KDC
)
398 argp_error (state
, _("Option `%s' only valid with KDC/AS/TGS."),
399 state
->argv
[state
->next
- 1]);
400 parse_filename (arg
, &arguments
->kdcrepwritetype
,
401 &arguments
->kdcrepwritefile
);
404 case OPTION_KDC_READ_RESPONSE_FILE
:
405 if (arguments
->command
!= COMMAND_KDC
)
406 argp_error (state
, _("Option `%s' only valid with KDC/AS/TGS."),
407 state
->argv
[state
->next
- 1]);
408 parse_filename (arg
, &arguments
->kdcrepreadtype
,
409 &arguments
->kdcrepreadfile
);
412 case OPTION_KDC_SENDRECV
:
413 if (arguments
->command
!= COMMAND_KDC
)
414 argp_error (state
, _("Option `%s' only valid with KDC/AS/TGS."),
415 state
->argv
[state
->next
- 1]);
416 arguments
->sendrecv_p
= 1;
419 case OPTION_KDC_RESPONSE
:
420 if (arguments
->command
!= COMMAND_KDC
)
421 argp_error (state
, _("Option `%s' only valid with KDC/AS/TGS."),
422 state
->argv
[state
->next
- 1]);
423 arguments
->response_p
= 1;
427 if (state
->arg_num
!= 0)
428 argp_error (state
, _("Too many arguments: `%s'"), arg
);
431 if (strcmp (arg
, "as") == 0)
433 arguments
->command
= COMMAND_AS
;
435 else if (strcmp (arg
, "tgs") == 0)
437 arguments
->command
= COMMAND_TGS
;
439 else if (strcmp (arg
, "list") == 0)
441 arguments
->command
= COMMAND_LIST
;
443 else if (strcmp (arg
, "destroy") == 0)
445 arguments
->command
= COMMAND_DESTROY
;
447 else if (strcmp (arg
, "client") == 0)
449 arguments
->command
= COMMAND_CLIENT
;
451 else if (strcmp (arg
, "server") == 0)
453 arguments
->command
= COMMAND_SERVER
;
455 else if (strcmp (arg
, "ap") == 0)
457 arguments
->command
= COMMAND_AP
;
459 else if (strcmp (arg
, "crypto") == 0)
461 arguments
->command
= COMMAND_CRYPTO
;
463 else if (strcmp (arg
, "kdc") == 0)
465 arguments
->command
= COMMAND_KDC
;
469 argp_error (state
, _("Unknown command: '%s'"), arg
);
476 return ARGP_ERR_UNKNOWN
;
482 static struct argp_option options
[] = {
484 {0, 0, 0, 0, "Authentication commands:", 10},
486 {"as", 0, 0, OPTION_DOC
| OPTION_NO_USAGE
,
487 "Acquire ticket granting ticket using password via the Authentication "
488 "Service (AS) exchange."},
490 {"tgs", 0, 0, OPTION_DOC
| OPTION_NO_USAGE
,
491 "Acquire ticket using the ticket granting ticket via the Ticket-Granting "
492 "Service (TGS) exchange."},
494 {0, 0, 0, 0, "Ticket management:", 20},
496 {"list", 0, 0, OPTION_DOC
| OPTION_NO_USAGE
,
499 {"destroy", 0, 0, OPTION_DOC
| OPTION_NO_USAGE
,
502 {0, 0, 0, 0, "Utilities:", 30},
504 {"client", 0, 0, OPTION_DOC
| OPTION_NO_USAGE
,
505 "Simple stdin/stdout client."},
507 {"server", 0, 0, OPTION_DOC
| OPTION_NO_USAGE
,
508 "Simple stdin/stdout server."},
510 {0, 0, 0, 0, "Low-level commands:", 40},
512 {"ap", 0, 0, OPTION_DOC
| OPTION_NO_USAGE
,
513 "Client/Server Authentication (AP-REQ and AP-REP)."},
515 {"crypto", 0, 0, OPTION_DOC
| OPTION_NO_USAGE
,
516 "Cryptographic functions."},
518 {"kdc", 0, 0, OPTION_DOC
| OPTION_NO_USAGE
,
519 "Key Distribution Center Services (AS and TGS)."},
521 {0, 0, 0, 0, "If no command is given, Shishi invokes the AS command "
522 "if no ticket granting ticket is found, otherwise the LIST command "
525 /************** AS */
527 {0, 0, 0, 0, "Options for Authentication Service (AS-OPTIONS):", 100},
529 {"client-name", OPTION_AS_CLIENT_NAME
, "NAME", 0,
530 "Client name. Default is login username."},
532 {"encryption-type", 'e', "ETYPE,[ETYPE...]", 0,
533 "Encryption types to use. ETYPE is either registered name or integer."},
535 {"realm", 'r', "REALM", 0,
536 "Realm of client and server. Default is DNS domain of local host."},
538 {"password", OPTION_AS_PASSWORD
, "PASSWORD", 0,
539 "Password to decrypt response (discouraged). Default is to prompt user."},
541 /************** TGS */
543 {0, 0, 0, 0, "Options for Ticket Granting Service (TGS-OPTIONS):", 200},
545 {"client-name", OPTION_TGS_CLIENT_NAME
, "NAME", 0,
546 "Client name. Default is login username. Used to locate ticket "
549 {"encryption-type", 'e', "ETYPE,[ETYPE...]", 0,
550 "Encryption types to use. ETYPE is either registered name or integer."},
552 {"ticket-granter", OPTION_KDC_TICKET_GRANTER
, "NAME", 0,
553 "Name of server field in the ticket to use as the ticket granter. "
554 "Defaults to \"krbtgt/REALM@REALM\" where REALM is server "
555 "realm (see --realm)."},
557 {"realm", 'r', "REALM", 0,
558 "Realm of server. Default is DNS domain of local host."},
560 {"server-name", OPTION_TGS_SERVER_NAME
, "NAME", 0,
563 /************** LIST */
565 {0, 0, 0, 0, "Options for the List command (LIST-OPTIONS):", 300},
567 {"server-name", OPTION_LIST_SERVER_NAME
, "NAME", 0,
568 "List only tickets for specified server."},
570 /************** DESTROY */
572 {0, 0, 0, 0, "Options for the Destroy command (DESTROY-OPTIONS):", 400},
574 {"server-name", OPTION_DESTROY_SERVER_NAME
, "NAME", 0,
575 "Destroy only tickets for specified server."},
577 /************** CLIENT */
579 {0, 0, 0, 0, "Options for Network Client (CLIENT-OPTIONS):", 500},
581 {"options", OPTION_CLIENT_AP_OPTIONS
, "OPTION[,OPTION...]", 0,
582 "Indicate AP-OPTIONS separated by comma (,) or whitespace. "
583 "Options are integers (ORed together) or the pre-defined strings "
584 "\"use-session-key\" indicating that the ticket is encrypted in the "
585 "server's TGT key rather than its own key (not implemented) or "
586 "\"mutual-required\" indicating that mutual authentication is required."},
588 {"realm", 'r', "REALM", 0,
589 "Realm of server. Defaults to DNS domain of local host."},
591 {"server-name", OPTION_CLIENT_SERVER_NAME
, "NAME", 0,
592 "Name of server. Defaults to \"sample/REALM\" where REALM "
593 "is realm of server (see --realm)."},
595 /************** SERVER */
597 {0, 0, 0, 0, "Options for Network Server (SERVER-OPTIONS):", 600},
599 {"client-name", OPTION_KDC_CLIENT_NAME
, "NAME", 0,
600 "Client name. Default is login username."},
602 {"key-value", OPTION_SERVER_KEY_VALUE
, "KEY", 0,
603 "Cipher key of server."},
605 {"realm", 'r', "REALM", 0,
606 "Realm of server. Defaults to DNS domain of local host."},
608 {"server-name", OPTION_SERVER_SERVER_NAME
, "NAME", 0,
609 "Name of server. Defaults to \"sample/REALM\" where REALM "
610 "is realm of server (see --realm)."},
612 {"password", OPTION_SERVER_PASSWORD
, "PASSWORD", 0,
613 "Password to decrypt response (discouraged)."},
615 /************** AP */
618 "Options for low-level Client/Server Authentication (AP-OPTIONS):", 700},
620 {"data", OPTION_AP_AUTHENTICATOR_DATA
, "B64STRING", 0,
621 "Base64 encoded data to checksum in generated authenticator. "
622 "By default checksum is omitted (indicating no application payload)."},
624 {"read-ap-request-file", OPTION_AP_REQUEST_READ_FILE
, "[TYPE,]FILE", 0,
625 "Read AP-REQ from FILE in format TYPE; TEXT (default) or DER. "
626 "Default is to generate it."},
628 {"read-data-file", OPTION_AP_AUTHENTICATOR_READ_DATA_FILE
, "[TYPE,]FILE", 0,
629 "Read data to checksum in generated authenticator from FILE in format "
630 "TYPE, BASE64, HEX or BINARY (default). "
631 "By default checksum is omitted (indicating no application payload)."},
633 {"realm", 'r', "REALM", 0,
634 "Realm of server. Defaults to DNS domain of local host. Used for "
635 "locating the ticket to use."},
637 {"server-name", OPTION_AP_SERVER_NAME
, "NAME", 0,
638 "Name of server. Defaults to \"krbtgt.DEFAULTREALM\" where DEFAULTREALM "
639 "is realm of server. Used for locating the ticket to use."},
641 {"write-authenticator-file", OPTION_AP_AUTHENTICATOR_WRITE_FILE
,
643 "Write authenticator to FILE in format TYPE; TEXT (default) or DER. "
644 "Not written by default."},
646 {"write-ap-request-file", OPTION_AP_REQUEST_WRITE_FILE
, "[TYPE,]FILE", 0,
647 "Write AP-REQ to FILE in format TYPE; TEXT (default) or DER. "
648 "Default is stdout."},
650 /************** CRYPTO */
653 "Options for low-level cryptography (CRYPTO-OPTIONS):", 800},
655 {"algorithm", OPTION_CRYPTO_ALGORITHM
, "ALGORITHM", 0,
656 "Cipher algorithm, expressed either as the etype integer or "
657 "the registered name."},
659 {"client-name", OPTION_KDC_CLIENT_NAME
, "NAME", 0,
660 "Username. Default is login name."},
662 {"decrypt", OPTION_CRYPTO_DECRYPT
, 0, 0,
665 {"encrypt", OPTION_CRYPTO_ENCRYPT
, 0, 0,
668 {"key-usage", OPTION_CRYPTO_KEY_USAGE
, "KEYUSAGE", 0,
669 "Encrypt or decrypt using specified key usage. Default is 0, which means no "
670 "key derivation are performed."},
672 {"key-value", OPTION_CRYPTO_KEY_VALUE
, "KEY", 0,
673 "Base64 encoded key value."},
675 {"key-version", OPTION_CRYPTO_KEY_VERSION
, "INTEGER", 0,
676 "Version number of key."},
678 {"password", OPTION_CRYPTO_PASSWORD
, "PASSWORD", 0,
679 "Password used to generate key. --client-name and --realm also modify "
680 "the computed key value."},
682 {"random", OPTION_CRYPTO_RANDOM
, 0, 0,
683 "Generate key from random data."},
685 {"read-key-file", OPTION_CRYPTO_READ_KEY_FILE
, "FILE", 0,
686 "Read cipher key from FILE"},
688 {"read-data-file", OPTION_CRYPTO_READ_DATA_FILE
, "[TYPE,]FILE", 0,
689 "Read data from FILE in TYPE, BASE64, HEX or BINARY (default)."},
691 {"realm", 'r', "REALM", 0,
692 "Realm of principal. Defaults to DNS domain of local host. "},
694 {"salt", OPTION_CRYPTO_SALT
, "SALT", 0,
695 "Salt to use when --password is specified. Defaults to using the"
696 "username (--client-name) and realm (--realm)."},
698 {"parameter", OPTION_CRYPTO_PARAMETER
, "STRING", 0,
699 "String-to-key parameter to use when --password is specified. This data "
700 "is specific for each encryption algorithm and rarely needed."},
702 {"write-key-file", OPTION_CRYPTO_WRITE_KEY_FILE
, "FILE", 0,
703 "Append cipher key to FILE"},
705 {"write-data-file", OPTION_CRYPTO_WRITE_DATA_FILE
, "[TYPE,]FILE", 0,
706 "Write data to FILE in TYPE, BASE64, HEX or BINARY (default)."},
708 /************** KDC */
711 "Options for low-level Key Distribution Services (KDC-OPTIONS):", 900},
713 {"client-name", OPTION_KDC_CLIENT_NAME
, "NAME", 0,
714 "Client name. Default is login username. Only for AS."},
716 {"encryption-type", 'e', "ETYPE,[ETYPE...]", 0,
717 "Encryption types to use. ETYPE is either registered name or integer."},
719 {"force-as", OPTION_KDC_FORCE_AS
, 0, 0,
720 "Force AS mode. Default is to use TGS iff a TGT is found."},
722 {"force-tgs", OPTION_KDC_FORCE_TGS
, 0, 0,
723 "Force TGS mode. Default is to use TGS iff a TGT is found."},
725 {"realm", 'r', "REALM", 0,
726 "Realm of server. Default is DNS domain of local host. For AS, this also "
727 "indicates realm of client."},
729 {"server", OPTION_KDC_SERVER
, "HOST", 0,
730 "Send request to HOST. Default uses address from configuration file."},
732 {"server-name", OPTION_KDC_SERVER_NAME
, "NAME", 0,
733 "Server name. Default is \"krbtgt/REALM\" where REALM is server "
734 "realm (see --realm)."},
736 {"ticket-granter", OPTION_KDC_TICKET_GRANTER
, "NAME", 0,
737 "Service name in ticket to use for authenticating request. Only for TGS. "
738 "Defaults to \"krbtgt/REALM@REALM\" where REALM is server "
739 "realm (see --realm)."},
741 {"key-value", OPTION_KDC_KEY_VALUE
, "KEY", 0,
742 "Cipher key to decrypt response (discouraged)."},
744 {"read-kdc-request-file", OPTION_KDC_READ_REQUEST_FILE
, "[TYPE,]FILE", 0,
745 "Read KDC-REQ from FILE in format TYPE; TEXT (default) or DER. "
746 "Default is to generate it."},
748 {"read-kdc-response-file", OPTION_KDC_READ_RESPONSE_FILE
, "[TYPE,]FILE", 0,
749 "Read KDC-REP from FILE in format TYPE; TEXT (default) or DER. "
750 "Default is to receive it from server."},
752 {"request", OPTION_KDC_REQUEST
, 0, 0,
753 "Only generate the request."},
755 {"response", OPTION_KDC_RESPONSE
, 0, 0,
756 "Only parse request and response and output ticket."},
758 {"sendrecv", OPTION_KDC_SENDRECV
, 0, 0,
759 "Only send request and receive response."},
761 {"password", OPTION_CRYPTO_PASSWORD
, "PASSWORD", 0,
762 "Password to decrypt response (discouraged). Only for AS."},
764 {"write-ap-request-file", OPTION_KDC_WRITE_AP_REQUEST_FILE
, "[TYPE,]FILE",
766 "Write AP-REQ to FILE in TYPE, either TEXT (default) or DER. "
767 "Only for TGS. Not written by default."},
769 {"write-authenticator-file", OPTION_KDC_WRITE_AUTHENTICATOR_FILE
,
771 "Write Authenticator to FILE in TYPE, either TEXT (default) or DER. "
772 "Only for TGS. Not written by default."},
774 {"write-kdc-request-file", OPTION_KDC_WRITE_REQUEST_FILE
, "[TYPE,]FILE", 0,
775 "Write KDC-REQ to FILE in format TYPE; TEXT (default) or DER. "
776 "Not written by default."},
778 {"write-kdc-response-file", OPTION_KDC_WRITE_RESPONSE_FILE
, "[TYPE,]FILE",
780 "Write KDC-REP to FILE in format TYPE; TEXT (default) or DER. "
781 "Not written by default."},
783 /************** OTHER */
785 {0, 0, 0, 0, "Other options:", 1000},
787 {"verbose", 'v', 0, 0,
788 "Produce verbose output.",},
790 {"verbose-library", OPTION_VERBOSE_LIBRARY
, 0, 0,
791 "Produce verbose output in the library.",},
794 "Don't produce any output."},
796 {"silent", 0, 0, OPTION_ALIAS
},
798 {"system-configuration-file", 's', "FILE", 0,
799 "Read system wide configuration from file. Default is " SYSTEMCFGFILE
802 {"configuration-file", 'c', "FILE", 0,
803 "Read user configuration from file. Default is ~/.shishi/config."},
805 {"library-options", 'o', "STRING", 0,
806 "Parse STRING as a configuration file statement."},
808 {"ticket-file", 't', "FILE", 0,
809 "Read tickets from FILE. Default is $HOME/.shishi/tickets."},
811 {"ticket-write-file", 'w', "FILE", 0,
812 "Write tickets to FILE. Default is to write them back to ticket file."},
814 /************** EXAMPLES */
816 {0, 0, 0, 0, "Examples:", 2000},
818 {"shishi as", 0, 0, OPTION_DOC
| OPTION_NO_USAGE
,
819 "Get a ticket granting ticket from the default KDC server for the "
820 "default user and realm."},
822 {"shishi tgs --server-name=imap", 0, 0, OPTION_DOC
| OPTION_NO_USAGE
,
823 "Get a ticket for the imap server."},
825 {"shishi list --server-name=krbtgt/JOSEFSSON.ORG@JOSEFSSON.ORG",
826 0, 0, OPTION_DOC
| OPTION_NO_USAGE
,
827 "List tickets for the Ticket Granting Service in the JOSEFSSON.ORG realm."},
832 static struct argp argp
= {
835 "[COMMAND [COMMAND-OPTION...]]\n"
836 "as [AS-OPTION...]\n"
837 "tgs [TGS-OPTION...]\n"
838 "list [LIST-OPTION...]\n"
839 "destroy [DESTROY-OPTION...]\n"
840 "client [CLIENT-OPTION...]\n"
841 "server [SERVER-OPTION...]\n"
842 "ap [AP-OPTION...]\n" "crypto [CRYPTO-OPTION...]\n" "kdc [KDC-OPTION...]",
843 "Shishi -- A RFC 1510(bis) implementation"
847 main (int argc
, char *argv
[])
849 struct arguments arg
;
853 setlocale (LC_ALL
, "");
854 bindtextdomain (PACKAGE
, LOCALEDIR
);
855 textdomain (PACKAGE
);
857 memset (&arg
, 0, sizeof (arg
));
858 argp_parse (&argp
, argc
, argv
, ARGP_IN_ORDER
, 0, &arg
);
860 rc
= shishi_init_with_paths (&handle
, arg
.ticketfile
,
861 arg
.systemcfgfile
, arg
.usercfgfile
);
862 if (rc
== SHISHI_HANDLE_ERROR
)
863 error (1, 0, "Internal error: could not initialize shishi\n");
865 rc
= shishi_cfg_clientkdcetype_set (handle
, arg
.etypes
);
867 error (1, 0, "Could not set encryption types: %s\n", shishi_strerror (rc
));
869 rc
= shishi_cfg (handle
, arg
.lib_options
);
871 error (1, 0, "Could not read library options: %s\n", shishi_strerror (rc
));
873 if (arg
.verbose_library
)
875 rc
= shishi_cfg (handle
, "verbose");
877 error (1, 0, "Could not make library verbose: %s\n",
878 shishi_strerror (rc
));
881 if (arg
.cname
!= NULL
)
882 shishi_principal_default_set (handle
, arg
.cname
);
884 if (arg
.realm
!= NULL
)
885 shishi_realm_default_set (handle
, arg
.realm
);
887 if (arg
.tgtname
== NULL
)
889 asprintf (&arg
.tgtname
, "krbtgt/%s",
890 shishi_realm_default (handle
));
891 if (arg
.tgtname
== NULL
)
892 error (1, 0, "Could not allocate TGT name.");
904 rc
= shishi_as (handle
, &as
);
906 rc
= shishi_as_sendrecv (as
);
908 rc
= shishi_as_rep_process (as
, NULL
, arg
.password
);
911 printf ("AS exchange failed: %s\n%s\n", shishi_strerror (rc
),
912 shishi_strerror_details (handle
));
913 if (rc
== SHISHI_GOT_KRBERROR
)
914 shishi_krberror_pretty_print (handle
, stdout
,
915 shishi_as_krberror (as
));
921 shishi_kdcreq_print (handle
, stdout
, shishi_as_req (as
));
922 shishi_kdcrep_print (handle
, stdout
, shishi_as_rep (as
));
923 shishi_enckdcreppart_print
924 (handle
, stdout
, shishi_tkt_enckdcreppart (shishi_as_tkt (as
)));
927 tkt
= shishi_as_tkt (as
);
931 shishi_tkt_pretty_print (tkt
, stdout
);
932 shishi_tkt_lastreq_pretty_print (tkt
, stdout
);
935 rc
= shishi_tkts_add (shishi_tkts_default (handle
), tkt
);
937 printf ("Could not add ticket: %s", shishi_strerror (rc
));
947 tgt
= shishi_tkts_find_for_clientserver
948 (shishi_tkts_default (handle
),
949 shishi_principal_default (handle
), arg
.tgtname
);
952 printf ("TGT not found. Please use the AS command first.\n");
957 rc
= shishi_tgs (handle
, &tgs
);
958 shishi_tgs_tgtkt_set (tgs
, tgt
);
960 rc
= shishi_tgs_set_server (tgs
, arg
.sname
?
961 arg
.sname
: arg
.tgtname
);
963 rc
= shishi_tgs_req_build (tgs
);
965 rc
= shishi_tgs_sendrecv (tgs
);
967 rc
= shishi_tgs_rep_process (tgs
);
970 printf ("TGS exchange failed: %s\n%s\n", shishi_strerror (rc
),
971 shishi_strerror_details (handle
));
972 if (rc
== SHISHI_GOT_KRBERROR
)
973 shishi_krberror_pretty_print (handle
, stdout
,
974 shishi_tgs_krberror (tgs
));
980 shishi_authenticator_print
981 (handle
, stdout
, shishi_ap_authenticator (shishi_tgs_ap (tgs
)));
983 (handle
, stdout
, shishi_ap_req (shishi_tgs_ap (tgs
)));
984 shishi_kdcreq_print (handle
, stdout
, shishi_tgs_req (tgs
));
985 shishi_kdcrep_print (handle
, stdout
, shishi_tgs_rep (tgs
));
988 tkt
= shishi_tgs_tkt (tgs
);
992 shishi_tkt_lastreq_pretty_print (tkt
, stdout
);
993 shishi_tkt_pretty_print (tkt
, stdout
);
996 rc
= shishi_tkts_add (shishi_tkts_default (handle
), tkt
);
998 printf ("Could not add ticket: %s", shishi_strerror (rc
));
1004 printf (_("Tickets in `%s':\n"), shishi_tkts_default_file (handle
));
1006 rc
= shishi_tkts_print_for_service (shishi_tkts_default (handle
),
1008 if (rc
!= SHISHI_OK
)
1009 fprintf (stderr
, "Could not list tickets: %s", shishi_strerror (rc
));
1012 case COMMAND_DESTROY
:
1015 for (i
= 0; i
< shishi_tkts_size (shishi_tkts_default (handle
)); i
++)
1018 !shishi_tkt_server_p (shishi_tkts_nth
1019 (shishi_tkts_default (handle
),
1025 printf ("Removing ticket:\n");
1026 shishi_tkt_pretty_print (shishi_tkts_nth
1027 (shishi_tkts_default
1028 (handle
), i
), stdout
);
1031 rc
= shishi_tkts_remove (shishi_tkts_default (handle
), i
);
1032 if (rc
!= SHISHI_OK
)
1033 fprintf (stderr
, "Could not destroy ticket %d:\n%s\n", i
,
1034 shishi_strerror (rc
));
1039 printf ("No tickets removed.\n");
1040 else if (removed
== 1)
1041 printf ("1 ticket removed.\n");
1043 printf ("%d tickets removed.\n", removed
);
1048 case COMMAND_CLIENT
:
1049 rc
= client (handle
, arg
);
1052 case COMMAND_SERVER
:
1053 rc
= server (handle
, arg
);
1057 rc
= ap (handle
, arg
);
1060 case COMMAND_CRYPTO
:
1061 rc
= crypto (handle
, arg
);
1062 if (rc
!= SHISHI_OK
)
1063 fprintf (stderr
, "Operation failed:\n%s\n%s\n",
1064 shishi_strerror (rc
), shishi_strerror_details (handle
));
1068 //rc = kdc (handle, arg);
1075 tkt
= shishi_tkts_get_for_server (shishi_tkts_default (handle
),
1079 printf ("Could not get ticket for `%s'.\n", arg
.tgtname
);
1084 rc
= shishi_tkt_pretty_print (tkt
, stdout
);
1085 if (rc
!= SHISHI_OK
)
1086 fprintf (stderr
, "Operation failed:\n%s\n%s\n",
1087 shishi_strerror (rc
), shishi_strerror_details (handle
));
1092 shishi_tkts_expire (shishi_tkts_default (handle
));
1094 if (arg
.ticketwritefile
)
1095 shishi_tkts_default_file_set (handle
, arg
.ticketwritefile
);
1097 shishi_done (handle
);
1099 return rc
== SHISHI_OK
? 0 : 1;