1*159d09a2SMark Phalan #include "k5-int.h"
2*159d09a2SMark Phalan #include "int-proto.h"
3*159d09a2SMark Phalan
4*159d09a2SMark Phalan static void
init_common(krb5_get_init_creds_opt * opt)5*159d09a2SMark Phalan init_common(krb5_get_init_creds_opt *opt)
6*159d09a2SMark Phalan {
7*159d09a2SMark Phalan opt->flags |= KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT;
8*159d09a2SMark Phalan }
97c478bd9Sstevel@tonic-gate
10505d05c7Sgtb void KRB5_CALLCONV
krb5_get_init_creds_opt_init(krb5_get_init_creds_opt * opt)11505d05c7Sgtb krb5_get_init_creds_opt_init(krb5_get_init_creds_opt *opt)
127c478bd9Sstevel@tonic-gate {
137c478bd9Sstevel@tonic-gate opt->flags = 0;
14*159d09a2SMark Phalan init_common(opt);
157c478bd9Sstevel@tonic-gate }
167c478bd9Sstevel@tonic-gate
17505d05c7Sgtb void KRB5_CALLCONV
krb5_get_init_creds_opt_set_tkt_life(krb5_get_init_creds_opt * opt,krb5_deltat tkt_life)18505d05c7Sgtb krb5_get_init_creds_opt_set_tkt_life(krb5_get_init_creds_opt *opt, krb5_deltat tkt_life)
197c478bd9Sstevel@tonic-gate {
207c478bd9Sstevel@tonic-gate opt->flags |= KRB5_GET_INIT_CREDS_OPT_TKT_LIFE;
217c478bd9Sstevel@tonic-gate opt->tkt_life = tkt_life;
227c478bd9Sstevel@tonic-gate }
237c478bd9Sstevel@tonic-gate
24505d05c7Sgtb void KRB5_CALLCONV
krb5_get_init_creds_opt_set_renew_life(krb5_get_init_creds_opt * opt,krb5_deltat renew_life)25505d05c7Sgtb krb5_get_init_creds_opt_set_renew_life(krb5_get_init_creds_opt *opt, krb5_deltat renew_life)
267c478bd9Sstevel@tonic-gate {
277c478bd9Sstevel@tonic-gate opt->flags |= KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE;
287c478bd9Sstevel@tonic-gate opt->renew_life = renew_life;
297c478bd9Sstevel@tonic-gate }
307c478bd9Sstevel@tonic-gate
31505d05c7Sgtb void KRB5_CALLCONV
krb5_get_init_creds_opt_set_forwardable(krb5_get_init_creds_opt * opt,int forwardable)32505d05c7Sgtb krb5_get_init_creds_opt_set_forwardable(krb5_get_init_creds_opt *opt, int forwardable)
337c478bd9Sstevel@tonic-gate {
347c478bd9Sstevel@tonic-gate opt->flags |= KRB5_GET_INIT_CREDS_OPT_FORWARDABLE;
357c478bd9Sstevel@tonic-gate opt->forwardable = forwardable;
367c478bd9Sstevel@tonic-gate }
377c478bd9Sstevel@tonic-gate
38505d05c7Sgtb void KRB5_CALLCONV
krb5_get_init_creds_opt_set_proxiable(krb5_get_init_creds_opt * opt,int proxiable)39505d05c7Sgtb krb5_get_init_creds_opt_set_proxiable(krb5_get_init_creds_opt *opt, int proxiable)
407c478bd9Sstevel@tonic-gate {
417c478bd9Sstevel@tonic-gate opt->flags |= KRB5_GET_INIT_CREDS_OPT_PROXIABLE;
427c478bd9Sstevel@tonic-gate opt->proxiable = proxiable;
437c478bd9Sstevel@tonic-gate }
447c478bd9Sstevel@tonic-gate
45505d05c7Sgtb void KRB5_CALLCONV
krb5_get_init_creds_opt_set_etype_list(krb5_get_init_creds_opt * opt,krb5_enctype * etype_list,int etype_list_length)46505d05c7Sgtb krb5_get_init_creds_opt_set_etype_list(krb5_get_init_creds_opt *opt, krb5_enctype *etype_list, int etype_list_length)
477c478bd9Sstevel@tonic-gate {
487c478bd9Sstevel@tonic-gate opt->flags |= KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST;
497c478bd9Sstevel@tonic-gate opt->etype_list = etype_list;
507c478bd9Sstevel@tonic-gate opt->etype_list_length = etype_list_length;
517c478bd9Sstevel@tonic-gate }
527c478bd9Sstevel@tonic-gate
53505d05c7Sgtb void KRB5_CALLCONV
krb5_get_init_creds_opt_set_address_list(krb5_get_init_creds_opt * opt,krb5_address ** addresses)54505d05c7Sgtb krb5_get_init_creds_opt_set_address_list(krb5_get_init_creds_opt *opt, krb5_address **addresses)
557c478bd9Sstevel@tonic-gate {
567c478bd9Sstevel@tonic-gate opt->flags |= KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST;
577c478bd9Sstevel@tonic-gate opt->address_list = addresses;
587c478bd9Sstevel@tonic-gate }
597c478bd9Sstevel@tonic-gate
60505d05c7Sgtb void KRB5_CALLCONV
krb5_get_init_creds_opt_set_preauth_list(krb5_get_init_creds_opt * opt,krb5_preauthtype * preauth_list,int preauth_list_length)61505d05c7Sgtb krb5_get_init_creds_opt_set_preauth_list(krb5_get_init_creds_opt *opt, krb5_preauthtype *preauth_list, int preauth_list_length)
627c478bd9Sstevel@tonic-gate {
637c478bd9Sstevel@tonic-gate opt->flags |= KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST;
647c478bd9Sstevel@tonic-gate opt->preauth_list = preauth_list;
657c478bd9Sstevel@tonic-gate opt->preauth_list_length = preauth_list_length;
667c478bd9Sstevel@tonic-gate }
677c478bd9Sstevel@tonic-gate
68505d05c7Sgtb void KRB5_CALLCONV
krb5_get_init_creds_opt_set_salt(krb5_get_init_creds_opt * opt,krb5_data * salt)69505d05c7Sgtb krb5_get_init_creds_opt_set_salt(krb5_get_init_creds_opt *opt, krb5_data *salt)
707c478bd9Sstevel@tonic-gate {
717c478bd9Sstevel@tonic-gate opt->flags |= KRB5_GET_INIT_CREDS_OPT_SALT;
727c478bd9Sstevel@tonic-gate opt->salt = salt;
737c478bd9Sstevel@tonic-gate }
74*159d09a2SMark Phalan
75*159d09a2SMark Phalan void KRB5_CALLCONV
krb5_get_init_creds_opt_set_change_password_prompt(krb5_get_init_creds_opt * opt,int prompt)76*159d09a2SMark Phalan krb5_get_init_creds_opt_set_change_password_prompt(krb5_get_init_creds_opt *opt, int prompt)
77*159d09a2SMark Phalan {
78*159d09a2SMark Phalan if (prompt)
79*159d09a2SMark Phalan opt->flags |= KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT;
80*159d09a2SMark Phalan else
81*159d09a2SMark Phalan opt->flags &= ~KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT;
82*159d09a2SMark Phalan }
83*159d09a2SMark Phalan
84*159d09a2SMark Phalan /*
85*159d09a2SMark Phalan * Extending the krb5_get_init_creds_opt structure. The original
86*159d09a2SMark Phalan * krb5_get_init_creds_opt structure is defined publicly. The
87*159d09a2SMark Phalan * new extended version is private. The original interface
88*159d09a2SMark Phalan * assumed a pre-allocated structure which was passed to
89*159d09a2SMark Phalan * krb5_get_init_creds_init(). The new interface assumes that
90*159d09a2SMark Phalan * the caller will call krb5_get_init_creds_alloc() and
91*159d09a2SMark Phalan * krb5_get_init_creds_free().
92*159d09a2SMark Phalan *
93*159d09a2SMark Phalan * Callers MUST NOT call krb5_get_init_creds_init() after allocating an
94*159d09a2SMark Phalan * opts structure using krb5_get_init_creds_alloc(). To do so will
95*159d09a2SMark Phalan * introduce memory leaks. Unfortunately, there is no way to enforce
96*159d09a2SMark Phalan * this behavior.
97*159d09a2SMark Phalan *
98*159d09a2SMark Phalan * Two private flags are added for backward compatibility.
99*159d09a2SMark Phalan * KRB5_GET_INIT_CREDS_OPT_EXTENDED says that the structure was allocated
100*159d09a2SMark Phalan * with the new krb5_get_init_creds_opt_alloc() function.
101*159d09a2SMark Phalan * KRB5_GET_INIT_CREDS_OPT_SHADOWED is set to indicate that the extended
102*159d09a2SMark Phalan * structure is a shadow copy of an original krb5_get_init_creds_opt
103*159d09a2SMark Phalan * structure.
104*159d09a2SMark Phalan * If KRB5_GET_INIT_CREDS_OPT_SHADOWED is set after a call to
105*159d09a2SMark Phalan * krb5int_gic_opt_to_opte(), the resulting extended structure should be
106*159d09a2SMark Phalan * freed (using krb5_get_init_creds_free). Otherwise, the original
107*159d09a2SMark Phalan * structure was already extended and there is no need to free it.
108*159d09a2SMark Phalan */
109*159d09a2SMark Phalan
110*159d09a2SMark Phalan /* Forward prototype */
111*159d09a2SMark Phalan static void
112*159d09a2SMark Phalan free_gic_opt_ext_preauth_data(krb5_context context,
113*159d09a2SMark Phalan krb5_gic_opt_ext *opte);
114*159d09a2SMark Phalan
115*159d09a2SMark Phalan static krb5_error_code
krb5int_gic_opte_private_alloc(krb5_context context,krb5_gic_opt_ext * opte)116*159d09a2SMark Phalan krb5int_gic_opte_private_alloc(krb5_context context, krb5_gic_opt_ext *opte)
117*159d09a2SMark Phalan {
118*159d09a2SMark Phalan if (NULL == opte || !krb5_gic_opt_is_extended(opte))
119*159d09a2SMark Phalan return EINVAL;
120*159d09a2SMark Phalan
121*159d09a2SMark Phalan opte->opt_private = calloc(1, sizeof(*opte->opt_private));
122*159d09a2SMark Phalan if (NULL == opte->opt_private) {
123*159d09a2SMark Phalan return ENOMEM;
124*159d09a2SMark Phalan }
125*159d09a2SMark Phalan /* Allocate any private stuff */
126*159d09a2SMark Phalan opte->opt_private->num_preauth_data = 0;
127*159d09a2SMark Phalan opte->opt_private->preauth_data = NULL;
128*159d09a2SMark Phalan return 0;
129*159d09a2SMark Phalan }
130*159d09a2SMark Phalan
131*159d09a2SMark Phalan static krb5_error_code
krb5int_gic_opte_private_free(krb5_context context,krb5_gic_opt_ext * opte)132*159d09a2SMark Phalan krb5int_gic_opte_private_free(krb5_context context, krb5_gic_opt_ext *opte)
133*159d09a2SMark Phalan {
134*159d09a2SMark Phalan if (NULL == opte || !krb5_gic_opt_is_extended(opte))
135*159d09a2SMark Phalan return EINVAL;
136*159d09a2SMark Phalan
137*159d09a2SMark Phalan /* Free up any private stuff */
138*159d09a2SMark Phalan if (opte->opt_private->preauth_data != NULL)
139*159d09a2SMark Phalan free_gic_opt_ext_preauth_data(context, opte);
140*159d09a2SMark Phalan free(opte->opt_private);
141*159d09a2SMark Phalan opte->opt_private = NULL;
142*159d09a2SMark Phalan return 0;
143*159d09a2SMark Phalan }
144*159d09a2SMark Phalan
145*159d09a2SMark Phalan static krb5_gic_opt_ext *
krb5int_gic_opte_alloc(krb5_context context)146*159d09a2SMark Phalan krb5int_gic_opte_alloc(krb5_context context)
147*159d09a2SMark Phalan {
148*159d09a2SMark Phalan krb5_gic_opt_ext *opte;
149*159d09a2SMark Phalan krb5_error_code code;
150*159d09a2SMark Phalan
151*159d09a2SMark Phalan opte = calloc(1, sizeof(*opte));
152*159d09a2SMark Phalan if (NULL == opte)
153*159d09a2SMark Phalan return NULL;
154*159d09a2SMark Phalan opte->flags = KRB5_GET_INIT_CREDS_OPT_EXTENDED;
155*159d09a2SMark Phalan
156*159d09a2SMark Phalan code = krb5int_gic_opte_private_alloc(context, opte);
157*159d09a2SMark Phalan if (code) {
158*159d09a2SMark Phalan krb5int_set_error(&context->err, code,
159*159d09a2SMark Phalan "krb5int_gic_opte_alloc: krb5int_gic_opte_private_alloc failed");
160*159d09a2SMark Phalan free(opte);
161*159d09a2SMark Phalan return NULL;
162*159d09a2SMark Phalan }
163*159d09a2SMark Phalan return(opte);
164*159d09a2SMark Phalan }
165*159d09a2SMark Phalan
166*159d09a2SMark Phalan krb5_error_code KRB5_CALLCONV
krb5_get_init_creds_opt_alloc(krb5_context context,krb5_get_init_creds_opt ** opt)167*159d09a2SMark Phalan krb5_get_init_creds_opt_alloc(krb5_context context,
168*159d09a2SMark Phalan krb5_get_init_creds_opt **opt)
169*159d09a2SMark Phalan {
170*159d09a2SMark Phalan krb5_gic_opt_ext *opte;
171*159d09a2SMark Phalan
172*159d09a2SMark Phalan if (NULL == opt)
173*159d09a2SMark Phalan return EINVAL;
174*159d09a2SMark Phalan *opt = NULL;
175*159d09a2SMark Phalan
176*159d09a2SMark Phalan /*
177*159d09a2SMark Phalan * We return a new extended structure cast as a krb5_get_init_creds_opt
178*159d09a2SMark Phalan */
179*159d09a2SMark Phalan opte = krb5int_gic_opte_alloc(context);
180*159d09a2SMark Phalan if (NULL == opte)
181*159d09a2SMark Phalan return ENOMEM;
182*159d09a2SMark Phalan
183*159d09a2SMark Phalan *opt = (krb5_get_init_creds_opt *) opte;
184*159d09a2SMark Phalan init_common(*opt);
185*159d09a2SMark Phalan return 0;
186*159d09a2SMark Phalan }
187*159d09a2SMark Phalan
188*159d09a2SMark Phalan void KRB5_CALLCONV
krb5_get_init_creds_opt_free(krb5_context context,krb5_get_init_creds_opt * opt)189*159d09a2SMark Phalan krb5_get_init_creds_opt_free(krb5_context context,
190*159d09a2SMark Phalan krb5_get_init_creds_opt *opt)
191*159d09a2SMark Phalan {
192*159d09a2SMark Phalan krb5_gic_opt_ext *opte;
193*159d09a2SMark Phalan
194*159d09a2SMark Phalan if (NULL == opt)
195*159d09a2SMark Phalan return;
196*159d09a2SMark Phalan
197*159d09a2SMark Phalan /* Don't touch it if we didn't allocate it */
198*159d09a2SMark Phalan if (!krb5_gic_opt_is_extended(opt))
199*159d09a2SMark Phalan return;
200*159d09a2SMark Phalan
201*159d09a2SMark Phalan opte = (krb5_gic_opt_ext *)opt;
202*159d09a2SMark Phalan if (opte->opt_private)
203*159d09a2SMark Phalan krb5int_gic_opte_private_free(context, opte);
204*159d09a2SMark Phalan
205*159d09a2SMark Phalan free(opte);
206*159d09a2SMark Phalan }
207*159d09a2SMark Phalan
208*159d09a2SMark Phalan static krb5_error_code
krb5int_gic_opte_copy(krb5_context context,krb5_get_init_creds_opt * opt,krb5_gic_opt_ext ** opte)209*159d09a2SMark Phalan krb5int_gic_opte_copy(krb5_context context,
210*159d09a2SMark Phalan krb5_get_init_creds_opt *opt,
211*159d09a2SMark Phalan krb5_gic_opt_ext **opte)
212*159d09a2SMark Phalan {
213*159d09a2SMark Phalan krb5_gic_opt_ext *oe;
214*159d09a2SMark Phalan
215*159d09a2SMark Phalan oe = krb5int_gic_opte_alloc(context);
216*159d09a2SMark Phalan if (NULL == oe)
217*159d09a2SMark Phalan return ENOMEM;
218*159d09a2SMark Phalan
219*159d09a2SMark Phalan if (opt)
220*159d09a2SMark Phalan memcpy(oe, opt, sizeof(*opt));
221*159d09a2SMark Phalan
222*159d09a2SMark Phalan /*
223*159d09a2SMark Phalan * Fix the flags -- the EXTENDED flag would have been
224*159d09a2SMark Phalan * overwritten by the copy if there was one. The
225*159d09a2SMark Phalan * SHADOWED flag is necessary to ensure that the
226*159d09a2SMark Phalan * krb5_gic_opt_ext structure that was allocated
227*159d09a2SMark Phalan * here will be freed by the library because the
228*159d09a2SMark Phalan * application is unaware of its existence.
229*159d09a2SMark Phalan */
230*159d09a2SMark Phalan oe->flags |= ( KRB5_GET_INIT_CREDS_OPT_EXTENDED |
231*159d09a2SMark Phalan KRB5_GET_INIT_CREDS_OPT_SHADOWED);
232*159d09a2SMark Phalan
233*159d09a2SMark Phalan *opte = oe;
234*159d09a2SMark Phalan return 0;
235*159d09a2SMark Phalan }
236*159d09a2SMark Phalan
237*159d09a2SMark Phalan /*
238*159d09a2SMark Phalan * Convert a krb5_get_init_creds_opt pointer to a pointer to
239*159d09a2SMark Phalan * an extended, krb5_gic_opt_ext pointer. If the original
240*159d09a2SMark Phalan * pointer already points to an extended structure, then simply
241*159d09a2SMark Phalan * return the original pointer. Otherwise, if 'force' is non-zero,
242*159d09a2SMark Phalan * allocate an extended structure and copy the original over it.
243*159d09a2SMark Phalan * If the original pointer did not point to an extended structure
244*159d09a2SMark Phalan * and 'force' is zero, then return an error. This is used in
245*159d09a2SMark Phalan * cases where the original *should* be an extended structure.
246*159d09a2SMark Phalan */
247*159d09a2SMark Phalan krb5_error_code
krb5int_gic_opt_to_opte(krb5_context context,krb5_get_init_creds_opt * opt,krb5_gic_opt_ext ** opte,unsigned int force,const char * where)248*159d09a2SMark Phalan krb5int_gic_opt_to_opte(krb5_context context,
249*159d09a2SMark Phalan krb5_get_init_creds_opt *opt,
250*159d09a2SMark Phalan krb5_gic_opt_ext **opte,
251*159d09a2SMark Phalan unsigned int force,
252*159d09a2SMark Phalan const char *where)
253*159d09a2SMark Phalan {
254*159d09a2SMark Phalan if (!krb5_gic_opt_is_extended(opt)) {
255*159d09a2SMark Phalan if (force) {
256*159d09a2SMark Phalan return krb5int_gic_opte_copy(context, opt, opte);
257*159d09a2SMark Phalan } else {
258*159d09a2SMark Phalan krb5int_set_error(&context->err, EINVAL,
259*159d09a2SMark Phalan "%s: attempt to convert non-extended krb5_get_init_creds_opt",
260*159d09a2SMark Phalan where);
261*159d09a2SMark Phalan return EINVAL;
262*159d09a2SMark Phalan }
263*159d09a2SMark Phalan }
264*159d09a2SMark Phalan /* If it is already extended, just return it */
265*159d09a2SMark Phalan *opte = (krb5_gic_opt_ext *)opt;
266*159d09a2SMark Phalan return 0;
267*159d09a2SMark Phalan }
268*159d09a2SMark Phalan
269*159d09a2SMark Phalan static void
free_gic_opt_ext_preauth_data(krb5_context context,krb5_gic_opt_ext * opte)270*159d09a2SMark Phalan free_gic_opt_ext_preauth_data(krb5_context context,
271*159d09a2SMark Phalan krb5_gic_opt_ext *opte)
272*159d09a2SMark Phalan {
273*159d09a2SMark Phalan int i;
274*159d09a2SMark Phalan
275*159d09a2SMark Phalan if (NULL == opte || !krb5_gic_opt_is_extended(opte))
276*159d09a2SMark Phalan return;
277*159d09a2SMark Phalan if (NULL == opte->opt_private || NULL == opte->opt_private->preauth_data)
278*159d09a2SMark Phalan return;
279*159d09a2SMark Phalan
280*159d09a2SMark Phalan for (i = 0; i < opte->opt_private->num_preauth_data; i++) {
281*159d09a2SMark Phalan if (opte->opt_private->preauth_data[i].attr != NULL)
282*159d09a2SMark Phalan free(opte->opt_private->preauth_data[i].attr);
283*159d09a2SMark Phalan if (opte->opt_private->preauth_data[i].value != NULL)
284*159d09a2SMark Phalan free(opte->opt_private->preauth_data[i].value);
285*159d09a2SMark Phalan }
286*159d09a2SMark Phalan free(opte->opt_private->preauth_data);
287*159d09a2SMark Phalan opte->opt_private->preauth_data = NULL;
288*159d09a2SMark Phalan opte->opt_private->num_preauth_data = 0;
289*159d09a2SMark Phalan }
290*159d09a2SMark Phalan
291*159d09a2SMark Phalan static krb5_error_code
add_gic_opt_ext_preauth_data(krb5_context context,krb5_gic_opt_ext * opte,const char * attr,const char * value)292*159d09a2SMark Phalan add_gic_opt_ext_preauth_data(krb5_context context,
293*159d09a2SMark Phalan krb5_gic_opt_ext *opte,
294*159d09a2SMark Phalan const char *attr,
295*159d09a2SMark Phalan const char *value)
296*159d09a2SMark Phalan {
297*159d09a2SMark Phalan size_t newsize;
298*159d09a2SMark Phalan int i;
299*159d09a2SMark Phalan krb5_gic_opt_pa_data *newpad;
300*159d09a2SMark Phalan
301*159d09a2SMark Phalan newsize = opte->opt_private->num_preauth_data + 1;
302*159d09a2SMark Phalan newsize = newsize * sizeof(*opte->opt_private->preauth_data);
303*159d09a2SMark Phalan if (opte->opt_private->preauth_data == NULL)
304*159d09a2SMark Phalan newpad = malloc(newsize);
305*159d09a2SMark Phalan else
306*159d09a2SMark Phalan newpad = realloc(opte->opt_private->preauth_data, newsize);
307*159d09a2SMark Phalan if (newpad == NULL)
308*159d09a2SMark Phalan return ENOMEM;
309*159d09a2SMark Phalan
310*159d09a2SMark Phalan i = opte->opt_private->num_preauth_data;
311*159d09a2SMark Phalan newpad[i].attr = strdup(attr);
312*159d09a2SMark Phalan if (newpad[i].attr == NULL)
313*159d09a2SMark Phalan return ENOMEM;
314*159d09a2SMark Phalan newpad[i].value = strdup(value);
315*159d09a2SMark Phalan if (newpad[i].value == NULL) {
316*159d09a2SMark Phalan free(newpad[i].attr);
317*159d09a2SMark Phalan return ENOMEM;
318*159d09a2SMark Phalan }
319*159d09a2SMark Phalan opte->opt_private->num_preauth_data += 1;
320*159d09a2SMark Phalan opte->opt_private->preauth_data = newpad;
321*159d09a2SMark Phalan return 0;
322*159d09a2SMark Phalan }
323*159d09a2SMark Phalan
324*159d09a2SMark Phalan /*
325*159d09a2SMark Phalan * This function allows the caller to supply options to preauth
326*159d09a2SMark Phalan * plugins. Preauth plugin modules are given a chance to look
327*159d09a2SMark Phalan * at each option at the time this function is called in ordre
328*159d09a2SMark Phalan * to check the validity of the option.
329*159d09a2SMark Phalan * The 'opt' pointer supplied to this function must have been
330*159d09a2SMark Phalan * obtained using krb5_get_init_creds_opt_alloc()
331*159d09a2SMark Phalan */
332*159d09a2SMark Phalan krb5_error_code KRB5_CALLCONV
krb5_get_init_creds_opt_set_pa(krb5_context context,krb5_get_init_creds_opt * opt,const char * attr,const char * value)333*159d09a2SMark Phalan krb5_get_init_creds_opt_set_pa(krb5_context context,
334*159d09a2SMark Phalan krb5_get_init_creds_opt *opt,
335*159d09a2SMark Phalan const char *attr,
336*159d09a2SMark Phalan const char *value)
337*159d09a2SMark Phalan {
338*159d09a2SMark Phalan krb5_error_code retval;
339*159d09a2SMark Phalan krb5_gic_opt_ext *opte;
340*159d09a2SMark Phalan
341*159d09a2SMark Phalan retval = krb5int_gic_opt_to_opte(context, opt, &opte, 0,
342*159d09a2SMark Phalan "krb5_get_init_creds_opt_set_pa");
343*159d09a2SMark Phalan if (retval)
344*159d09a2SMark Phalan return retval;
345*159d09a2SMark Phalan
346*159d09a2SMark Phalan /*
347*159d09a2SMark Phalan * Copy the option into the extended get_init_creds_opt structure
348*159d09a2SMark Phalan */
349*159d09a2SMark Phalan retval = add_gic_opt_ext_preauth_data(context, opte, attr, value);
350*159d09a2SMark Phalan if (retval)
351*159d09a2SMark Phalan return retval;
352*159d09a2SMark Phalan
353*159d09a2SMark Phalan /*
354*159d09a2SMark Phalan * Give the plugins a chance to look at the option now.
355*159d09a2SMark Phalan */
356*159d09a2SMark Phalan retval = krb5_preauth_supply_preauth_data(context, opte, attr, value);
357*159d09a2SMark Phalan return retval;
358*159d09a2SMark Phalan }
359*159d09a2SMark Phalan
360*159d09a2SMark Phalan /*
361*159d09a2SMark Phalan * This function allows a preauth plugin to obtain preauth
362*159d09a2SMark Phalan * options. The preauth_data returned from this function
363*159d09a2SMark Phalan * should be freed by calling krb5_get_init_creds_opt_free_pa().
364*159d09a2SMark Phalan *
365*159d09a2SMark Phalan * The 'opt' pointer supplied to this function must have been
366*159d09a2SMark Phalan * obtained using krb5_get_init_creds_opt_alloc()
367*159d09a2SMark Phalan */
368*159d09a2SMark Phalan krb5_error_code KRB5_CALLCONV
krb5_get_init_creds_opt_get_pa(krb5_context context,krb5_get_init_creds_opt * opt,int * num_preauth_data,krb5_gic_opt_pa_data ** preauth_data)369*159d09a2SMark Phalan krb5_get_init_creds_opt_get_pa(krb5_context context,
370*159d09a2SMark Phalan krb5_get_init_creds_opt *opt,
371*159d09a2SMark Phalan int *num_preauth_data,
372*159d09a2SMark Phalan krb5_gic_opt_pa_data **preauth_data)
373*159d09a2SMark Phalan {
374*159d09a2SMark Phalan krb5_error_code retval;
375*159d09a2SMark Phalan krb5_gic_opt_ext *opte;
376*159d09a2SMark Phalan krb5_gic_opt_pa_data *p = NULL;
377*159d09a2SMark Phalan int i;
378*159d09a2SMark Phalan size_t allocsize;
379*159d09a2SMark Phalan
380*159d09a2SMark Phalan retval = krb5int_gic_opt_to_opte(context, opt, &opte, 0,
381*159d09a2SMark Phalan "krb5_get_init_creds_opt_get_pa");
382*159d09a2SMark Phalan if (retval)
383*159d09a2SMark Phalan return retval;
384*159d09a2SMark Phalan
385*159d09a2SMark Phalan if (num_preauth_data == NULL || preauth_data == NULL)
386*159d09a2SMark Phalan return EINVAL;
387*159d09a2SMark Phalan
388*159d09a2SMark Phalan *num_preauth_data = 0;
389*159d09a2SMark Phalan *preauth_data = NULL;
390*159d09a2SMark Phalan
391*159d09a2SMark Phalan if (opte->opt_private->num_preauth_data == 0)
392*159d09a2SMark Phalan return 0;
393*159d09a2SMark Phalan
394*159d09a2SMark Phalan allocsize =
395*159d09a2SMark Phalan opte->opt_private->num_preauth_data * sizeof(krb5_gic_opt_pa_data);
396*159d09a2SMark Phalan p = malloc(allocsize);
397*159d09a2SMark Phalan if (p == NULL)
398*159d09a2SMark Phalan return ENOMEM;
399*159d09a2SMark Phalan
400*159d09a2SMark Phalan /* Init these to make cleanup easier */
401*159d09a2SMark Phalan for (i = 0; i < opte->opt_private->num_preauth_data; i++) {
402*159d09a2SMark Phalan p[i].attr = NULL;
403*159d09a2SMark Phalan p[i].value = NULL;
404*159d09a2SMark Phalan }
405*159d09a2SMark Phalan
406*159d09a2SMark Phalan for (i = 0; i < opte->opt_private->num_preauth_data; i++) {
407*159d09a2SMark Phalan p[i].attr = strdup(opte->opt_private->preauth_data[i].attr);
408*159d09a2SMark Phalan p[i].value = strdup(opte->opt_private->preauth_data[i].value);
409*159d09a2SMark Phalan if (p[i].attr == NULL || p[i].value == NULL)
410*159d09a2SMark Phalan goto cleanup;
411*159d09a2SMark Phalan }
412*159d09a2SMark Phalan *num_preauth_data = i;
413*159d09a2SMark Phalan *preauth_data = p;
414*159d09a2SMark Phalan return 0;
415*159d09a2SMark Phalan cleanup:
416*159d09a2SMark Phalan for (i = 0; i < opte->opt_private->num_preauth_data; i++) {
417*159d09a2SMark Phalan if (p[i].attr != NULL)
418*159d09a2SMark Phalan free(p[i].attr);
419*159d09a2SMark Phalan if (p[i].value != NULL)
420*159d09a2SMark Phalan free(p[i].value);
421*159d09a2SMark Phalan }
422*159d09a2SMark Phalan free(p);
423*159d09a2SMark Phalan return ENOMEM;
424*159d09a2SMark Phalan }
425*159d09a2SMark Phalan
426*159d09a2SMark Phalan /*
427*159d09a2SMark Phalan * This function frees the preauth_data that was returned by
428*159d09a2SMark Phalan * krb5_get_init_creds_opt_get_pa().
429*159d09a2SMark Phalan */
430*159d09a2SMark Phalan void KRB5_CALLCONV
krb5_get_init_creds_opt_free_pa(krb5_context context,int num_preauth_data,krb5_gic_opt_pa_data * preauth_data)431*159d09a2SMark Phalan krb5_get_init_creds_opt_free_pa(krb5_context context,
432*159d09a2SMark Phalan int num_preauth_data,
433*159d09a2SMark Phalan krb5_gic_opt_pa_data *preauth_data)
434*159d09a2SMark Phalan {
435*159d09a2SMark Phalan int i;
436*159d09a2SMark Phalan
437*159d09a2SMark Phalan if (num_preauth_data <= 0 || preauth_data == NULL)
438*159d09a2SMark Phalan return;
439*159d09a2SMark Phalan
440*159d09a2SMark Phalan for (i = 0; i < num_preauth_data; i++) {
441*159d09a2SMark Phalan if (preauth_data[i].attr != NULL)
442*159d09a2SMark Phalan free(preauth_data[i].attr);
443*159d09a2SMark Phalan if (preauth_data[i].value != NULL)
444*159d09a2SMark Phalan free(preauth_data[i].value);
445*159d09a2SMark Phalan }
446*159d09a2SMark Phalan free(preauth_data);
447*159d09a2SMark Phalan }
448