1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
4 #include <krb5/clpreauth_plugin.h>
6 #define GIC_OPT_EXTENDED 0x80000000
7 #define GIC_OPT_SHALLOW_COPY 0x40000000
9 #define DEFAULT_FLAGS KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT
11 #if defined(__MACH__) && defined(__APPLE__)
12 #include <TargetConditionals.h>
15 /* Match struct packing of krb5_get_init_creds_opt on MacOS X. */
19 struct extended_options {
20 krb5_get_init_creds_opt opt;
22 krb5_gic_opt_pa_data *preauth_data;
23 char *fast_ccache_name;
24 krb5_ccache in_ccache;
25 krb5_ccache out_ccache;
26 krb5_flags fast_flags;
27 krb5_expire_callback_func expire_cb;
29 krb5_responder_fn responder;
31 int pac_request; /* -1 unset, 0 false, 1 true */
38 krb5_get_init_creds_opt_init(krb5_get_init_creds_opt *opt)
40 opt->flags = DEFAULT_FLAGS;
44 krb5_get_init_creds_opt_set_tkt_life(krb5_get_init_creds_opt *opt,
47 opt->flags |= KRB5_GET_INIT_CREDS_OPT_TKT_LIFE;
48 opt->tkt_life = tkt_life;
52 krb5_get_init_creds_opt_set_renew_life(krb5_get_init_creds_opt *opt,
53 krb5_deltat renew_life)
55 opt->flags |= KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE;
56 opt->renew_life = renew_life;
60 krb5_get_init_creds_opt_set_forwardable(krb5_get_init_creds_opt *opt,
63 opt->flags |= KRB5_GET_INIT_CREDS_OPT_FORWARDABLE;
64 opt->forwardable = forwardable;
68 krb5_get_init_creds_opt_set_proxiable(krb5_get_init_creds_opt *opt,
71 opt->flags |= KRB5_GET_INIT_CREDS_OPT_PROXIABLE;
72 opt->proxiable = proxiable;
76 krb5_get_init_creds_opt_set_canonicalize(krb5_get_init_creds_opt *opt,
80 opt->flags |= KRB5_GET_INIT_CREDS_OPT_CANONICALIZE;
82 opt->flags &= ~(KRB5_GET_INIT_CREDS_OPT_CANONICALIZE);
86 krb5_get_init_creds_opt_set_anonymous (krb5_get_init_creds_opt *opt,
90 opt->flags |= KRB5_GET_INIT_CREDS_OPT_ANONYMOUS;
91 else opt->flags &= ~KRB5_GET_INIT_CREDS_OPT_ANONYMOUS;
95 krb5_get_init_creds_opt_set_etype_list(krb5_get_init_creds_opt *opt, krb5_enctype *etype_list, int etype_list_length)
97 opt->flags |= KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST;
98 opt->etype_list = etype_list;
99 opt->etype_list_length = etype_list_length;
103 krb5_get_init_creds_opt_set_address_list(krb5_get_init_creds_opt *opt,
104 krb5_address **addresses)
106 opt->flags |= KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST;
107 opt->address_list = addresses;
111 krb5_get_init_creds_opt_set_preauth_list(krb5_get_init_creds_opt *opt,
112 krb5_preauthtype *preauth_list,
113 int preauth_list_length)
115 opt->flags |= KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST;
116 opt->preauth_list = preauth_list;
117 opt->preauth_list_length = preauth_list_length;
121 krb5_get_init_creds_opt_set_salt(krb5_get_init_creds_opt *opt, krb5_data *salt)
123 opt->flags |= KRB5_GET_INIT_CREDS_OPT_SALT;
128 krb5_get_init_creds_opt_set_change_password_prompt(
129 krb5_get_init_creds_opt *opt, int prompt)
132 opt->flags |= KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT;
134 opt->flags &= ~KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT;
137 krb5_error_code KRB5_CALLCONV
138 krb5_get_init_creds_opt_alloc(krb5_context context,
139 krb5_get_init_creds_opt **opt)
141 struct extended_options *opte;
147 /* Return an extended structure cast as a krb5_get_init_creds_opt. */
148 opte = calloc(1, sizeof(*opte));
151 opte->opt.flags = DEFAULT_FLAGS | GIC_OPT_EXTENDED;
152 opte->pac_request = -1;
153 *opt = (krb5_get_init_creds_opt *)opte;
158 krb5_get_init_creds_opt_free(krb5_context context,
159 krb5_get_init_creds_opt *opt)
161 struct extended_options *opte = (struct extended_options *)opt;
164 if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED))
166 assert(!(opt->flags & GIC_OPT_SHALLOW_COPY));
167 for (i = 0; i < opte->num_preauth_data; i++) {
168 free(opte->preauth_data[i].attr);
169 free(opte->preauth_data[i].value);
171 free(opte->preauth_data);
172 free(opte->fast_ccache_name);
176 krb5_error_code KRB5_CALLCONV
177 krb5_get_init_creds_opt_set_pa(krb5_context context,
178 krb5_get_init_creds_opt *opt,
182 struct extended_options *opte = (struct extended_options *)opt;
183 krb5_gic_opt_pa_data *t, *pa;
185 if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED))
187 assert(!(opt->flags & GIC_OPT_SHALLOW_COPY));
189 /* Allocate space for another option. */
190 t = realloc(opte->preauth_data, (opte->num_preauth_data + 1) * sizeof(*t));
193 opte->preauth_data = t;
195 /* Copy the option into the new slot. */
196 pa = &opte->preauth_data[opte->num_preauth_data];
197 pa->attr = strdup(attr);
198 if (pa->attr == NULL)
200 pa->value = strdup(value);
201 if (pa->value == NULL) {
205 opte->num_preauth_data++;
207 /* Give preauth modules a chance to look at the option now. */
208 return krb5_preauth_supply_preauth_data(context, opt, attr, value);
212 * This function allows a preauth plugin to obtain preauth
213 * options. The preauth_data returned from this function
214 * should be freed by calling krb5_get_init_creds_opt_free_pa().
216 * The 'opt' pointer supplied to this function must have been
217 * obtained using krb5_get_init_creds_opt_alloc()
219 krb5_error_code KRB5_CALLCONV
220 krb5_get_init_creds_opt_get_pa(krb5_context context,
221 krb5_get_init_creds_opt *opt,
222 int *num_preauth_data,
223 krb5_gic_opt_pa_data **preauth_data)
225 struct extended_options *opte = (struct extended_options *)opt;
226 krb5_gic_opt_pa_data *p = NULL;
229 if (num_preauth_data == NULL || preauth_data == NULL)
231 *num_preauth_data = 0;
232 *preauth_data = NULL;
233 if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED))
236 if (opte->num_preauth_data == 0)
239 p = calloc(opte->num_preauth_data, sizeof(*p));
243 for (i = 0; i < opte->num_preauth_data; i++) {
244 p[i].attr = strdup(opte->preauth_data[i].attr);
245 p[i].value = strdup(opte->preauth_data[i].value);
246 if (p[i].attr == NULL || p[i].value == NULL)
249 *num_preauth_data = i;
254 krb5_get_init_creds_opt_free_pa(context, opte->num_preauth_data, p);
259 * This function frees the preauth_data that was returned by
260 * krb5_get_init_creds_opt_get_pa().
263 krb5_get_init_creds_opt_free_pa(krb5_context context, int num_preauth_data,
264 krb5_gic_opt_pa_data *preauth_data)
268 if (num_preauth_data <= 0 || preauth_data == NULL)
271 for (i = 0; i < num_preauth_data; i++) {
272 free(preauth_data[i].attr);
273 free(preauth_data[i].value);
278 krb5_error_code KRB5_CALLCONV
279 krb5_get_init_creds_opt_set_fast_ccache_name(krb5_context context,
280 krb5_get_init_creds_opt *opt,
281 const char *ccache_name)
283 struct extended_options *opte = (struct extended_options *)opt;
285 if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED))
287 assert(!(opt->flags & GIC_OPT_SHALLOW_COPY));
288 free(opte->fast_ccache_name);
289 opte->fast_ccache_name = strdup(ccache_name);
290 if (opte->fast_ccache_name == NULL)
295 krb5_error_code KRB5_CALLCONV
296 krb5_get_init_creds_opt_set_fast_ccache(krb5_context context,
297 krb5_get_init_creds_opt *opt,
303 ret = krb5_cc_get_full_name(context, ccache, &name);
306 ret = krb5_get_init_creds_opt_set_fast_ccache_name(context, opt, name);
312 k5_gic_opt_get_fast_ccache_name(krb5_get_init_creds_opt *opt)
314 struct extended_options *opte = (struct extended_options *)opt;
316 if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED))
318 return opte->fast_ccache_name;
321 krb5_error_code KRB5_CALLCONV
322 krb5_get_init_creds_opt_set_in_ccache(krb5_context context,
323 krb5_get_init_creds_opt *opt,
326 struct extended_options *opte = (struct extended_options *)opt;
328 if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED))
330 opte->in_ccache = ccache;
335 k5_gic_opt_get_in_ccache(krb5_get_init_creds_opt *opt)
337 struct extended_options *opte = (struct extended_options *)opt;
339 if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED))
341 return opte->in_ccache;
344 krb5_error_code KRB5_CALLCONV
345 krb5_get_init_creds_opt_set_out_ccache(krb5_context context,
346 krb5_get_init_creds_opt *opt,
349 struct extended_options *opte = (struct extended_options *)opt;
351 if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED))
353 opte->out_ccache = ccache;
358 k5_gic_opt_get_out_ccache(krb5_get_init_creds_opt *opt)
360 struct extended_options *opte = (struct extended_options *)opt;
362 if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED))
364 return opte->out_ccache;
367 krb5_error_code KRB5_CALLCONV
368 krb5_get_init_creds_opt_set_fast_flags(krb5_context context,
369 krb5_get_init_creds_opt *opt,
372 struct extended_options *opte = (struct extended_options *)opt;
374 if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED))
376 opte->fast_flags = flags;
380 krb5_error_code KRB5_CALLCONV
381 krb5_get_init_creds_opt_get_fast_flags(krb5_context context,
382 krb5_get_init_creds_opt *opt,
383 krb5_flags *out_flags)
385 struct extended_options *opte = (struct extended_options *)opt;
387 if (out_flags == NULL)
390 if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED))
392 *out_flags = opte->fast_flags;
397 k5_gic_opt_get_fast_flags(krb5_get_init_creds_opt *opt)
399 struct extended_options *opte = (struct extended_options *)opt;
401 if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED))
403 return opte->fast_flags;
406 krb5_error_code KRB5_CALLCONV
407 krb5_get_init_creds_opt_set_expire_callback(krb5_context context,
408 krb5_get_init_creds_opt *opt,
409 krb5_expire_callback_func cb,
412 struct extended_options *opte = (struct extended_options *)opt;
414 if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED))
416 opte->expire_cb = cb;
417 opte->expire_data = data;
422 k5_gic_opt_get_expire_cb(krb5_get_init_creds_opt *opt,
423 krb5_expire_callback_func *cb_out, void **data_out)
425 struct extended_options *opte = (struct extended_options *)opt;
429 if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED))
431 *cb_out = opte->expire_cb;
432 *data_out = opte->expire_data;
435 krb5_error_code KRB5_CALLCONV
436 krb5_get_init_creds_opt_set_responder(krb5_context context,
437 krb5_get_init_creds_opt *opt,
438 krb5_responder_fn responder, void *data)
440 struct extended_options *opte = (struct extended_options *)opt;
442 if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED))
444 opte->responder = responder;
445 opte->responder_data = data;
450 k5_gic_opt_get_responder(krb5_get_init_creds_opt *opt,
451 krb5_responder_fn *responder_out, void **data_out)
453 struct extended_options *opte = (struct extended_options *)opt;
455 *responder_out = NULL;
457 if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED))
459 *responder_out = opte->responder;
460 *data_out = opte->responder_data;
463 krb5_get_init_creds_opt *
464 k5_gic_opt_shallow_copy(krb5_get_init_creds_opt *opt)
466 struct extended_options *opte;
468 opte = calloc(1, sizeof(*opte));
470 opte->opt.flags = DEFAULT_FLAGS;
471 else if (opt->flags & GIC_OPT_EXTENDED)
472 *opte = *(struct extended_options *)opt;
475 opte->opt.flags |= GIC_OPT_SHALLOW_COPY;
476 return (krb5_get_init_creds_opt *)opte;
479 krb5_error_code KRB5_CALLCONV
480 krb5_get_init_creds_opt_set_pac_request(krb5_context context,
481 krb5_get_init_creds_opt *opt,
482 krb5_boolean req_pac)
484 struct extended_options *opte = (struct extended_options *)opt;
486 if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED))
488 opte->pac_request = !!req_pac;
493 k5_gic_opt_pac_request(krb5_get_init_creds_opt *opt)
495 struct extended_options *opte = (struct extended_options *)opt;
497 if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED))
499 return opte->pac_request;