1*159d09a2SMark Phalan #include "k5-int.h" 2*159d09a2SMark Phalan #include "int-proto.h" 3*159d09a2SMark Phalan 4*159d09a2SMark Phalan static void 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 11505d05c7Sgtb krb5_get_init_creds_opt_init(krb5_get_init_creds_opt *opt) 127c478bd9Sstevel@tonic-gate { 13*159d09a2SMark Phalan opt->flags = 0; 14*159d09a2SMark Phalan init_common(opt); 157c478bd9Sstevel@tonic-gate } 167c478bd9Sstevel@tonic-gate 17505d05c7Sgtb void KRB5_CALLCONV 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 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 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 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 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 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 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 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 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 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 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 * 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 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 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 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 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 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 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 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 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 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