17c478bd9Sstevel@tonic-gate /* 2*56a424ccSmp153739 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 37c478bd9Sstevel@tonic-gate * Use is subject to license terms. 47c478bd9Sstevel@tonic-gate */ 57c478bd9Sstevel@tonic-gate 67c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 77c478bd9Sstevel@tonic-gate 87c478bd9Sstevel@tonic-gate /* 97c478bd9Sstevel@tonic-gate * clients/kinit/kinit.c 107c478bd9Sstevel@tonic-gate * 117c478bd9Sstevel@tonic-gate * Copyright 1990 by the Massachusetts Institute of Technology. 127c478bd9Sstevel@tonic-gate * All Rights Reserved. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * Export of this software from the United States of America may 157c478bd9Sstevel@tonic-gate * require a specific license from the United States Government. 167c478bd9Sstevel@tonic-gate * It is the responsibility of any person or organization contemplating 177c478bd9Sstevel@tonic-gate * export to obtain such a license before exporting. 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 207c478bd9Sstevel@tonic-gate * distribute this software and its documentation for any purpose and 217c478bd9Sstevel@tonic-gate * without fee is hereby granted, provided that the above copyright 227c478bd9Sstevel@tonic-gate * notice appear in all copies and that both that copyright notice and 237c478bd9Sstevel@tonic-gate * this permission notice appear in supporting documentation, and that 247c478bd9Sstevel@tonic-gate * the name of M.I.T. not be used in advertising or publicity pertaining 257c478bd9Sstevel@tonic-gate * to distribution of the software without specific, written prior 267c478bd9Sstevel@tonic-gate * permission. Furthermore if you modify this software you must label 277c478bd9Sstevel@tonic-gate * your software as modified software and not distribute it in such a 287c478bd9Sstevel@tonic-gate * fashion that it might be confused with the original M.I.T. software. 297c478bd9Sstevel@tonic-gate * M.I.T. makes no representations about the suitability of 307c478bd9Sstevel@tonic-gate * this software for any purpose. It is provided "as is" without express 317c478bd9Sstevel@tonic-gate * or implied warranty. 327c478bd9Sstevel@tonic-gate * 337c478bd9Sstevel@tonic-gate * 347c478bd9Sstevel@tonic-gate * Initialize a credentials cache. 357c478bd9Sstevel@tonic-gate */ 367c478bd9Sstevel@tonic-gate #include <k5-int.h> 377c478bd9Sstevel@tonic-gate #include <profile/prof_int.h> 387c478bd9Sstevel@tonic-gate #include <com_err.h> 397c478bd9Sstevel@tonic-gate #include <libintl.h> 407c478bd9Sstevel@tonic-gate 417c478bd9Sstevel@tonic-gate #include <krb5.h> 427c478bd9Sstevel@tonic-gate 437c478bd9Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT 447c478bd9Sstevel@tonic-gate #include <kerberosIV/krb.h> 457c478bd9Sstevel@tonic-gate #define HAVE_KRB524 467c478bd9Sstevel@tonic-gate #else 477c478bd9Sstevel@tonic-gate #undef HAVE_KRB524 487c478bd9Sstevel@tonic-gate #endif /* KRB5_KRB4_COMPAT */ 497c478bd9Sstevel@tonic-gate 507c478bd9Sstevel@tonic-gate #include <string.h> 517c478bd9Sstevel@tonic-gate #include <stdio.h> 527c478bd9Sstevel@tonic-gate #include <time.h> 537c478bd9Sstevel@tonic-gate #include <netdb.h> 547c478bd9Sstevel@tonic-gate #include <locale.h> 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate #ifdef GETOPT_LONG 577c478bd9Sstevel@tonic-gate #include <getopt.h> 587c478bd9Sstevel@tonic-gate #else /* GETOPT_LONG */ 597c478bd9Sstevel@tonic-gate #ifdef HAVE_UNISTD_H 607c478bd9Sstevel@tonic-gate #include <unistd.h> 617c478bd9Sstevel@tonic-gate #else /* HAVE_UNISTD_H */ 627c478bd9Sstevel@tonic-gate extern int optind; 637c478bd9Sstevel@tonic-gate extern char *optarg; 647c478bd9Sstevel@tonic-gate extern int getopt(); 657c478bd9Sstevel@tonic-gate #endif /* HAVE_UNISTD_H */ 667c478bd9Sstevel@tonic-gate #endif /* GETOPT_LONG */ 677c478bd9Sstevel@tonic-gate 687c478bd9Sstevel@tonic-gate #ifndef _WIN32 697c478bd9Sstevel@tonic-gate #define GET_PROGNAME(x) (strrchr((x), '/') ? strrchr((x), '/')+1 : (x)) 707c478bd9Sstevel@tonic-gate #else /* _WIN32 */ 717c478bd9Sstevel@tonic-gate #define GET_PROGNAME(x) max(max(strrchr((x), '/'), strrchr((x), '\\')) + 1,(x)) 727c478bd9Sstevel@tonic-gate #endif /* _WIN32 */ 737c478bd9Sstevel@tonic-gate 747c478bd9Sstevel@tonic-gate #ifdef HAVE_PWD_H 757c478bd9Sstevel@tonic-gate #include <pwd.h> 76*56a424ccSmp153739 static 777c478bd9Sstevel@tonic-gate char * get_name_from_os() 787c478bd9Sstevel@tonic-gate { 797c478bd9Sstevel@tonic-gate struct passwd *pw; 80*56a424ccSmp153739 if ((pw = getpwuid((int) getuid()))) 817c478bd9Sstevel@tonic-gate return pw->pw_name; 827c478bd9Sstevel@tonic-gate return 0; 837c478bd9Sstevel@tonic-gate } 847c478bd9Sstevel@tonic-gate #else /* HAVE_PWD_H */ 857c478bd9Sstevel@tonic-gate #ifdef _WIN32 86*56a424ccSmp153739 static 877c478bd9Sstevel@tonic-gate char * get_name_from_os() 887c478bd9Sstevel@tonic-gate { 897c478bd9Sstevel@tonic-gate static char name[1024]; 907c478bd9Sstevel@tonic-gate DWORD name_size = sizeof(name); 917c478bd9Sstevel@tonic-gate if (GetUserName(name, &name_size)) { 927c478bd9Sstevel@tonic-gate name[sizeof(name)-1] = 0; /* Just to be extra safe */ 937c478bd9Sstevel@tonic-gate return name; 947c478bd9Sstevel@tonic-gate } else { 957c478bd9Sstevel@tonic-gate return 0; 967c478bd9Sstevel@tonic-gate } 977c478bd9Sstevel@tonic-gate } 987c478bd9Sstevel@tonic-gate #else /* _WIN32 */ 99*56a424ccSmp153739 static 1007c478bd9Sstevel@tonic-gate char * get_name_from_os() 1017c478bd9Sstevel@tonic-gate { 1027c478bd9Sstevel@tonic-gate return 0; 1037c478bd9Sstevel@tonic-gate } 1047c478bd9Sstevel@tonic-gate #endif /* _WIN32 */ 1057c478bd9Sstevel@tonic-gate #endif /* HAVE_PWD_H */ 1067c478bd9Sstevel@tonic-gate 1077c478bd9Sstevel@tonic-gate static char* progname_v5 = 0; 1087c478bd9Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT 1097c478bd9Sstevel@tonic-gate static char* progname_v4 = 0; 1107c478bd9Sstevel@tonic-gate static char* progname_v524 = 0; 1117c478bd9Sstevel@tonic-gate #endif /* KRB5_KRB4_COMPAT */ 1127c478bd9Sstevel@tonic-gate #include <locale.h> 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate static int got_k5 = 0; 1157c478bd9Sstevel@tonic-gate static int got_k4 = 0; 1167c478bd9Sstevel@tonic-gate 1177c478bd9Sstevel@tonic-gate static int default_k5 = 1; 1187c478bd9Sstevel@tonic-gate #if defined(KRB5_KRB4_COMPAT) && defined(KINIT_DEFAULT_BOTH) 1197c478bd9Sstevel@tonic-gate static int default_k4 = 1; 1207c478bd9Sstevel@tonic-gate #else /* KRB5_KRB4_COMPAT && KINIT_DEFAULT_BOTH */ 1217c478bd9Sstevel@tonic-gate static int default_k4 = 0; 1227c478bd9Sstevel@tonic-gate #endif /* KRB5_KRB4_COMPAT && KINIT_DEFAULT_BOTH */ 1237c478bd9Sstevel@tonic-gate 1247c478bd9Sstevel@tonic-gate static int authed_k5 = 0; 1257c478bd9Sstevel@tonic-gate static int authed_k4 = 0; 1267c478bd9Sstevel@tonic-gate 127*56a424ccSmp153739 #define KRB4_BACKUP_DEFAULT_LIFE_SECS 24*60*60 /* 1 day */ 1287c478bd9Sstevel@tonic-gate #define ROOT_UNAME "root" 1297c478bd9Sstevel@tonic-gate 1307c478bd9Sstevel@tonic-gate typedef enum { INIT_PW, INIT_KT, RENEW, VALIDATE } action_type; 1317c478bd9Sstevel@tonic-gate 1327c478bd9Sstevel@tonic-gate struct k_opts 1337c478bd9Sstevel@tonic-gate { 1347c478bd9Sstevel@tonic-gate /* in seconds */ 1357c478bd9Sstevel@tonic-gate krb5_deltat starttime; 1367c478bd9Sstevel@tonic-gate krb5_deltat lifetime; 1377c478bd9Sstevel@tonic-gate krb5_deltat rlife; 1387c478bd9Sstevel@tonic-gate 1397c478bd9Sstevel@tonic-gate int forwardable; 1407c478bd9Sstevel@tonic-gate int proxiable; 1417c478bd9Sstevel@tonic-gate int addresses; 1427c478bd9Sstevel@tonic-gate 1437c478bd9Sstevel@tonic-gate int not_forwardable; 1447c478bd9Sstevel@tonic-gate int not_proxiable; 1457c478bd9Sstevel@tonic-gate int no_addresses; 1467c478bd9Sstevel@tonic-gate 1477c478bd9Sstevel@tonic-gate int verbose; 1487c478bd9Sstevel@tonic-gate 1497c478bd9Sstevel@tonic-gate char* principal_name; 1507c478bd9Sstevel@tonic-gate char* service_name; 1517c478bd9Sstevel@tonic-gate char* keytab_name; 1527c478bd9Sstevel@tonic-gate char* k5_cache_name; 1537c478bd9Sstevel@tonic-gate char* k4_cache_name; 1547c478bd9Sstevel@tonic-gate 1557c478bd9Sstevel@tonic-gate action_type action; 1567c478bd9Sstevel@tonic-gate }; 1577c478bd9Sstevel@tonic-gate 1587c478bd9Sstevel@tonic-gate int forwardable_flag = 0; 1597c478bd9Sstevel@tonic-gate int renewable_flag = 0; 1607c478bd9Sstevel@tonic-gate int proxiable_flag = 0; 1617c478bd9Sstevel@tonic-gate int no_address_flag = 0; 1627c478bd9Sstevel@tonic-gate profile_options_boolean config_option[] = { 1637c478bd9Sstevel@tonic-gate { "forwardable", &forwardable_flag, 0 }, 1647c478bd9Sstevel@tonic-gate { "renewable", &renewable_flag, 0 }, 1657c478bd9Sstevel@tonic-gate { "proxiable", &proxiable_flag, 0 }, 1667c478bd9Sstevel@tonic-gate { "no_addresses", &no_address_flag, 0 }, 1677c478bd9Sstevel@tonic-gate { NULL, NULL, 0 } 1687c478bd9Sstevel@tonic-gate }; 1697c478bd9Sstevel@tonic-gate 1707c478bd9Sstevel@tonic-gate char *renew_timeval=NULL; 1717c478bd9Sstevel@tonic-gate char *life_timeval=NULL; 1727c478bd9Sstevel@tonic-gate int lifetime_specified; 1737c478bd9Sstevel@tonic-gate int renewtime_specified; 1747c478bd9Sstevel@tonic-gate profile_option_strings config_times[] = { 1757c478bd9Sstevel@tonic-gate { "max_life", &life_timeval, 0 }, 1767c478bd9Sstevel@tonic-gate { "max_renewable_life", &renew_timeval, 0 }, 1777c478bd9Sstevel@tonic-gate { NULL, NULL, 0 } 1787c478bd9Sstevel@tonic-gate }; 1797c478bd9Sstevel@tonic-gate 1807c478bd9Sstevel@tonic-gate struct k5_data 1817c478bd9Sstevel@tonic-gate { 1827c478bd9Sstevel@tonic-gate krb5_context ctx; 1837c478bd9Sstevel@tonic-gate krb5_ccache cc; 1847c478bd9Sstevel@tonic-gate krb5_principal me; 1857c478bd9Sstevel@tonic-gate char* name; 1867c478bd9Sstevel@tonic-gate }; 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate struct k4_data 1897c478bd9Sstevel@tonic-gate { 1907c478bd9Sstevel@tonic-gate krb5_deltat lifetime; 1917c478bd9Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT 1927c478bd9Sstevel@tonic-gate char aname[ANAME_SZ + 1]; 1937c478bd9Sstevel@tonic-gate char inst[INST_SZ + 1]; 1947c478bd9Sstevel@tonic-gate char realm[REALM_SZ + 1]; 1957c478bd9Sstevel@tonic-gate char name[ANAME_SZ + 1 + INST_SZ + 1 + REALM_SZ + 1]; 1967c478bd9Sstevel@tonic-gate #endif /*KRB5_KRB4_COMPAT */ 1977c478bd9Sstevel@tonic-gate }; 1987c478bd9Sstevel@tonic-gate 1997c478bd9Sstevel@tonic-gate char *realmdef[] = { "realms", NULL, "kinit", NULL }; 2007c478bd9Sstevel@tonic-gate char *appdef[] = { "appdefaults", "kinit", NULL }; 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate #define krb_realm (*(realmdef + 1)) 2037c478bd9Sstevel@tonic-gate 2047c478bd9Sstevel@tonic-gate #define lifetime_specified config_times[0].found 2057c478bd9Sstevel@tonic-gate #define renewtime_specified config_times[1].found 2067c478bd9Sstevel@tonic-gate 2077c478bd9Sstevel@tonic-gate /* 2087c478bd9Sstevel@tonic-gate * Try no preauthentication first; then try the encrypted timestamp 2097c478bd9Sstevel@tonic-gate */ 2107c478bd9Sstevel@tonic-gate krb5_preauthtype * preauth = NULL; 2117c478bd9Sstevel@tonic-gate krb5_preauthtype preauth_list[2] = { 0, -1 }; 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate static void _kwarnd_add_warning(char *, time_t); 2147c478bd9Sstevel@tonic-gate static void _kwarnd_del_warning(char *); 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate #ifdef GETOPT_LONG 2177c478bd9Sstevel@tonic-gate /* if struct[2] == NULL, then long_getopt acts as if the short flag 2187c478bd9Sstevel@tonic-gate struct[3] was specified. If struct[2] != NULL, then struct[3] is 2197c478bd9Sstevel@tonic-gate stored in *(struct[2]), the array index which was specified is 2207c478bd9Sstevel@tonic-gate stored in *index, and long_getopt() returns 0. */ 2217c478bd9Sstevel@tonic-gate 2227c478bd9Sstevel@tonic-gate struct option long_options[] = { 2237c478bd9Sstevel@tonic-gate { "noforwardable", 0, NULL, 'F' }, 2247c478bd9Sstevel@tonic-gate { "noproxiable", 0, NULL, 'P' }, 2257c478bd9Sstevel@tonic-gate { "addresses", 0, NULL, 'a'}, 2267c478bd9Sstevel@tonic-gate { "forwardable", 0, NULL, 'f' }, 2277c478bd9Sstevel@tonic-gate { "proxiable", 0, NULL, 'p' }, 2287c478bd9Sstevel@tonic-gate { "noaddresses", 0, NULL, 'A' }, 2297c478bd9Sstevel@tonic-gate { NULL, 0, NULL, 0 } 2307c478bd9Sstevel@tonic-gate }; 2317c478bd9Sstevel@tonic-gate 2327c478bd9Sstevel@tonic-gate #define GETOPT(argc, argv, str) getopt_long(argc, argv, str, long_options, 0) 2337c478bd9Sstevel@tonic-gate #else /* GETOPT_LONG */ 2347c478bd9Sstevel@tonic-gate #define GETOPT(argc, argv, str) getopt(argc, argv, str) 2357c478bd9Sstevel@tonic-gate #endif /* GETOPT_LONG */ 2367c478bd9Sstevel@tonic-gate 2377c478bd9Sstevel@tonic-gate /* Save the program name for the error messages */ 2387c478bd9Sstevel@tonic-gate static char *progname; 2397c478bd9Sstevel@tonic-gate 240*56a424ccSmp153739 static void 241*56a424ccSmp153739 usage(progname) 2427c478bd9Sstevel@tonic-gate { 2437c478bd9Sstevel@tonic-gate #define USAGE_BREAK "\n\t" 244*56a424ccSmp153739 2457c478bd9Sstevel@tonic-gate #ifdef GETOPT_LONG 2467c478bd9Sstevel@tonic-gate #define USAGE_LONG_FORWARDABLE " | --forwardable | --noforwardable" 2477c478bd9Sstevel@tonic-gate #define USAGE_LONG_PROXIABLE " | --proxiable | --noproxiable" 2487c478bd9Sstevel@tonic-gate #define USAGE_LONG_ADDRESSES " | --addresses | --noaddresses" 2497c478bd9Sstevel@tonic-gate #define USAGE_BREAK_LONG USAGE_BREAK 2507c478bd9Sstevel@tonic-gate #else /* GETOPT_LONG */ 2517c478bd9Sstevel@tonic-gate #define USAGE_LONG_FORWARDABLE "" 2527c478bd9Sstevel@tonic-gate #define USAGE_LONG_PROXIABLE "" 2537c478bd9Sstevel@tonic-gate #define USAGE_LONG_ADDRESSES "" 2547c478bd9Sstevel@tonic-gate #define USAGE_BREAK_LONG "" 2557c478bd9Sstevel@tonic-gate #endif /* GETOPT_LONG */ 2567c478bd9Sstevel@tonic-gate 2577c478bd9Sstevel@tonic-gate fprintf(stderr, "%s : %s [-V] " 2587c478bd9Sstevel@tonic-gate "[-l lifetime] [-s start_time] " 2597c478bd9Sstevel@tonic-gate USAGE_BREAK 2607c478bd9Sstevel@tonic-gate "[-r renewable_life] " 2617c478bd9Sstevel@tonic-gate "[-f | -F" USAGE_LONG_FORWARDABLE "] " 2627c478bd9Sstevel@tonic-gate USAGE_BREAK_LONG 2637c478bd9Sstevel@tonic-gate "[-p | -P" USAGE_LONG_PROXIABLE "] " 2647c478bd9Sstevel@tonic-gate USAGE_BREAK_LONG 265*56a424ccSmp153739 "[-a | -A" USAGE_LONG_ADDRESSES "] " 2667c478bd9Sstevel@tonic-gate USAGE_BREAK 2677c478bd9Sstevel@tonic-gate "[-v] [-R] " 2687c478bd9Sstevel@tonic-gate "[-k [-t keytab_file]] " 2697c478bd9Sstevel@tonic-gate USAGE_BREAK 2707c478bd9Sstevel@tonic-gate "[-c cachename] " 2717c478bd9Sstevel@tonic-gate "[-S service_name] [principal]" 2727c478bd9Sstevel@tonic-gate "\n\n", 2737c478bd9Sstevel@tonic-gate gettext("Usage"), progname); 2747c478bd9Sstevel@tonic-gate 2757c478bd9Sstevel@tonic-gate #define KRB_AVAIL_STRING(x) ((x)?gettext("available"):gettext("not available")) 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate #define OPTTYPE_KRB5 "5" 2787c478bd9Sstevel@tonic-gate #define OPTTYPE_KRB4 "4" 2797c478bd9Sstevel@tonic-gate #define OPTTYPE_EITHER "Either 4 or 5" 2807c478bd9Sstevel@tonic-gate #ifdef HAVE_KRB524 2817c478bd9Sstevel@tonic-gate #define OPTTYPE_BOTH "5, or both 5 and 4" 2827c478bd9Sstevel@tonic-gate #else 2837c478bd9Sstevel@tonic-gate #define OPTTYPE_BOTH "5" 2847c478bd9Sstevel@tonic-gate #endif 2857c478bd9Sstevel@tonic-gate 2867c478bd9Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT 2877c478bd9Sstevel@tonic-gate #define USAGE_OPT_FMT "%s%-50s%s\n" 2887c478bd9Sstevel@tonic-gate #define ULINE(indent, col1, col2) \ 2897c478bd9Sstevel@tonic-gate fprintf(stderr, USAGE_OPT_FMT, indent, col1, col2) 290*56a424ccSmp153739 #else 291*56a424ccSmp153739 #define USAGE_OPT_FMT "%s%s\n" 292*56a424ccSmp153739 #define ULINE(indent, col1, col2) \ 293*56a424ccSmp153739 fprintf(stderr, USAGE_OPT_FMT, indent, col1) 294*56a424ccSmp153739 #endif 2957c478bd9Sstevel@tonic-gate 2967c478bd9Sstevel@tonic-gate ULINE(" ", "options:", "valid with Kerberos:"); 2977c478bd9Sstevel@tonic-gate fprintf(stderr, "\t-5 Kerberos 5 (%s)\n", KRB_AVAIL_STRING(got_k5)); 2987c478bd9Sstevel@tonic-gate fprintf(stderr, "\t-4 Kerberos 4 (%s)\n", KRB_AVAIL_STRING(got_k4)); 2997c478bd9Sstevel@tonic-gate fprintf(stderr, "\t (Default behavior is to try %s%s%s%s)\n", 3007c478bd9Sstevel@tonic-gate default_k5?"Kerberos 5":"", 3017c478bd9Sstevel@tonic-gate (default_k5 && default_k4)?gettext(" and "):"", 3027c478bd9Sstevel@tonic-gate default_k4?"Kerberos 4":"", 3037c478bd9Sstevel@tonic-gate (!default_k5 && !default_k4)?gettext("neither"):""); 3047c478bd9Sstevel@tonic-gate ULINE("\t", gettext("-V verbose"), OPTTYPE_EITHER); 3057c478bd9Sstevel@tonic-gate ULINE("\t", gettext("-l lifetime"), OPTTYPE_EITHER); 3067c478bd9Sstevel@tonic-gate ULINE("\t", gettext("-s start time"), OPTTYPE_KRB5); 3077c478bd9Sstevel@tonic-gate ULINE("\t", gettext("-r renewable lifetime"), OPTTYPE_KRB5); 3087c478bd9Sstevel@tonic-gate ULINE("\t", gettext("-f forwardable"), OPTTYPE_KRB5); 3097c478bd9Sstevel@tonic-gate ULINE("\t", gettext("-F not forwardable"), OPTTYPE_KRB5); 3107c478bd9Sstevel@tonic-gate ULINE("\t", gettext("-p proxiable"), OPTTYPE_KRB5); 3117c478bd9Sstevel@tonic-gate ULINE("\t", gettext("-P not proxiable"), OPTTYPE_KRB5); 3127c478bd9Sstevel@tonic-gate ULINE("\t", gettext("-A do not include addresses"), OPTTYPE_KRB5); 313*56a424ccSmp153739 ULINE("\t", gettext("-a include addresses"), OPTTYPE_KRB5); 3147c478bd9Sstevel@tonic-gate ULINE("\t", gettext("-v validate"), OPTTYPE_KRB5); 3157c478bd9Sstevel@tonic-gate ULINE("\t", gettext("-R renew"), OPTTYPE_BOTH); 3167c478bd9Sstevel@tonic-gate ULINE("\t", gettext("-k use keytab"), OPTTYPE_BOTH); 3177c478bd9Sstevel@tonic-gate ULINE("\t", gettext("-t filename of keytab to use"), OPTTYPE_BOTH); 3187c478bd9Sstevel@tonic-gate ULINE("\t", gettext("-c Kerberos 5 cache name"), OPTTYPE_KRB5); 3197c478bd9Sstevel@tonic-gate /* This options is not yet available: */ 3207c478bd9Sstevel@tonic-gate /* ULINE("\t", "-C Kerberos 4 cache name", OPTTYPE_KRB4); */ 3217c478bd9Sstevel@tonic-gate ULINE("\t", gettext("-S service"), OPTTYPE_BOTH); 3227c478bd9Sstevel@tonic-gate exit(2); 3237c478bd9Sstevel@tonic-gate } 3247c478bd9Sstevel@tonic-gate 325*56a424ccSmp153739 static char * 326*56a424ccSmp153739 parse_options(argc, argv, opts, progname) 3277c478bd9Sstevel@tonic-gate int argc; 3287c478bd9Sstevel@tonic-gate char **argv; 3297c478bd9Sstevel@tonic-gate struct k_opts* opts; 330*56a424ccSmp153739 char *progname; 3317c478bd9Sstevel@tonic-gate { 3327c478bd9Sstevel@tonic-gate krb5_error_code code; 3337c478bd9Sstevel@tonic-gate int errflg = 0; 3347c478bd9Sstevel@tonic-gate int use_k4 = 0; 3357c478bd9Sstevel@tonic-gate int use_k5 = 0; 3367c478bd9Sstevel@tonic-gate int i; 3377c478bd9Sstevel@tonic-gate 338*56a424ccSmp153739 while ((i = GETOPT(argc, argv, "r:fpFP54aAVl:s:c:kt:RS:v")) 3397c478bd9Sstevel@tonic-gate != -1) { 3407c478bd9Sstevel@tonic-gate switch (i) { 3417c478bd9Sstevel@tonic-gate case 'V': 3427c478bd9Sstevel@tonic-gate opts->verbose = 1; 3437c478bd9Sstevel@tonic-gate break; 3447c478bd9Sstevel@tonic-gate case 'l': 3457c478bd9Sstevel@tonic-gate /* Lifetime */ 3467c478bd9Sstevel@tonic-gate code = krb5_string_to_deltat(optarg, &opts->lifetime); 3477c478bd9Sstevel@tonic-gate if (code != 0 || opts->lifetime == 0) { 3487c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Bad lifetime value %s\n"), optarg); 3497c478bd9Sstevel@tonic-gate errflg++; 3507c478bd9Sstevel@tonic-gate } 3517c478bd9Sstevel@tonic-gate break; 3527c478bd9Sstevel@tonic-gate case 'r': 3537c478bd9Sstevel@tonic-gate /* Renewable Time */ 3547c478bd9Sstevel@tonic-gate code = krb5_string_to_deltat(optarg, &opts->rlife); 3557c478bd9Sstevel@tonic-gate if (code != 0 || opts->rlife == 0) { 3567c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Bad lifetime value %s\n"), optarg); 3577c478bd9Sstevel@tonic-gate errflg++; 3587c478bd9Sstevel@tonic-gate } 3597c478bd9Sstevel@tonic-gate break; 3607c478bd9Sstevel@tonic-gate case 'f': 3617c478bd9Sstevel@tonic-gate opts->forwardable = 1; 3627c478bd9Sstevel@tonic-gate break; 3637c478bd9Sstevel@tonic-gate case 'F': 3647c478bd9Sstevel@tonic-gate opts->not_forwardable = 1; 3657c478bd9Sstevel@tonic-gate break; 3667c478bd9Sstevel@tonic-gate case 'p': 3677c478bd9Sstevel@tonic-gate opts->proxiable = 1; 3687c478bd9Sstevel@tonic-gate break; 3697c478bd9Sstevel@tonic-gate case 'P': 3707c478bd9Sstevel@tonic-gate opts->not_proxiable = 1; 3717c478bd9Sstevel@tonic-gate break; 3727c478bd9Sstevel@tonic-gate case 'a': 3737c478bd9Sstevel@tonic-gate /* Note: This is supported only with GETOPT_LONG */ 3747c478bd9Sstevel@tonic-gate opts->addresses = 1; 3757c478bd9Sstevel@tonic-gate break; 3767c478bd9Sstevel@tonic-gate case 'A': 3777c478bd9Sstevel@tonic-gate opts->no_addresses = 1; 3787c478bd9Sstevel@tonic-gate break; 3797c478bd9Sstevel@tonic-gate case 's': 3807c478bd9Sstevel@tonic-gate code = krb5_string_to_deltat(optarg, &opts->starttime); 3817c478bd9Sstevel@tonic-gate if (code != 0 || opts->starttime == 0) { 3827c478bd9Sstevel@tonic-gate krb5_timestamp abs_starttime; 3837c478bd9Sstevel@tonic-gate 3847c478bd9Sstevel@tonic-gate code = krb5_string_to_timestamp(optarg, &abs_starttime); 3857c478bd9Sstevel@tonic-gate if (code != 0 || abs_starttime == 0) { 3867c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Bad start time value %s\n"), optarg); 3877c478bd9Sstevel@tonic-gate errflg++; 3887c478bd9Sstevel@tonic-gate } else { 3897c478bd9Sstevel@tonic-gate opts->starttime = abs_starttime - time(0); 3907c478bd9Sstevel@tonic-gate } 3917c478bd9Sstevel@tonic-gate } 3927c478bd9Sstevel@tonic-gate break; 3937c478bd9Sstevel@tonic-gate case 'S': 3947c478bd9Sstevel@tonic-gate opts->service_name = optarg; 3957c478bd9Sstevel@tonic-gate break; 3967c478bd9Sstevel@tonic-gate case 'k': 3977c478bd9Sstevel@tonic-gate opts->action = INIT_KT; 3987c478bd9Sstevel@tonic-gate break; 3997c478bd9Sstevel@tonic-gate case 't': 4007c478bd9Sstevel@tonic-gate if (opts->keytab_name) 4017c478bd9Sstevel@tonic-gate { 4027c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Only one -t option allowed.\n")); 4037c478bd9Sstevel@tonic-gate errflg++; 4047c478bd9Sstevel@tonic-gate } else { 4057c478bd9Sstevel@tonic-gate opts->keytab_name = optarg; 4067c478bd9Sstevel@tonic-gate } 4077c478bd9Sstevel@tonic-gate break; 4087c478bd9Sstevel@tonic-gate case 'R': 4097c478bd9Sstevel@tonic-gate opts->action = RENEW; 4107c478bd9Sstevel@tonic-gate break; 4117c478bd9Sstevel@tonic-gate case 'v': 4127c478bd9Sstevel@tonic-gate opts->action = VALIDATE; 4137c478bd9Sstevel@tonic-gate break; 4147c478bd9Sstevel@tonic-gate case 'c': 4157c478bd9Sstevel@tonic-gate if (opts->k5_cache_name) 4167c478bd9Sstevel@tonic-gate { 4177c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Only one -c option allowed\n")); 4187c478bd9Sstevel@tonic-gate errflg++; 4197c478bd9Sstevel@tonic-gate } else { 4207c478bd9Sstevel@tonic-gate opts->k5_cache_name = optarg; 4217c478bd9Sstevel@tonic-gate } 4227c478bd9Sstevel@tonic-gate break; 4237c478bd9Sstevel@tonic-gate #if 0 4247c478bd9Sstevel@tonic-gate /* 4257c478bd9Sstevel@tonic-gate A little more work is needed before we can enable this 4267c478bd9Sstevel@tonic-gate option. 4277c478bd9Sstevel@tonic-gate */ 4287c478bd9Sstevel@tonic-gate case 'C': 4297c478bd9Sstevel@tonic-gate if (opts->k4_cache_name) 4307c478bd9Sstevel@tonic-gate { 4317c478bd9Sstevel@tonic-gate fprintf(stderr, "Only one -C option allowed\n"); 4327c478bd9Sstevel@tonic-gate errflg++; 4337c478bd9Sstevel@tonic-gate } else { 4347c478bd9Sstevel@tonic-gate opts->k4_cache_name = optarg; 4357c478bd9Sstevel@tonic-gate } 4367c478bd9Sstevel@tonic-gate break; 4377c478bd9Sstevel@tonic-gate #endif 4387c478bd9Sstevel@tonic-gate case '4': 4397c478bd9Sstevel@tonic-gate if (!got_k4) 4407c478bd9Sstevel@tonic-gate { 4417c478bd9Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT 4427c478bd9Sstevel@tonic-gate fprintf(stderr, "Kerberos 4 support could not be loaded\n"); 4437c478bd9Sstevel@tonic-gate #else 4447c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("This was not built with Kerberos 4 support\n")); 4457c478bd9Sstevel@tonic-gate #endif 4467c478bd9Sstevel@tonic-gate exit(3); 4477c478bd9Sstevel@tonic-gate } 4487c478bd9Sstevel@tonic-gate use_k4 = 1; 4497c478bd9Sstevel@tonic-gate break; 4507c478bd9Sstevel@tonic-gate case '5': 4517c478bd9Sstevel@tonic-gate if (!got_k5) 4527c478bd9Sstevel@tonic-gate { 4537c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Kerberos 5 support could not be loaded\n")); 4547c478bd9Sstevel@tonic-gate exit(3); 4557c478bd9Sstevel@tonic-gate } 4567c478bd9Sstevel@tonic-gate use_k5 = 1; 4577c478bd9Sstevel@tonic-gate break; 4587c478bd9Sstevel@tonic-gate default: 4597c478bd9Sstevel@tonic-gate errflg++; 4607c478bd9Sstevel@tonic-gate break; 4617c478bd9Sstevel@tonic-gate } 4627c478bd9Sstevel@tonic-gate } 4637c478bd9Sstevel@tonic-gate 4647c478bd9Sstevel@tonic-gate if (opts->forwardable && opts->not_forwardable) 4657c478bd9Sstevel@tonic-gate { 4667c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Only one of -f and -F allowed\n")); 4677c478bd9Sstevel@tonic-gate errflg++; 4687c478bd9Sstevel@tonic-gate } 4697c478bd9Sstevel@tonic-gate if (opts->proxiable && opts->not_proxiable) 4707c478bd9Sstevel@tonic-gate { 4717c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Only one of -p and -P allowed\n")); 4727c478bd9Sstevel@tonic-gate errflg++; 4737c478bd9Sstevel@tonic-gate } 4747c478bd9Sstevel@tonic-gate if (opts->addresses && opts->no_addresses) 4757c478bd9Sstevel@tonic-gate { 4767c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Only one of -a and -A allowed\n")); 4777c478bd9Sstevel@tonic-gate errflg++; 4787c478bd9Sstevel@tonic-gate } 4797c478bd9Sstevel@tonic-gate 4807c478bd9Sstevel@tonic-gate if (argc - optind > 1) { 4817c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Extra arguments (starting with \"%s\").\n"), 4827c478bd9Sstevel@tonic-gate argv[optind+1]); 4837c478bd9Sstevel@tonic-gate errflg++; 4847c478bd9Sstevel@tonic-gate } 4857c478bd9Sstevel@tonic-gate 4867c478bd9Sstevel@tonic-gate /* At this point, if errorless, we know we only have one option 4877c478bd9Sstevel@tonic-gate selection */ 4887c478bd9Sstevel@tonic-gate if (!use_k5 && !use_k4) { 4897c478bd9Sstevel@tonic-gate use_k5 = default_k5; 4907c478bd9Sstevel@tonic-gate use_k4 = default_k4; 4917c478bd9Sstevel@tonic-gate } 4927c478bd9Sstevel@tonic-gate 4937c478bd9Sstevel@tonic-gate /* Now, we encode the OPTTYPE stuff here... */ 4947c478bd9Sstevel@tonic-gate if (!use_k5 && 4957c478bd9Sstevel@tonic-gate (opts->starttime || opts->rlife || opts->forwardable || 4967c478bd9Sstevel@tonic-gate opts->proxiable || opts->addresses || opts->not_forwardable || 4977c478bd9Sstevel@tonic-gate opts->not_proxiable || opts->no_addresses || 4987c478bd9Sstevel@tonic-gate (opts->action == VALIDATE) || opts->k5_cache_name)) 4997c478bd9Sstevel@tonic-gate { 5007c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Specified option that requires Kerberos 5\n")); 5017c478bd9Sstevel@tonic-gate errflg++; 5027c478bd9Sstevel@tonic-gate } 5037c478bd9Sstevel@tonic-gate if (!use_k4 && 5047c478bd9Sstevel@tonic-gate opts->k4_cache_name) 5057c478bd9Sstevel@tonic-gate { 5067c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Specified option that require Kerberos 4\n")); 5077c478bd9Sstevel@tonic-gate errflg++; 5087c478bd9Sstevel@tonic-gate } 5097c478bd9Sstevel@tonic-gate if ( 5107c478bd9Sstevel@tonic-gate #ifdef HAVE_KRB524 5117c478bd9Sstevel@tonic-gate !use_k5 5127c478bd9Sstevel@tonic-gate #else 5137c478bd9Sstevel@tonic-gate use_k4 5147c478bd9Sstevel@tonic-gate #endif 5157c478bd9Sstevel@tonic-gate && (opts->service_name || opts->keytab_name || 5167c478bd9Sstevel@tonic-gate (opts->action == INIT_KT) || (opts->action == RENEW)) 5177c478bd9Sstevel@tonic-gate ) 5187c478bd9Sstevel@tonic-gate { 5197c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Specified option that requires Kerberos 5\n")); 5207c478bd9Sstevel@tonic-gate errflg++; 5217c478bd9Sstevel@tonic-gate } 5227c478bd9Sstevel@tonic-gate 5237c478bd9Sstevel@tonic-gate if (errflg) { 524*56a424ccSmp153739 usage(progname); 5257c478bd9Sstevel@tonic-gate } 5267c478bd9Sstevel@tonic-gate 5277c478bd9Sstevel@tonic-gate got_k5 = got_k5 && use_k5; 5287c478bd9Sstevel@tonic-gate got_k4 = got_k4 && use_k4; 5297c478bd9Sstevel@tonic-gate 5307c478bd9Sstevel@tonic-gate opts->principal_name = (optind == argc-1) ? argv[optind] : 0; 5317c478bd9Sstevel@tonic-gate return opts->principal_name; 5327c478bd9Sstevel@tonic-gate } 5337c478bd9Sstevel@tonic-gate 534*56a424ccSmp153739 static int 5357c478bd9Sstevel@tonic-gate k5_begin(opts, k5, k4) 5367c478bd9Sstevel@tonic-gate struct k_opts* opts; 5377c478bd9Sstevel@tonic-gate struct k5_data* k5; 5387c478bd9Sstevel@tonic-gate struct k4_data* k4; 5397c478bd9Sstevel@tonic-gate { 5407c478bd9Sstevel@tonic-gate char* progname = progname_v5; 5417c478bd9Sstevel@tonic-gate krb5_error_code code = 0; 5427c478bd9Sstevel@tonic-gate 5437c478bd9Sstevel@tonic-gate if (!got_k5) 5447c478bd9Sstevel@tonic-gate return 0; 5457c478bd9Sstevel@tonic-gate 546*56a424ccSmp153739 code = krb5_init_context(&k5->ctx); 547*56a424ccSmp153739 if (code) { 5487c478bd9Sstevel@tonic-gate com_err(progname, code, gettext("while initializing Kerberos 5 library")); 5497c478bd9Sstevel@tonic-gate return 0; 5507c478bd9Sstevel@tonic-gate } 5517c478bd9Sstevel@tonic-gate if (opts->k5_cache_name) 5527c478bd9Sstevel@tonic-gate { 5537c478bd9Sstevel@tonic-gate code = krb5_cc_resolve(k5->ctx, opts->k5_cache_name, &k5->cc); 5547c478bd9Sstevel@tonic-gate if (code != 0) { 5557c478bd9Sstevel@tonic-gate com_err(progname, code, gettext("resolving ccache %s"), 5567c478bd9Sstevel@tonic-gate opts->k5_cache_name); 5577c478bd9Sstevel@tonic-gate return 0; 5587c478bd9Sstevel@tonic-gate } 5597c478bd9Sstevel@tonic-gate } 5607c478bd9Sstevel@tonic-gate else 5617c478bd9Sstevel@tonic-gate { 5627c478bd9Sstevel@tonic-gate if ((code = krb5_cc_default(k5->ctx, &k5->cc))) { 5637c478bd9Sstevel@tonic-gate com_err(progname, code, gettext("while getting default ccache")); 5647c478bd9Sstevel@tonic-gate return 0; 5657c478bd9Sstevel@tonic-gate } 5667c478bd9Sstevel@tonic-gate } 5677c478bd9Sstevel@tonic-gate 5687c478bd9Sstevel@tonic-gate if (opts->principal_name) 5697c478bd9Sstevel@tonic-gate { 5707c478bd9Sstevel@tonic-gate /* Use specified name */ 5717c478bd9Sstevel@tonic-gate if ((code = krb5_parse_name(k5->ctx, opts->principal_name, 5727c478bd9Sstevel@tonic-gate &k5->me))) { 5737c478bd9Sstevel@tonic-gate com_err(progname, code, gettext("when parsing name %s"), 5747c478bd9Sstevel@tonic-gate opts->principal_name); 5757c478bd9Sstevel@tonic-gate return 0; 5767c478bd9Sstevel@tonic-gate } 5777c478bd9Sstevel@tonic-gate } 5787c478bd9Sstevel@tonic-gate else 5797c478bd9Sstevel@tonic-gate { 5807c478bd9Sstevel@tonic-gate /* No principal name specified */ 5817c478bd9Sstevel@tonic-gate if (opts->action == INIT_KT) { 5827c478bd9Sstevel@tonic-gate /* Use the default host/service name */ 583*56a424ccSmp153739 code = krb5_sname_to_principal(k5->ctx, NULL, NULL, 584*56a424ccSmp153739 KRB5_NT_SRV_HST, &k5->me); 585*56a424ccSmp153739 if (code) { 5867c478bd9Sstevel@tonic-gate com_err(progname, code, gettext( 5877c478bd9Sstevel@tonic-gate "when creating default server principal name")); 5887c478bd9Sstevel@tonic-gate return 0; 5897c478bd9Sstevel@tonic-gate } 5907c478bd9Sstevel@tonic-gate } else { 5917c478bd9Sstevel@tonic-gate /* Get default principal from cache if one exists */ 592*56a424ccSmp153739 code = krb5_cc_get_principal(k5->ctx, k5->cc, 593*56a424ccSmp153739 &k5->me); 594*56a424ccSmp153739 if (code) 595*56a424ccSmp153739 { 5967c478bd9Sstevel@tonic-gate char *name = get_name_from_os(); 5977c478bd9Sstevel@tonic-gate if (!name) 5987c478bd9Sstevel@tonic-gate { 5997c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Unable to identify user\n")); 6007c478bd9Sstevel@tonic-gate return 0; 6017c478bd9Sstevel@tonic-gate } 6027c478bd9Sstevel@tonic-gate /* use strcmp to ensure only "root" is matched */ 6037c478bd9Sstevel@tonic-gate if (strcmp(name, ROOT_UNAME) == 0) 6047c478bd9Sstevel@tonic-gate { 6057c478bd9Sstevel@tonic-gate if (code = krb5_sname_to_principal(k5->ctx, NULL, ROOT_UNAME, 6067c478bd9Sstevel@tonic-gate KRB5_NT_SRV_HST, &k5->me)) { 6077c478bd9Sstevel@tonic-gate com_err(progname, code, gettext( 6087c478bd9Sstevel@tonic-gate "when creating default server principal name")); 6097c478bd9Sstevel@tonic-gate return 0; 6107c478bd9Sstevel@tonic-gate } 611*56a424ccSmp153739 } else 612*56a424ccSmp153739 if ((code = krb5_parse_name(k5->ctx, name, 613*56a424ccSmp153739 &k5->me))) 614*56a424ccSmp153739 { 6157c478bd9Sstevel@tonic-gate com_err(progname, code, gettext("when parsing name %s"), 6167c478bd9Sstevel@tonic-gate name); 6177c478bd9Sstevel@tonic-gate return 0; 6187c478bd9Sstevel@tonic-gate } 6197c478bd9Sstevel@tonic-gate } 6207c478bd9Sstevel@tonic-gate } 6217c478bd9Sstevel@tonic-gate } 622*56a424ccSmp153739 623*56a424ccSmp153739 code = krb5_unparse_name(k5->ctx, k5->me, &k5->name); 624*56a424ccSmp153739 if (code) { 6257c478bd9Sstevel@tonic-gate com_err(progname, code, gettext("when unparsing name")); 6267c478bd9Sstevel@tonic-gate return 0; 6277c478bd9Sstevel@tonic-gate } 6287c478bd9Sstevel@tonic-gate opts->principal_name = k5->name; 6297c478bd9Sstevel@tonic-gate 6307c478bd9Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT 6317c478bd9Sstevel@tonic-gate if (got_k4) 6327c478bd9Sstevel@tonic-gate { 6337c478bd9Sstevel@tonic-gate /* Translate to a Kerberos 4 principal */ 6347c478bd9Sstevel@tonic-gate code = krb5_524_conv_principal(k5->ctx, k5->me, 6357c478bd9Sstevel@tonic-gate k4->aname, k4->inst, k4->realm); 6367c478bd9Sstevel@tonic-gate if (code) { 6377c478bd9Sstevel@tonic-gate k4->aname[0] = 0; 6387c478bd9Sstevel@tonic-gate k4->inst[0] = 0; 6397c478bd9Sstevel@tonic-gate k4->realm[0] = 0; 6407c478bd9Sstevel@tonic-gate } 6417c478bd9Sstevel@tonic-gate } 6427c478bd9Sstevel@tonic-gate #endif 6437c478bd9Sstevel@tonic-gate return 1; 6447c478bd9Sstevel@tonic-gate } 6457c478bd9Sstevel@tonic-gate 646*56a424ccSmp153739 static void 6477c478bd9Sstevel@tonic-gate k5_end(k5) 6487c478bd9Sstevel@tonic-gate struct k5_data* k5; 6497c478bd9Sstevel@tonic-gate { 6507c478bd9Sstevel@tonic-gate if (k5->name) 6517c478bd9Sstevel@tonic-gate krb5_free_unparsed_name(k5->ctx, k5->name); 6527c478bd9Sstevel@tonic-gate if (k5->me) 6537c478bd9Sstevel@tonic-gate krb5_free_principal(k5->ctx, k5->me); 6547c478bd9Sstevel@tonic-gate if (k5->cc) 6557c478bd9Sstevel@tonic-gate krb5_cc_close(k5->ctx, k5->cc); 6567c478bd9Sstevel@tonic-gate if (k5->ctx) 6577c478bd9Sstevel@tonic-gate krb5_free_context(k5->ctx); 6587c478bd9Sstevel@tonic-gate memset(k5, 0, sizeof(*k5)); 6597c478bd9Sstevel@tonic-gate } 6607c478bd9Sstevel@tonic-gate 661*56a424ccSmp153739 static int 6627c478bd9Sstevel@tonic-gate k4_begin(opts, k4) 6637c478bd9Sstevel@tonic-gate struct k_opts* opts; 6647c478bd9Sstevel@tonic-gate struct k4_data* k4; 6657c478bd9Sstevel@tonic-gate { 6667c478bd9Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT 6677c478bd9Sstevel@tonic-gate char* progname = progname_v4; 6687c478bd9Sstevel@tonic-gate int k_errno = 0; 6697c478bd9Sstevel@tonic-gate #endif 6707c478bd9Sstevel@tonic-gate 6717c478bd9Sstevel@tonic-gate if (!got_k4) 6727c478bd9Sstevel@tonic-gate return 0; 6737c478bd9Sstevel@tonic-gate 6747c478bd9Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT 6757c478bd9Sstevel@tonic-gate if (k4->aname[0]) 6767c478bd9Sstevel@tonic-gate goto skip; 6777c478bd9Sstevel@tonic-gate 6787c478bd9Sstevel@tonic-gate if (opts->principal_name) 6797c478bd9Sstevel@tonic-gate { 6807c478bd9Sstevel@tonic-gate /* Use specified name */ 681*56a424ccSmp153739 k_errno = kname_parse(k4->aname, k4->inst, k4->realm, 682*56a424ccSmp153739 opts->principal_name); 683*56a424ccSmp153739 if (k_errno) 6847c478bd9Sstevel@tonic-gate { 6857c478bd9Sstevel@tonic-gate fprintf(stderr, "%s: %s\n", progname, 6867c478bd9Sstevel@tonic-gate krb_get_err_text(k_errno)); 6877c478bd9Sstevel@tonic-gate return 0; 6887c478bd9Sstevel@tonic-gate } 6897c478bd9Sstevel@tonic-gate } else { 6907c478bd9Sstevel@tonic-gate /* No principal name specified */ 6917c478bd9Sstevel@tonic-gate if (opts->action == INIT_KT) { 6927c478bd9Sstevel@tonic-gate /* Use the default host/service name */ 6937c478bd9Sstevel@tonic-gate /* XXX - need to add this functionality */ 6947c478bd9Sstevel@tonic-gate fprintf(stderr, "%s: Kerberos 4 srvtab support is not " 6957c478bd9Sstevel@tonic-gate "implemented\n", progname); 6967c478bd9Sstevel@tonic-gate return 0; 6977c478bd9Sstevel@tonic-gate } else { 6987c478bd9Sstevel@tonic-gate /* Get default principal from cache if one exists */ 699*56a424ccSmp153739 k_errno = krb_get_tf_fullname(tkt_string(), k4->aname, 700*56a424ccSmp153739 k4->inst, k4->realm); 701*56a424ccSmp153739 if (k_errno) 7027c478bd9Sstevel@tonic-gate { 7037c478bd9Sstevel@tonic-gate char *name = get_name_from_os(); 7047c478bd9Sstevel@tonic-gate if (!name) 7057c478bd9Sstevel@tonic-gate { 7067c478bd9Sstevel@tonic-gate fprintf(stderr, "Unable to identify user\n"); 7077c478bd9Sstevel@tonic-gate return 0; 7087c478bd9Sstevel@tonic-gate } 709*56a424ccSmp153739 k_errno = kname_parse(k4->aname, k4->inst, k4->realm, 710*56a424ccSmp153739 name); 711*56a424ccSmp153739 if (k_errno) 7127c478bd9Sstevel@tonic-gate { 7137c478bd9Sstevel@tonic-gate fprintf(stderr, "%s: %s\n", progname, 7147c478bd9Sstevel@tonic-gate krb_get_err_text(k_errno)); 7157c478bd9Sstevel@tonic-gate return 0; 7167c478bd9Sstevel@tonic-gate } 7177c478bd9Sstevel@tonic-gate } 7187c478bd9Sstevel@tonic-gate } 7197c478bd9Sstevel@tonic-gate } 7207c478bd9Sstevel@tonic-gate 7217c478bd9Sstevel@tonic-gate if (!k4->realm[0]) 7227c478bd9Sstevel@tonic-gate krb_get_lrealm(k4->realm, 1); 7237c478bd9Sstevel@tonic-gate 7247c478bd9Sstevel@tonic-gate if (k4->inst[0]) 7257c478bd9Sstevel@tonic-gate sprintf(k4->name, "%s.%s@%s", k4->aname, k4->inst, k4->realm); 7267c478bd9Sstevel@tonic-gate else 7277c478bd9Sstevel@tonic-gate sprintf(k4->name, "%s@%s", k4->aname, k4->realm); 7287c478bd9Sstevel@tonic-gate opts->principal_name = k4->name; 7297c478bd9Sstevel@tonic-gate 7307c478bd9Sstevel@tonic-gate skip: 7317c478bd9Sstevel@tonic-gate if (k4->aname[0] && !k_isname(k4->aname)) 7327c478bd9Sstevel@tonic-gate { 7337c478bd9Sstevel@tonic-gate fprintf(stderr, "%s: bad Kerberos 4 name format\n", progname); 7347c478bd9Sstevel@tonic-gate return 0; 7357c478bd9Sstevel@tonic-gate } 7367c478bd9Sstevel@tonic-gate 7377c478bd9Sstevel@tonic-gate if (k4->inst[0] && !k_isinst(k4->inst)) 7387c478bd9Sstevel@tonic-gate { 7397c478bd9Sstevel@tonic-gate fprintf(stderr, "%s: bad Kerberos 4 instance format\n", progname); 7407c478bd9Sstevel@tonic-gate return 0; 7417c478bd9Sstevel@tonic-gate } 7427c478bd9Sstevel@tonic-gate 7437c478bd9Sstevel@tonic-gate if (k4->realm[0] && !k_isrealm(k4->realm)) 7447c478bd9Sstevel@tonic-gate { 7457c478bd9Sstevel@tonic-gate fprintf(stderr, "%s: bad Kerberos 4 realm format\n", progname); 7467c478bd9Sstevel@tonic-gate return 0; 7477c478bd9Sstevel@tonic-gate } 7487c478bd9Sstevel@tonic-gate #endif /* KRB5_KRB4_COMPAT */ 7497c478bd9Sstevel@tonic-gate return 1; 7507c478bd9Sstevel@tonic-gate } 7517c478bd9Sstevel@tonic-gate 752*56a424ccSmp153739 static void 7537c478bd9Sstevel@tonic-gate k4_end(k4) 7547c478bd9Sstevel@tonic-gate struct k4_data* k4; 7557c478bd9Sstevel@tonic-gate { 7567c478bd9Sstevel@tonic-gate memset(k4, 0, sizeof(*k4)); 7577c478bd9Sstevel@tonic-gate } 7587c478bd9Sstevel@tonic-gate 7597c478bd9Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT 7607c478bd9Sstevel@tonic-gate static char stash_password[1024]; 7617c478bd9Sstevel@tonic-gate static int got_password = 0; 7627c478bd9Sstevel@tonic-gate #endif /* KRB5_KRB4_COMPAT */ 7637c478bd9Sstevel@tonic-gate 764*56a424ccSmp153739 static krb5_error_code 7657c478bd9Sstevel@tonic-gate KRB5_CALLCONV 7667c478bd9Sstevel@tonic-gate kinit_prompter( 7677c478bd9Sstevel@tonic-gate krb5_context ctx, 7687c478bd9Sstevel@tonic-gate void *data, 7697c478bd9Sstevel@tonic-gate const char *name, 7707c478bd9Sstevel@tonic-gate const char *banner, 7717c478bd9Sstevel@tonic-gate int num_prompts, 7727c478bd9Sstevel@tonic-gate krb5_prompt prompts[] 7737c478bd9Sstevel@tonic-gate ) 7747c478bd9Sstevel@tonic-gate { 7757c478bd9Sstevel@tonic-gate int i; 7767c478bd9Sstevel@tonic-gate krb5_prompt_type *types; 7777c478bd9Sstevel@tonic-gate krb5_error_code rc = 7787c478bd9Sstevel@tonic-gate krb5_prompter_posix(ctx, data, name, banner, num_prompts, prompts); 7797c478bd9Sstevel@tonic-gate if (!rc && (types = krb5_get_prompt_types(ctx))) 7807c478bd9Sstevel@tonic-gate for (i = 0; i < num_prompts; i++) 7817c478bd9Sstevel@tonic-gate if ((types[i] == KRB5_PROMPT_TYPE_PASSWORD) || 7827c478bd9Sstevel@tonic-gate (types[i] == KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN)) 7837c478bd9Sstevel@tonic-gate { 7847c478bd9Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT 7857c478bd9Sstevel@tonic-gate strncpy(stash_password, prompts[i].reply->data, 7867c478bd9Sstevel@tonic-gate sizeof(stash_password)); 7877c478bd9Sstevel@tonic-gate got_password = 1; 7887c478bd9Sstevel@tonic-gate #endif 7897c478bd9Sstevel@tonic-gate } 7907c478bd9Sstevel@tonic-gate return rc; 7917c478bd9Sstevel@tonic-gate } 7927c478bd9Sstevel@tonic-gate 793*56a424ccSmp153739 static int 7947c478bd9Sstevel@tonic-gate k5_kinit(opts, k5) 7957c478bd9Sstevel@tonic-gate struct k_opts* opts; 7967c478bd9Sstevel@tonic-gate struct k5_data* k5; 7977c478bd9Sstevel@tonic-gate { 7987c478bd9Sstevel@tonic-gate char* progname = progname_v5; 7997c478bd9Sstevel@tonic-gate int notix = 1; 8007c478bd9Sstevel@tonic-gate krb5_keytab keytab = 0; 8017c478bd9Sstevel@tonic-gate krb5_creds my_creds; 8027c478bd9Sstevel@tonic-gate krb5_error_code code = 0; 8037c478bd9Sstevel@tonic-gate krb5_get_init_creds_opt options; 8047c478bd9Sstevel@tonic-gate krb5_timestamp now; 8057c478bd9Sstevel@tonic-gate krb5_deltat lifetime = 0, rlife = 0, krb5_max_duration; 8067c478bd9Sstevel@tonic-gate 8077c478bd9Sstevel@tonic-gate if (!got_k5) 8087c478bd9Sstevel@tonic-gate return 0; 8097c478bd9Sstevel@tonic-gate 8107c478bd9Sstevel@tonic-gate krb5_get_init_creds_opt_init(&options); 8117c478bd9Sstevel@tonic-gate memset(&my_creds, 0, sizeof(my_creds)); 8127c478bd9Sstevel@tonic-gate 8137c478bd9Sstevel@tonic-gate /* 8147c478bd9Sstevel@tonic-gate * Solaris Kerberos: added support for max_life and max_renewable_life 8157c478bd9Sstevel@tonic-gate * which should be removed in the next minor release. See PSARC 2003/545 8167c478bd9Sstevel@tonic-gate * for more info. 8177c478bd9Sstevel@tonic-gate * 8187c478bd9Sstevel@tonic-gate * Also, check krb5.conf for proxiable/forwardable/renewable/no_address 8197c478bd9Sstevel@tonic-gate * parameter values. 8207c478bd9Sstevel@tonic-gate */ 8217c478bd9Sstevel@tonic-gate /* If either tkt life or renew life weren't set earlier take common steps to 8227c478bd9Sstevel@tonic-gate * get the krb5.conf parameter values. 8237c478bd9Sstevel@tonic-gate */ 8247c478bd9Sstevel@tonic-gate 8257c478bd9Sstevel@tonic-gate if ((code = krb5_timeofday(k5->ctx, &now))) { 8267c478bd9Sstevel@tonic-gate com_err(progname, code, gettext("while getting time of day")); 8277c478bd9Sstevel@tonic-gate exit(1); 8287c478bd9Sstevel@tonic-gate } 8297c478bd9Sstevel@tonic-gate krb5_max_duration = KRB5_KDB_EXPIRATION - now - 60*60; 8307c478bd9Sstevel@tonic-gate 8317c478bd9Sstevel@tonic-gate if (opts->lifetime == 0 || opts->rlife == 0) { 8327c478bd9Sstevel@tonic-gate 8337c478bd9Sstevel@tonic-gate krb_realm = krb5_princ_realm(k5->ctx, k5->me)->data; 8347c478bd9Sstevel@tonic-gate /* realm params take precedence */ 8357c478bd9Sstevel@tonic-gate profile_get_options_string(k5->ctx->profile, realmdef, config_times); 8367c478bd9Sstevel@tonic-gate profile_get_options_string(k5->ctx->profile, appdef, config_times); 8377c478bd9Sstevel@tonic-gate 8387c478bd9Sstevel@tonic-gate /* if the input opts doesn't have lifetime set and the krb5.conf 8397c478bd9Sstevel@tonic-gate * parameter has been set, use that. 8407c478bd9Sstevel@tonic-gate */ 8417c478bd9Sstevel@tonic-gate if (opts->lifetime == 0 && life_timeval != NULL) { 8427c478bd9Sstevel@tonic-gate code = krb5_string_to_deltat(life_timeval, &lifetime); 8437c478bd9Sstevel@tonic-gate if (code != 0 || lifetime == 0 || lifetime > krb5_max_duration) { 8447c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Bad max_life " 8457c478bd9Sstevel@tonic-gate "value in Kerberos config file %s\n"), 8467c478bd9Sstevel@tonic-gate life_timeval); 8477c478bd9Sstevel@tonic-gate exit(1); 8487c478bd9Sstevel@tonic-gate } 8497c478bd9Sstevel@tonic-gate opts->lifetime = lifetime; 8507c478bd9Sstevel@tonic-gate } 8517c478bd9Sstevel@tonic-gate if (opts->rlife == 0 && renew_timeval != NULL) { 8527c478bd9Sstevel@tonic-gate code = krb5_string_to_deltat(renew_timeval, &rlife); 8537c478bd9Sstevel@tonic-gate if (code != 0 || rlife == 0 || rlife > krb5_max_duration) { 8547c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Bad max_renewable_life " 8557c478bd9Sstevel@tonic-gate "value in Kerberos config file %s\n"), 8567c478bd9Sstevel@tonic-gate renew_timeval); 8577c478bd9Sstevel@tonic-gate exit(1); 8587c478bd9Sstevel@tonic-gate } 8597c478bd9Sstevel@tonic-gate opts->rlife = rlife; 8607c478bd9Sstevel@tonic-gate } 8617c478bd9Sstevel@tonic-gate } 8627c478bd9Sstevel@tonic-gate 8637c478bd9Sstevel@tonic-gate /* 8647c478bd9Sstevel@tonic-gate * If lifetime is not set on the cmdline or in the krb5.conf 8657c478bd9Sstevel@tonic-gate * file, default to max. 8667c478bd9Sstevel@tonic-gate */ 8677c478bd9Sstevel@tonic-gate if (opts->lifetime == 0) 8687c478bd9Sstevel@tonic-gate opts->lifetime = krb5_max_duration; 8697c478bd9Sstevel@tonic-gate 8707c478bd9Sstevel@tonic-gate 8717c478bd9Sstevel@tonic-gate profile_get_options_boolean(k5->ctx->profile, 8727c478bd9Sstevel@tonic-gate realmdef, config_option); 8737c478bd9Sstevel@tonic-gate profile_get_options_boolean(k5->ctx->profile, 8747c478bd9Sstevel@tonic-gate appdef, config_option); 8757c478bd9Sstevel@tonic-gate 8767c478bd9Sstevel@tonic-gate 8777c478bd9Sstevel@tonic-gate /* cmdline opts take precedence over krb5.conf file values */ 8787c478bd9Sstevel@tonic-gate if (!opts->not_proxiable && proxiable_flag) { 8797c478bd9Sstevel@tonic-gate krb5_get_init_creds_opt_set_proxiable(&options, 1); 8807c478bd9Sstevel@tonic-gate } 8817c478bd9Sstevel@tonic-gate if (!opts->not_forwardable && forwardable_flag) { 8827c478bd9Sstevel@tonic-gate krb5_get_init_creds_opt_set_forwardable(&options, 1); 8837c478bd9Sstevel@tonic-gate } 8847c478bd9Sstevel@tonic-gate if (renewable_flag) { 8857c478bd9Sstevel@tonic-gate /* 8867c478bd9Sstevel@tonic-gate * If this flag is set in krb5.conf, but rlife is 0, then 8877c478bd9Sstevel@tonic-gate * set it to the max (and let the KDC sort it out). 8887c478bd9Sstevel@tonic-gate */ 8897c478bd9Sstevel@tonic-gate opts->rlife = opts->rlife ? opts->rlife : krb5_max_duration; 8907c478bd9Sstevel@tonic-gate } 8917c478bd9Sstevel@tonic-gate if (no_address_flag) { 8927c478bd9Sstevel@tonic-gate /* cmdline opts will overwrite this below if needbe */ 8937c478bd9Sstevel@tonic-gate krb5_get_init_creds_opt_set_address_list(&options, NULL); 8947c478bd9Sstevel@tonic-gate } 8957c478bd9Sstevel@tonic-gate 8967c478bd9Sstevel@tonic-gate 8977c478bd9Sstevel@tonic-gate /* 8987c478bd9Sstevel@tonic-gate From this point on, we can goto cleanup because my_creds is 8997c478bd9Sstevel@tonic-gate initialized. 9007c478bd9Sstevel@tonic-gate */ 9017c478bd9Sstevel@tonic-gate 9027c478bd9Sstevel@tonic-gate if (opts->lifetime) 9037c478bd9Sstevel@tonic-gate krb5_get_init_creds_opt_set_tkt_life(&options, opts->lifetime); 9047c478bd9Sstevel@tonic-gate if (opts->rlife) 9057c478bd9Sstevel@tonic-gate krb5_get_init_creds_opt_set_renew_life(&options, opts->rlife); 9067c478bd9Sstevel@tonic-gate if (opts->forwardable) 9077c478bd9Sstevel@tonic-gate krb5_get_init_creds_opt_set_forwardable(&options, 1); 9087c478bd9Sstevel@tonic-gate if (opts->not_forwardable) 9097c478bd9Sstevel@tonic-gate krb5_get_init_creds_opt_set_forwardable(&options, 0); 9107c478bd9Sstevel@tonic-gate if (opts->proxiable) 9117c478bd9Sstevel@tonic-gate krb5_get_init_creds_opt_set_proxiable(&options, 1); 9127c478bd9Sstevel@tonic-gate if (opts->not_proxiable) 9137c478bd9Sstevel@tonic-gate krb5_get_init_creds_opt_set_proxiable(&options, 0); 9147c478bd9Sstevel@tonic-gate if (opts->addresses) 9157c478bd9Sstevel@tonic-gate { 9167c478bd9Sstevel@tonic-gate krb5_address **addresses = NULL; 9177c478bd9Sstevel@tonic-gate code = krb5_os_localaddr(k5->ctx, &addresses); 9187c478bd9Sstevel@tonic-gate if (code != 0) { 9197c478bd9Sstevel@tonic-gate com_err(progname, code, gettext("getting local addresses")); 9207c478bd9Sstevel@tonic-gate goto cleanup; 9217c478bd9Sstevel@tonic-gate } 9227c478bd9Sstevel@tonic-gate krb5_get_init_creds_opt_set_address_list(&options, addresses); 9237c478bd9Sstevel@tonic-gate } 9247c478bd9Sstevel@tonic-gate if (opts->no_addresses) 9257c478bd9Sstevel@tonic-gate krb5_get_init_creds_opt_set_address_list(&options, NULL); 9267c478bd9Sstevel@tonic-gate 9277c478bd9Sstevel@tonic-gate if ((opts->action == INIT_KT) && opts->keytab_name) 9287c478bd9Sstevel@tonic-gate { 9297c478bd9Sstevel@tonic-gate code = krb5_kt_resolve(k5->ctx, opts->keytab_name, &keytab); 9307c478bd9Sstevel@tonic-gate if (code != 0) { 9317c478bd9Sstevel@tonic-gate com_err(progname, code, gettext("resolving keytab %s"), 9327c478bd9Sstevel@tonic-gate opts->keytab_name); 9337c478bd9Sstevel@tonic-gate goto cleanup; 9347c478bd9Sstevel@tonic-gate } 9357c478bd9Sstevel@tonic-gate } 9367c478bd9Sstevel@tonic-gate 9377c478bd9Sstevel@tonic-gate switch (opts->action) { 9387c478bd9Sstevel@tonic-gate case INIT_PW: 9397c478bd9Sstevel@tonic-gate code = krb5_get_init_creds_password(k5->ctx, &my_creds, k5->me, 9407c478bd9Sstevel@tonic-gate 0, kinit_prompter, 0, 9417c478bd9Sstevel@tonic-gate opts->starttime, 9427c478bd9Sstevel@tonic-gate opts->service_name, 9437c478bd9Sstevel@tonic-gate &options); 9447c478bd9Sstevel@tonic-gate break; 9457c478bd9Sstevel@tonic-gate case INIT_KT: 9467c478bd9Sstevel@tonic-gate code = krb5_get_init_creds_keytab(k5->ctx, &my_creds, k5->me, 9477c478bd9Sstevel@tonic-gate keytab, 9487c478bd9Sstevel@tonic-gate opts->starttime, 9497c478bd9Sstevel@tonic-gate opts->service_name, 9507c478bd9Sstevel@tonic-gate &options); 9517c478bd9Sstevel@tonic-gate break; 9527c478bd9Sstevel@tonic-gate case VALIDATE: 9537c478bd9Sstevel@tonic-gate code = krb5_get_validated_creds(k5->ctx, &my_creds, k5->me, k5->cc, 9547c478bd9Sstevel@tonic-gate opts->service_name); 9557c478bd9Sstevel@tonic-gate break; 9567c478bd9Sstevel@tonic-gate case RENEW: 9577c478bd9Sstevel@tonic-gate code = krb5_get_renewed_creds(k5->ctx, &my_creds, k5->me, k5->cc, 9587c478bd9Sstevel@tonic-gate opts->service_name); 9597c478bd9Sstevel@tonic-gate break; 9607c478bd9Sstevel@tonic-gate } 9617c478bd9Sstevel@tonic-gate 9627c478bd9Sstevel@tonic-gate if (code) { 9637c478bd9Sstevel@tonic-gate char *doing = 0; 9647c478bd9Sstevel@tonic-gate switch (opts->action) { 9657c478bd9Sstevel@tonic-gate case INIT_PW: 9667c478bd9Sstevel@tonic-gate case INIT_KT: 9677c478bd9Sstevel@tonic-gate doing = gettext("getting initial credentials"); 9687c478bd9Sstevel@tonic-gate break; 9697c478bd9Sstevel@tonic-gate case VALIDATE: 9707c478bd9Sstevel@tonic-gate doing = gettext("validating credentials"); 9717c478bd9Sstevel@tonic-gate break; 9727c478bd9Sstevel@tonic-gate case RENEW: 9737c478bd9Sstevel@tonic-gate doing = gettext("renewing credentials"); 9747c478bd9Sstevel@tonic-gate break; 9757c478bd9Sstevel@tonic-gate } 9767c478bd9Sstevel@tonic-gate 9777c478bd9Sstevel@tonic-gate /* If got code == KRB5_AP_ERR_V4_REPLY && got_k4, we should 9787c478bd9Sstevel@tonic-gate let the user know that maybe he/she wants -4. */ 9797c478bd9Sstevel@tonic-gate if (code == KRB5KRB_AP_ERR_V4_REPLY && got_k4) 9807c478bd9Sstevel@tonic-gate com_err(progname, code, "while %s\n" 9817c478bd9Sstevel@tonic-gate "The KDC doesn't support v5. " 9827c478bd9Sstevel@tonic-gate "You may want the -4 option in the future", 9837c478bd9Sstevel@tonic-gate doing); 9847c478bd9Sstevel@tonic-gate else if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY) 9857c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("%s: Password incorrect while %s\n"), progname, 9867c478bd9Sstevel@tonic-gate doing); 9877c478bd9Sstevel@tonic-gate else 9887c478bd9Sstevel@tonic-gate com_err(progname, code, gettext("while %s"), doing); 9897c478bd9Sstevel@tonic-gate goto cleanup; 9907c478bd9Sstevel@tonic-gate } 9917c478bd9Sstevel@tonic-gate 9927c478bd9Sstevel@tonic-gate if (!opts->lifetime) { 9937c478bd9Sstevel@tonic-gate /* We need to figure out what lifetime to use for Kerberos 4. */ 9947c478bd9Sstevel@tonic-gate opts->lifetime = my_creds.times.endtime - my_creds.times.authtime; 9957c478bd9Sstevel@tonic-gate } 9967c478bd9Sstevel@tonic-gate 997*56a424ccSmp153739 code = krb5_cc_initialize(k5->ctx, k5->cc, k5->me); 998*56a424ccSmp153739 if (code) { 9997c478bd9Sstevel@tonic-gate com_err(progname, code, gettext("when initializing cache %s"), 10007c478bd9Sstevel@tonic-gate opts->k5_cache_name?opts->k5_cache_name:""); 10017c478bd9Sstevel@tonic-gate goto cleanup; 10027c478bd9Sstevel@tonic-gate } 10037c478bd9Sstevel@tonic-gate 1004*56a424ccSmp153739 code = krb5_cc_store_cred(k5->ctx, k5->cc, &my_creds); 1005*56a424ccSmp153739 if (code) { 10067c478bd9Sstevel@tonic-gate com_err(progname, code, gettext("while storing credentials")); 10077c478bd9Sstevel@tonic-gate goto cleanup; 10087c478bd9Sstevel@tonic-gate } 10097c478bd9Sstevel@tonic-gate 10107c478bd9Sstevel@tonic-gate if (opts->action == RENEW) { 10117c478bd9Sstevel@tonic-gate _kwarnd_del_warning(opts->principal_name); 10127c478bd9Sstevel@tonic-gate _kwarnd_add_warning(opts->principal_name, my_creds.times.endtime); 10137c478bd9Sstevel@tonic-gate } else if ((opts->action == INIT_KT) || (opts->action == INIT_PW)) { 10147c478bd9Sstevel@tonic-gate _kwarnd_add_warning(opts->principal_name, my_creds.times.endtime); 10157c478bd9Sstevel@tonic-gate } 10167c478bd9Sstevel@tonic-gate 10177c478bd9Sstevel@tonic-gate notix = 0; 10187c478bd9Sstevel@tonic-gate 10197c478bd9Sstevel@tonic-gate cleanup: 10207c478bd9Sstevel@tonic-gate if (my_creds.client == k5->me) { 10217c478bd9Sstevel@tonic-gate my_creds.client = 0; 10227c478bd9Sstevel@tonic-gate } 10237c478bd9Sstevel@tonic-gate krb5_free_cred_contents(k5->ctx, &my_creds); 10247c478bd9Sstevel@tonic-gate if (keytab) 10257c478bd9Sstevel@tonic-gate krb5_kt_close(k5->ctx, keytab); 10267c478bd9Sstevel@tonic-gate return notix?0:1; 10277c478bd9Sstevel@tonic-gate } 10287c478bd9Sstevel@tonic-gate 1029*56a424ccSmp153739 static int 10307c478bd9Sstevel@tonic-gate k4_kinit(opts, k4, ctx) 10317c478bd9Sstevel@tonic-gate struct k_opts* opts; 10327c478bd9Sstevel@tonic-gate struct k4_data* k4; 10337c478bd9Sstevel@tonic-gate krb5_context ctx; 10347c478bd9Sstevel@tonic-gate { 10357c478bd9Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT 10367c478bd9Sstevel@tonic-gate char* progname = progname_v4; 10377c478bd9Sstevel@tonic-gate int k_errno = 0; 10387c478bd9Sstevel@tonic-gate #endif 10397c478bd9Sstevel@tonic-gate 10407c478bd9Sstevel@tonic-gate if (!got_k4) 10417c478bd9Sstevel@tonic-gate return 0; 10427c478bd9Sstevel@tonic-gate 10437c478bd9Sstevel@tonic-gate if (opts->starttime) 10447c478bd9Sstevel@tonic-gate return 0; 10457c478bd9Sstevel@tonic-gate 10467c478bd9Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT 10477c478bd9Sstevel@tonic-gate if (!k4->lifetime) 10487c478bd9Sstevel@tonic-gate k4->lifetime = opts->lifetime; 10497c478bd9Sstevel@tonic-gate if (!k4->lifetime) 10507c478bd9Sstevel@tonic-gate k4->lifetime = KRB4_BACKUP_DEFAULT_LIFE_SECS; 10517c478bd9Sstevel@tonic-gate 1052*56a424ccSmp153739 k4->lifetime = krb_time_to_life(0, k4->lifetime); 10537c478bd9Sstevel@tonic-gate 10547c478bd9Sstevel@tonic-gate switch (opts->action) 10557c478bd9Sstevel@tonic-gate { 10567c478bd9Sstevel@tonic-gate case INIT_PW: 10577c478bd9Sstevel@tonic-gate if (!got_password) { 1058*56a424ccSmp153739 unsigned int pwsize = sizeof(stash_password); 10597c478bd9Sstevel@tonic-gate krb5_error_code code; 10607c478bd9Sstevel@tonic-gate char prompt[1024]; 10617c478bd9Sstevel@tonic-gate 10627c478bd9Sstevel@tonic-gate sprintf(prompt, gettext("Password for %s: "), opts->principal_name); 10637c478bd9Sstevel@tonic-gate stash_password[0] = 0; 10647c478bd9Sstevel@tonic-gate /* 10657c478bd9Sstevel@tonic-gate Note: krb5_read_password does not actually look at the 10667c478bd9Sstevel@tonic-gate context, so we're ok even if we don't have a context. If 10677c478bd9Sstevel@tonic-gate we cannot dynamically load krb5, we can substitute any 10687c478bd9Sstevel@tonic-gate decent read password function instead of the krb5 one. 10697c478bd9Sstevel@tonic-gate */ 10707c478bd9Sstevel@tonic-gate code = krb5_read_password(ctx, prompt, 0, stash_password, &pwsize); 10717c478bd9Sstevel@tonic-gate if (code || pwsize == 0) 10727c478bd9Sstevel@tonic-gate { 10737c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Error while reading password for '%s'\n"), 10747c478bd9Sstevel@tonic-gate opts->principal_name); 10757c478bd9Sstevel@tonic-gate memset(stash_password, 0, sizeof(stash_password)); 10767c478bd9Sstevel@tonic-gate return 0; 10777c478bd9Sstevel@tonic-gate } 10787c478bd9Sstevel@tonic-gate got_password = 1; 10797c478bd9Sstevel@tonic-gate } 10807c478bd9Sstevel@tonic-gate k_errno = krb_get_pw_in_tkt(k4->aname, k4->inst, k4->realm, "krbtgt", 10817c478bd9Sstevel@tonic-gate k4->realm, k4->lifetime, stash_password); 10827c478bd9Sstevel@tonic-gate 10837c478bd9Sstevel@tonic-gate if (k_errno) { 10847c478bd9Sstevel@tonic-gate fprintf(stderr, "%s: %s\n", progname, 10857c478bd9Sstevel@tonic-gate krb_get_err_text(k_errno)); 10867c478bd9Sstevel@tonic-gate if (authed_k5) 10877c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Maybe your KDC does not support v4. " 10887c478bd9Sstevel@tonic-gate "Try the -5 option next time.\n")); 10897c478bd9Sstevel@tonic-gate return 0; 10907c478bd9Sstevel@tonic-gate } 10917c478bd9Sstevel@tonic-gate return 1; 10927c478bd9Sstevel@tonic-gate #ifndef HAVE_KRB524 10937c478bd9Sstevel@tonic-gate case INIT_KT: 10947c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("%s: srvtabs are not supported\n"), progname); 10957c478bd9Sstevel@tonic-gate return 0; 10967c478bd9Sstevel@tonic-gate case RENEW: 10977c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("%s: renewal of krb4 tickets is not supported\n"), 10987c478bd9Sstevel@tonic-gate progname); 10997c478bd9Sstevel@tonic-gate return 0; 1100*56a424ccSmp153739 #else 1101*56a424ccSmp153739 /* These cases are handled by the 524 code - this prevents the compiler 1102*56a424ccSmp153739 warnings of not using all the enumerated types. 1103*56a424ccSmp153739 */ 1104*56a424ccSmp153739 case INIT_KT: 1105*56a424ccSmp153739 case RENEW: 1106*56a424ccSmp153739 case VALIDATE: 1107*56a424ccSmp153739 return 0; 11087c478bd9Sstevel@tonic-gate #endif 11097c478bd9Sstevel@tonic-gate } 11107c478bd9Sstevel@tonic-gate #endif 11117c478bd9Sstevel@tonic-gate return 0; 11127c478bd9Sstevel@tonic-gate } 11137c478bd9Sstevel@tonic-gate 1114*56a424ccSmp153739 static char* 1115*56a424ccSmp153739 getvprogname(v, progname) 1116*56a424ccSmp153739 char *v, *progname; 11177c478bd9Sstevel@tonic-gate { 1118*56a424ccSmp153739 unsigned int len = strlen(progname) + 2 + strlen(v) + 2; 11197c478bd9Sstevel@tonic-gate char *ret = malloc(len); 11207c478bd9Sstevel@tonic-gate if (ret) 11217c478bd9Sstevel@tonic-gate sprintf(ret, "%s(v%s)", progname, v); 11227c478bd9Sstevel@tonic-gate else 11237c478bd9Sstevel@tonic-gate ret = progname; 11247c478bd9Sstevel@tonic-gate return ret; 11257c478bd9Sstevel@tonic-gate } 11267c478bd9Sstevel@tonic-gate 11277c478bd9Sstevel@tonic-gate #ifdef HAVE_KRB524 11287c478bd9Sstevel@tonic-gate /* Convert krb5 tickets to krb4. */ 1129*56a424ccSmp153739 static int try_convert524(k5) 11307c478bd9Sstevel@tonic-gate struct k5_data* k5; 11317c478bd9Sstevel@tonic-gate { 11327c478bd9Sstevel@tonic-gate char * progname = progname_v524; 11337c478bd9Sstevel@tonic-gate krb5_error_code code = 0; 11347c478bd9Sstevel@tonic-gate int icode = 0; 11357c478bd9Sstevel@tonic-gate krb5_principal kpcserver = 0; 11367c478bd9Sstevel@tonic-gate krb5_creds *v5creds = 0; 11377c478bd9Sstevel@tonic-gate krb5_creds increds; 11387c478bd9Sstevel@tonic-gate CREDENTIALS v4creds; 11397c478bd9Sstevel@tonic-gate 11407c478bd9Sstevel@tonic-gate if (!got_k4 || !got_k5) 11417c478bd9Sstevel@tonic-gate return 0; 11427c478bd9Sstevel@tonic-gate 11437c478bd9Sstevel@tonic-gate memset((char *) &increds, 0, sizeof(increds)); 11447c478bd9Sstevel@tonic-gate /* 11457c478bd9Sstevel@tonic-gate From this point on, we can goto cleanup because increds is 11467c478bd9Sstevel@tonic-gate initialized. 11477c478bd9Sstevel@tonic-gate */ 11487c478bd9Sstevel@tonic-gate 11497c478bd9Sstevel@tonic-gate if ((code = krb5_build_principal(k5->ctx, 11507c478bd9Sstevel@tonic-gate &kpcserver, 11517c478bd9Sstevel@tonic-gate krb5_princ_realm(k5->ctx, k5->me)->length, 11527c478bd9Sstevel@tonic-gate krb5_princ_realm(k5->ctx, k5->me)->data, 11537c478bd9Sstevel@tonic-gate "krbtgt", 11547c478bd9Sstevel@tonic-gate krb5_princ_realm(k5->ctx, k5->me)->data, 11557c478bd9Sstevel@tonic-gate NULL))) { 11567c478bd9Sstevel@tonic-gate com_err(progname, code, gettext( 11577c478bd9Sstevel@tonic-gate "while creating service principal name")); 11587c478bd9Sstevel@tonic-gate goto cleanup; 11597c478bd9Sstevel@tonic-gate } 11607c478bd9Sstevel@tonic-gate 11617c478bd9Sstevel@tonic-gate increds.client = k5->me; 11627c478bd9Sstevel@tonic-gate increds.server = kpcserver; 11637c478bd9Sstevel@tonic-gate /* Prevent duplicate free calls. */ 11647c478bd9Sstevel@tonic-gate kpcserver = 0; 11657c478bd9Sstevel@tonic-gate 11667c478bd9Sstevel@tonic-gate increds.times.endtime = 0; 11677c478bd9Sstevel@tonic-gate increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC; 11687c478bd9Sstevel@tonic-gate if ((code = krb5_get_credentials(k5->ctx, 0, 11697c478bd9Sstevel@tonic-gate k5->cc, 11707c478bd9Sstevel@tonic-gate &increds, 11717c478bd9Sstevel@tonic-gate &v5creds))) { 11727c478bd9Sstevel@tonic-gate com_err(progname, code, 11737c478bd9Sstevel@tonic-gate gettext("getting V5 credentials")); 11747c478bd9Sstevel@tonic-gate goto cleanup; 11757c478bd9Sstevel@tonic-gate } 11767c478bd9Sstevel@tonic-gate if ((icode = krb524_convert_creds_kdc(k5->ctx, 11777c478bd9Sstevel@tonic-gate v5creds, 11787c478bd9Sstevel@tonic-gate &v4creds))) { 11797c478bd9Sstevel@tonic-gate com_err(progname, icode, 11807c478bd9Sstevel@tonic-gate gettext("converting to V4 credentials")); 11817c478bd9Sstevel@tonic-gate goto cleanup; 11827c478bd9Sstevel@tonic-gate } 11837c478bd9Sstevel@tonic-gate /* this is stolen from the v4 kinit */ 11847c478bd9Sstevel@tonic-gate /* initialize ticket cache */ 11857c478bd9Sstevel@tonic-gate if ((icode = in_tkt(v4creds.pname, v4creds.pinst) 11867c478bd9Sstevel@tonic-gate != KSUCCESS)) { 11877c478bd9Sstevel@tonic-gate com_err(progname, icode, gettext( 11887c478bd9Sstevel@tonic-gate "trying to create the V4 ticket file")); 11897c478bd9Sstevel@tonic-gate goto cleanup; 11907c478bd9Sstevel@tonic-gate } 11917c478bd9Sstevel@tonic-gate /* stash ticket, session key, etc. for future use */ 11927c478bd9Sstevel@tonic-gate if ((icode = krb_save_credentials(v4creds.service, 11937c478bd9Sstevel@tonic-gate v4creds.instance, 11947c478bd9Sstevel@tonic-gate v4creds.realm, 11957c478bd9Sstevel@tonic-gate v4creds.session, 11967c478bd9Sstevel@tonic-gate v4creds.lifetime, 11977c478bd9Sstevel@tonic-gate v4creds.kvno, 11987c478bd9Sstevel@tonic-gate &(v4creds.ticket_st), 11997c478bd9Sstevel@tonic-gate v4creds.issue_date))) { 12007c478bd9Sstevel@tonic-gate com_err(progname, icode, gettext( 12017c478bd9Sstevel@tonic-gate "trying to save the V4 ticket")); 12027c478bd9Sstevel@tonic-gate goto cleanup; 12037c478bd9Sstevel@tonic-gate } 12047c478bd9Sstevel@tonic-gate 12057c478bd9Sstevel@tonic-gate cleanup: 12067c478bd9Sstevel@tonic-gate memset(&v4creds, 0, sizeof(v4creds)); 12077c478bd9Sstevel@tonic-gate if (v5creds) 12087c478bd9Sstevel@tonic-gate krb5_free_creds(k5->ctx, v5creds); 12097c478bd9Sstevel@tonic-gate increds.client = 0; 12107c478bd9Sstevel@tonic-gate krb5_free_cred_contents(k5->ctx, &increds); 12117c478bd9Sstevel@tonic-gate if (kpcserver) 12127c478bd9Sstevel@tonic-gate krb5_free_principal(k5->ctx, kpcserver); 12137c478bd9Sstevel@tonic-gate return !(code || icode); 12147c478bd9Sstevel@tonic-gate } 12157c478bd9Sstevel@tonic-gate #endif /* HAVE_KRB524 */ 12167c478bd9Sstevel@tonic-gate 12177c478bd9Sstevel@tonic-gate int 12187c478bd9Sstevel@tonic-gate main(argc, argv) 12197c478bd9Sstevel@tonic-gate int argc; 12207c478bd9Sstevel@tonic-gate char **argv; 12217c478bd9Sstevel@tonic-gate { 12227c478bd9Sstevel@tonic-gate struct k_opts opts; 12237c478bd9Sstevel@tonic-gate struct k5_data k5; 12247c478bd9Sstevel@tonic-gate struct k4_data k4; 12257c478bd9Sstevel@tonic-gate 12267c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 12277c478bd9Sstevel@tonic-gate 12287c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 12297c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 12307c478bd9Sstevel@tonic-gate #endif 12317c478bd9Sstevel@tonic-gate 12327c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 12337c478bd9Sstevel@tonic-gate 12347c478bd9Sstevel@tonic-gate progname = GET_PROGNAME(argv[0]); 1235*56a424ccSmp153739 progname_v5 = getvprogname("5", progname); 12367c478bd9Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT 1237*56a424ccSmp153739 progname_v4 = getvprogname("4", progname); 1238*56a424ccSmp153739 progname_v524 = getvprogname("524", progname); 12397c478bd9Sstevel@tonic-gate #endif 12407c478bd9Sstevel@tonic-gate 12417c478bd9Sstevel@tonic-gate /* Ensure we can be driven from a pipe */ 12427c478bd9Sstevel@tonic-gate if(!isatty(fileno(stdin))) 12437c478bd9Sstevel@tonic-gate setvbuf(stdin, 0, _IONBF, 0); 12447c478bd9Sstevel@tonic-gate if(!isatty(fileno(stdout))) 12457c478bd9Sstevel@tonic-gate setvbuf(stdout, 0, _IONBF, 0); 12467c478bd9Sstevel@tonic-gate if(!isatty(fileno(stderr))) 12477c478bd9Sstevel@tonic-gate setvbuf(stderr, 0, _IONBF, 0); 12487c478bd9Sstevel@tonic-gate 12497c478bd9Sstevel@tonic-gate /* 12507c478bd9Sstevel@tonic-gate This is where we would put in code to dynamically load Kerberos 12517c478bd9Sstevel@tonic-gate libraries. Currenlty, we just get them implicitly. 12527c478bd9Sstevel@tonic-gate */ 12537c478bd9Sstevel@tonic-gate got_k5 = 1; 12547c478bd9Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT 12557c478bd9Sstevel@tonic-gate got_k4 = 1; 12567c478bd9Sstevel@tonic-gate #endif 12577c478bd9Sstevel@tonic-gate 12587c478bd9Sstevel@tonic-gate memset(&opts, 0, sizeof(opts)); 12597c478bd9Sstevel@tonic-gate opts.action = INIT_PW; 12607c478bd9Sstevel@tonic-gate 12617c478bd9Sstevel@tonic-gate memset(&k5, 0, sizeof(k5)); 12627c478bd9Sstevel@tonic-gate memset(&k4, 0, sizeof(k4)); 12637c478bd9Sstevel@tonic-gate 1264*56a424ccSmp153739 parse_options(argc, argv, &opts, progname); 12657c478bd9Sstevel@tonic-gate 12667c478bd9Sstevel@tonic-gate got_k5 = k5_begin(&opts, &k5, &k4); 12677c478bd9Sstevel@tonic-gate got_k4 = k4_begin(&opts, &k4); 12687c478bd9Sstevel@tonic-gate 12697c478bd9Sstevel@tonic-gate authed_k5 = k5_kinit(&opts, &k5); 12707c478bd9Sstevel@tonic-gate #ifdef HAVE_KRB524 12717c478bd9Sstevel@tonic-gate if (authed_k5) 12727c478bd9Sstevel@tonic-gate authed_k4 = try_convert524(&k5); 12737c478bd9Sstevel@tonic-gate #endif 12747c478bd9Sstevel@tonic-gate if (!authed_k4) 12757c478bd9Sstevel@tonic-gate authed_k4 = k4_kinit(&opts, &k4, k5.ctx); 12767c478bd9Sstevel@tonic-gate #ifdef KRB5_KRB4_COMPAT 12777c478bd9Sstevel@tonic-gate memset(stash_password, 0, sizeof(stash_password)); 12787c478bd9Sstevel@tonic-gate #endif 12797c478bd9Sstevel@tonic-gate 12807c478bd9Sstevel@tonic-gate if (authed_k5 && opts.verbose) 12817c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Authenticated to Kerberos v5\n")); 12827c478bd9Sstevel@tonic-gate if (authed_k4 && opts.verbose) 12837c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Authenticated to Kerberos v4\n")); 12847c478bd9Sstevel@tonic-gate 12857c478bd9Sstevel@tonic-gate k5_end(&k5); 12867c478bd9Sstevel@tonic-gate k4_end(&k4); 12877c478bd9Sstevel@tonic-gate 1288*56a424ccSmp153739 if ((got_k5 && !authed_k5) || (got_k4 && !authed_k4) || 1289*56a424ccSmp153739 (!got_k5 && !got_k4)) 12907c478bd9Sstevel@tonic-gate exit(1); 12917c478bd9Sstevel@tonic-gate return 0; 12927c478bd9Sstevel@tonic-gate } 12937c478bd9Sstevel@tonic-gate 12947c478bd9Sstevel@tonic-gate static void 12957c478bd9Sstevel@tonic-gate _kwarnd_add_warning(char *me, time_t endtime) 12967c478bd9Sstevel@tonic-gate { 12977c478bd9Sstevel@tonic-gate if (kwarn_add_warning(me, endtime) != 0) 12987c478bd9Sstevel@tonic-gate fprintf(stderr, gettext( 12997c478bd9Sstevel@tonic-gate "%s: no ktkt_warnd warning possible\n"), progname); 13007c478bd9Sstevel@tonic-gate return; 13017c478bd9Sstevel@tonic-gate } 13027c478bd9Sstevel@tonic-gate 13037c478bd9Sstevel@tonic-gate 13047c478bd9Sstevel@tonic-gate static void 13057c478bd9Sstevel@tonic-gate _kwarnd_del_warning(char *me) 13067c478bd9Sstevel@tonic-gate { 13077c478bd9Sstevel@tonic-gate if (kwarn_del_warning(me) != 0) 13087c478bd9Sstevel@tonic-gate fprintf(stderr, gettext( 13097c478bd9Sstevel@tonic-gate "%s: unable to delete ktkt_warnd message for %s\n"), 13107c478bd9Sstevel@tonic-gate progname, me); 13117c478bd9Sstevel@tonic-gate return; 13127c478bd9Sstevel@tonic-gate } 1313