1b528cefcSMark MurrayCurrently, getting an initial ticket for a user involves many function 2b528cefcSMark Murraycalls, especially when a full set of features including password 3b528cefcSMark Murrayexpiration and challenge preauthentication is desired. In order to 4b528cefcSMark Murraysolve this problem, a new api is proposed. 5b528cefcSMark Murray 6b528cefcSMark Murraytypedef struct _krb5_prompt { 7b528cefcSMark Murray char *prompt; 8b528cefcSMark Murray int hidden; 9b528cefcSMark Murray krb5_data *reply; 10b528cefcSMark Murray} krb5_prompt; 11b528cefcSMark Murray 12b528cefcSMark Murraytypedef int (*krb5_prompter_fct)(krb5_context context, 13b528cefcSMark Murray void *data, 14b528cefcSMark Murray const char *banner, 15b528cefcSMark Murray int num_prompts, 16b528cefcSMark Murray krb5_prompt prompts[]); 17b528cefcSMark Murray 18b528cefcSMark Murraytypedef struct _krb5_get_init_creds_opt { 19b528cefcSMark Murray krb5_flags flags; 20b528cefcSMark Murray krb5_deltat tkt_life; 21b528cefcSMark Murray krb5_deltat renew_life; 22b528cefcSMark Murray int forwardable; 23b528cefcSMark Murray int proxiable; 24b528cefcSMark Murray krb5_enctype *etype_list; 25b528cefcSMark Murray int etype_list_length; 26b528cefcSMark Murray krb5_address **address_list; 27b528cefcSMark Murray /* XXX the next three should not be used, as they may be 28b528cefcSMark Murray removed later */ 29b528cefcSMark Murray krb5_preauthtype *preauth_list; 30b528cefcSMark Murray int preauth_list_length; 31b528cefcSMark Murray krb5_data *salt; 32b528cefcSMark Murray} krb5_get_init_creds_opt; 33b528cefcSMark Murray 34b528cefcSMark Murray#define KRB5_GET_INIT_CREDS_OPT_TKT_LIFE 0x0001 35b528cefcSMark Murray#define KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE 0x0002 36b528cefcSMark Murray#define KRB5_GET_INIT_CREDS_OPT_FORWARDABLE 0x0004 37b528cefcSMark Murray#define KRB5_GET_INIT_CREDS_OPT_PROXIABLE 0x0008 38b528cefcSMark Murray#define KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST 0x0010 39b528cefcSMark Murray#define KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST 0x0020 40b528cefcSMark Murray#define KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST 0x0040 41b528cefcSMark Murray#define KRB5_GET_INIT_CREDS_OPT_SALT 0x0080 42b528cefcSMark Murray 43b528cefcSMark Murrayvoid krb5_get_init_creds_opt_init(krb5_get_init_creds_opt *opt); 44b528cefcSMark Murray 45b528cefcSMark Murrayvoid krb5_get_init_creds_opt_set_tkt_life(krb5_get_init_creds_opt *opt, 46b528cefcSMark Murray krb5_deltat tkt_life); 47b528cefcSMark Murrayvoid krb5_get_init_creds_opt_set_renew_life(krb5_get_init_creds_opt *opt, 48b528cefcSMark Murray krb5_deltat renew_life); 49b528cefcSMark Murrayvoid krb5_get_init_creds_opt_set_forwardable(krb5_get_init_creds_opt *opt, 50b528cefcSMark Murray int forwardable); 51b528cefcSMark Murrayvoid krb5_get_init_creds_opt_set_proxiable(krb5_get_init_creds_opt *opt, 52b528cefcSMark Murray int proxiable); 53b528cefcSMark Murrayvoid krb5_get_init_creds_opt_set_etype_list(krb5_get_init_creds_opt *opt, 54b528cefcSMark Murray krb5_enctype *etype_list, 55b528cefcSMark Murray int etype_list_length); 56b528cefcSMark Murrayvoid krb5_get_init_creds_opt_set_address_list(krb5_get_init_creds_opt *opt, 57b528cefcSMark Murray krb5_address **addresses); 58b528cefcSMark Murrayvoid krb5_get_init_creds_opt_set_preauth_list(krb5_get_init_creds_opt *opt, 59b528cefcSMark Murray krb5_preauthtype *preauth_list, 60b528cefcSMark Murray int preauth_list_length); 61b528cefcSMark Murrayvoid krb5_get_init_creds_opt_set_salt(krb5_get_init_creds_opt *opt, 62b528cefcSMark Murray krb5_data *salt); 63b528cefcSMark Murray 64b528cefcSMark Murraykrb5_error_code 65b528cefcSMark Murraykrb5_get_init_creds_password(krb5_context context, 66b528cefcSMark Murray krb5_creds *creds, 67b528cefcSMark Murray krb5_principal client, 68b528cefcSMark Murray char *password, 69b528cefcSMark Murray krb5_prompter_fct prompter, 70b528cefcSMark Murray void *data, 71b528cefcSMark Murray krb5_deltat start_time, 72b528cefcSMark Murray char *in_tkt_service, 73b528cefcSMark Murray krb5_get_init_creds_opt *options); 74b528cefcSMark Murray 75b528cefcSMark MurrayThis function will attempt to acquire an initial ticket. The function 76b528cefcSMark Murraywill perform whatever tasks are necessary to do so. This may include 77b528cefcSMark Murraychanging an expired password, preauthentication. 78b528cefcSMark Murray 79b528cefcSMark MurrayThe arguments divide into two types. Some arguments are basically 80b528cefcSMark Murrayinvariant and arbitrary across all initial tickets, and if not 81b528cefcSMark Murrayspecified are determined by configuration or library defaults. Some 82b528cefcSMark Murrayarguments are different for each execution or application, and if not 83b528cefcSMark Murrayspecified can be determined correctly from system configuration or 84b528cefcSMark Murrayenvironment. The former arguments are contained in a structure whose 85b528cefcSMark Murraypointer is passed to the function. A bitmask specifies which elements 86b528cefcSMark Murrayof the structure should be used. In most cases, a NULL pointer can be 87b528cefcSMark Murrayused. The latter arguments are specified as individual arguments to 88b528cefcSMark Murraythe function. 89b528cefcSMark Murray 90b528cefcSMark MurrayIf a pointer to a credential is specified, the initial credential is 91b528cefcSMark Murrayfilled in. If the caller only wishes to do a simple password check 92b528cefcSMark Murrayand will not be doing any other kerberos functions, then a NULL 93b528cefcSMark Murraypointer may be specified, and the credential will be destroyed. 94b528cefcSMark Murray 95b528cefcSMark MurrayIf the client name is non-NULL, the initial ticket requested will be 96c19800e8SDoug Rabsonfor that principal. Otherwise, the principal will be the username 97b528cefcSMark Murrayspecified by the USER environment variable, or if the USER environment 98b528cefcSMark Murrayvariable is not set, the username corresponding to the real user id of 99b528cefcSMark Murraythe caller. 100b528cefcSMark Murray 101b528cefcSMark MurrayIf the password is non-NULL, then this string is used as the password. 102b528cefcSMark MurrayOtherwise, the prompter function will be used to prompt the user for 103b528cefcSMark Murraythe password. 104b528cefcSMark Murray 105b528cefcSMark MurrayIf a prompter function is non-NULL, it will be used if additional user 106b528cefcSMark Murrayinput is required, such as if the user's password has expired and 107b528cefcSMark Murrayneeds to be changed, or if input preauthentication is necessary. If 108b528cefcSMark Murrayno function is specified and input is required, then the login will 109b528cefcSMark Murrayfail. 110b528cefcSMark Murray 111b528cefcSMark Murray The context argument is the same as that passed to krb5_login. 112b528cefcSMark Murray The data argument is passed unmodified to the prompter 113b528cefcSMark Murray function and is intended to be used to pass application data 114b528cefcSMark Murray (such as a display handle) to the prompter function. 115b528cefcSMark Murray 116b528cefcSMark Murray The banner argument, if non-NULL, will indicate what sort of 117b528cefcSMark Murray input is expected from the user (for example, "Password has 118b528cefcSMark Murray expired and must be changed" or "Enter Activcard response for 119b528cefcSMark Murray challenge 012345678"), and should be displayed accordingly. 120b528cefcSMark Murray 121b528cefcSMark Murray The num_prompts argument indicates the number of values which 122b528cefcSMark Murray should be prompted for. If num_prompts == 0, then the banner 123b528cefcSMark Murray contains an informational message which should be displayed to 124b528cefcSMark Murray the user. 125b528cefcSMark Murray 126b528cefcSMark Murray The prompts argument contains an array describing the values 127b528cefcSMark Murray for which the user should be prompted. The prompt member 128b528cefcSMark Murray indicates the prompt for each value ("Enter new 129b528cefcSMark Murray password"/"Enter it again", or "Challenge response"). The 130b528cefcSMark Murray hidden member is nonzero if the response should not be 131b528cefcSMark Murray displayed back to the user. The reply member is a pointer to 132b528cefcSMark Murray krb5_data structure which has already been allocated. The 133b528cefcSMark Murray prompter should fill in the structure with the NUL-terminated 134b528cefcSMark Murray response from the user. 135b528cefcSMark Murray 136b528cefcSMark Murray If the response data does not fit, or if any other error 137b528cefcSMark Murray occurs, then the prompter function should return a non-zero 138b528cefcSMark Murray value which will be returned by the krb5_get_init_creds 139b528cefcSMark Murray function. Otherwise, zero should be returned. 140b528cefcSMark Murray 141b528cefcSMark Murray The library function krb5_prompter_posix() implements 142b528cefcSMark Murray a prompter using a posix terminal for user in. This function 143b528cefcSMark Murray does not use the data argument. 144b528cefcSMark Murray 145b528cefcSMark MurrayIf the start_time is zero, then the requested ticket will be valid 146b528cefcSMark Murraybeginning immediately. Otherwise, the start_time indicates how far in 147b528cefcSMark Murraythe future the ticket should be postdated. 148b528cefcSMark Murray 149b528cefcSMark MurrayIf the in_tkt_service name is non-NULL, that principal name will be 150b528cefcSMark Murrayused as the server name for the initial ticket request. The realm of 151b528cefcSMark Murraythe name specified will be ignored and will be set to the realm of the 152b528cefcSMark Murrayclient name. If no in_tkt_service name is specified, 153b528cefcSMark Murraykrbtgt/CLIENT-REALM@CLIENT-REALM will be used. 154b528cefcSMark Murray 155b528cefcSMark MurrayFor the rest of arguments, a configuration or library default will be 156b528cefcSMark Murrayused if no value is specified in the options structure. 157b528cefcSMark Murray 158b528cefcSMark MurrayIf a tkt_life is specified, that will be the lifetime of the ticket. 159b528cefcSMark MurrayThe library default is 10 hours; there is no configuration variable 160b528cefcSMark Murray(there should be, but it's not there now). 161b528cefcSMark Murray 162b528cefcSMark MurrayIf a renew_life is specified and non-zero, then the RENEWABLE option 163b528cefcSMark Murrayon the ticket will be set, and the value of the argument will be the 164b528cefcSMark Murraythe renewable lifetime. The configuration variable [libdefaults] 165b528cefcSMark Murray"renew_lifetime" is the renewable lifetime if none is passed in. The 166b528cefcSMark Murraylibrary default is not to set the RENEWABLE option. 167b528cefcSMark Murray 168b528cefcSMark MurrayIf forwardable is specified, the FORWARDABLE option on the ticket will 169b528cefcSMark Murraybe set if and only if forwardable is non-zero. The configuration 170b528cefcSMark Murrayvariable [libdefaults] "forwardable" is used if no value is passed in. 171b528cefcSMark MurrayThe option will be set if and only if the variable is "y", "yes", 172b528cefcSMark Murray"true", "t", "1", or "on", case insensitive. The library default is 173b528cefcSMark Murraynot to set the FORWARDABLE option. 174b528cefcSMark Murray 175b528cefcSMark MurrayIf proxiable is specified, the PROXIABLE option on the ticket will be 176b528cefcSMark Murrayset if and only if proxiable is non-zero. The configuration variable 177b528cefcSMark Murray[libdefaults] "proxiable" is used if no value is passed in. The 178b528cefcSMark Murrayoption will be set if and only if the variable is "y", "yes", "true", 179b528cefcSMark Murray"t", "1", or "on", case insensitive. The library default is not to 180b528cefcSMark Murrayset the PROXIABLE option. 181b528cefcSMark Murray 182b528cefcSMark MurrayIf etype_list is specified, it will be used as the list of desired 183b528cefcSMark Murrayencryption algorithms in the request. The configuration variable 184b528cefcSMark Murray[libdefaults] "default_tkt_enctypes" is used if no value is passed in. 185b528cefcSMark MurrayThe library default is "des-cbc-md5 des-cbc-crc". 186b528cefcSMark Murray 187b528cefcSMark MurrayIf address_list is specified, it will be used as the list of addresses 188b528cefcSMark Murrayfor which the ticket will be valid. The library default is to use all 189b528cefcSMark Murraylocal non-loopback addresses. There is no configuration variable. 190b528cefcSMark Murray 191b528cefcSMark MurrayIf preauth_list is specified, it names preauth data types which will 192b528cefcSMark Murraybe included in the request. The library default is to interact with 193b528cefcSMark Murraythe kdc to determine the required preauth types. There is no 194b528cefcSMark Murrayconfiguration variable. 195b528cefcSMark Murray 196b528cefcSMark MurrayIf salt is specified, it specifies the salt which will be used when 197b528cefcSMark Murrayconverting the password to a key. The library default is to interact 198b528cefcSMark Murraywith the kdc to determine the correct salt. There is no configuration 199b528cefcSMark Murrayvariable. 200b528cefcSMark Murray 201b528cefcSMark Murray================================================================ 202b528cefcSMark Murray 203b528cefcSMark Murraytypedef struct _krb5_verify_init_creds_opt { 204b528cefcSMark Murray krb5_flags flags; 205b528cefcSMark Murray int ap_req_nofail; 206b528cefcSMark Murray} krb5_verify_init_creds_opt; 207b528cefcSMark Murray 208b528cefcSMark Murray#define KRB5_VERIFY_INIT_CREDS_OPT_AP_REQ_NOFAIL 0x0001 209b528cefcSMark Murray 210b528cefcSMark Murrayvoid krb5_verify_init_creds_opt_init(krb5_init_creds_opt *options); 211b528cefcSMark Murrayvoid krb5_verify_init_creds_opt_set_ap_req_nofail(krb5_init_creds_opt *options, 212b528cefcSMark Murray int ap_req_nofail); 213b528cefcSMark Murray 214b528cefcSMark Murraykrb5_error_code 215b528cefcSMark Murraykrb5_verify_init_creds(krb5_context context, 216b528cefcSMark Murray krb5_creds *creds, 217b528cefcSMark Murray krb5_principal ap_req_server, 218b528cefcSMark Murray krb5_keytab ap_req_keytab, 219b528cefcSMark Murray krb5_ccache *ccache, 220b528cefcSMark Murray krb5_verify_init_creds_opt *options); 221b528cefcSMark Murray 222b528cefcSMark MurrayThis function will use the initial ticket in creds to make an AP_REQ 223b528cefcSMark Murrayand verify it to insure that the AS_REP has not been spoofed. 224b528cefcSMark Murray 225b528cefcSMark MurrayIf the ap_req_server name is non-NULL, then this service name will be 226b528cefcSMark Murrayused for the AP_REQ; otherwise, the default host key 227b528cefcSMark Murray(host/hostname.domain@LOCAL-REALM) will be used. 228b528cefcSMark Murray 229b528cefcSMark MurrayIf ap_req_keytab is non-NULL, the service key for the verification 230b528cefcSMark Murraywill be read from that keytab; otherwise, the service key will be read 231b528cefcSMark Murrayfrom the default keytab. 232b528cefcSMark Murray 233b528cefcSMark MurrayIf the service of the ticket in creds is the same as the service name 234b528cefcSMark Murrayfor the AP_REQ, then this ticket will be used directly. If the ticket 235b528cefcSMark Murrayis a tgt, then it will be used to obtain credentials for the service. 236b528cefcSMark MurrayOtherwise, the verification will fail, and return an error. 237b528cefcSMark Murray 238b528cefcSMark MurrayOther failures of the AP_REQ verification may or may not be considered 239b528cefcSMark Murrayerrors, as described below. 240b528cefcSMark Murray 241b528cefcSMark MurrayIf a pointer to a credential cache handle is specified, and the handle 242b528cefcSMark Murrayis NULL, a credential cache handle referring to all credentials 243b528cefcSMark Murrayobtained in the course of verifying the user will be returned. In 244b528cefcSMark Murrayorder to avoid potential setuid race conditions and other problems 245b528cefcSMark Murrayrelated to file system access, this handle will refer to a memory 246b528cefcSMark Murraycredential cache. If the handle is non-NULL, then the credentials 247b528cefcSMark Murraywill be added to the existing ccache. If the caller only wishes to 248b528cefcSMark Murrayverify the password and will not be doing any other kerberos 249b528cefcSMark Murrayfunctions, then a NULL pointer may be specified, and the credentials 250b528cefcSMark Murraywill be deleted before the function returns. 251b528cefcSMark Murray 252b528cefcSMark MurrayIf ap_req_nofail is specified, then failures of the AP_REQ 253b528cefcSMark Murrayverification are considered errors if and only if ap_req_nofail is 254b528cefcSMark Murraynon-zero. 255b528cefcSMark Murray 256b528cefcSMark MurrayWhether or not AP_REQ validation is performed and what failures mean 257b528cefcSMark Murraydepends on these inputs: 258b528cefcSMark Murray 259b528cefcSMark Murray A) The appropriate keytab exists and contains the named key. 260b528cefcSMark Murray 261b528cefcSMark Murray B) An AP_REQ request to the kdc succeeds, and the resulting AP_REQ 262b528cefcSMark Murraycan be decrypted and verified. 263b528cefcSMark Murray 264b528cefcSMark Murray C) The administrator has specified in a configuration file that 265b528cefcSMark MurrayAP_REQ validation must succeed. This is basically a paranoid bit, and 266b528cefcSMark Murraycan be overridden by the application based on a command line flag or 267b528cefcSMark Murrayother application-specific info. This flag is especially useful if 268b528cefcSMark Murraythe admin is concerned that DNS might be spoofed while determining the 269b528cefcSMark Murrayhost/FQDN name. The configuration variable [libdefaults] 270b528cefcSMark Murray"verify_ap_req_nofail" is used if no value is passed in. The library 271b528cefcSMark Murraydefault is not to set this option. 272b528cefcSMark Murray 273b528cefcSMark MurrayInitial ticket verification will succeed if and only if: 274b528cefcSMark Murray 275b528cefcSMark Murray - A && B or 276b528cefcSMark Murray - !A && !C 277b528cefcSMark Murray 278b528cefcSMark Murray================================================================ 279b528cefcSMark Murray 280b528cefcSMark MurrayFor illustrative purposes, here's the invocations I expect some 281b528cefcSMark Murrayprograms will use. Of course, error checking needs to be added. 282b528cefcSMark Murray 283b528cefcSMark Murraykinit: 284b528cefcSMark Murray 285b528cefcSMark Murray /* Fill in client from the command line || existing ccache, and, 286b528cefcSMark Murray start_time, and options.{tkt_life,renew_life,forwardable,proxiable} 287b528cefcSMark Murray from the command line. Some or all may remain unset. */ 288b528cefcSMark Murray 289b528cefcSMark Murray krb5_get_init_creds(context, &creds, client, 290b528cefcSMark Murray krb5_initial_prompter_posix, NULL, 291b528cefcSMark Murray start_time, NULL, &options); 292b528cefcSMark Murray krb5_cc_store_cred(context, ccache, &creds); 293b528cefcSMark Murray krb5_free_cred_contents(context, &creds); 294b528cefcSMark Murray 295b528cefcSMark Murraylogin: 296b528cefcSMark Murray 297b528cefcSMark Murray krb5_get_init_creds(context, &creds, client, 298b528cefcSMark Murray krb5_initial_prompter_posix, NULL, 299b528cefcSMark Murray 0, NULL, NULL); 300b528cefcSMark Murray krb5_verify_init_creds(context, &creds, NULL, NULL, &vcc, NULL); 301b528cefcSMark Murray /* setuid */ 302b528cefcSMark Murray krb5_cc_store_cred(context, ccache, &creds); 303b528cefcSMark Murray krb5_cc_copy(context, vcc, ccache); 304b528cefcSMark Murray krb5_free_cred_contents(context, &creds); 305b528cefcSMark Murray krb5_cc_destroy(context, vcc); 306b528cefcSMark Murray 307b528cefcSMark Murrayxdm: 308b528cefcSMark Murray 309b528cefcSMark Murray krb5_get_initial_creds(context, &creds, client, 310b528cefcSMark Murray krb5_initial_prompter_xt, (void *) &xtstuff, 311b528cefcSMark Murray 0, NULL, NULL); 312b528cefcSMark Murray krb5_verify_init_creds(context, &creds, NULL, NULL, &vcc, NULL); 313b528cefcSMark Murray /* setuid */ 314b528cefcSMark Murray krb5_cc_store_cred(context, ccache, &creds); 315b528cefcSMark Murray krb5_free_cred_contents(context, &creds); 316b528cefcSMark Murray krb5_cc_copy(context, vcc, ccache); 317b528cefcSMark Murray krb5_cc_destroy(context, vcc); 318b528cefcSMark Murray 319b528cefcSMark Murraypasswd: 320b528cefcSMark Murray 321b528cefcSMark Murray krb5_init_creds_opt_init(&options); 322b528cefcSMark Murray krb5_init_creds_opt_set_tkt_life = 300; 323b528cefcSMark Murray krb5_get_initial_creds(context, &creds, client, 324b528cefcSMark Murray krb5_initial_prompter_posix, NULL, 325b528cefcSMark Murray 0, "kadmin/changepw", &options); 326b528cefcSMark Murray /* change password */ 327b528cefcSMark Murray krb5_free_cred_contents(context, &creds); 328b528cefcSMark Murray 329b528cefcSMark Murraypop3d (simple password validator when no user interation possible): 330b528cefcSMark Murray 331b528cefcSMark Murray krb5_get_initial_creds(context, &creds, client, 332b528cefcSMark Murray NULL, NULL, 0, NULL, NULL); 333b528cefcSMark Murray krb5_verify_init_creds(context, &creds, NULL, NULL, &vcc, NULL); 334b528cefcSMark Murray krb5_cc_destroy(context, vcc); 335b528cefcSMark Murray 336b528cefcSMark Murray================================================================ 337b528cefcSMark Murray 338b528cefcSMark Murraypassword expiration has a subtlety. When a password expires and is 339b528cefcSMark Murraychanged, there is a delay between when the master gets the new key 340b528cefcSMark Murray(immediately), and the slaves (propogation interval). So, when 341b528cefcSMark Murraygetting an in_tkt, if the password is expired, the request should be 342b528cefcSMark Murrayreissued to the master (this kind of sucks if you have SAM, oh well). 343b528cefcSMark MurrayIf this says expired, too, then the password should be changed, and 344b528cefcSMark Murraythen the initial ticket request should be issued to the master again. 345b528cefcSMark MurrayIf the master times out, then a message that the password has expired 346b528cefcSMark Murrayand cannot be changed due to the master being unreachable should be 347b528cefcSMark Murraydisplayed. 348b528cefcSMark Murray 349b528cefcSMark Murray================================================================ 350b528cefcSMark Murray 351b528cefcSMark Murrayget_init_creds reads config stuff from: 352b528cefcSMark Murray 353b528cefcSMark Murray[libdefaults] 354b528cefcSMark Murray varname1 = defvalue 355b528cefcSMark Murray REALM = { 356b528cefcSMark Murray varname1 = value 357b528cefcSMark Murray varname2 = value 358b528cefcSMark Murray } 359b528cefcSMark Murray 360b528cefcSMark Murraytypedef struct _krb5_get_init_creds_opt { 361b528cefcSMark Murray krb5_flags flags; 362b528cefcSMark Murray krb5_deltat tkt_life; /* varname = "ticket_lifetime" */ 363b528cefcSMark Murray krb5_deltat renew_life; /* varname = "renew_lifetime" */ 364b528cefcSMark Murray int forwardable; /* varname = "forwardable" */ 365b528cefcSMark Murray int proxiable; /* varname = "proxiable" */ 366b528cefcSMark Murray krb5_enctype *etype_list; /* varname = "default_tkt_enctypes" */ 367b528cefcSMark Murray int etype_list_length; 368b528cefcSMark Murray krb5_address **address_list; /* no varname */ 369b528cefcSMark Murray krb5_preauthtype *preauth_list; /* no varname */ 370b528cefcSMark Murray int preauth_list_length; 371b528cefcSMark Murray krb5_data *salt; 372b528cefcSMark Murray} krb5_get_init_creds_opt; 373b528cefcSMark Murray 374b528cefcSMark Murray 375