196
165
#define USAGE_BREAK "\n\t"
198
167
#ifdef GETOPT_LONG
199
#define USAGE_LONG_FORWARDABLE " | --forwardable | --noforwardable"
200
#define USAGE_LONG_PROXIABLE " | --proxiable | --noproxiable"
201
#define USAGE_LONG_ADDRESSES " | --addresses | --noaddresses"
168
#define USAGE_LONG_FORWARDABLE " | --forwardable | --noforwardable"
169
#define USAGE_LONG_PROXIABLE " | --proxiable | --noproxiable"
170
#define USAGE_LONG_ADDRESSES " | --addresses | --noaddresses"
171
#define USAGE_LONG_CANONICALIZE " | --canonicalize"
172
#define USAGE_LONG_ENTERPRISE " | --enterprise"
202
173
#define USAGE_BREAK_LONG USAGE_BREAK
204
#define USAGE_LONG_FORWARDABLE ""
205
#define USAGE_LONG_PROXIABLE ""
206
#define USAGE_LONG_ADDRESSES ""
207
#define USAGE_BREAK_LONG ""
175
#define USAGE_LONG_FORWARDABLE ""
176
#define USAGE_LONG_PROXIABLE ""
177
#define USAGE_LONG_ADDRESSES ""
178
#define USAGE_LONG_CANONICALIZE ""
179
#define USAGE_LONG_ENTERPRISE ""
180
#define USAGE_BREAK_LONG ""
210
fprintf(stderr, "Usage: %s [-5] [-4] [-V] "
183
fprintf(stderr, "Usage: %s [-V] "
211
184
"[-l lifetime] [-s start_time] "
213
186
"[-r renewable_life] "
216
189
"[-p | -P" USAGE_LONG_PROXIABLE "] "
218
191
"[-a | -A" USAGE_LONG_ADDRESSES "] "
193
"[-C" USAGE_LONG_CANONICALIZE "] "
195
"[-E" USAGE_LONG_ENTERPRISE "] "
221
198
"[-k [-t keytab_file]] "
201
"[-S service_name]""-T ticket_armor_cache"
225
203
"[-X <attribute>[=<value>]] [principal]"
229
#define KRB_AVAIL_STRING(x) ((x)?"available":"not available")
231
#define OPTTYPE_KRB5 "5"
232
#define OPTTYPE_KRB4 "4"
233
#define OPTTYPE_EITHER "Either 4 or 5"
235
#define OPTTYPE_BOTH "5, or both 5 and 4"
237
#define OPTTYPE_BOTH "5"
240
#ifdef KRB5_KRB4_COMPAT
241
#define USAGE_OPT_FMT "%s%-50s%s\n"
242
#define ULINE(indent, col1, col2) \
243
fprintf(stderr, USAGE_OPT_FMT, indent, col1, col2)
245
#define USAGE_OPT_FMT "%s%s\n"
246
#define ULINE(indent, col1, col2) \
247
fprintf(stderr, USAGE_OPT_FMT, indent, col1)
250
ULINE(" ", "options:", "valid with Kerberos:");
251
fprintf(stderr, "\t-5 Kerberos 5 (%s)\n", KRB_AVAIL_STRING(got_k5));
252
fprintf(stderr, "\t-4 Kerberos 4 (%s)\n", KRB_AVAIL_STRING(got_k4));
253
fprintf(stderr, "\t (Default behavior is to try %s%s%s%s)\n",
254
default_k5?"Kerberos 5":"",
255
(default_k5 && default_k4)?" and ":"",
256
default_k4?"Kerberos 4":"",
257
(!default_k5 && !default_k4)?"neither":"");
258
ULINE("\t", "-V verbose", OPTTYPE_EITHER);
259
ULINE("\t", "-l lifetime", OPTTYPE_EITHER);
260
ULINE("\t", "-s start time", OPTTYPE_KRB5);
261
ULINE("\t", "-r renewable lifetime", OPTTYPE_KRB5);
262
ULINE("\t", "-f forwardable", OPTTYPE_KRB5);
263
ULINE("\t", "-F not forwardable", OPTTYPE_KRB5);
264
ULINE("\t", "-p proxiable", OPTTYPE_KRB5);
265
ULINE("\t", "-P not proxiable", OPTTYPE_KRB5);
266
ULINE("\t", "-a include addresses", OPTTYPE_KRB5);
267
ULINE("\t", "-A do not include addresses", OPTTYPE_KRB5);
268
ULINE("\t", "-v validate", OPTTYPE_KRB5);
269
ULINE("\t", "-R renew", OPTTYPE_BOTH);
270
ULINE("\t", "-k use keytab", OPTTYPE_BOTH);
271
ULINE("\t", "-t filename of keytab to use", OPTTYPE_BOTH);
272
ULINE("\t", "-c Kerberos 5 cache name", OPTTYPE_KRB5);
273
/* This options is not yet available: */
274
/* ULINE("\t", "-C Kerberos 4 cache name", OPTTYPE_KRB4); */
275
ULINE("\t", "-S service", OPTTYPE_BOTH);
276
ULINE("\t", "-X <attribute>[=<value>]", OPTTYPE_KRB5);
207
fprintf(stderr, " options:");
208
fprintf(stderr, "\t-V verbose\n");
209
fprintf(stderr, "\t-l lifetime\n");
210
fprintf(stderr, "\t-s start time\n");
211
fprintf(stderr, "\t-r renewable lifetime\n");
212
fprintf(stderr, "\t-f forwardable\n");
213
fprintf(stderr, "\t-F not forwardable\n");
214
fprintf(stderr, "\t-p proxiable\n");
215
fprintf(stderr, "\t-P not proxiable\n");
216
fprintf(stderr, "\t-a include addresses\n");
217
fprintf(stderr, "\t-A do not include addresses\n");
218
fprintf(stderr, "\t-v validate\n");
219
fprintf(stderr, "\t-R renew\n");
220
fprintf(stderr, "\t-C canonicalize\n");
221
fprintf(stderr, "\t-E client is enterprise principal name\n");
222
fprintf(stderr, "\t-k use keytab\n");
223
fprintf(stderr, "\t-t filename of keytab to use\n");
224
fprintf(stderr, "\t-c Kerberos 5 cache name\n");
225
fprintf(stderr, "\t-S service\n");
226
fprintf(stderr, "\t-X <attribute>[=<value>]\n");
491
/* At this point, if errorless, we know we only have one option
493
if (!use_k5 && !use_k4) {
498
/* Now, we encode the OPTTYPE stuff here... */
500
(opts->starttime || opts->rlife || opts->forwardable ||
501
opts->proxiable || opts->addresses || opts->not_forwardable ||
502
opts->not_proxiable || opts->no_addresses ||
503
(opts->action == VALIDATE) || opts->k5_cache_name))
505
fprintf(stderr, "Specified option that requires Kerberos 5\n");
511
fprintf(stderr, "Specified option that require Kerberos 4\n");
520
&& (opts->service_name || opts->keytab_name ||
521
(opts->action == INIT_KT) || (opts->action == RENEW))
524
fprintf(stderr, "Specified option that requires Kerberos 5\n");
532
got_k5 = got_k5 && use_k5;
533
got_k4 = got_k4 && use_k4;
535
425
opts->principal_name = (optind == argc-1) ? argv[optind] : 0;
536
426
return opts->principal_name;
540
k5_begin(opts, k5, k4)
541
431
struct k_opts* opts;
545
char* progname = progname_v5;
546
434
krb5_error_code code = 0;
435
int flags = opts->enterprise ? KRB5_PRINCIPAL_PARSE_ENTERPRISE : 0;
551
437
code = krb5_init_context(&k5->ctx);
655
528
memset(k5, 0, sizeof(*k5));
663
#ifdef KRB5_KRB4_COMPAT
664
char* progname = progname_v4;
671
#ifdef KRB5_KRB4_COMPAT
675
if (opts->principal_name)
677
/* Use specified name */
678
k_errno = kname_parse(k4->aname, k4->inst, k4->realm,
679
opts->principal_name);
682
fprintf(stderr, "%s: %s\n", progname,
683
krb_get_err_text(k_errno));
687
/* No principal name specified */
688
if (opts->action == INIT_KT) {
689
/* Use the default host/service name */
690
/* XXX - need to add this functionality */
691
fprintf(stderr, "%s: Kerberos 4 srvtab support is not "
692
"implemented\n", progname);
695
/* Get default principal from cache if one exists */
696
k_errno = krb_get_tf_fullname(tkt_string(), k4->aname,
697
k4->inst, k4->realm);
700
char *name = get_name_from_os();
703
fprintf(stderr, "Unable to identify user\n");
706
k_errno = kname_parse(k4->aname, k4->inst, k4->realm,
710
fprintf(stderr, "%s: %s\n", progname,
711
krb_get_err_text(k_errno));
719
krb_get_lrealm(k4->realm, 1);
722
sprintf(k4->name, "%s.%s@%s", k4->aname, k4->inst, k4->realm);
724
sprintf(k4->name, "%s@%s", k4->aname, k4->realm);
725
opts->principal_name = k4->name;
728
if (k4->aname[0] && !k_isname(k4->aname))
730
fprintf(stderr, "%s: bad Kerberos 4 name format\n", progname);
734
if (k4->inst[0] && !k_isinst(k4->inst))
736
fprintf(stderr, "%s: bad Kerberos 4 instance format\n", progname);
740
if (k4->realm[0] && !k_isrealm(k4->realm))
742
fprintf(stderr, "%s: bad Kerberos 4 realm format\n", progname);
745
#endif /* KRB5_KRB4_COMPAT */
753
memset(k4, 0, sizeof(*k4));
756
#ifdef KRB5_KRB4_COMPAT
757
static char stash_password[1024];
758
static int got_password = 0;
759
#endif /* KRB5_KRB4_COMPAT */
761
531
static krb5_error_code
951
699
return notix?0:1;
955
k4_kinit(opts, k4, ctx)
960
#ifdef KRB5_KRB4_COMPAT
961
char* progname = progname_v4;
971
#ifdef KRB5_KRB4_COMPAT
973
k4->lifetime = opts->lifetime;
975
k4->lifetime = KRB4_BACKUP_DEFAULT_LIFE_SECS;
977
k4->lifetime = krb_time_to_life(0, k4->lifetime);
979
switch (opts->action)
983
unsigned int pwsize = sizeof(stash_password);
984
krb5_error_code code;
987
sprintf(prompt, "Password for %s", opts->principal_name);
988
stash_password[0] = 0;
990
Note: krb5_read_password does not actually look at the
991
context, so we're ok even if we don't have a context. If
992
we cannot dynamically load krb5, we can substitute any
993
decent read password function instead of the krb5 one.
995
code = krb5_read_password(ctx, prompt, 0, stash_password, &pwsize);
996
if (code || pwsize == 0)
998
fprintf(stderr, "Error while reading password for '%s'\n",
999
opts->principal_name);
1000
memset(stash_password, 0, sizeof(stash_password));
1005
k_errno = krb_get_pw_in_tkt(k4->aname, k4->inst, k4->realm, "krbtgt",
1006
k4->realm, k4->lifetime, stash_password);
1009
fprintf(stderr, "%s: %s\n", progname,
1010
krb_get_err_text(k_errno));
1012
fprintf(stderr, "Maybe your KDC does not support v4. "
1013
"Try the -5 option next time.\n");
1019
fprintf(stderr, "%s: srvtabs are not supported\n", progname);
1022
fprintf(stderr, "%s: renewal of krb4 tickets is not supported\n",
1026
/* These cases are handled by the 524 code - this prevents the compiler
1027
warnings of not using all the enumerated types.
1040
getvprogname(v, progname)
1043
unsigned int len = strlen(progname) + 2 + strlen(v) + 2;
1044
char *ret = malloc(len);
1046
sprintf(ret, "%s(v%s)", progname, v);
1053
/* Convert krb5 tickets to krb4. */
1054
static int try_convert524(k5)
1057
char * progname = progname_v524;
1058
krb5_error_code code = 0;
1060
krb5_principal kpcserver = 0;
1061
krb5_creds *v5creds = 0;
1063
CREDENTIALS v4creds;
1065
if (!got_k4 || !got_k5)
1068
memset((char *) &increds, 0, sizeof(increds));
1070
From this point on, we can goto cleanup because increds is
1074
if ((code = krb5_build_principal(k5->ctx,
1076
krb5_princ_realm(k5->ctx, k5->me)->length,
1077
krb5_princ_realm(k5->ctx, k5->me)->data,
1079
krb5_princ_realm(k5->ctx, k5->me)->data,
1081
com_err(progname, code,
1082
"while creating service principal name");
1086
increds.client = k5->me;
1087
increds.server = kpcserver;
1088
/* Prevent duplicate free calls. */
1091
increds.times.endtime = 0;
1092
increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
1093
if ((code = krb5_get_credentials(k5->ctx, 0,
1097
com_err(progname, code,
1098
"getting V5 credentials");
1101
if ((icode = krb524_convert_creds_kdc(k5->ctx,
1104
com_err(progname, icode,
1105
"converting to V4 credentials");
1108
/* this is stolen from the v4 kinit */
1109
/* initialize ticket cache */
1110
if ((icode = in_tkt(v4creds.pname, v4creds.pinst)
1112
com_err(progname, icode,
1113
"trying to create the V4 ticket file");
1116
/* stash ticket, session key, etc. for future use */
1117
if ((icode = krb_save_credentials(v4creds.service,
1123
&(v4creds.ticket_st),
1124
v4creds.issue_date))) {
1125
com_err(progname, icode,
1126
"trying to save the V4 ticket");
1131
memset(&v4creds, 0, sizeof(v4creds));
1133
krb5_free_creds(k5->ctx, v5creds);
1135
krb5_free_cred_contents(k5->ctx, &increds);
1137
krb5_free_principal(k5->ctx, kpcserver);
1138
return !(code || icode);
1140
#endif /* HAVE_KRB524 */
1143
703
main(argc, argv)
1165
718
if(!isatty(fileno(stderr)))
1166
719
setvbuf(stderr, 0, _IONBF, 0);
1169
This is where we would put in code to dynamically load Kerberos
1170
libraries. Currenlty, we just get them implicitly.
1173
#ifdef KRB5_KRB4_COMPAT
1177
721
memset(&opts, 0, sizeof(opts));
1178
722
opts.action = INIT_PW;
1180
724
memset(&k5, 0, sizeof(k5));
1181
memset(&k4, 0, sizeof(k4));
1183
726
set_com_err_hook (extended_com_err_fn);
1185
parse_options(argc, argv, &opts, progname);
1187
got_k5 = k5_begin(&opts, &k5, &k4);
1188
got_k4 = k4_begin(&opts, &k4);
1190
authed_k5 = k5_kinit(&opts, &k5);
1193
authed_k4 = try_convert524(&k5);
1196
authed_k4 = k4_kinit(&opts, &k4, k5.ctx);
1197
#ifdef KRB5_KRB4_COMPAT
1198
memset(stash_password, 0, sizeof(stash_password));
728
parse_options(argc, argv, &opts);
730
if (k5_begin(&opts, &k5))
731
authed_k5 = k5_kinit(&opts, &k5);
1201
733
if (authed_k5 && opts.verbose)
1202
734
fprintf(stderr, "Authenticated to Kerberos v5\n");
1203
if (authed_k4 && opts.verbose)
1204
fprintf(stderr, "Authenticated to Kerberos v4\n");
1209
if ((got_k5 && !authed_k5) || (got_k4 && !authed_k4) ||
1210
(!got_k5 && !got_k4))