Issue certificates.
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@19909 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
199
kdc/kx509.c
199
kdc/kx509.c
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2006 Kungliga Tekniska H<>gskolan
|
* Copyright (c) 2006 - 2007 Kungliga Tekniska H<>gskolan
|
||||||
* (Royal Institute of Technology, Stockholm, Sweden).
|
* (Royal Institute of Technology, Stockholm, Sweden).
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
@@ -33,6 +33,8 @@
|
|||||||
|
|
||||||
#include "kdc_locl.h"
|
#include "kdc_locl.h"
|
||||||
#include <hex.h>
|
#include <hex.h>
|
||||||
|
#include <rfc2459_asn1.h>
|
||||||
|
#include <hx509.h>
|
||||||
|
|
||||||
RCSID("$Id$");
|
RCSID("$Id$");
|
||||||
|
|
||||||
@@ -140,72 +142,145 @@ build_certificate(krb5_context context,
|
|||||||
krb5_principal principal,
|
krb5_principal principal,
|
||||||
krb5_data *certificate)
|
krb5_data *certificate)
|
||||||
{
|
{
|
||||||
/* XXX write code here to generate certificates */
|
hx509_context hxctx = NULL;
|
||||||
FILE *in, *out;
|
hx509_ca_tbs tbs = NULL;
|
||||||
krb5_error_code ret;
|
hx509_env env = NULL;
|
||||||
const char *program;
|
hx509_cert cert = NULL;
|
||||||
char *str, *strkey;
|
hx509_cert signer = NULL;
|
||||||
char tstr[64];
|
int ret;
|
||||||
pid_t pid;
|
|
||||||
|
|
||||||
snprintf(tstr, sizeof(tstr), "%lu", (unsigned long)endtime);
|
if (krb5_principal_get_comp_string(context, principal, 1) != NULL) {
|
||||||
|
kdc_log(context, config, 0, "Principal is not a user");
|
||||||
ret = base64_encode(key->data, key->length, &strkey);
|
return EINVAL;
|
||||||
if (ret < 0) {
|
|
||||||
krb5_set_error_string(context, "failed to base64 encode key");
|
|
||||||
return ENOMEM;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
program = krb5_config_get_string(context,
|
ret = hx509_context_init(&hxctx);
|
||||||
NULL,
|
if (ret)
|
||||||
"kdc",
|
goto out;
|
||||||
"kx509_cert_program",
|
|
||||||
NULL);
|
|
||||||
if (program == NULL) {
|
|
||||||
free(strkey);
|
|
||||||
krb5_set_error_string(context, "no certificate program configured");
|
|
||||||
return ENOENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = krb5_unparse_name(context, principal, &str);
|
ret = hx509_env_init(hxctx, &env);
|
||||||
if (ret) {
|
if (ret)
|
||||||
free(strkey);
|
goto out;
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
pid = pipe_execv(&in, &out, NULL, program, str, tstr, NULL);
|
ret = hx509_env_add(hxctx, env, "principal-name",
|
||||||
free(str);
|
krb5_principal_get_comp_string(context, principal, 0));
|
||||||
if (pid <= 0) {
|
if (ret)
|
||||||
free(strkey);
|
goto out;
|
||||||
krb5_set_error_string(context,
|
|
||||||
"Failed to run the cert program %s",
|
|
||||||
program);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
fprintf(in, "%s\n", strkey);
|
|
||||||
fclose(in);
|
|
||||||
free(strkey);
|
|
||||||
|
|
||||||
{
|
{
|
||||||
unsigned buf[1024 * 10];
|
hx509_certs certs;
|
||||||
size_t len;
|
hx509_query *q;
|
||||||
|
|
||||||
len = fread(buf, 1, sizeof(buf), out);
|
ret = hx509_certs_init(hxctx, config->kx509_ca, 0,
|
||||||
fclose(out);
|
NULL, &certs);
|
||||||
if(len == 0) {
|
|
||||||
krb5_set_error_string(context,
|
|
||||||
"Certificate program returned no data");
|
|
||||||
return KRB5KDC_ERR_PREAUTH_FAILED;
|
|
||||||
}
|
|
||||||
ret = krb5_data_copy(certificate, buf, len);
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
krb5_set_error_string(context, "Failed To copy certificate");
|
kdc_log(context, config, 0, "Failed to load CA %s",
|
||||||
return ret;
|
config->kx509_ca);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
ret = hx509_query_alloc(hxctx, &q);
|
||||||
|
if (ret) {
|
||||||
|
hx509_certs_free(&certs);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY);
|
||||||
|
hx509_query_match_option(q, HX509_QUERY_OPTION_KU_KEYCERTSIGN);
|
||||||
|
|
||||||
|
ret = hx509_certs_find(hxctx, certs, q, &signer);
|
||||||
|
hx509_query_free(hxctx, q);
|
||||||
|
hx509_certs_free(&certs);
|
||||||
|
if (ret) {
|
||||||
|
kdc_log(context, config, 0, "Failed to find a CA in %s",
|
||||||
|
config->kx509_ca);
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
kill(pid, SIGKILL);
|
|
||||||
waitpid(pid, NULL, 0);
|
ret = hx509_ca_tbs_init(hxctx, &tbs);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
{
|
||||||
|
SubjectPublicKeyInfo spki;
|
||||||
|
memset(&spki, 0, sizeof(spki));
|
||||||
|
heim_any any;
|
||||||
|
|
||||||
|
spki.subjectPublicKey.data = key->data;
|
||||||
|
spki.subjectPublicKey.length = key->length * 8;
|
||||||
|
|
||||||
|
ret = der_copy_oid(oid_id_pkcs1_rsaEncryption(),
|
||||||
|
&spki.algorithm.algorithm);
|
||||||
|
|
||||||
|
any.data = "\x05\x00";
|
||||||
|
any.length = 2;
|
||||||
|
spki.algorithm.parameters = &any;
|
||||||
|
|
||||||
|
ret = hx509_ca_tbs_set_spki(hxctx, tbs, &spki);
|
||||||
|
der_free_oid(&spki.algorithm.algorithm);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
hx509_certs certs;
|
||||||
|
hx509_cert template;
|
||||||
|
|
||||||
|
ret = hx509_certs_init(hxctx, config->kx509_template, 0,
|
||||||
|
NULL, &certs);
|
||||||
|
if (ret) {
|
||||||
|
kdc_log(context, config, 0, "Failed to load template %s",
|
||||||
|
config->kx509_template);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
ret = hx509_get_one_cert(hxctx, certs, &template);
|
||||||
|
hx509_certs_free(&certs);
|
||||||
|
if (ret) {
|
||||||
|
kdc_log(context, config, 0, "Failed to find template in %s",
|
||||||
|
config->kx509_template);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
ret = hx509_ca_tbs_set_template(hxctx, tbs,
|
||||||
|
HX509_CA_TEMPLATE_SUBJECT|
|
||||||
|
HX509_CA_TEMPLATE_KU|
|
||||||
|
HX509_CA_TEMPLATE_EKU,
|
||||||
|
template);
|
||||||
|
hx509_cert_free(template);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
hx509_ca_tbs_set_notAfter(hxctx, tbs, endtime);
|
||||||
|
|
||||||
|
hx509_ca_tbs_subject_expand(hxctx, tbs, env);
|
||||||
|
hx509_env_free(&env);
|
||||||
|
|
||||||
|
ret = hx509_ca_sign(hxctx, tbs, signer, &cert);
|
||||||
|
hx509_cert_free(signer);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
hx509_ca_tbs_free(&tbs);
|
||||||
|
|
||||||
|
ret = hx509_cert_binary(hxctx, cert, certificate);
|
||||||
|
hx509_cert_free(cert);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
hx509_context_free(&hxctx);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
out:
|
||||||
|
if (env)
|
||||||
|
hx509_env_free(&env);
|
||||||
|
if (tbs)
|
||||||
|
hx509_ca_tbs_free(&tbs);
|
||||||
|
if (signer)
|
||||||
|
hx509_cert_free(signer);
|
||||||
|
if (hxctx)
|
||||||
|
hx509_context_free(&hxctx);
|
||||||
|
krb5_set_error_string(context, "cert creation failed");
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -299,6 +374,20 @@ _kdc_do_kx509(krb5_context context,
|
|||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
/* Verify that the key is encoded RSA key */
|
||||||
|
{
|
||||||
|
RSAPublicKey key;
|
||||||
|
size_t size;
|
||||||
|
|
||||||
|
ret = decode_RSAPublicKey(req->pk_key.data, req->pk_key.length,
|
||||||
|
&key, &size);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
free_RSAPublicKey(&key);
|
||||||
|
if (size != req->pk_key.length)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
ALLOC(rep.certificate);
|
ALLOC(rep.certificate);
|
||||||
if (rep.certificate == NULL)
|
if (rep.certificate == NULL)
|
||||||
goto out;
|
goto out;
|
||||||
|
Reference in New Issue
Block a user