/crypto/heimdal/doc/init-creds

https://bitbucket.org/freebsd/freebsd-head/ · #! · 374 lines · 305 code · 69 blank · 0 comment · 0 complexity · ec6dd12a276cdb3199833b3873d32ddc MD5 · raw file

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