📄 init_creds_pw.c
字号:
memset(a, 0, sizeof(*a)); a->pvno = 5; a->msg_type = krb_as_req; a->req_body.kdc_options = opts; a->req_body.cname = malloc(sizeof(*a->req_body.cname)); if (a->req_body.cname == NULL) { ret = ENOMEM; krb5_set_error_string(context, "malloc: out of memory"); goto fail; } a->req_body.sname = malloc(sizeof(*a->req_body.sname)); if (a->req_body.sname == NULL) { ret = ENOMEM; krb5_set_error_string(context, "malloc: out of memory"); goto fail; } ret = _krb5_principal2principalname (a->req_body.cname, creds->client); if (ret) goto fail; ret = copy_Realm(&creds->client->realm, &a->req_body.realm); if (ret) goto fail; ret = _krb5_principal2principalname (a->req_body.sname, creds->server); if (ret) goto fail; if(creds->times.starttime) { a->req_body.from = malloc(sizeof(*a->req_body.from)); if (a->req_body.from == NULL) { ret = ENOMEM; krb5_set_error_string(context, "malloc: out of memory"); goto fail; } *a->req_body.from = creds->times.starttime; } if(creds->times.endtime){ ALLOC(a->req_body.till, 1); *a->req_body.till = creds->times.endtime; } if(creds->times.renew_till){ a->req_body.rtime = malloc(sizeof(*a->req_body.rtime)); if (a->req_body.rtime == NULL) { ret = ENOMEM; krb5_set_error_string(context, "malloc: out of memory"); goto fail; } *a->req_body.rtime = creds->times.renew_till; } a->req_body.nonce = 0; ret = krb5_init_etype (context, &a->req_body.etype.len, &a->req_body.etype.val, etypes); if (ret) goto fail; /* * This means no addresses */ if (addrs && addrs->len == 0) { a->req_body.addresses = NULL; } else { a->req_body.addresses = malloc(sizeof(*a->req_body.addresses)); if (a->req_body.addresses == NULL) { ret = ENOMEM; krb5_set_error_string(context, "malloc: out of memory"); goto fail; } if (addrs) ret = krb5_copy_addresses(context, addrs, a->req_body.addresses); else { ret = krb5_get_all_client_addrs (context, a->req_body.addresses); if(ret == 0 && a->req_body.addresses->len == 0) { free(a->req_body.addresses); a->req_body.addresses = NULL; } } if (ret) goto fail; } a->req_body.enc_authorization_data = NULL; a->req_body.additional_tickets = NULL; a->padata = NULL; return 0; fail: free_AS_REQ(a); memset(a, 0, sizeof(*a)); return ret;}struct pa_info_data { krb5_enctype etype; krb5_salt salt; krb5_data *s2kparams;};static voidfree_paid(krb5_context context, struct pa_info_data *ppaid){ krb5_free_salt(context, ppaid->salt); if (ppaid->s2kparams) krb5_free_data(context, ppaid->s2kparams);}static krb5_error_codeset_paid(struct pa_info_data *paid, krb5_context context, krb5_enctype etype, krb5_salttype salttype, void *salt_string, size_t salt_len, krb5_data *s2kparams){ paid->etype = etype; paid->salt.salttype = salttype; paid->salt.saltvalue.data = malloc(salt_len + 1); if (paid->salt.saltvalue.data == NULL) { krb5_clear_error_string(context); return ENOMEM; } memcpy(paid->salt.saltvalue.data, salt_string, salt_len); ((char *)paid->salt.saltvalue.data)[salt_len] = '\0'; paid->salt.saltvalue.length = salt_len; if (s2kparams) { krb5_error_code ret; ret = krb5_copy_data(context, s2kparams, &paid->s2kparams); if (ret) { krb5_clear_error_string(context); krb5_free_salt(context, paid->salt); return ret; } } else paid->s2kparams = NULL; return 0;}static struct pa_info_data *pa_etype_info2(krb5_context context, const krb5_principal client, const AS_REQ *asreq, struct pa_info_data *paid, heim_octet_string *data){ krb5_error_code ret; ETYPE_INFO2 e; size_t sz; int i, j; memset(&e, 0, sizeof(e)); ret = decode_ETYPE_INFO2(data->data, data->length, &e, &sz); if (ret) goto out; if (e.len == 0) goto out; for (j = 0; j < asreq->req_body.etype.len; j++) { for (i = 0; i < e.len; i++) { if (asreq->req_body.etype.val[j] == e.val[i].etype) { krb5_salt salt; if (e.val[i].salt == NULL) ret = krb5_get_pw_salt(context, client, &salt); else { salt.saltvalue.data = *e.val[i].salt; salt.saltvalue.length = strlen(*e.val[i].salt); ret = 0; } if (ret == 0) ret = set_paid(paid, context, e.val[i].etype, KRB5_PW_SALT, salt.saltvalue.data, salt.saltvalue.length, e.val[i].s2kparams); if (e.val[i].salt == NULL) krb5_free_salt(context, salt); if (ret == 0) { free_ETYPE_INFO2(&e); return paid; } } } } out: free_ETYPE_INFO2(&e); return NULL;}static struct pa_info_data *pa_etype_info(krb5_context context, const krb5_principal client, const AS_REQ *asreq, struct pa_info_data *paid, heim_octet_string *data){ krb5_error_code ret; ETYPE_INFO e; size_t sz; int i, j; memset(&e, 0, sizeof(e)); ret = decode_ETYPE_INFO(data->data, data->length, &e, &sz); if (ret) goto out; if (e.len == 0) goto out; for (j = 0; j < asreq->req_body.etype.len; j++) { for (i = 0; i < e.len; i++) { if (asreq->req_body.etype.val[j] == e.val[i].etype) { krb5_salt salt; salt.salttype = KRB5_PW_SALT; if (e.val[i].salt == NULL) ret = krb5_get_pw_salt(context, client, &salt); else { salt.saltvalue = *e.val[i].salt; ret = 0; } if (e.val[i].salttype) salt.salttype = *e.val[i].salttype; if (ret == 0) { ret = set_paid(paid, context, e.val[i].etype, salt.salttype, salt.saltvalue.data, salt.saltvalue.length, NULL); if (e.val[i].salt == NULL) krb5_free_salt(context, salt); } if (ret == 0) { free_ETYPE_INFO(&e); return paid; } } } } out: free_ETYPE_INFO(&e); return NULL;}static struct pa_info_data *pa_pw_or_afs3_salt(krb5_context context, const krb5_principal client, const AS_REQ *asreq, struct pa_info_data *paid, heim_octet_string *data){ krb5_error_code ret; if (paid->etype == ENCTYPE_NULL) return NULL; ret = set_paid(paid, context, paid->etype, paid->salt.salttype, data->data, data->length, NULL); if (ret) return NULL; return paid;}struct pa_info { krb5_preauthtype type; struct pa_info_data *(*salt_info)(krb5_context, const krb5_principal, const AS_REQ *, struct pa_info_data *, heim_octet_string *);};static struct pa_info pa_prefs[] = { { KRB5_PADATA_ETYPE_INFO2, pa_etype_info2 }, { KRB5_PADATA_ETYPE_INFO, pa_etype_info }, { KRB5_PADATA_PW_SALT, pa_pw_or_afs3_salt }, { KRB5_PADATA_AFS3_SALT, pa_pw_or_afs3_salt }}; static PA_DATA *find_pa_data(const METHOD_DATA *md, int type){ int i; if (md == NULL) return NULL; for (i = 0; i < md->len; i++) if (md->val[i].padata_type == type) return &md->val[i]; return NULL;}static struct pa_info_data *process_pa_info(krb5_context context, const krb5_principal client, const AS_REQ *asreq, struct pa_info_data *paid, METHOD_DATA *md){ struct pa_info_data *p = NULL; int i; for (i = 0; p == NULL && i < sizeof(pa_prefs)/sizeof(pa_prefs[0]); i++) { PA_DATA *pa = find_pa_data(md, pa_prefs[i].type); if (pa == NULL) continue; paid->salt.salttype = pa_prefs[i].type; p = (*pa_prefs[i].salt_info)(context, client, asreq, paid, &pa->padata_value); } return p;}static krb5_error_codemake_pa_enc_timestamp(krb5_context context, METHOD_DATA *md, krb5_enctype etype, krb5_keyblock *key){ PA_ENC_TS_ENC p; unsigned char *buf; size_t buf_size; size_t len; EncryptedData encdata; krb5_error_code ret; int32_t usec; int usec2; krb5_crypto crypto; krb5_us_timeofday (context, &p.patimestamp, &usec); usec2 = usec; p.pausec = &usec2; ASN1_MALLOC_ENCODE(PA_ENC_TS_ENC, buf, buf_size, &p, &len, ret); if (ret) return ret; if(buf_size != len) krb5_abortx(context, "internal error in ASN.1 encoder"); ret = krb5_crypto_init(context, key, 0, &crypto); if (ret) { free(buf); return ret; } ret = krb5_encrypt_EncryptedData(context, crypto, KRB5_KU_PA_ENC_TIMESTAMP, buf, len, 0, &encdata); free(buf); krb5_crypto_destroy(context, crypto); if (ret) return ret; ASN1_MALLOC_ENCODE(EncryptedData, buf, buf_size, &encdata, &len, ret); free_EncryptedData(&encdata); if (ret) return ret; if(buf_size != len) krb5_abortx(context, "internal error in ASN.1 encoder"); ret = krb5_padata_add(context, md, KRB5_PADATA_ENC_TIMESTAMP, buf, len); if (ret) free(buf); return ret;}static krb5_error_codeadd_enc_ts_padata(krb5_context context, METHOD_DATA *md, krb5_principal client, krb5_s2k_proc key_proc, krb5_const_pointer keyseed, krb5_enctype *enctypes, unsigned netypes, krb5_salt *salt, krb5_data *s2kparams){ krb5_error_code ret; krb5_salt salt2; krb5_enctype *ep; int i; if(salt == NULL) { /* default to standard salt */ ret = krb5_get_pw_salt (context, client, &salt2); salt = &salt2; } if (!enctypes) { enctypes = context->etypes; netypes = 0; for (ep = enctypes; *ep != ETYPE_NULL; ep++) netypes++; } for (i = 0; i < netypes; ++i) { krb5_keyblock *key; ret = (*key_proc)(context, enctypes[i], keyseed, *salt, s2kparams, &key); if (ret) continue; ret = make_pa_enc_timestamp (context, md, enctypes[i], key); krb5_free_keyblock (context, key); if (ret) return ret; } if(salt == &salt2) krb5_free_salt(context, salt2); return 0;}static krb5_error_codepa_data_to_md_ts_enc(krb5_context context, const AS_REQ *a, const krb5_principal client, krb5_get_init_creds_ctx *ctx, struct pa_info_data *ppaid, METHOD_DATA *md){ if (ctx->key_proc == NULL || ctx->password == NULL) return 0; if (ppaid) { add_enc_ts_padata(context, md, client, ctx->key_proc, ctx->password, &ppaid->etype, 1, &ppaid->salt, ppaid->s2kparams); } else { krb5_salt salt; /* make a v5 salted pa-data */ add_enc_ts_padata(context, md, client, ctx->key_proc, ctx->password, a->req_body.etype.val, a->req_body.etype.len, NULL, NULL); /* make a v4 salted pa-data */ salt.salttype = KRB5_PW_SALT; krb5_data_zero(&salt.saltvalue); add_enc_ts_padata(context, md, client, ctx->key_proc, ctx->password, a->req_body.etype.val, a->req_body.etype.len, &salt, NULL); } return 0;}static krb5_error_codepa_data_to_key_plain(krb5_context context, const krb5_principal client, krb5_get_init_creds_ctx *ctx, krb5_salt salt, krb5_data *s2kparams, krb5_enctype etype, krb5_keyblock **key){ krb5_error_code ret; ret = (*ctx->key_proc)(context, etype, ctx->password, salt, s2kparams, key); return ret;}static krb5_error_codepa_data_to_md_pkinit(krb5_context context, const AS_REQ *a, const krb5_principal client, krb5_get_init_creds_ctx *ctx, METHOD_DATA *md){ if (ctx->pk_init_ctx == NULL) return 0;#ifdef PKINIT return _krb5_pk_mk_padata(context, ctx->pk_init_ctx, &a->req_body, ctx->pk_nonce, md);#else krb5_set_error_string(context, "no support for PKINIT compiled in"); return EINVAL;#endif}static krb5_error_codepa_data_add_pac_request(krb5_context context, krb5_get_init_creds_ctx *ctx, METHOD_DATA *md){ size_t len, length; krb5_error_code ret; PA_PAC_REQUEST req; void *buf; switch (ctx->req_pac) { case KRB5_INIT_CREDS_TRISTATE_UNSET: return 0; /* don't bother */ case KRB5_INIT_CREDS_TRISTATE_TRUE: req.include_pac = 1; break; case KRB5_INIT_CREDS_TRISTATE_FALSE: req.include_pac = 0; } ASN1_MALLOC_ENCODE(PA_PAC_REQUEST, buf, length, &req, &len, ret); if (ret) return ret; if(len != length) krb5_abortx(context, "internal error in ASN.1 encoder"); ret = krb5_padata_add(context, md, KRB5_PADATA_PA_PAC_REQUEST, buf, len); if (ret) free(buf); return 0;}/* * Assumes caller always will free `out_md', even on error. */static krb5_error_codeprocess_pa_data_to_md(krb5_context context, const krb5_creds *creds, const AS_REQ *a, krb5_get_init_creds_ctx *ctx, METHOD_DATA *in_md, METHOD_DATA **out_md, krb5_prompter_fct prompter, void *prompter_data){ krb5_error_code ret; ALLOC(*out_md, 1); if (*out_md == NULL) { krb5_set_error_string(context, "malloc: out of memory"); return ENOMEM; } (*out_md)->len = 0; (*out_md)->val = NULL; /* * Make sure we don't sent both ENC-TS and PK-INIT pa data, no * need to expose our password protecting our PKCS12 key. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -