Issue certificates.

git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@19909 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
Love Hörnquist Åstrand
2007-01-14 23:16:14 +00:00
parent 2df6875132
commit 70056908b1

View File

@@ -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).
* All rights reserved.
*
@@ -33,6 +33,8 @@
#include "kdc_locl.h"
#include <hex.h>
#include <rfc2459_asn1.h>
#include <hx509.h>
RCSID("$Id$");
@@ -140,72 +142,145 @@ build_certificate(krb5_context context,
krb5_principal principal,
krb5_data *certificate)
{
/* XXX write code here to generate certificates */
FILE *in, *out;
krb5_error_code ret;
const char *program;
char *str, *strkey;
char tstr[64];
pid_t pid;
hx509_context hxctx = NULL;
hx509_ca_tbs tbs = NULL;
hx509_env env = NULL;
hx509_cert cert = NULL;
hx509_cert signer = NULL;
int ret;
snprintf(tstr, sizeof(tstr), "%lu", (unsigned long)endtime);
ret = base64_encode(key->data, key->length, &strkey);
if (ret < 0) {
krb5_set_error_string(context, "failed to base64 encode key");
return ENOMEM;
if (krb5_principal_get_comp_string(context, principal, 1) != NULL) {
kdc_log(context, config, 0, "Principal is not a user");
return EINVAL;
}
program = krb5_config_get_string(context,
NULL,
"kdc",
"kx509_cert_program",
NULL);
if (program == NULL) {
free(strkey);
krb5_set_error_string(context, "no certificate program configured");
return ENOENT;
}
ret = hx509_context_init(&hxctx);
if (ret)
goto out;
ret = krb5_unparse_name(context, principal, &str);
if (ret) {
free(strkey);
return ret;
}
ret = hx509_env_init(hxctx, &env);
if (ret)
goto out;
pid = pipe_execv(&in, &out, NULL, program, str, tstr, NULL);
free(str);
if (pid <= 0) {
free(strkey);
krb5_set_error_string(context,
"Failed to run the cert program %s",
program);
return ret;
}
fprintf(in, "%s\n", strkey);
fclose(in);
free(strkey);
ret = hx509_env_add(hxctx, env, "principal-name",
krb5_principal_get_comp_string(context, principal, 0));
if (ret)
goto out;
{
unsigned buf[1024 * 10];
size_t len;
hx509_certs certs;
hx509_query *q;
len = fread(buf, 1, sizeof(buf), out);
fclose(out);
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);
ret = hx509_certs_init(hxctx, config->kx509_ca, 0,
NULL, &certs);
if (ret) {
krb5_set_error_string(context, "Failed To copy certificate");
return ret;
kdc_log(context, config, 0, "Failed to load CA %s",
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;
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)
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);
if (rep.certificate == NULL)
goto out;