static int set_ptypes(krb5_context context, KRB_ERROR *error, const krb5_preauthtype **ptypes, krb5_preauthdata **preauth) { static krb5_preauthdata preauth2; static krb5_preauthtype ptypes2[] = { KRB5_PADATA_ENC_TIMESTAMP, KRB5_PADATA_NONE }; if(error->e_data) { METHOD_DATA md; int i; decode_METHOD_DATA(error->e_data->data, error->e_data->length, &md, NULL); for(i = 0; i < md.len; i++){ switch(md.val[i].padata_type){ case KRB5_PADATA_ENC_TIMESTAMP: *ptypes = ptypes2; break; case KRB5_PADATA_ETYPE_INFO: *preauth = &preauth2; ALLOC_SEQ(*preauth, 1); (*preauth)->val[0].type = KRB5_PADATA_ENC_TIMESTAMP; krb5_decode_ETYPE_INFO(context, md.val[i].padata_value.data, md.val[i].padata_value.length, &(*preauth)->val[0].info, NULL); break; default: break; } } free_METHOD_DATA(&md); } else { *ptypes = ptypes2; } return(1); }
krb5_error_code KRB5_LIB_FUNCTION krb5_init_creds_step(krb5_context context, krb5_init_creds_context ctx, krb5_data *in, krb5_data *out, krb5_krbhst_info *hostinfo, unsigned int *flags) { krb5_error_code ret; size_t len; size_t size; krb5_data_zero(out); if (ctx->as_req.req_body.cname == NULL) { ret = init_as_req(context, ctx->flags, &ctx->cred, ctx->addrs, ctx->etypes, &ctx->as_req); if (ret) { free_init_creds_ctx(context, ctx); return ret; } } #define MAX_PA_COUNTER 10 if (ctx->pa_counter > MAX_PA_COUNTER) { krb5_set_error_message(context, KRB5_GET_IN_TKT_LOOP, N_("Looping %d times while getting " "initial credentials", ""), ctx->pa_counter); return KRB5_GET_IN_TKT_LOOP; } ctx->pa_counter++; /* Lets process the input packet */ if (in && in->length) { krb5_kdc_rep rep; memset(&rep, 0, sizeof(rep)); ret = decode_AS_REP(in->data, in->length, &rep.kdc_rep, &size); if (ret == 0) { krb5_keyblock *key = NULL; unsigned eflags = EXTRACT_TICKET_AS_REQ; if (ctx->flags.canonicalize) { eflags |= EXTRACT_TICKET_ALLOW_SERVER_MISMATCH; eflags |= EXTRACT_TICKET_MATCH_REALM; } if (ctx->ic_flags & KRB5_INIT_CREDS_NO_C_CANON_CHECK) eflags |= EXTRACT_TICKET_ALLOW_CNAME_MISMATCH; ret = process_pa_data_to_key(context, ctx, &ctx->cred, &ctx->as_req, &rep.kdc_rep, hostinfo, &key); if (ret) { free_AS_REP(&rep.kdc_rep); goto out; } ret = _krb5_extract_ticket(context, &rep, &ctx->cred, key, NULL, KRB5_KU_AS_REP_ENC_PART, NULL, ctx->nonce, eflags, NULL, NULL); krb5_free_keyblock(context, key); *flags = 0; if (ret == 0) ret = copy_EncKDCRepPart(&rep.enc_part, &ctx->enc_part); free_AS_REP(&rep.kdc_rep); free_EncASRepPart(&rep.enc_part); return ret; } else { /* let's try to parse it as a KRB-ERROR */ free_KRB_ERROR(&ctx->error); ret = krb5_rd_error(context, in, &ctx->error); if(ret && in->length && ((char*)in->data)[0] == 4) ret = KRB5KRB_AP_ERR_V4_REPLY; if (ret) goto out; ret = krb5_error_from_rd_error(context, &ctx->error, &ctx->cred); /* * If no preauth was set and KDC requires it, give it one * more try. */ if (ret == KRB5KDC_ERR_PREAUTH_REQUIRED) { free_METHOD_DATA(&ctx->md); memset(&ctx->md, 0, sizeof(ctx->md)); if (ctx->error.e_data) { ret = decode_METHOD_DATA(ctx->error.e_data->data, ctx->error.e_data->length, &ctx->md, NULL); if (ret) krb5_set_error_message(context, ret, N_("Failed to decode METHOD-DATA", "")); } else { krb5_set_error_message(context, ret, N_("Preauth required but no preauth " "options send by KDC", "")); } } else if (ret == KRB5KRB_AP_ERR_SKEW && context->kdc_sec_offset == 0) { /* * Try adapt to timeskrew when we are using pre-auth, and * if there was a time skew, try again. */ krb5_set_real_time(context, ctx->error.stime, -1); if (context->kdc_sec_offset) ret = 0; } else if (ret == KRB5_KDC_ERR_WRONG_REALM && ctx->flags.canonicalize) { /* client referal to a new realm */ if (ctx->error.crealm == NULL) { krb5_set_error_message(context, ret, N_("Got a client referral, not but no realm", "")); goto out; } ret = krb5_principal_set_realm(context, ctx->cred.client, *ctx->error.crealm); } if (ret) goto out; } } if (ctx->as_req.padata) { free_METHOD_DATA(ctx->as_req.padata); free(ctx->as_req.padata); ctx->as_req.padata = NULL; } /* Set a new nonce. */ ctx->as_req.req_body.nonce = ctx->nonce; /* fill_in_md_data */ ret = process_pa_data_to_md(context, &ctx->cred, &ctx->as_req, ctx, &ctx->md, &ctx->as_req.padata, ctx->prompter, ctx->prompter_data); if (ret) goto out; krb5_data_free(&ctx->req_buffer); ASN1_MALLOC_ENCODE(AS_REQ, ctx->req_buffer.data, ctx->req_buffer.length, &ctx->as_req, &len, ret); if (ret) goto out; if(len != ctx->req_buffer.length) krb5_abortx(context, "internal error in ASN.1 encoder"); out->data = ctx->req_buffer.data; out->length = ctx->req_buffer.length; *flags = 1; return 0; out: return ret; }