add support for pkinit
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@13093 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
@@ -43,6 +43,7 @@ typedef struct krb5_get_init_creds_ctx {
|
|||||||
krb5_preauthtype *pre_auth_types;
|
krb5_preauthtype *pre_auth_types;
|
||||||
const char *in_tkt_service;
|
const char *in_tkt_service;
|
||||||
unsigned nonce;
|
unsigned nonce;
|
||||||
|
unsigned pk_nonce;
|
||||||
|
|
||||||
AS_REQ as_req;
|
AS_REQ as_req;
|
||||||
int pa_counter;
|
int pa_counter;
|
||||||
@@ -51,6 +52,8 @@ typedef struct krb5_get_init_creds_ctx {
|
|||||||
krb5_s2k_proc key_proc;
|
krb5_s2k_proc key_proc;
|
||||||
|
|
||||||
krb5_get_init_creds_req_pac req_pac;
|
krb5_get_init_creds_req_pac req_pac;
|
||||||
|
|
||||||
|
krb5_pk_init_ctx pk_init_ctx;
|
||||||
} krb5_get_init_creds_ctx;
|
} krb5_get_init_creds_ctx;
|
||||||
|
|
||||||
static krb5_error_code
|
static krb5_error_code
|
||||||
@@ -92,6 +95,7 @@ init_init_creds_ctx(krb5_context context,
|
|||||||
ctx->password = init_cred_opts->private->password;
|
ctx->password = init_cred_opts->private->password;
|
||||||
ctx->key_proc = init_cred_opts->private->key_proc;
|
ctx->key_proc = init_cred_opts->private->key_proc;
|
||||||
ctx->req_pac = init_cred_opts->private->req_pac;
|
ctx->req_pac = init_cred_opts->private->req_pac;
|
||||||
|
ctx->pk_init_ctx = init_cred_opts->private->pk_init_ctx;
|
||||||
} else
|
} else
|
||||||
ctx->req_pac = KRB5_PA_PAC_DONT_CARE;
|
ctx->req_pac = KRB5_PA_PAC_DONT_CARE;
|
||||||
|
|
||||||
@@ -551,13 +555,24 @@ init_creds_init_as_req (krb5_context context,
|
|||||||
krb5_set_error_string(context, "malloc: out of memory");
|
krb5_set_error_string(context, "malloc: out of memory");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
if (creds->client) {
|
||||||
ret = krb5_principal2principalname (a->req_body.cname, creds->client);
|
ret = krb5_principal2principalname (a->req_body.cname, creds->client);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto fail;
|
goto fail;
|
||||||
ret = krb5_principal2principalname (a->req_body.sname, creds->server);
|
ret = copy_Realm(&creds->client->realm, &a->req_body.realm);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto fail;
|
goto fail;
|
||||||
ret = copy_Realm(&creds->client->realm, &a->req_body.realm);
|
} else {
|
||||||
|
krb5_realm realm;
|
||||||
|
|
||||||
|
a->req_body.cname = NULL;
|
||||||
|
ret = krb5_get_default_realm(context, &realm);
|
||||||
|
if (ret)
|
||||||
|
goto fail;
|
||||||
|
ret = copy_Realm(&realm, &a->req_body.realm);
|
||||||
|
free(realm);
|
||||||
|
}
|
||||||
|
ret = krb5_principal2principalname (a->req_body.sname, creds->server);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
@@ -846,27 +861,6 @@ process_pa_info(krb5_context context,
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
pa_add_pa(krb5_context context, METHOD_DATA *md,
|
|
||||||
int type, void *buf, size_t len)
|
|
||||||
{
|
|
||||||
PA_DATA *pa;
|
|
||||||
|
|
||||||
pa = realloc (md->val, (md->len + 1) * sizeof(*md->val));
|
|
||||||
if (pa == NULL) {
|
|
||||||
krb5_set_error_string(context, "malloc: out of memory");
|
|
||||||
return ENOMEM;
|
|
||||||
}
|
|
||||||
md->val = pa;
|
|
||||||
|
|
||||||
pa[md->len].padata_type = type;
|
|
||||||
pa[md->len].padata_value.length = len;
|
|
||||||
pa[md->len].padata_value.data = buf;
|
|
||||||
md->len++;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static krb5_error_code
|
static krb5_error_code
|
||||||
make_pa_enc_timestamp(krb5_context context, METHOD_DATA *md,
|
make_pa_enc_timestamp(krb5_context context, METHOD_DATA *md,
|
||||||
krb5_enctype etype, krb5_keyblock *key)
|
krb5_enctype etype, krb5_keyblock *key)
|
||||||
@@ -915,7 +909,7 @@ make_pa_enc_timestamp(krb5_context context, METHOD_DATA *md,
|
|||||||
if(buf_size != len)
|
if(buf_size != len)
|
||||||
krb5_abortx(context, "internal error in ASN.1 encoder");
|
krb5_abortx(context, "internal error in ASN.1 encoder");
|
||||||
|
|
||||||
ret = pa_add_pa(context, md, KRB5_PADATA_ENC_TIMESTAMP, buf, len);
|
ret = krb5_padata_add(context, md, KRB5_PADATA_ENC_TIMESTAMP, buf, len);
|
||||||
if (ret)
|
if (ret)
|
||||||
free(buf);
|
free(buf);
|
||||||
return ret;
|
return ret;
|
||||||
@@ -1018,6 +1012,28 @@ pa_data_to_key_plain(krb5_context context,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static krb5_error_code
|
||||||
|
pa_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_code
|
static krb5_error_code
|
||||||
pa_data_add_pac_request(krb5_context context,
|
pa_data_add_pac_request(krb5_context context,
|
||||||
krb5_get_init_creds_ctx *ctx,
|
krb5_get_init_creds_ctx *ctx,
|
||||||
@@ -1045,7 +1061,7 @@ pa_data_add_pac_request(krb5_context context,
|
|||||||
if(len != length)
|
if(len != length)
|
||||||
krb5_abortx(context, "internal error in ASN.1 encoder");
|
krb5_abortx(context, "internal error in ASN.1 encoder");
|
||||||
|
|
||||||
ret = pa_add_pa(context, md, KRB5_PADATA_PA_PAC_REQUEST, buf, len);
|
ret = krb5_padata_add(context, md, KRB5_PADATA_PA_PAC_REQUEST, buf, len);
|
||||||
if (ret)
|
if (ret)
|
||||||
free(buf);
|
free(buf);
|
||||||
md->len++;
|
md->len++;
|
||||||
@@ -1063,36 +1079,38 @@ process_pa_data_to_md(krb5_context context,
|
|||||||
krb5_prompter_fct prompter,
|
krb5_prompter_fct prompter,
|
||||||
void *prompter_data)
|
void *prompter_data)
|
||||||
{
|
{
|
||||||
struct pa_info_data paid, *ppaid;
|
krb5_error_code ret;
|
||||||
|
|
||||||
memset(&paid, 0, sizeof(paid));
|
|
||||||
|
|
||||||
if (in_md->len == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
paid.etype = ENCTYPE_NULL;
|
|
||||||
ppaid = process_pa_info(context, creds->client, a, &paid, in_md);
|
|
||||||
|
|
||||||
ALLOC(*out_md, 1);
|
ALLOC(*out_md, 1);
|
||||||
if (*out_md == NULL) {
|
if (*out_md == NULL) {
|
||||||
if (ppaid)
|
|
||||||
free_paid(context, ppaid);
|
|
||||||
krb5_set_error_string(context, "malloc: out of memory");
|
krb5_set_error_string(context, "malloc: out of memory");
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
}
|
}
|
||||||
(*out_md)->len = 0;
|
(*out_md)->len = 0;
|
||||||
(*out_md)->val = NULL;
|
(*out_md)->val = NULL;
|
||||||
|
|
||||||
/*
|
if (in_md->len == 0) {
|
||||||
* here is where we should check for other pre-auth types then
|
struct pa_info_data paid, *ppaid;
|
||||||
* KRB5_PADATA_ENC_TIMESTAMP
|
|
||||||
*/
|
memset(&paid, 0, sizeof(paid));
|
||||||
|
|
||||||
|
paid.etype = ENCTYPE_NULL;
|
||||||
|
ppaid = process_pa_info(context, creds->client, a, &paid, in_md);
|
||||||
|
|
||||||
pa_data_to_md_ts_enc(context, a, creds->client, ctx, ppaid, *out_md);
|
pa_data_to_md_ts_enc(context, a, creds->client, ctx, ppaid, *out_md);
|
||||||
if (ppaid)
|
if (ppaid)
|
||||||
free_paid(context, ppaid);
|
free_paid(context, ppaid);
|
||||||
|
}
|
||||||
|
|
||||||
pa_data_add_pac_request(context, ctx, *out_md);
|
pa_data_add_pac_request(context, ctx, *out_md);
|
||||||
|
ret = pa_data_to_md_pkinit(context, a, creds->client, ctx, *out_md);
|
||||||
|
if (ret)
|
||||||
|
return ret; /* XXX memory leak */
|
||||||
|
|
||||||
|
if ((*out_md)->len == 0) {
|
||||||
|
free(*out_md);
|
||||||
|
*out_md = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1108,6 +1126,8 @@ process_pa_data_to_key(krb5_context context,
|
|||||||
struct pa_info_data paid, *ppaid = NULL;
|
struct pa_info_data paid, *ppaid = NULL;
|
||||||
krb5_error_code ret;
|
krb5_error_code ret;
|
||||||
krb5_enctype etype;
|
krb5_enctype etype;
|
||||||
|
PA_DATA *pa;
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
memset(&paid, 0, sizeof(paid));
|
memset(&paid, 0, sizeof(paid));
|
||||||
|
|
||||||
@@ -1126,13 +1146,32 @@ process_pa_data_to_key(krb5_context context,
|
|||||||
paid.s2kparams = NULL;
|
paid.s2kparams = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
pa = NULL;
|
||||||
* Here is the second place we want to add hook when we support
|
if (rep->kdc_rep.padata)
|
||||||
* other preauth mechs then KRB5_PA_ENC_TIMESTAMP.
|
pa = krb5_find_padata(rep->kdc_rep.padata->val,
|
||||||
*/
|
rep->kdc_rep.padata->len,
|
||||||
|
KRB5_PADATA_PK_AS_REP,
|
||||||
|
&index);
|
||||||
|
if (pa && ctx->pk_init_ctx) {
|
||||||
|
#ifdef PKINIT
|
||||||
|
ret = _krb5_pk_rd_pa_reply(context,
|
||||||
|
ctx->pk_init_ctx,
|
||||||
|
etype,
|
||||||
|
ctx->pk_nonce,
|
||||||
|
pa,
|
||||||
|
key);
|
||||||
|
#else
|
||||||
|
krb5_set_error_string(context, "no support for PKINIT compiled in");
|
||||||
|
ret = EINVAL;
|
||||||
|
#endif
|
||||||
|
} else if (ctx->password)
|
||||||
ret = pa_data_to_key_plain(context, creds->client, ctx,
|
ret = pa_data_to_key_plain(context, creds->client, ctx,
|
||||||
paid.salt, paid.s2kparams, etype, key);
|
paid.salt, paid.s2kparams, etype, key);
|
||||||
|
else {
|
||||||
|
krb5_set_error_string(context, "no usable pa data type");
|
||||||
|
ret = EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
free_paid(context, &paid);
|
free_paid(context, &paid);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -1184,6 +1223,9 @@ init_cred_loop(krb5_context context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Set a new nonce. */
|
/* Set a new nonce. */
|
||||||
|
krb5_generate_random_block (&ctx->pk_nonce, sizeof(ctx->pk_nonce));
|
||||||
|
ctx->pk_nonce &= 0xffffffff;
|
||||||
|
|
||||||
krb5_generate_random_block (&ctx->nonce, sizeof(ctx->nonce));
|
krb5_generate_random_block (&ctx->nonce, sizeof(ctx->nonce));
|
||||||
ctx->nonce &= 0xffffffff;
|
ctx->nonce &= 0xffffffff;
|
||||||
ctx->as_req.req_body.nonce = ctx->nonce;
|
ctx->as_req.req_body.nonce = ctx->nonce;
|
||||||
@@ -1408,7 +1450,10 @@ krb5_get_init_creds_password(krb5_context context,
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (password == NULL && options->private->password == NULL) {
|
if (password == NULL &&
|
||||||
|
options->private->password == NULL &&
|
||||||
|
options->private->pk_init_ctx == NULL)
|
||||||
|
{
|
||||||
krb5_prompt prompt;
|
krb5_prompt prompt;
|
||||||
krb5_data password_data;
|
krb5_data password_data;
|
||||||
char *p, *q;
|
char *p, *q;
|
||||||
|
Reference in New Issue
Block a user