Heimdal is a Kerberos 5 implementation.
-Please see the manual in doc, by default installed in
-/usr/heimdal/info/heimdal.info for information on how to install.
-There are also briefer man pages for most of the commands.
+For information how to install see <http://www.h5l.org/compile.html>.
+
+There are briefer man pages for most of the commands.
Bug reports and bugs are appreciated, see more under Bug reports in
-the manual on how we prefer them.
+the manual on how we prefer them: <heimdal-bugs@h5l.org>.
For more information see the web-page at
<http://www.h5l.org/> or the mailing lists:
krb5_enctype etype,
int skvno, const EncryptionKey *skey,
int ckvno, const EncryptionKey *reply_key,
+ int rk_is_subkey,
const char **e_text,
krb5_data *reply)
{
ASN1_MALLOC_ENCODE(EncTicketPart, buf, buf_size, et, &len, ret);
if(ret) {
- kdc_log(context, config, 0, "Failed to encode ticket: %s",
- krb5_get_err_text(context, ret));
+ const char *msg = krb5_get_error_message(context, ret);
+ kdc_log(context, config, 0, "Failed to encode ticket: %s", msg);
+ krb5_free_error_message(context, msg);
return ret;
}
if(buf_size != len) {
ret = krb5_crypto_init(context, skey, etype, &crypto);
if (ret) {
free(buf);
- kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
- krb5_get_err_text(context, ret));
+ const char *msg = krb5_get_error_message(context, ret);
+ kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg);
+ krb5_free_error_message(context, msg);
return ret;
}
free(buf);
krb5_crypto_destroy(context, crypto);
if(ret) {
- kdc_log(context, config, 0, "Failed to encrypt data: %s",
- krb5_get_err_text(context, ret));
+ const char *msg = krb5_get_error_message(context, ret);
+ kdc_log(context, config, 0, "Failed to encrypt data: %s", msg);
+ krb5_free_error_message(context, msg);
return ret;
}
else
ASN1_MALLOC_ENCODE(EncTGSRepPart, buf, buf_size, ek, &len, ret);
if(ret) {
- kdc_log(context, config, 0, "Failed to encode KDC-REP: %s",
- krb5_get_err_text(context, ret));
+ const char *msg = krb5_get_error_message(context, ret);
+ kdc_log(context, config, 0, "Failed to encode KDC-REP: %s", msg);
+ krb5_free_error_message(context, msg);
return ret;
}
if(buf_size != len) {
}
ret = krb5_crypto_init(context, reply_key, 0, &crypto);
if (ret) {
+ const char *msg = krb5_get_error_message(context, ret);
free(buf);
- kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
- krb5_get_err_text(context, ret));
+ kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg);
+ krb5_free_error_message(context, msg);
return ret;
}
if(rep->msg_type == krb_as_rep) {
} else {
krb5_encrypt_EncryptedData(context,
crypto,
- KRB5_KU_TGS_REP_ENC_PART_SESSION,
+ rk_is_subkey ? KRB5_KU_TGS_REP_ENC_PART_SUB_KEY : KRB5_KU_TGS_REP_ENC_PART_SESSION,
buf,
len,
ckvno,
}
krb5_crypto_destroy(context, crypto);
if(ret) {
- kdc_log(context, config, 0, "Failed to encode KDC-REP: %s",
- krb5_get_err_text(context, ret));
+ const char *msg = krb5_get_error_message(context, ret);
+ kdc_log(context, config, 0, "Failed to encode KDC-REP: %s", msg);
+ krb5_free_error_message(context, msg);
return ret;
}
if(buf_size != len) {
ret = _kdc_db_fetch(context, config, client_princ,
HDB_F_GET_CLIENT | flags, &clientdb, &client);
if(ret){
- kdc_log(context, config, 0, "UNKNOWN -- %s: %s", client_name,
- krb5_get_err_text(context, ret));
+ const char *msg = krb5_get_error_message(context, ret);
+ kdc_log(context, config, 0, "UNKNOWN -- %s: %s", client_name, msg);
+ krb5_free_error_message(context, msg);
ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
goto out;
}
HDB_F_GET_SERVER|HDB_F_GET_KRBTGT,
NULL, &server);
if(ret){
- kdc_log(context, config, 0, "UNKNOWN -- %s: %s", server_name,
- krb5_get_err_text(context, ret));
+ const char *msg = krb5_get_error_message(context, ret);
+ kdc_log(context, config, 0, "UNKNOWN -- %s: %s", server_name, msg);
+ krb5_free_error_message(context, msg);
ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
goto out;
}
try_next_key:
ret = krb5_crypto_init(context, &pa_key->key, 0, &crypto);
if (ret) {
- kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
- krb5_get_err_text(context, ret));
+ const char *msg = krb5_get_error_message(context, ret);
+ kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg);
+ krb5_free_error_message(context, msg);
free_EncryptedData(&enc_data);
continue;
}
*/
if(ret){
krb5_error_code ret2;
+ const char *msg = krb5_get_error_message(context, ret);
+
ret2 = krb5_enctype_to_string(context,
pa_key->key.keytype, &str);
if (ret2)
kdc_log(context, config, 5,
"Failed to decrypt PA-DATA -- %s "
"(enctype %s) error %s",
- client_name,
- str ? str : "unknown enctype",
- krb5_get_err_text(context, ret));
+ client_name, str ? str : "unknown enctype", msg);
+ krb5_free_error_message(context, msg);
free(str);
if(hdb_next_enctype2key(context, &client->entry,
ret = _kdc_encode_reply(context, config,
&rep, &et, &ek, setype, server->entry.kvno,
&skey->key, client->entry.kvno,
- reply_key, &e_text, reply);
+ reply_key, 0, &e_text, reply);
free_EncTicketPart(&et);
free_EncKDCRepPart(&ek);
if (ret)
KDC_REQ_BODY *b,
krb5_const_principal tgt_name,
const EncTicketPart *tgt,
+ const krb5_keyblock *replykey,
+ int rk_is_subkey,
const EncryptionKey *serverkey,
const krb5_keyblock *sessionkey,
krb5_kvno kvno,
unsigned int i = 0;
/* XXX check authdata */
+
if (et.authorization_data == NULL) {
- ret = ENOMEM;
- krb5_set_error_message(context, ret, "malloc: out of memory");
- goto out;
+ et.authorization_data = calloc(1, sizeof(*et.authorization_data));
+ if (et.authorization_data == NULL) {
+ ret = ENOMEM;
+ krb5_set_error_message(context, ret, "malloc: out of memory");
+ goto out;
+ }
}
for(i = 0; i < auth_data->len ; i++) {
ret = add_AuthorizationData(et.authorization_data, &auth_data->val[i]);
ret = _kdc_encode_reply(context, config,
&rep, &et, &ek, et.key.keytype,
kvno,
- serverkey, 0, &tgt->key, e_text, reply);
+ serverkey, 0, replykey, rk_is_subkey,
+ e_text, reply);
if (is_weak)
krb5_enctype_disable(context, et.key.keytype);
/* XXX should not re-encode this */
ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, b, &len, ret);
if(ret){
- kdc_log(context, config, 0, "Failed to encode KDC-REQ-BODY: %s",
- krb5_get_err_text(context, ret));
+ const char *msg = krb5_get_error_message(context, ret);
+ kdc_log(context, config, 0, "Failed to encode KDC-REQ-BODY: %s", msg);
+ krb5_free_error_message(context, msg);
goto out;
}
if(buf_size != len) {
}
ret = krb5_crypto_init(context, key, 0, &crypto);
if (ret) {
+ const char *msg = krb5_get_error_message(context, ret);
free(buf);
- kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
- krb5_get_err_text(context, ret));
+ kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg);
+ krb5_free_error_message(context, msg);
goto out;
}
ret = krb5_verify_checksum(context,
free(buf);
krb5_crypto_destroy(context, crypto);
if(ret){
+ const char *msg = krb5_get_error_message(context, ret);
kdc_log(context, config, 0,
- "Failed to verify authenticator checksum: %s",
- krb5_get_err_text(context, ret));
+ "Failed to verify authenticator checksum: %s", msg);
+ krb5_free_error_message(context, msg);
}
out:
free_Authenticator(auth);
const struct sockaddr *from_addr,
time_t **csec,
int **cusec,
- AuthorizationData **auth_data)
+ AuthorizationData **auth_data,
+ krb5_keyblock **replykey,
+ int *rk_is_subkey)
{
krb5_ap_req ap_req;
krb5_error_code ret;
krb5_flags verify_ap_req_flags;
krb5_crypto crypto;
Key *tkey;
+ krb5_keyblock *subkey = NULL;
+ unsigned usage;
*auth_data = NULL;
*csec = NULL;
*cusec = NULL;
+ *replykey = NULL;
memset(&ap_req, 0, sizeof(ap_req));
ret = krb5_decode_ap_req(context, &tgs_req->padata_value, &ap_req);
if(ret){
- kdc_log(context, config, 0, "Failed to decode AP-REQ: %s",
- krb5_get_err_text(context, ret));
+ const char *msg = krb5_get_error_message(context, ret);
+ kdc_log(context, config, 0, "Failed to decode AP-REQ: %s", msg);
+ krb5_free_error_message(context, msg);
goto out;
}
ret = _kdc_db_fetch(context, config, princ, HDB_F_GET_KRBTGT, NULL, krbtgt);
if(ret) {
+ const char *msg = krb5_get_error_message(context, ret);
char *p;
ret = krb5_unparse_name(context, princ, &p);
if (ret != 0)
p = "<unparse_name failed>";
krb5_free_principal(context, princ);
kdc_log(context, config, 0,
- "Ticket-granting ticket not found in database: %s: %s",
- p, krb5_get_err_text(context, ret));
+ "Ticket-granting ticket not found in database: %s: %s", msg);
+ krb5_free_error_message(context, msg);
if (ret == 0)
free(p);
ret = KRB5KRB_AP_ERR_NOT_US;
krb5_free_principal(context, princ);
if(ret) {
- kdc_log(context, config, 0, "Failed to verify AP-REQ: %s",
- krb5_get_err_text(context, ret));
+ const char *msg = krb5_get_error_message(context, ret);
+ kdc_log(context, config, 0, "Failed to verify AP-REQ: %s", msg);
+ krb5_free_error_message(context, msg);
goto out;
}
goto out;
}
- if (b->enc_authorization_data) {
- unsigned usage = KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY;
- krb5_keyblock *subkey;
- krb5_data ad;
+ usage = KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY;
+ *rk_is_subkey = 1;
- ret = krb5_auth_con_getremotesubkey(context, ac, &subkey);
- if(ret){
- krb5_auth_con_free(context, ac);
- kdc_log(context, config, 0, "Failed to get remote subkey: %s",
- krb5_get_err_text(context, ret));
- goto out;
- }
- if(subkey == NULL){
- usage = KRB5_KU_TGS_REQ_AUTH_DAT_SESSION;
- ret = krb5_auth_con_getkey(context, ac, &subkey);
- if(ret) {
- krb5_auth_con_free(context, ac);
- kdc_log(context, config, 0, "Failed to get session key: %s",
- krb5_get_err_text(context, ret));
- goto out;
- }
- }
- if(subkey == NULL){
+ ret = krb5_auth_con_getremotesubkey(context, ac, &subkey);
+ if(ret){
+ const char *msg = krb5_get_error_message(context, ret);
+ krb5_auth_con_free(context, ac);
+ kdc_log(context, config, 0, "Failed to get remote subkey: %s", msg);
+ krb5_free_error_message(context, msg);
+ goto out;
+ }
+ if(subkey == NULL){
+ usage = KRB5_KU_TGS_REQ_AUTH_DAT_SESSION;
+ *rk_is_subkey = 0;
+
+ ret = krb5_auth_con_getkey(context, ac, &subkey);
+ if(ret) {
+ const char *msg = krb5_get_error_message(context, ret);
krb5_auth_con_free(context, ac);
- kdc_log(context, config, 0,
- "Failed to get key for enc-authorization-data");
- ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
+ kdc_log(context, config, 0, "Failed to get session key: %s", msg);
+ krb5_free_error_message(context, msg);
goto out;
}
+ }
+ if(subkey == NULL){
+ krb5_auth_con_free(context, ac);
+ kdc_log(context, config, 0,
+ "Failed to get key for enc-authorization-data");
+ ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
+ goto out;
+ }
+
+ *replykey = subkey;
+
+ if (b->enc_authorization_data) {
+ krb5_data ad;
+
ret = krb5_crypto_init(context, subkey, 0, &crypto);
- krb5_free_keyblock(context, subkey);
if (ret) {
+ const char *msg = krb5_get_error_message(context, ret);
krb5_auth_con_free(context, ac);
- kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
- krb5_get_err_text(context, ret));
+ kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg);
+ krb5_free_error_message(context, msg);
goto out;
}
ret = krb5_decrypt_EncryptedData (context,
KDC_REQ_BODY *b,
hdb_entry_ex *krbtgt,
krb5_enctype krbtgt_etype,
+ const krb5_keyblock *replykey,
+ int rk_is_subkey,
krb5_ticket *ticket,
krb5_data *reply,
const char *from,
NULL, &server);
if(ret){
- const char *new_rlm;
+ const char *new_rlm, *msg;
Realm req_rlm;
krb5_realm *realms;
}
krb5_free_host_realm(context, realms);
}
+ msg = krb5_get_error_message(context, ret);
kdc_log(context, config, 0,
- "Server not found in database: %s: %s", spn,
- krb5_get_err_text(context, ret));
+ "Server not found in database: %s: %s", spn, msg);
+ krb5_free_error_message(context, msg);
if (ret == HDB_ERR_NOENTRY)
ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
goto out;
ret = _kdc_db_fetch(context, config, cp, HDB_F_GET_CLIENT | HDB_F_CANON,
&clientdb, &client);
if(ret) {
- const char *krbtgt_realm;
+ const char *krbtgt_realm, *msg;
/*
* If the client belongs to the same realm as our krbtgt, it
goto out;
}
- kdc_log(context, config, 1, "Client not found in database: %s: %s",
- cpn, krb5_get_err_text(context, ret));
+ msg = krb5_get_error_message(context, ret);
+ kdc_log(context, config, 1, "Client not found in database: %s", msg);
+ krb5_free_error_message(context, msg);
}
/*
client, server, ekey, &tkey->key,
tgt, &rspac, &signedpath);
if (ret) {
+ const char *msg = krb5_get_error_message(context, ret);
kdc_log(context, config, 0,
"Verify PAC failed for %s (%s) from %s with %s",
- spn, cpn, from, krb5_get_err_text(context, ret));
+ spn, cpn, from, msg);
+ krb5_free_error_message(context, msg);
goto out;
}
&spp,
&signedpath);
if (ret) {
+ const char *msg = krb5_get_error_message(context, ret);
kdc_log(context, config, 0,
"KRB5SignedPath check failed for %s (%s) from %s with %s",
- spn, cpn, from, krb5_get_err_text(context, ret));
+ spn, cpn, from, msg);
+ krb5_free_error_message(context, msg);
goto out;
}
ret = krb5_crypto_init(context, &tgt->key, 0, &crypto);
if (ret) {
+ const char *msg = krb5_get_error_message(context, ret);
free_PA_S4U2Self(&self);
krb5_data_free(&datack);
- kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
- krb5_get_err_text(context, ret));
+ kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg);
+ krb5_free_error_message(context, msg);
goto out;
}
krb5_data_free(&datack);
krb5_crypto_destroy(context, crypto);
if (ret) {
+ const char *msg = krb5_get_error_message(context, ret);
free_PA_S4U2Self(&self);
kdc_log(context, config, 0,
- "krb5_verify_checksum failed for S4U2Self: %s",
- krb5_get_err_text(context, ret));
+ "krb5_verify_checksum failed for S4U2Self: %s", msg);
+ krb5_free_error_message(context, msg);
goto out;
}
if (ret == 0 && !ad_signedpath)
ret = KRB5KDC_ERR_BADOPTION;
if (ret) {
+ const char *msg = krb5_get_error_message(context, ret);
kdc_log(context, config, 0,
"KRB5SignedPath check from service %s failed "
"for delegation to %s for client %s "
"from %s failed with %s",
- spn, str, cpn, from, krb5_get_err_text(context, ret));
+ spn, str, cpn, from, msg);
+ krb5_free_error_message(context, msg);
free(str);
goto out;
}
b,
client_principal,
tgt,
+ replykey,
+ rk_is_subkey,
ekey,
&sessionkey,
kvno,
const char *e_text = NULL;
krb5_enctype krbtgt_etype = ETYPE_NULL;
+ krb5_keyblock *replykey = NULL;
+ int rk_is_subkey = 0;
time_t *csec = NULL;
int *cusec = NULL;
&e_text,
from, from_addr,
&csec, &cusec,
- &auth_data);
+ &auth_data,
+ &replykey,
+ &rk_is_subkey);
if (ret) {
kdc_log(context, config, 0,
"Failed parsing TGS-REQ from %s", from);
&req->req_body,
krbtgt,
krbtgt_etype,
+ replykey,
+ rk_is_subkey,
ticket,
data,
from,
}
out:
+ if (replykey)
+ krb5_free_keyblock(context, replykey);
if(ret && data->data == NULL){
krb5_mk_error(context,
ret,
krb5_principal principal,
krb5_data *certificate)
{
- hx509_context hxctx = NULL;
hx509_ca_tbs tbs = NULL;
hx509_env env = NULL;
hx509_cert cert = NULL;
return EINVAL;
}
- ret = hx509_context_init(&hxctx);
- if (ret)
- goto out;
-
- ret = hx509_env_add(hxctx, &env, "principal-name",
+ ret = hx509_env_add(context->hx509ctx, &env, "principal-name",
krb5_principal_get_comp_string(context, principal, 0));
if (ret)
goto out;
hx509_certs certs;
hx509_query *q;
- ret = hx509_certs_init(hxctx, config->kx509_ca, 0,
+ ret = hx509_certs_init(context->hx509ctx, config->kx509_ca, 0,
NULL, &certs);
if (ret) {
kdc_log(context, config, 0, "Failed to load CA %s",
config->kx509_ca);
goto out;
}
- ret = hx509_query_alloc(hxctx, &q);
+ ret = hx509_query_alloc(context->hx509ctx, &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);
+ ret = hx509_certs_find(context->hx509ctx, certs, q, &signer);
+ hx509_query_free(context->hx509ctx, q);
hx509_certs_free(&certs);
if (ret) {
kdc_log(context, config, 0, "Failed to find a CA in %s",
}
}
- ret = hx509_ca_tbs_init(hxctx, &tbs);
+ ret = hx509_ca_tbs_init(context->hx509ctx, &tbs);
if (ret)
goto out;
any.length = 2;
spki.algorithm.parameters = &any;
- ret = hx509_ca_tbs_set_spki(hxctx, tbs, &spki);
+ ret = hx509_ca_tbs_set_spki(context->hx509ctx, 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,
+ ret = hx509_certs_init(context->hx509ctx, 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);
+ ret = hx509_get_one_cert(context->hx509ctx, 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,
+ ret = hx509_ca_tbs_set_template(context->hx509ctx, tbs,
HX509_CA_TEMPLATE_SUBJECT|
HX509_CA_TEMPLATE_KU|
HX509_CA_TEMPLATE_EKU,
goto out;
}
- hx509_ca_tbs_set_notAfter(hxctx, tbs, endtime);
+ hx509_ca_tbs_set_notAfter(context->hx509ctx, tbs, endtime);
- hx509_ca_tbs_subject_expand(hxctx, tbs, env);
+ hx509_ca_tbs_subject_expand(context->hx509ctx, tbs, env);
hx509_env_free(&env);
- ret = hx509_ca_sign(hxctx, tbs, signer, &cert);
+ ret = hx509_ca_sign(context->hx509ctx, tbs, signer, &cert);
hx509_cert_free(signer);
if (ret)
goto out;
hx509_ca_tbs_free(&tbs);
- ret = hx509_cert_binary(hxctx, cert, certificate);
+ ret = hx509_cert_binary(context->hx509ctx, cert, certificate);
hx509_cert_free(cert);
if (ret)
goto out;
- hx509_context_free(&hxctx);
-
return 0;
out:
if (env)
hx509_ca_tbs_free(&tbs);
if (signer)
hx509_cert_free(signer);
- if (hxctx)
- hx509_context_free(&hxctx);
krb5_set_error_message(context, ret, "cert creation failed");
return ret;
}
ret = config->db[i]->hdb_open(context, config->db[i], O_RDONLY, 0);
if (ret) {
- kdc_log(context, config, 0, "Failed to open database: %s",
- krb5_get_err_text(context, ret));
+ const char *msg = krb5_get_error_message(context, ret);
+ kdc_log(context, config, 0, "Failed to open database: %s", msg);
+ krb5_free_error_message(context, msg);
continue;
}
goto out;
}
- ret = hx509_certs_init(kdc_identity->hx509ctx,
+ ret = hx509_certs_init(context->hx509ctx,
"MEMORY:trust-anchors",
0, NULL, &trust_anchors);
if (ret) {
goto out;
}
- ret = hx509_certs_merge(kdc_identity->hx509ctx, trust_anchors,
+ ret = hx509_certs_merge(context->hx509ctx, trust_anchors,
kdc_identity->anchors);
if (ret) {
hx509_certs_free(&trust_anchors);
unsigned int i;
for (i = 0; i < pc->len; i++) {
- ret = hx509_cert_init_data(kdc_identity->hx509ctx,
+ ret = hx509_cert_init_data(context->hx509ctx,
pc->val[i].cert.data,
pc->val[i].cert.length,
&cert);
if (ret)
continue;
- hx509_certs_add(kdc_identity->hx509ctx, trust_anchors, cert);
+ hx509_certs_add(context->hx509ctx, trust_anchors, cert);
hx509_cert_free(cert);
}
}
- ret = hx509_verify_init_ctx(kdc_identity->hx509ctx, &cp->verify_ctx);
+ ret = hx509_verify_init_ctx(context->hx509ctx, &cp->verify_ctx);
if (ret) {
hx509_certs_free(&trust_anchors);
krb5_set_error_message(context, ret, "failed to create verify context");
ExternalPrincipalIdentifiers *edi = r.trustedCertifiers;
unsigned int i, maxedi;
- ret = hx509_certs_init(kdc_identity->hx509ctx,
+ ret = hx509_certs_init(context->hx509ctx,
"MEMORY:client-anchors",
0, NULL,
&cp->client_anchors);
if (edi->val[i].issuerAndSerialNumber == NULL)
continue;
- ret = hx509_query_alloc(kdc_identity->hx509ctx, &q);
+ ret = hx509_query_alloc(context->hx509ctx, &q);
if (ret) {
krb5_set_error_message(context, ret,
"Failed to allocate hx509_query");
&iasn,
&size);
if (ret) {
- hx509_query_free(kdc_identity->hx509ctx, q);
+ hx509_query_free(context->hx509ctx, q);
continue;
}
ret = hx509_query_match_issuer_serial(q, &iasn.issuer, &iasn.serialNumber);
free_IssuerAndSerialNumber(&iasn);
if (ret) {
- hx509_query_free(kdc_identity->hx509ctx, q);
+ hx509_query_free(context->hx509ctx, q);
continue;
}
- ret = hx509_certs_find(kdc_identity->hx509ctx,
+ ret = hx509_certs_find(context->hx509ctx,
kdc_identity->certs,
q,
&cert);
- hx509_query_free(kdc_identity->hx509ctx, q);
+ hx509_query_free(context->hx509ctx, q);
if (ret)
continue;
- hx509_certs_add(kdc_identity->hx509ctx,
+ hx509_certs_add(context->hx509ctx,
cp->client_anchors, cert);
hx509_cert_free(cert);
}
if (req->req_body.kdc_options.request_anonymous)
flags |= HX509_CMS_VS_ALLOW_ZERO_SIGNER;
- ret = hx509_cms_verify_signed(kdc_identity->hx509ctx,
+ ret = hx509_cms_verify_signed(context->hx509ctx,
cp->verify_ctx,
flags,
signed_content.data,
&eContent,
&signer_certs);
if (ret) {
- char *s = hx509_get_error_string(kdc_identity->hx509ctx, ret);
+ char *s = hx509_get_error_string(context->hx509ctx, ret);
krb5_warnx(context, "PKINIT: failed to verify signature: %s: %d",
s, ret);
free(s);
}
if (signer_certs) {
- ret = hx509_get_one_cert(kdc_identity->hx509ctx, signer_certs,
+ ret = hx509_get_one_cert(context->hx509ctx, signer_certs,
&cp->cert);
hx509_certs_free(&signer_certs);
}
} else
cp->keyex = USE_RSA;
- ret = hx509_peer_info_alloc(kdc_identity->hx509ctx,
+ ret = hx509_peer_info_alloc(context->hx509ctx,
&cp->peer);
if (ret) {
free_AuthPack(&ap);
}
if (ap.supportedCMSTypes) {
- ret = hx509_peer_info_set_cms_algs(kdc_identity->hx509ctx,
+ ret = hx509_peer_info_set_cms_algs(context->hx509ctx,
cp->peer,
ap.supportedCMSTypes->val,
ap.supportedCMSTypes->len);
}
} else {
/* assume old client */
- hx509_peer_info_add_cms_alg(kdc_identity->hx509ctx, cp->peer,
+ hx509_peer_info_add_cms_alg(context->hx509ctx, cp->peer,
hx509_crypto_des_rsdi_ede3_cbc());
- hx509_peer_info_add_cms_alg(kdc_identity->hx509ctx, cp->peer,
+ hx509_peer_info_add_cms_alg(context->hx509ctx, cp->peer,
hx509_signature_rsa_with_sha1());
- hx509_peer_info_add_cms_alg(kdc_identity->hx509ctx, cp->peer,
+ hx509_peer_info_add_cms_alg(context->hx509ctx, cp->peer,
hx509_signature_sha1());
}
free_AuthPack(&ap);
hx509_query *q;
hx509_cert cert;
- ret = hx509_query_alloc(kdc_identity->hx509ctx, &q);
+ ret = hx509_query_alloc(context->hx509ctx, &q);
if (ret)
goto out;
if (config->pkinit_kdc_friendly_name)
hx509_query_match_friendly_name(q, config->pkinit_kdc_friendly_name);
- ret = hx509_certs_find(kdc_identity->hx509ctx,
+ ret = hx509_certs_find(context->hx509ctx,
kdc_identity->certs,
q,
&cert);
- hx509_query_free(kdc_identity->hx509ctx, q);
+ hx509_query_free(context->hx509ctx, q);
if (ret)
goto out;
- ret = hx509_cms_create_signed_1(kdc_identity->hx509ctx,
+ ret = hx509_cms_create_signed_1(context->hx509ctx,
0,
sdAlg,
buf.data,
signed_data = buf;
}
- ret = hx509_cms_envelope_1(kdc_identity->hx509ctx,
+ ret = hx509_cms_envelope_1(context->hx509ctx,
HX509_CMS_EV_NO_KU_CHECK,
cp->cert,
signed_data.data, signed_data.length,
* filled in above
*/
- ret = hx509_query_alloc(kdc_identity->hx509ctx, &q);
+ ret = hx509_query_alloc(context->hx509ctx, &q);
if (ret)
goto out;
if (config->pkinit_kdc_friendly_name)
hx509_query_match_friendly_name(q, config->pkinit_kdc_friendly_name);
- ret = hx509_certs_find(kdc_identity->hx509ctx,
+ ret = hx509_certs_find(context->hx509ctx,
kdc_identity->certs,
q,
&cert);
- hx509_query_free(kdc_identity->hx509ctx, q);
+ hx509_query_free(context->hx509ctx, q);
if (ret)
goto out;
- ret = hx509_cms_create_signed_1(kdc_identity->hx509ctx,
+ ret = hx509_cms_create_signed_1(context->hx509ctx,
0,
&asn1_oid_id_pkdhkeydata,
buf.data,
goto out_ocsp;
}
- ret = hx509_ocsp_verify(kdc_identity->hx509ctx,
+ ret = hx509_ocsp_verify(context->hx509ctx,
kdc_time,
kdc_cert,
0,
list.val[i].length,
&kn, &size);
if (ret) {
+ const char *msg = krb5_get_error_message(context, ret);
kdc_log(context, config, 0,
- "Decoding kerberos name in certificate failed: %s",
- krb5_get_err_text(context, ret));
+ "Decoding kerberos name in certificate failed: %s", msg);
+ krb5_free_error_message(context, msg);
break;
}
if (size != list.val[i].length) {
kdc_log(context, config, 0, "Decode of MS-UPN-SAN failed");
goto out;
}
+ if (size != list.val[0].length) {
+ free_MS_UPN_SAN(&upn);
+ kdc_log(context, config, 0, "Trailing data in ");
+ ret = KRB5_KDC_ERR_CLIENT_NAME_MISMATCH;
+ goto out;
+ }
kdc_log(context, config, 0, "found MS UPN SAN: %s", upn);
return 0;
}
- ret = hx509_cert_get_base_subject(kdc_identity->hx509ctx,
+ ret = hx509_cert_get_base_subject(context->hx509ctx,
cp->cert,
&name);
if (ret)
unsigned int i;
for (i = 0; i < pc->len; i++) {
- ret = hx509_cert_init_data(kdc_identity->hx509ctx,
+ ret = hx509_cert_init_data(context->hx509ctx,
pc->val[i].cert.data,
pc->val[i].cert.length,
&cert);
if (config->pkinit_princ_in_cert) {
ret = match_rfc_san(context, config,
- kdc_identity->hx509ctx,
+ context->hx509ctx,
cp->cert,
client->entry.principal);
if (ret == 0) {
return 0;
}
ret = match_ms_upn_san(context, config,
- kdc_identity->hx509ctx,
+ context->hx509ctx,
cp->cert,
clientdb,
client);
ret = _krb5_pk_load_id(context,
&kdc_identity,
- 0,
user_id,
anchors,
pool,
hx509_query *q;
hx509_cert cert;
- ret = hx509_query_alloc(kdc_identity->hx509ctx, &q);
+ ret = hx509_query_alloc(context->hx509ctx, &q);
if (ret) {
krb5_warnx(context, "PKINIT: out of memory");
return ENOMEM;
if (config->pkinit_kdc_friendly_name)
hx509_query_match_friendly_name(q, config->pkinit_kdc_friendly_name);
- ret = hx509_certs_find(kdc_identity->hx509ctx,
+ ret = hx509_certs_find(context->hx509ctx,
kdc_identity->certs,
q,
&cert);
- hx509_query_free(kdc_identity->hx509ctx, q);
+ hx509_query_free(context->hx509ctx, q);
if (ret == 0) {
- if (hx509_cert_check_eku(kdc_identity->hx509ctx, cert,
+ if (hx509_cert_check_eku(context->hx509ctx, cert,
&asn1_oid_id_pkkdcekuoid, 0)) {
hx509_name name;
char *str;
for (e = list; e != NULL; e = _krb5_plugin_get_next(e)) {
windcft = _krb5_plugin_get_symbol(e);
- if (windcft->minor_version < KRB5_WINDC_PLUGING_MINOR)
+ if (windcft->minor_version < KRB5_WINDC_PLUGIN_MINOR)
continue;
(*windcft->init)(context, &windcctx);
#define KRB5_WINDC_PLUGING_MINOR 4
+#define KRB5_WINDC_PLUGIN_MINOR 4
typedef struct krb5plugin_windc_ftable {
int minor_version;
struct krb5_dh_moduli;
struct AlgorithmIdentifier;
struct _krb5_krb_auth_data;
+struct hx509_certs_data;
#include <krb5-private.h>
#ifndef NO_NTLM
char *password_file = NULL;
char *pk_user_id = NULL;
int pk_enterprise_flag = 0;
+struct hx509_certs_data *ent_user_id = NULL;
char *pk_x509_anchors = NULL;
int pk_use_enckey = 0;
static int canonicalize_flag = 0;
real_creds = creds;
else {
krb5_principal client;
- krb5_cc_get_principal(context, ccache, &client);
+ ret = krb5_cc_get_principal(context, ccache, &client);
+ if (ret) {
+ krb5_warn(context, ret, "524init: can't get client principal");
+ return ret;
+ }
memset(&in_creds, 0, sizeof(in_creds));
ret = get_server(context, client, server, &in_creds.server);
if(ret) {
+ krb5_warn(context, ret, "524init: can't get server principal");
krb5_free_principal(context, client);
return ret;
}
char passwd[256];
krb5_deltat start_time = 0;
krb5_deltat renew = 0;
- char *renewstr = NULL;
+ const char *renewstr = NULL;
krb5_enctype *enctype = NULL;
krb5_ccache tempccache;
#ifndef NO_NTLM
krb5_get_init_creds_opt_set_canonicalize(context, opt, TRUE);
if (pk_enterprise_flag && windows_flag)
krb5_get_init_creds_opt_set_win2k(context, opt, TRUE);
- if (pk_user_id || anonymous_flag) {
+ if (pk_user_id || ent_user_id || anonymous_flag) {
ret = krb5_get_init_creds_opt_set_pkinit(context, opt,
principal,
pk_user_id,
passwd);
if (ret)
krb5_err(context, 1, ret, "krb5_get_init_creds_opt_set_pkinit");
+ if (ent_user_id)
+ _krb5_get_init_creds_opt_set_pkinit_user_certs(context, opt, ent_user_id);
}
if (addrs_flag != -1)
addrs_flag ? FALSE : TRUE);
if (renew_life == NULL && renewable_flag)
- asprintf(&renewstr, "1 month");
+ renewstr = "1 month";
if (renew_life)
- asprintf(&renewstr, "%s", renew_life);
+ renewstr = renew_life;
if (renewstr) {
renew = parse_time (renewstr, "s");
if (renew < 0)
errx (1, "unparsable time: %s", renewstr);
- free(renewstr);
+
krb5_get_init_creds_opt_set_renew_life (opt, renew);
}
server_str,
opt);
krb5_kt_close(context, kt);
- } else if (pk_user_id || anonymous_flag) {
+ } else if (pk_user_id || ent_user_id || anonymous_flag) {
ret = krb5_get_init_creds_password (context,
&cred,
principal,
if (pk_enterprise_flag) {
ret = _krb5_pk_enterprise_cert(context, pk_user_id,
- argv[0], &principal);
+ argv[0], &principal,
+ &ent_user_id);
if (ret)
krb5_err(context, 1, ret, "krb5_pk_enterprise_certs");
+ pk_user_id = NULL;
+
} else if (anonymous_flag) {
ret = krb5_make_principal(context, &principal, argv[0],
KRB5_WELLKNOWN_NAME, KRB5_ANON_NAME,
NULL);
if (ret)
- krb5_err(context, 1, ret, "krb5_build_principal");
+ krb5_err(context, 1, ret, "krb5_make_principal");
krb5_principal_set_type(context, principal, KRB5_NT_WELLKNOWN);
} else {
$$ = new_tag(ASN1_C_UNIV, UT_GeneralString,
TE_EXPLICIT, new_type(TGeneralString));
}
+ | kw_TeletexString
+ {
+ $$ = new_tag(ASN1_C_UNIV, UT_TeletexString,
+ TE_EXPLICIT, new_type(TTeletexString));
+ }
| kw_UTF8String
{
$$ = new_tag(ASN1_C_UNIV, UT_UTF8String,
void *ptr;
ptr = realloc(data->data, data->length + datalen);
- if (ptr == NULL) {
+ if (ptr == NULL && data->length + datalen != 0) {
e = ENOMEM;
goto out;
}
p++;
data->length--;
}
- data->data = malloc(data->length);
- if (data->data == NULL) {
- data->length = 0;
- if (size)
- *size = 0;
- return ENOMEM;
- }
- q = &((unsigned char*)data->data)[data->length - 1];
- p += data->length - 1;
- while (q >= (unsigned char*)data->data) {
- *q = *p ^ 0xff;
- if (carry)
- carry = !++*q;
- p--;
- q--;
+ if (data->length) {
+ data->data = malloc(data->length);
+ if (data->data == NULL) {
+ data->length = 0;
+ if (size)
+ *size = 0;
+ return ENOMEM;
+ }
+ q = &((unsigned char*)data->data)[data->length - 1];
+ p += data->length - 1;
+ while (q >= (unsigned char*)data->data) {
+ *q = *p ^ 0xff;
+ if (carry)
+ carry = !++*q;
+ p--;
+ q--;
+ }
}
} else {
data->negative = 0;
case TGeneralString:
fprintf (headerfile, "GeneralString");
break;
+ case TTeletexString:
+ fprintf (headerfile, "TeletexString");
+ break;
case TTag: {
const char *classnames[] = { "UNIVERSAL ", "APPLICATION ",
"" /* CONTEXT */, "PRIVATE " };
space(level);
fprintf (headerfile, "heim_general_string %s;\n", name);
break;
+ case TTeletexString:
+ space(level);
+ fprintf (headerfile, "heim_general_string %s;\n", name);
+ break;
case TTag:
define_type (level, name, t->subtype, typedefp, preservep);
break;
case TGeneralString:
copy_primitive ("general_string", from, to);
break;
+ case TTeletexString:
+ copy_primitive ("general_string", from, to);
+ break;
case TUTCTime:
fprintf(codefile, "*(%s) = *(%s);\n", to, from);
break;
case TEnumerated:
case TGeneralizedTime:
case TGeneralString:
+ case TTeletexString:
case TOID:
case TUTCTime:
case TUTF8String:
*ty = PRIM;
*tag = UT_GeneralString;
break;
+ case TTeletexString:
+ *cl = ASN1_C_UNIV;
+ *ty = PRIM;
+ *tag = UT_TeletexString;
+ break;
case TGeneralizedTime:
*cl = ASN1_C_UNIV;
*ty = PRIM;
case TGeneralString:
decode_primitive ("general_string", name, forwstr);
break;
+ case TTeletexString:
+ decode_primitive ("general_string", name, forwstr);
+ break;
case TTag:{
char *tname, *typestring;
char *ide = NULL;
fprintf(codefile,
"else {\n"
"(%s)->u.%s.data = calloc(1, len);\n"
- "if ((%s)->u.%s.data == NULL) {\n"
+ "if ((%s)->u.%s.data == NULL && len != 0) {\n"
"e = ENOMEM; %s;\n"
"}\n"
"(%s)->u.%s.length = len;\n"
case TOID:
case TGeneralizedTime:
case TGeneralString:
+ case TTeletexString:
case TUTF8String:
case TPrintableString:
case TIA5String:
if (preserve)
fprintf (codefile,
"data->_save.data = calloc(1, ret);\n"
- "if (data->_save.data == NULL) { \n"
+ "if (data->_save.data == NULL && ret != 0) { \n"
"e = ENOMEM; goto fail; \n"
"}\n"
"data->_save.length = ret;\n"
encode_primitive ("general_string", name);
constructed = 0;
break;
+ case TTeletexString:
+ encode_primitive ("general_string", name);
+ constructed = 0;
+ break;
case TTag: {
char *tname;
int c;
case TOctetString:
case TGeneralizedTime:
case TGeneralString:
+ case TTeletexString:
case TUTCTime:
case TUTF8String:
case TPrintableString:
case TGeneralString:
free_primitive ("general_string", name);
break;
+ case TTeletexString:
+ free_primitive ("general_string", name);
+ break;
case TUTF8String:
free_primitive ("utf8string", name);
break;
case TGeneralString:
length_primitive ("general_string", name, variable);
break;
+ case TTeletexString:
+ length_primitive ("general_string", name, variable);
+ break;
case TUTCTime:
length_primitive ("utctime", name, variable);
break;
AttributeValue ::= heim_any
-TeletexStringx ::= [UNIVERSAL 20] IMPLICIT OCTET STRING
-
DirectoryString ::= CHOICE {
ia5String IA5String,
- teletexString TeletexStringx,
+ teletexString TeletexString,
printableString PrintableString,
universalString UniversalString,
utf8String UTF8String,
TChoice,
TEnumerated,
TGeneralString,
+ TTeletexString,
TGeneralizedTime,
TIA5String,
TInteger,
extern struct et_list *_et_list;
const char *com_right (struct et_list *list, long code);
+const char *com_right_r (struct et_list *list, long code, char *, size_t);
void initialize_error_table_r (struct et_list **, const char **, int, long);
void free_error_table (struct et_list *);
const char *
com_right(struct et_list *list, long code)
+{
+ struct et_list *p;
+ for (p = list; p; p = p->next)
+ if (code >= p->table->base && code < p->table->base + p->table->n_msgs)
+ return p->table->msgs[code - p->table->base];
+ return NULL;
+}
+
+const char *
+com_right_r(struct et_list *list, long code, char *str, size_t len)
{
struct et_list *p;
for (p = list; p; p = p->next) {
if (code >= p->table->base && code < p->table->base + p->table->n_msgs) {
- const char *str = p->table->msgs[code - p->table->base];
+ const char *msg = p->table->msgs[code - p->table->base];
#ifdef LIBINTL
char domain[12 + 20];
snprintf(domain, sizeof(domain), "heim_com_err%d", p->table->base);
#endif
- return dgettext(domain, str);
+ strlcpy(str, dgettext(domain, msg), len);
+ return str;
}
-
}
return NULL;
}
if (kret)
goto out;
- kret = krb5_build_principal(context,
- &creds.server,
- strlen(creds.client->realm),
- creds.client->realm,
- KRB5_TGS_NAME,
- creds.client->realm,
- NULL);
+ kret = krb5_make_principal(context,
+ &creds.server,
+ creds.client->realm,
+ KRB5_TGS_NAME,
+ creds.client->realm,
+ NULL);
if (kret)
goto out;
krb5_set_kdc_sec_offset (context, offset, -1);
}
- kret = krb5_build_authenticator (context,
+ kret = _krb5_build_authenticator(context,
ctx->auth_context,
enctype,
ctx->kcred,
&cksum,
- NULL,
&authenticator,
KRB5_KU_AP_REQ_AUTH);
*
*/
+#ifdef COMMONCRYPTO_SUPPORTS_RC2
static int
cc_rc2_cbc_init(EVP_CIPHER_CTX *ctx,
const unsigned char * key,
struct cc_key *cc = ctx->cipher_data;
return init_cc_key(encp, kCCAlgorithmRC2, key, ctx->cipher->key_len, iv, &cc->href);
}
+#endif
/**
* The RC2 cipher type - common crypto
const EVP_CIPHER *
EVP_cc_rc2_cbc(void)
{
+#ifdef COMMONCRYPTO_SUPPORTS_RC2
static const EVP_CIPHER rc2_cbc = {
0,
kCCBlockSizeRC2,
NULL
};
return &rc2_cbc;
+#else
+ return NULL;
+#endif
}
/**
const EVP_CIPHER *
EVP_cc_rc2_40_cbc(void)
{
+#ifdef COMMONCRYPTO_SUPPORTS_RC2
static const EVP_CIPHER rc2_40_cbc = {
0,
kCCBlockSizeRC2,
NULL
};
return &rc2_40_cbc;
+#else
+ return NULL;
+#endif
}
const EVP_CIPHER *
EVP_cc_rc2_64_cbc(void)
{
+#ifdef COMMONCRYPTO_SUPPORTS_RC2
static const EVP_CIPHER rc2_64_cbc = {
0,
kCCBlockSizeRC2,
NULL
};
return &rc2_64_cbc;
+#else
+ return NULL;
+#endif
}
/**
for (i = 0, p = ctx->opad; i < keylen; i++)
p[i] ^= ((const unsigned char *)key)[i];
- ctx->ctx = EVP_MD_CTX_create();
+ if (ctx->ctx == NULL)
+ ctx->ctx = EVP_MD_CTX_create();
EVP_DigestInit_ex(ctx->ctx, ctx->md, ctx->engine);
EVP_DigestUpdate(ctx->ctx, ctx->ipad, EVP_MD_block_size(ctx->md));
ssize_t count;
int once = 0;
- if (size <= 0)
+ if (size < 0)
return 0;
+ else if (size == 0)
+ return 1;
HEIMDAL_MUTEX_lock(&random_mutex);
if (random_fd == -1) {
const hdb_entry *entry, char **p)
{
HDB_extension *ext;
- char *str;
int ret;
ext = hdb_find_extension(entry, choice_HDB_extension_data_password);
if (ext) {
- heim_utf8_string str2;
+ heim_utf8_string str;
heim_octet_string pw;
if (db->hdb_master_key_set && ext->data.u.password.mkvno) {
return ret;
}
- str2 = pw.data;
- if (str2[pw.length - 1] != '\0') {
+ str = pw.data;
+ if (str[pw.length - 1] != '\0') {
krb5_set_error_message(context, EINVAL, "password malformated");
return EINVAL;
}
- *p = strdup(str2);
+ *p = strdup(str);
der_free_octet_string(&pw);
if (*p == NULL) {
return 0;
}
- ret = krb5_unparse_name(context, entry->principal, &str);
- if (ret == 0) {
- krb5_set_error_message(context, ENOENT, "no password attributefor %s", str);
- free(str);
- } else
- krb5_clear_error_message(context);
-
- return ENOENT;
+ {
+ char *name;
+ ret = krb5_unparse_name(context, entry->principal, &name);
+ if (ret == 0) {
+ krb5_set_error_message(context, ENOENT, "no password attributefor %s", name);
+ free(name);
+ } else
+ krb5_clear_error_message(context);
+
+ return ENOENT;
+ }
}
int
*
*/
-
+const int hdb_interface_version = HDB_INTERFACE_VERSION;
static struct hdb_method methods[] = {
#if HAVE_DB1 || HAVE_DB3
#define HDB_F_GET_KRBTGT 16 /* fetch krbtgt */
#define HDB_F_GET_ANY 28 /* fetch any of client,server,krbtgt */
#define HDB_F_CANON 32 /* want canonicalition */
+#define HDB_F_ADMIN_DATA 64 /* want data that kdc don't use */
/* hdb_capability_flags */
#define HDB_CAP_F_HANDLE_ENTERPRISE_PRINCIPAL 1
krb5_error_code (*create)(krb5_context, HDB **, const char *filename);
};
+extern const int hdb_interface_version;
+
#include <hdb-protos.h>
#endif /* __HDB_H__ */
const heim_oid *oid,
const char *string)
{
- const PKIXXmppAddr ustring = string;
+ const PKIXXmppAddr ustring = (const PKIXXmppAddr)string;
heim_octet_string os;
size_t size;
int ret;
return ret;
}
if (size != len) {
+ free_Certificate(&t);
hx509_set_error_string(context, 0, HX509_EXTRA_DATA_AFTER_STRUCTURE,
"Extra data after certificate");
return HX509_EXTRA_DATA_AFTER_STRUCTURE;
{
if (ctx->trust_anchors)
hx509_certs_free(&ctx->trust_anchors);
- ctx->trust_anchors = _hx509_certs_ref(set);
+ ctx->trust_anchors = hx509_certs_ref(set);
}
/**
*
*/
if (ctx->trust_anchors)
- anchors = _hx509_certs_ref(ctx->trust_anchors);
+ anchors = hx509_certs_ref(ctx->trust_anchors);
else if (context->default_trust_anchors && ALLOW_DEF_TA(ctx))
- anchors = _hx509_certs_ref(context->default_trust_anchors);
+ anchors = hx509_certs_ref(context->default_trust_anchors);
else {
ret = hx509_certs_init(context, "MEMORY:no-TA", 0, NULL, &anchors);
if (ret)
hx509_env_free(&envcert);
return ret;
}
+
+/**
+ * Print a simple representation of a certificate
+ *
+ * @param context A hx509 context, can be NULL
+ * @param cert certificate to print
+ * @param out the stdio output stream, if NULL, stdout is used
+ *
+ * @return An hx509 error code
+ *
+ * @ingroup hx509_cert
+ */
+
+int
+hx509_print_cert(hx509_context context, hx509_cert cert, FILE *out)
+{
+ hx509_name name;
+ char *str;
+ int ret;
+
+ if (out == NULL)
+ out = stderr;
+
+ ret = hx509_cert_get_issuer(cert, &name);
+ if (ret)
+ return ret;
+ hx509_name_to_string(name, &str);
+ hx509_name_free(&name);
+ fprintf(out, " issuer: \"%s\"\n", str);
+ free(str);
+
+ ret = hx509_cert_get_subject(cert, &name);
+ if (ret)
+ return ret;
+ hx509_name_to_string(name, &str);
+ hx509_name_free(&name);
+ fprintf(out, " subject: \"%s\"\n", str);
+ free(str);
+
+ {
+ heim_integer serialNumber;
+
+ ret = hx509_cert_get_serialnumber(cert, &serialNumber);
+ if (ret)
+ return ret;
+ ret = der_print_hex_heim_integer(&serialNumber, &str);
+ if (ret)
+ return ret;
+ der_free_heim_integer(&serialNumber);
+ fprintf(out, " serial: %s\n", str);
+ free(str);
+ }
+
+ printf(" keyusage: ");
+ ret = hx509_cert_keyusage_print(context, cert, &str);
+ if (ret == 0) {
+ fprintf(out, "%s\n", str);
+ free(str);
+ } else
+ fprintf(out, "no");
+
+ return 0;
+}
void
hx509_clear_error_string(hx509_context context)
{
- free_error_string(context->error);
- context->error = NULL;
+ if (context) {
+ free_error_string(context->error);
+ context->error = NULL;
+ }
}
/**
{
hx509_error msg;
+ if (context == NULL)
+ return;
+
msg = calloc(1, sizeof(*msg));
if (msg == NULL) {
hx509_clear_error_string(context);
*/
static void
-header(FILE *f, const char *type, const char *str)
+print_pem_stamp(FILE *f, const char *type, const char *str)
{
fprintf(f, "-----%s %s-----\n", type, str);
}
#define ENCODE_LINE_LENGTH 54
- header(f, "BEGIN", type);
+ print_pem_stamp(f, "BEGIN", type);
while (headers) {
fprintf(f, "%s: %s\n%s",
free(line);
}
- header(f, "END", type);
+ print_pem_stamp(f, "END", type);
return 0;
}
int
hx509_pem_add_header(hx509_pem_header **headers,
- const char *hdr, const char *value)
+ const char *header, const char *value)
{
hx509_pem_header *h;
h = calloc(1, sizeof(*h));
if (h == NULL)
return ENOMEM;
- h->header = strdup(hdr);
+ h->header = strdup(header);
if (h->header == NULL) {
free(h);
return ENOMEM;
*/
const char *
-hx509_pem_find_header(const hx509_pem_header *h, const char *hdr)
+hx509_pem_find_header(const hx509_pem_header *h, const char *header)
{
while(h) {
- if (strcmp(hdr, h->header) == 0)
+ if (strcmp(header, h->header) == 0)
return h->value;
h = h->next;
}
hx509_certs
-_hx509_certs_ref(hx509_certs certs)
+hx509_certs_ref(hx509_certs certs)
{
if (certs == NULL)
return NULL;
const char *residue, hx509_lock lock, outformat format)
{
char *p, *pnext;
- struct ks_file *f = NULL;
+ struct ks_file *ksf = NULL;
hx509_private_key *keys = NULL;
int ret;
struct pem_ctx pem_ctx;
if (lock == NULL)
lock = _hx509_empty_lock;
- f = calloc(1, sizeof(*f));
- if (f == NULL) {
+ ksf = calloc(1, sizeof(*ksf));
+ if (ksf == NULL) {
hx509_clear_error_string(context);
return ENOMEM;
}
- f->format = format;
+ ksf->format = format;
- f->fn = strdup(residue);
- if (f->fn == NULL) {
+ ksf->fn = strdup(residue);
+ if (ksf->fn == NULL) {
hx509_clear_error_string(context);
ret = ENOMEM;
goto out;
if (flags & HX509_CERTS_CREATE) {
ret = hx509_certs_init(context, "MEMORY:ks-file-create",
- 0, lock, &f->certs);
+ 0, lock, &ksf->certs);
if (ret)
goto out;
- *data = f;
+ *data = ksf;
return 0;
}
if (ret)
goto out;
- for (p = f->fn; p != NULL; p = pnext) {
- FILE *f2;
+ for (p = ksf->fn; p != NULL; p = pnext) {
+ FILE *f;
pnext = strchr(p, ',');
if (pnext)
*pnext++ = '\0';
- if ((f2 = fopen(p, "r")) == NULL) {
+ if ((f = fopen(p, "r")) == NULL) {
ret = ENOENT;
hx509_set_error_string(context, 0, ret,
"Failed to open PEM file \"%s\": %s",
p, strerror(errno));
goto out;
}
- rk_cloexec_file(f2);
+ rk_cloexec_file(f);
- ret = hx509_pem_read(context, f2, pem_func, &pem_ctx);
- fclose(f2);
+ ret = hx509_pem_read(context, f, pem_func, &pem_ctx);
+ fclose(f);
if (ret != 0 && ret != HX509_PARSING_KEY_FAILED)
goto out;
else if (ret == HX509_PARSING_KEY_FAILED) {
}
}
- ret = _hx509_collector_collect_certs(context, pem_ctx.c, &f->certs);
+ ret = _hx509_collector_collect_certs(context, pem_ctx.c, &ksf->certs);
if (ret)
goto out;
int i;
for (i = 0; keys[i]; i++)
- _hx509_certs_keys_add(context, f->certs, keys[i]);
+ _hx509_certs_keys_add(context, ksf->certs, keys[i]);
_hx509_certs_keys_free(context, keys);
}
out:
if (ret == 0)
- *data = f;
+ *data = ksf;
else {
- if (f->fn)
- free(f->fn);
- free(f);
+ if (ksf->fn)
+ free(ksf->fn);
+ free(ksf);
}
if (pem_ctx.c)
_hx509_collector_free(pem_ctx.c);
static int
file_free(hx509_certs certs, void *data)
{
- struct ks_file *f = data;
- hx509_certs_free(&f->certs);
- free(f->fn);
- free(f);
+ struct ks_file *ksf = data;
+ hx509_certs_free(&ksf->certs);
+ free(ksf->fn);
+ free(ksf);
return 0;
}
file_store(hx509_context context,
hx509_certs certs, void *data, int flags, hx509_lock lock)
{
- struct ks_file *f = data;
+ struct ks_file *ksf = data;
struct store_ctx sc;
int ret;
- sc.f = fopen(f->fn, "w");
+ sc.f = fopen(ksf->fn, "w");
if (sc.f == NULL) {
hx509_set_error_string(context, 0, ENOENT,
"Failed to open file %s for writing");
return ENOENT;
}
rk_cloexec_file(sc.f);
- sc.format = f->format;
+ sc.format = ksf->format;
- ret = hx509_certs_iter(context, f->certs, store_func, &sc);
+ ret = hx509_certs_iter(context, ksf->certs, store_func, &sc);
fclose(sc.f);
return ret;
}
static int
file_add(hx509_context context, hx509_certs certs, void *data, hx509_cert c)
{
- struct ks_file *f = data;
- return hx509_certs_add(context, f->certs, c);
+ struct ks_file *ksf = data;
+ return hx509_certs_add(context, ksf->certs, c);
}
static int
file_iter_start(hx509_context context,
hx509_certs certs, void *data, void **cursor)
{
- struct ks_file *f = data;
- return hx509_certs_start_seq(context, f->certs, cursor);
+ struct ks_file *ksf = data;
+ return hx509_certs_start_seq(context, ksf->certs, cursor);
}
static int
file_iter(hx509_context context,
hx509_certs certs, void *data, void *iter, hx509_cert *cert)
{
- struct ks_file *f = data;
- return hx509_certs_next_cert(context, f->certs, iter, cert);
+ struct ks_file *ksf = data;
+ return hx509_certs_next_cert(context, ksf->certs, iter, cert);
}
static int
void *data,
void *cursor)
{
- struct ks_file *f = data;
- return hx509_certs_end_seq(context, f->certs, cursor);
+ struct ks_file *ksf = data;
+ return hx509_certs_end_seq(context, ksf->certs, cursor);
}
static int
void *data,
hx509_private_key **keys)
{
- struct ks_file *f = data;
- return _hx509_certs_keys_get(context, f->certs, keys);
+ struct ks_file *ksf = data;
+ return _hx509_certs_keys_get(context, ksf->certs, keys);
}
static int
void *data,
hx509_private_key key)
{
- struct ks_file *f = data;
- return _hx509_certs_keys_add(context, f->certs, key);
+ struct ks_file *ksf = data;
+ return _hx509_certs_keys_add(context, ksf->certs, key);
}
static struct hx509_keyset_ops keyset_file = {
void
hx509_lock_free(hx509_lock lock)
{
- hx509_certs_free(&lock->certs);
- hx509_lock_reset_passwords(lock);
- memset(lock, 0, sizeof(*lock));
- free(lock);
+ if (lock) {
+ hx509_certs_free(&lock->certs);
+ hx509_lock_reset_passwords(lock);
+ memset(lock, 0, sizeof(*lock));
+ free(lock);
+ }
}
int
break;
}
case choice_DirectoryString_teletexString:
- ss = malloc(ds->u.teletexString.length + 1);
- if (ss == NULL)
- _hx509_abort("allocation failure"); /* XXX */
- memcpy(ss, ds->u.teletexString.data, ds->u.teletexString.length);
- ss[ds->u.teletexString.length] = '\0';
+ ss = ds->u.teletexString;
break;
case choice_DirectoryString_universalString: {
const uint32_t *uni = ds->u.universalString.data;
len = strlen(ss);
append_string(str, &total_len, ss, len, 1);
if (ds->element == choice_DirectoryString_universalString ||
- ds->element == choice_DirectoryString_bmpString ||
- ds->element == choice_DirectoryString_teletexString)
+ ds->element == choice_DirectoryString_bmpString)
{
free(ss);
}
COPYCHARARRAY(ds, printableString, len, name);
break;
case choice_DirectoryString_teletexString:
- COPYVOIDARRAY(ds, teletexString, len, name);
+ COPYCHARARRAY(ds, teletexString, len, name);
break;
case choice_DirectoryString_bmpString:
COPYVALARRAY(ds, bmpString, len, name);
switch (name->element) {
case choice_GeneralName_otherName: {
- char *str2;
- hx509_oid_sprint(&name->u.otherName.type_id, &str2);
- if (str2 == NULL)
+ char *oid;
+ hx509_oid_sprint(&name->u.otherName.type_id, &oid);
+ if (oid == NULL)
return ENOMEM;
- strpool = rk_strpoolprintf(strpool, "otherName: %s", str2);
- free(str2);
+ strpool = rk_strpoolprintf(strpool, "otherName: %s", oid);
+ free(oid);
break;
}
case choice_GeneralName_rfc822Name:
break;
}
case choice_GeneralName_registeredID: {
- char *str2;
- hx509_oid_sprint(&name->u.registeredID, &str2);
- if (str2 == NULL)
+ char *oid;
+ hx509_oid_sprint(&name->u.registeredID, &oid);
+ if (oid == NULL)
return ENOMEM;
- strpool = rk_strpoolprintf(strpool, "registeredID: %s", str2);
- free(str2);
+ strpool = rk_strpoolprintf(strpool, "registeredID: %s", oid);
+ free(oid);
break;
}
default:
es = req.tbsRequest.requestExtensions;
- es->val = calloc(es->len, sizeof(es->val[0]));
+ es->val = calloc(1, sizeof(es->val[0]));
if (es->val == NULL) {
ret = ENOMEM;
goto out;
}
- es->len = 1;
ret = der_copy_oid(&asn1_oid_id_pkix_ocsp_nonce, &es->val[0].extnID);
if (ret) {
free_OCSPRequest(&req);
return ret;
}
+ es->len = 1;
es->val[0].extnValue.data = malloc(10);
if (es->val[0].extnValue.data == NULL) {
default:
_hx509_abort("hx509 eval expr with unknown op: %d", (int)expr->op);
}
- return 0;
}
void
if (auth_context->local_address == NULL) {
len = sizeof(ss_local);
if(getsockname(fd, local, &len) < 0) {
+ char buf[128];
ret = errno;
- krb5_set_error_message(context, ret,
- "getsockname: %s",
- strerror(ret));
+ strerror_r(ret, buf, sizeof(buf));
+ krb5_set_error_message(context, ret, "getsockname: %s", buf);
goto out;
}
ret = krb5_sockaddr2address (context, local, &local_k_address);
if(flags & KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR) {
len = sizeof(ss_remote);
if(getpeername(fd, remote, &len) < 0) {
+ char buf[128];
ret = errno;
- krb5_set_error_message(context, ret,
- "getpeername: %s", strerror(ret));
+ strerror_r(ret, buf, sizeof(buf));
+ krb5_set_error_message(context, ret, "getpeername: %s", buf);
goto out;
}
ret = krb5_sockaddr2address (context, remote, &remote_k_address);
}
krb5_error_code KRB5_LIB_FUNCTION
-krb5_build_authenticator (krb5_context context,
+_krb5_build_authenticator(krb5_context context,
krb5_auth_context auth_context,
krb5_enctype enctype,
krb5_creds *cred,
Checksum *cksum,
- Authenticator **auth_result,
krb5_data *result,
krb5_key_usage usage)
{
- Authenticator *auth;
+ Authenticator auth;
u_char *buf = NULL;
size_t buf_size;
size_t len;
krb5_error_code ret;
krb5_crypto crypto;
- auth = calloc(1, sizeof(*auth));
- if (auth == NULL) {
- krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
- return ENOMEM;
- }
+ memset(&auth, 0, sizeof(auth));
- auth->authenticator_vno = 5;
- copy_Realm(&cred->client->realm, &auth->crealm);
- copy_PrincipalName(&cred->client->name, &auth->cname);
+ auth.authenticator_vno = 5;
+ copy_Realm(&cred->client->realm, &auth.crealm);
+ copy_PrincipalName(&cred->client->name, &auth.cname);
- krb5_us_timeofday (context, &auth->ctime, &auth->cusec);
+ krb5_us_timeofday (context, &auth.ctime, &auth.cusec);
- ret = krb5_auth_con_getlocalsubkey(context, auth_context, &auth->subkey);
+ ret = krb5_auth_con_getlocalsubkey(context, auth_context, &auth.subkey);
if(ret)
goto fail;
krb5_generate_seq_number (context,
&cred->session,
&auth_context->local_seqnumber);
- ALLOC(auth->seq_number, 1);
- if(auth->seq_number == NULL) {
+ ALLOC(auth.seq_number, 1);
+ if(auth.seq_number == NULL) {
ret = ENOMEM;
goto fail;
}
- *auth->seq_number = auth_context->local_seqnumber;
+ *auth.seq_number = auth_context->local_seqnumber;
} else
- auth->seq_number = NULL;
- auth->authorization_data = NULL;
- auth->cksum = cksum;
-
- if (cksum != NULL && cksum->cksumtype == CKSUMTYPE_GSSAPI) {
- /*
- * This is not GSS-API specific, we only enable it for
- * GSS for now
- */
- ret = make_etypelist(context, &auth->authorization_data);
+ auth.seq_number = NULL;
+ auth.authorization_data = NULL;
+
+ if (cksum) {
+ ALLOC(auth.cksum, 1);
+ if (auth.cksum == NULL) {
+ ret = ENOMEM;
+ goto fail;
+ }
+ ret = copy_Checksum(cksum, auth.cksum);
if (ret)
goto fail;
+
+ if (auth.cksum->cksumtype == CKSUMTYPE_GSSAPI) {
+ /*
+ * This is not GSS-API specific, we only enable it for
+ * GSS for now
+ */
+ ret = make_etypelist(context, &auth.authorization_data);
+ if (ret)
+ goto fail;
+ }
}
/* XXX - Copy more to auth_context? */
- auth_context->authenticator->ctime = auth->ctime;
- auth_context->authenticator->cusec = auth->cusec;
+ auth_context->authenticator->ctime = auth.ctime;
+ auth_context->authenticator->cusec = auth.cusec;
- ASN1_MALLOC_ENCODE(Authenticator, buf, buf_size, auth, &len, ret);
+ ASN1_MALLOC_ENCODE(Authenticator, buf, buf_size, &auth, &len, ret);
if (ret)
goto fail;
if(buf_size != len)
ret = krb5_encrypt (context,
crypto,
usage /* KRB5_KU_AP_REQ_AUTH */,
- buf + buf_size - len,
+ buf,
len,
result);
krb5_crypto_destroy(context, crypto);
if (ret)
goto fail;
+ fail:
+ free_Authenticator (&auth);
free (buf);
- if (auth_result)
- *auth_result = auth;
- else {
- /* Don't free the `cksum', it's allocated by the caller */
- auth->cksum = NULL;
- free_Authenticator (auth);
- free (auth);
- }
- return ret;
- fail:
- free_Authenticator (auth);
- free (auth);
- free (buf);
return ret;
}
cc_ops_register(p);
kt_ops_register(p);
+#ifdef PKINIT
+ ret = hx509_context_init(&p->hx509ctx);
+ if (ret)
+ goto out;
+#endif
+
out:
if(ret) {
krb5_free_context(p);
return 0;
}
-/**
- * Return the error string for the error code. The caller must not
- * free the string.
- *
- * @param context Kerberos 5 context.
- * @param code Kerberos error code.
- *
- * @return the error message matching code
- *
- * @ingroup krb5
- */
-
-const char* KRB5_LIB_FUNCTION
-krb5_get_err_text(krb5_context context, krb5_error_code code)
-{
- const char *p = NULL;
- if(context != NULL)
- p = com_right(context->et_list, code);
- if(p == NULL)
- p = strerror(code);
- if (p == NULL)
- p = "Unknown error";
- return p;
-}
-
/**
* Init the built-in ets in the Kerberos library.
*
return 0;
}
-static const char zero_ivec[EVP_MAX_BLOCK_LENGTH] = { 0 };
+static const unsigned char zero_ivec[EVP_MAX_BLOCK_LENGTH] = { 0 };
static krb5_error_code
evp_encrypt_cts(krb5_context context,
HEIMDAL_MUTEX_unlock(context->mutex);
}
+/**
+ * Prepend the context full error string for a specific error code.
+ * The error that is stored should be internationalized.
+ *
+ * @param context Kerberos 5 context
+ * @param ret The error code
+ * @param fmt Error string for the error code
+ * @param ... printf(3) style parameters.
+ *
+ * @ingroup krb5_error
+ */
+
+void KRB5_LIB_FUNCTION
+krb5_prepend_error_message(krb5_context context, krb5_error_code ret,
+ const char *fmt, ...)
+ __attribute__ ((format (printf, 3, 4)))
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ krb5_vset_error_message (context, ret, fmt, ap);
+ va_end(ap);
+}
+
+/**
+ * Prepend the contexts's full error string for a specific error code.
+ *
+ * @param context Kerberos 5 context
+ * @param ret The error code
+ * @param fmt Error string for the error code
+ * @param args printf(3) style parameters.
+ *
+ * @ingroup krb5_error
+ */
+
+void KRB5_LIB_FUNCTION
+krb5_vprepend_error_message (krb5_context context, krb5_error_code ret,
+ const char *fmt, va_list args)
+ __attribute__ ((format (printf, 3, 0)))
+{
+ char *str, *str2;
+ HEIMDAL_MUTEX_lock(context->mutex);
+ if (context->error_code != ret) {
+ HEIMDAL_MUTEX_unlock(context->mutex);
+ return;
+ }
+ vasprintf(&str, fmt, args);
+ if (context->error_string) {
+ int e;
+
+ e = asprintf(&str2, "%s: %s", str, context->error_string);
+ free(context->error_string);
+ if (e < 0)
+ context->error_string = NULL;
+ else
+ context->error_string = str2;
+ free(str);
+ } else
+ context->error_string = str;
+ HEIMDAL_MUTEX_unlock(context->mutex);
+}
+
/**
* Return the error message in context. On error or no error string,
const char * KRB5_LIB_FUNCTION
krb5_get_error_message(krb5_context context, krb5_error_code code)
{
- const char *cstr;
char *str;
HEIMDAL_MUTEX_lock(context->mutex);
if (code == 0)
return strdup("Success");
-
- cstr = krb5_get_err_text(context, code);
- if (cstr)
- return strdup(cstr);
+ {
+ const char *msg;
+ char buf[128];
+ msg = com_right_r(context->et_list, code, buf, sizeof(buf));
+ if (msg)
+ return strdup(msg);
+ }
if (asprintf(&str, "<unknown error: %d>", (int)code) == -1)
return NULL;
{
free(rk_UNCONST(msg));
}
+
+
+/**
+ * Return the error string for the error code. The caller must not
+ * free the string.
+ *
+ * This function is deprecated since its not threadsafe.
+ *
+ * @param context Kerberos 5 context.
+ * @param code Kerberos error code.
+ *
+ * @return the error message matching code
+ *
+ * @ingroup krb5
+ */
+
+const char* KRB5_LIB_FUNCTION
+krb5_get_err_text(krb5_context context, krb5_error_code code) KRB5_DEPRECATED
+{
+ const char *p = NULL;
+ if(context != NULL)
+ p = com_right(context->et_list, code);
+ if(p == NULL)
+ p = strerror(code);
+ if (p == NULL)
+ p = "Unknown error";
+ return p;
+}
N_("timed out locking cache file %s", "file"),
filename);
break;
- default:
+ default: {
+ char buf[128];
+ strerror_r(ret, buf, sizeof(buf));
krb5_set_error_message(context, ret,
N_("error locking cache file %s: %s",
- "file, error"),
- filename, strerror(ret));
+ "file, error"), filename, buf);
break;
}
+ }
return ret;
}
case EINVAL: /* filesystem doesn't support locking, let the user have it */
ret = 0;
break;
- default:
+ default: {
+ char buf[128];
+ strerror_r(ret, buf, sizeof(buf));
krb5_set_error_message(context, ret,
- N_("Failed to unlock file: %s", ""),
- strerror(ret));
+ N_("Failed to unlock file: %s", ""), buf);
break;
}
+ }
return ret;
}
int fd;
fd = open(filename, flags, mode);
if(fd < 0) {
+ char buf[128];
ret = errno;
+ strerror_r(ret, buf, sizeof(buf));
krb5_set_error_message(context, ret, N_("open(%s): %s", "file, error"),
- filename, strerror(ret));
+ filename, buf);
return ret;
}
rk_cloexec(fd);
fcc_unlock(context, fd);
if (close(fd) < 0)
if (ret == 0) {
+ char buf[128];
ret = errno;
+ strerror_r(ret, buf, sizeof(buf));
krb5_set_error_message (context, ret, N_("close %s: %s", ""),
- FILENAME(id), strerror(ret));
+ FILENAME(id), buf);
}
return ret;
}
fcc_unlock(context, fd);
if (close(fd) < 0) {
if (ret == 0) {
+ char buf[128];
+ strerror_r(ret, buf, sizeof(buf));
ret = errno;
krb5_set_error_message (context, ret, N_("close %s: %s", ""),
- FILENAME(id), strerror(ret));
+ FILENAME(id), buf);
}
}
return ret;
ret = rename(FILENAME(from), FILENAME(to));
if (ret && errno != EXDEV) {
+ char buf[128];
ret = errno;
+ strerror_r(ret, buf, sizeof(buf));
krb5_set_error_message(context, ret,
N_("Rename of file from %s "
"to %s failed: %s", ""),
- FILENAME(from), FILENAME(to),
- strerror(ret));
+ FILENAME(from), FILENAME(to), buf);
return ret;
} else if (ret && errno == EXDEV) {
/* make a copy and delete the orignal */
const krb5_keyblock *key,
uint32_t *seqno)
{
- krb5_error_code ret;
- krb5_keyblock *subkey;
- uint32_t q;
- u_char *p;
- int i;
-
- ret = krb5_generate_subkey (context, key, &subkey);
- if (ret)
- return ret;
-
- q = 0;
- for (p = (u_char *)subkey->keyvalue.data, i = 0;
- i < subkey->keyvalue.length;
- ++i, ++p)
- q = (q << 8) | *p;
- q &= 0xffffffff;
- *seqno = q;
- krb5_free_keyblock (context, subkey);
+ if (RAND_bytes((void *)seqno, sizeof(*seqno)) != 1)
+ krb5_abortx(context, "Failed to generate random block");
+ /* MIT used signed numbers, lets not stomp into that space directly */
+ *seqno &= 0x3fffffff;
+ if (*seqno == 0)
+ *seqno = 1;
return 0;
}
#include <krb5_locl.h>
-krb5_error_code KRB5_LIB_FUNCTION
-krb5_generate_subkey(krb5_context context,
- const krb5_keyblock *key,
- krb5_keyblock **subkey)
-{
- return krb5_generate_subkey_extended(context, key, key->keytype, subkey);
-}
+/**
+ * Generate subkey, from keyblock
+ *
+ * @param context kerberos context
+ * @param key session key
+ * @param etype encryption type of subkey, if ETYPE_NULL, use key's enctype
+ * @param subkey returned new, free with krb5_free_keyblock().
+ *
+ * @return 0 on success or a Kerberos 5 error code
+ *
+* @ingroup krb5_crypto
+ */
krb5_error_code KRB5_LIB_FUNCTION
krb5_generate_subkey_extended(krb5_context context,
*/
#include <krb5_locl.h>
+#include <assert.h>
/*
* Take the `body' and encode it into `padata' using the credentials
set_auth_data (krb5_context context,
KDC_REQ_BODY *req_body,
krb5_authdata *authdata,
- krb5_keyblock *key)
+ krb5_keyblock *subkey)
{
if(authdata->len) {
size_t len, buf_size;
N_("malloc: out of memory", ""));
return ENOMEM;
}
- ret = krb5_crypto_init(context, key, 0, &crypto);
+ ret = krb5_crypto_init(context, subkey, 0, &crypto);
if (ret) {
free (buf);
free (req_body->enc_authorization_data);
krb5_encrypt_EncryptedData(context,
crypto,
KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY,
- /* KRB5_KU_TGS_REQ_AUTH_DAT_SESSION? */
buf,
len,
0,
krb5_keyblock **subkey,
TGS_REQ *t)
{
+ krb5_auth_context ac = NULL;
krb5_error_code ret = 0;
+ krb5_keyblock *key = NULL;
memset(t, 0, sizeof(*t));
t->pvno = 5;
}
}
- {
- krb5_auth_context ac;
- krb5_keyblock *key = NULL;
-
- ret = krb5_auth_con_init(context, &ac);
- if(ret)
- goto fail;
-
- if (krb5_config_get_bool_default(context, NULL, FALSE,
- "realms",
- krbtgt->server->realm,
- "tgs_require_subkey",
- NULL))
- {
- ret = krb5_generate_subkey (context, &krbtgt->session, &key);
- if (ret) {
- krb5_auth_con_free (context, ac);
- goto fail;
- }
-
- ret = krb5_auth_con_setlocalsubkey(context, ac, key);
- if (ret) {
- if (key)
- krb5_free_keyblock (context, key);
- krb5_auth_con_free (context, ac);
- goto fail;
- }
- }
-
- ret = set_auth_data (context, &t->req_body, &in_creds->authdata,
- key ? key : &krbtgt->session);
- if (ret) {
- if (key)
- krb5_free_keyblock (context, key);
- krb5_auth_con_free (context, ac);
- goto fail;
- }
+ ret = krb5_auth_con_init(context, &ac);
+ if(ret)
+ goto fail;
+
+ ret = krb5_generate_subkey_extended(context, &krbtgt->session,
+ ETYPE_NULL, &key);
+ if (ret)
+ goto fail;
+
+ ret = krb5_auth_con_setlocalsubkey(context, ac, key);
+ if (ret)
+ goto fail;
+
+ ret = set_auth_data (context, &t->req_body, &in_creds->authdata, key);
+ if (ret)
+ goto fail;
+
+ ret = make_pa_tgs_req(context,
+ ac,
+ &t->req_body,
+ &t->padata->val[0],
+ krbtgt);
+ if(ret)
+ goto fail;
- ret = make_pa_tgs_req(context,
- ac,
- &t->req_body,
- &t->padata->val[0],
- krbtgt);
- if(ret) {
- if (key)
- krb5_free_keyblock (context, key);
- krb5_auth_con_free(context, ac);
- goto fail;
- }
- *subkey = key;
-
- krb5_auth_con_free(context, ac);
- }
+ *subkey = key;
+ key = NULL;
+
fail:
+ if (key)
+ krb5_free_keyblock (context, key);
+ if (ac)
+ krb5_auth_con_free(context, ac);
if (ret) {
t->req_body.addresses = NULL;
free_TGS_REQ (t);
size_t size;
krb5_crypto crypto;
- ret = krb5_crypto_init(context, key, 0, &crypto);
- if (ret)
- return ret;
- ret = krb5_decrypt_EncryptedData (context,
- crypto,
- usage,
- &dec_rep->kdc_rep.enc_part,
- &data);
- krb5_crypto_destroy(context, crypto);
- if(ret && subkey){
- /* DCE compat -- try to decrypt with subkey */
+ assert(usage == 0);
+
+ /*
+ * start out with trying with subkey if we have one
+ */
+ if (subkey) {
ret = krb5_crypto_init(context, subkey, 0, &crypto);
if (ret)
return ret;
&data);
krb5_crypto_destroy(context, crypto);
}
+ if (subkey == NULL || ret) {
+ ret = krb5_crypto_init(context, key, 0, &crypto);
+ if (ret)
+ return ret;
+ ret = krb5_decrypt_EncryptedData (context,
+ crypto,
+ KRB5_KU_TGS_REP_ENC_PART_SESSION,
+ &dec_rep->kdc_rep.enc_part,
+ &data);
+ krb5_crypto_destroy(context, crypto);
+ }
if (ret)
return ret;
out_creds,
&krbtgt->session,
NULL,
- KRB5_KU_TGS_REP_ENC_PART_SESSION,
+ 0,
&krbtgt->addresses,
nonce,
eflags,
free_METHOD_DATA(&padata);
krb5_data_free(&resp);
krb5_data_free(&enc);
- if(subkey){
- krb5_free_keyblock_contents(context, subkey);
- free(subkey);
- }
+ if(subkey)
+ krb5_free_keyblock(context, subkey);
return ret;
}
int loop = 0;
int ok_as_delegate = 1;
+ if (in_creds->server->name.name_string.len < 2 && !flags.b.canonicalize) {
+ krb5_set_error_message(context, KRB5KDC_ERR_PATH_NOT_ACCEPTED,
+ N_("Name too short to do referals, skipping", ""));
+ return KRB5KDC_ERR_PATH_NOT_ACCEPTED;
+ }
+
memset(&tgt, 0, sizeof(tgt));
memset(&ticket, 0, sizeof(ticket));
krb5_creds *res_creds;
int i;
+ if (in_creds->session.keytype) {
+ ret = krb5_enctype_valid(context, in_creds->session.keytype);
+ if (ret)
+ return ret;
+ }
+
*out_creds = NULL;
res_creds = calloc(1, sizeof(*res_creds));
if (res_creds == NULL) {
krb5_creds *res_creds;
int i;
+ if (opt && opt->enctype) {
+ ret = krb5_enctype_valid(context, opt->enctype);
+ if (ret)
+ return ret;
+ }
+
memset(&in_creds, 0, sizeof(in_creds));
in_creds.server = rk_UNCONST(inprinc);
if (ret)
return ret;
- options = opt->options;
+ if (opt)
+ options = opt->options;
+ else
+ options = 0;
flags.i = 0;
*out_creds = NULL;
return ENOMEM;
}
- if (opt->enctype) {
+ if (opt && opt->enctype) {
in_creds.session.keytype = opt->enctype;
options |= KRB5_TC_MATCH_KEYTYPE;
}
*/
ret = krb5_cc_retrieve_cred(context,
ccache,
- opt->enctype ? KRB5_TC_MATCH_KEYTYPE : 0,
+ options & KRB5_TC_MATCH_KEYTYPE,
&in_creds, res_creds);
/*
* If we got a credential, check if credential is expired before
memset (&creds, 0, sizeof(creds));
creds.client = client;
- ret = krb5_build_principal(context,
- &creds.server,
- strlen(client_realm),
- client_realm,
- KRB5_TGS_NAME,
- client_realm,
- NULL);
+ ret = krb5_make_principal(context,
+ &creds.server,
+ client_realm,
+ KRB5_TGS_NAME,
+ client_realm,
+ NULL);
if (ret)
return ret;
#include <door.h>
#endif
+#include <com_err.h>
+
#include <roken.h>
#include <parse_time.h>
#include <base64.h>
struct send_to_kdc;
/* XXX glue for pkinit */
+struct hx509_certs_data;
struct krb5_pk_identity;
struct krb5_pk_cert;
struct ContentInfo;
#define KRB5_CTX_F_CHECK_PAC 2
#define KRB5_CTX_F_HOMEDIR_ACCESS 4
struct send_to_kdc *send_to_kdc;
+#ifdef PKINIT
+ hx509_context hx509ctx;
+#endif
} krb5_context_data;
#define KRB5_DEFAULT_CCNAME_FILE "FILE:/tmp/krb5cc_%{uid}"
#ifdef PKINIT
struct krb5_pk_identity {
- hx509_context hx509ctx;
hx509_verify_ctx verify_ctx;
hx509_certs certs;
hx509_cert cert;
int *client_usec,
krb5_data *reply)
{
+ const char *e_text2 = NULL;
KRB_ERROR msg;
krb5_timestamp sec;
int32_t usec;
/* Make sure we only send `protocol' error codes */
if(error_code < KRB5KDC_ERR_NONE || error_code >= KRB5_ERR_RCSID) {
if(e_text == NULL)
- e_text = krb5_get_err_text(context, error_code);
+ e_text = e_text2 = krb5_get_error_message(context, error_code);
error_code = KRB5KRB_ERR_GENERIC;
}
msg.error_code = error_code - KRB5KDC_ERR_NONE;
}
ASN1_MALLOC_ENCODE(KRB_ERROR, reply->data, reply->length, &msg, &len, ret);
+ if (e_text2)
+ krb5_free_error_message(context, e_text2);
if (ret)
return ret;
if(reply->length != len)
if (ret)
goto out;
- ret = krb5_build_authenticator (context,
+ ret = _krb5_build_authenticator(context,
ac,
ac->keyblock->keytype,
in_creds,
c_opt,
- NULL,
&authenticator,
encrypt_usage);
if (c_opt)
unsigned int require_krbtgt_otherName:1;
unsigned int require_hostname_match:1;
unsigned int trustedCertifiers:1;
+ unsigned int anonymous:1;
};
static void
for (i = 0; i < sizeof(cf)/sizeof(cf[0]); i++) {
ret = hx509_query_match_eku(q, cf[i].oid);
if (ret) {
- pk_copy_error(context, id->hx509ctx, ret,
+ pk_copy_error(context, context->hx509ctx, ret,
"Failed setting %s OID", cf[i].type);
return ret;
}
- ret = hx509_certs_find(id->hx509ctx, id->certs, q, cert);
+ ret = hx509_certs_find(context->hx509ctx, id->certs, q, cert);
if (ret == 0)
break;
- pk_copy_error(context, id->hx509ctx, ret,
+ pk_copy_error(context, context->hx509ctx, ret,
"Failed finding certificate with %s OID", cf[i].type);
}
return ret;
if (id->cert == NULL)
flags |= HX509_CMS_SIGNATURE_NO_SIGNER;
- ret = hx509_cms_create_signed_1(id->hx509ctx,
+ ret = hx509_cms_create_signed_1(context->hx509ctx,
flags,
eContentType,
eContent->data,
id->certs,
sd_data);
if (ret) {
- pk_copy_error(context, id->hx509ctx, ret,
+ pk_copy_error(context, context->hx509ctx, ret,
"Create CMS signedData");
return ret;
}
if (a->supportedCMSTypes == NULL)
return ENOMEM;
- ret = hx509_crypto_available(ctx->id->hx509ctx, HX509_SELECT_ALL, NULL,
+ ret = hx509_crypto_available(context->hx509ctx, HX509_SELECT_ALL, NULL,
&a->supportedCMSTypes->val,
&a->supportedCMSTypes->len);
if (ret)
free_PA_PK_AS_REQ(&req);
goto out;
}
- ret = build_edi(context, ctx->id->hx509ctx,
+ ret = build_edi(context, context->hx509ctx,
ctx->id->anchors, req.trustedCertifiers);
if (ret) {
krb5_set_error_message(context, ret,
krb5_pk_init_ctx ctx = c;
int win2k_compat;
+ if (ctx->id->certs == NULL && ctx->anonymous == 0) {
+ krb5_set_error_message(context, HEIM_PKINIT_NO_PRIVATE_KEY,
+ N_("PKINIT: No user certificate given", ""));
+ return HEIM_PKINIT_NO_PRIVATE_KEY;
+ }
+
win2k_compat = krb5_config_get_bool_default(context, NULL,
FALSE,
"realms",
*signer = NULL;
- ret = hx509_cms_verify_signed(id->hx509ctx,
+ ret = hx509_cms_verify_signed(context->hx509ctx,
id->verify_ctx,
HX509_CMS_VS_ALLOW_DATA_OID_MISMATCH|HX509_CMS_VS_NO_KU_CHECK,
data,
content,
&signer_certs);
if (ret) {
- pk_copy_error(context, id->hx509ctx, ret,
+ pk_copy_error(context, context->hx509ctx, ret,
"CMS verify signed failed");
return ret;
}
goto out;
}
- ret = hx509_get_one_cert(id->hx509ctx, signer_certs, &(*signer)->cert);
+ ret = hx509_get_one_cert(context->hx509ctx, signer_certs, &(*signer)->cert);
if (ret) {
- pk_copy_error(context, id->hx509ctx, ret,
+ pk_copy_error(context, context->hx509ctx, ret,
"Failed to get on of the signer certs");
goto out;
}
krb5_error_code ret = 0;
if (ctx->require_eku) {
- ret = hx509_cert_check_eku(ctx->id->hx509ctx, host->cert,
+ ret = hx509_cert_check_eku(context->hx509ctx, host->cert,
&asn1_oid_id_pkkdcekuoid, 0);
if (ret) {
krb5_set_error_message(context, ret,
hx509_octet_string_list list;
int i;
- ret = hx509_cert_find_subjectAltName_otherName(ctx->id->hx509ctx,
+ ret = hx509_cert_find_subjectAltName_otherName(context->hx509ctx,
host->cert,
&asn1_oid_id_pkinit_san,
&list);
return ret;
if (hi) {
- ret = hx509_verify_hostname(ctx->id->hx509ctx, host->cert,
+ ret = hx509_verify_hostname(context->hx509ctx, host->cert,
ctx->require_hostname_match,
HX509_HN_HOSTNAME,
hi->hostname,
if (ctx->type == PKINIT_WIN2K)
flags |= HX509_CMS_UE_ALLOW_WEAK;
- ret = hx509_cms_unenvelope(ctx->id->hx509ctx,
+ ret = hx509_cms_unenvelope(context->hx509ctx,
ctx->id->certs,
flags,
indata->data,
&contentType,
&content);
if (ret) {
- pk_copy_error(context, ctx->id->hx509ctx, ret,
+ pk_copy_error(context, context->hx509ctx, ret,
"Failed to unenvelope CMS data in PK-INIT reply");
return ret;
}
heim_octet_string out;
ret = hx509_cms_unwrap_ContentInfo(&content, &type, &out, NULL);
- if (ret)
- goto out;
+ if (ret) {
+ /* windows LH with interesting CMS packets */
+ size_t ph = 1 + der_length_len(content.length);
+ unsigned char *ptr = malloc(content.length + ph);
+ size_t l;
+
+ memcpy(ptr + ph, content.data, content.length);
+
+ ret = der_put_length_and_tag (ptr + ph - 1, ph, content.length,
+ ASN1_C_UNIV, CONS, UT_Sequence, &l);
+ if (ret)
+ return ret;
+ free(content.data);
+ content.data = ptr;
+ content.length += ph;
+
+ ret = hx509_cms_unwrap_ContentInfo(&content, &type, &out, NULL);
+ if (ret)
+ goto out;
+ }
if (der_heim_oid_cmp(&type, &asn1_oid_id_pkcs7_signedData)) {
ret = EINVAL; /* XXX */
krb5_set_error_message(context, ret,
return 0;
}
+static krb5_error_code
+_krb5_pk_set_user_id(krb5_context context,
+ krb5_pk_init_ctx ctx,
+ struct hx509_certs_data *certs)
+{
+ hx509_certs c = hx509_certs_ref(certs);
+ hx509_query *q = NULL;
+ int ret;
+
+ if (ctx->id->certs)
+ hx509_certs_free(&ctx->id->certs);
+ if (ctx->id->cert) {
+ hx509_cert_free(ctx->id->cert);
+ ctx->id->cert = NULL;
+ }
+
+ ctx->id->certs = c;
+ ctx->anonymous = 0;
+
+ ret = hx509_query_alloc(context->hx509ctx, &q);
+ if (ret) {
+ pk_copy_error(context, context->hx509ctx, ret,
+ "Allocate query to find signing certificate");
+ return ret;
+ }
+
+ hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY);
+ hx509_query_match_option(q, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE);
+
+ ret = find_cert(context, ctx->id, q, &ctx->id->cert);
+ hx509_query_free(context->hx509ctx, q);
+
+ return ret;
+}
+
krb5_error_code KRB5_LIB_FUNCTION
_krb5_pk_load_id(krb5_context context,
struct krb5_pk_identity **ret_id,
- int flags,
const char *user_id,
const char *anchor_id,
char * const *chain_list,
char *password)
{
struct krb5_pk_identity *id = NULL;
- hx509_lock lock = NULL;
struct prompter p;
int ret;
return HEIM_PKINIT_NO_VALID_CA;
}
- if (user_id == NULL && (flags & 4) == 0) {
- krb5_set_error_message(context, HEIM_PKINIT_NO_PRIVATE_KEY,
- N_("PKINIT: No user certificate given", ""));
- return HEIM_PKINIT_NO_PRIVATE_KEY;
- }
-
/* load cert */
id = calloc(1, sizeof(*id));
return ENOMEM;
}
- ret = hx509_context_init(&id->hx509ctx);
- if (ret)
- goto out;
-
- ret = hx509_lock_init(id->hx509ctx, &lock);
- if (ret) {
- pk_copy_error(context, id->hx509ctx, ret, "Failed init lock");
- goto out;
- }
-
- if (password && password[0])
- hx509_lock_add_password(lock, password);
-
- if (prompter) {
- p.context = context;
- p.prompter = prompter;
- p.prompter_data = prompter_data;
+ if (user_id) {
+ hx509_lock lock;
- ret = hx509_lock_set_prompter(lock, hx_pass_prompter, &p);
- if (ret)
+ ret = hx509_lock_init(context->hx509ctx, &lock);
+ if (ret) {
+ pk_copy_error(context, context->hx509ctx, ret, "Failed init lock");
goto out;
- }
+ }
+
+ if (password && password[0])
+ hx509_lock_add_password(lock, password);
+
+ if (prompter) {
+ p.context = context;
+ p.prompter = prompter;
+ p.prompter_data = prompter_data;
+
+ ret = hx509_lock_set_prompter(lock, hx_pass_prompter, &p);
+ if (ret) {
+ hx509_lock_free(lock);
+ goto out;
+ }
+ }
- if (user_id) {
- ret = hx509_certs_init(id->hx509ctx, user_id, 0, lock, &id->certs);
+ ret = hx509_certs_init(context->hx509ctx, user_id, 0, lock, &id->certs);
+ hx509_lock_free(lock);
if (ret) {
- pk_copy_error(context, id->hx509ctx, ret,
+ pk_copy_error(context, context->hx509ctx, ret,
"Failed to init cert certs");
goto out;
}
id->certs = NULL;
}
- ret = hx509_certs_init(id->hx509ctx, anchor_id, 0, NULL, &id->anchors);
+ ret = hx509_certs_init(context->hx509ctx, anchor_id, 0, NULL, &id->anchors);
if (ret) {
- pk_copy_error(context, id->hx509ctx, ret,
+ pk_copy_error(context, context->hx509ctx, ret,
"Failed to init anchors");
goto out;
}
- ret = hx509_certs_init(id->hx509ctx, "MEMORY:pkinit-cert-chain",
+ ret = hx509_certs_init(context->hx509ctx, "MEMORY:pkinit-cert-chain",
0, NULL, &id->certpool);
if (ret) {
- pk_copy_error(context, id->hx509ctx, ret,
+ pk_copy_error(context, context->hx509ctx, ret,
"Failed to init chain");
goto out;
}
while (chain_list && *chain_list) {
- ret = hx509_certs_append(id->hx509ctx, id->certpool,
+ ret = hx509_certs_append(context->hx509ctx, id->certpool,
NULL, *chain_list);
if (ret) {
- pk_copy_error(context, id->hx509ctx, ret,
+ pk_copy_error(context, context->hx509ctx, ret,
"Failed to laod chain %s",
*chain_list);
goto out;
}
if (revoke_list) {
- ret = hx509_revoke_init(id->hx509ctx, &id->revokectx);
+ ret = hx509_revoke_init(context->hx509ctx, &id->revokectx);
if (ret) {
- pk_copy_error(context, id->hx509ctx, ret,
+ pk_copy_error(context, context->hx509ctx, ret,
"Failed init revoke list");
goto out;
}
while (*revoke_list) {
- ret = hx509_revoke_add_crl(id->hx509ctx,
+ ret = hx509_revoke_add_crl(context->hx509ctx,
id->revokectx,
*revoke_list);
if (ret) {
- pk_copy_error(context, id->hx509ctx, ret,
+ pk_copy_error(context, context->hx509ctx, ret,
"Failed load revoke list");
goto out;
}
revoke_list++;
}
} else
- hx509_context_set_missing_revoke(id->hx509ctx, 1);
+ hx509_context_set_missing_revoke(context->hx509ctx, 1);
- ret = hx509_verify_init_ctx(id->hx509ctx, &id->verify_ctx);
+ ret = hx509_verify_init_ctx(context->hx509ctx, &id->verify_ctx);
if (ret) {
- pk_copy_error(context, id->hx509ctx, ret,
+ pk_copy_error(context, context->hx509ctx, ret,
"Failed init verify context");
goto out;
}
hx509_certs_free(&id->anchors);
hx509_certs_free(&id->certpool);
hx509_revoke_free(&id->revokectx);
- hx509_context_free(&id->hx509ctx);
+ hx509_context_free(&context->hx509ctx);
free(id);
} else
*ret_id = id;
- if (lock)
- hx509_lock_free(lock);
-
return ret;
}
hx509_cert_free(ctx->id->cert);
hx509_certs_free(&ctx->id->anchors);
hx509_certs_free(&ctx->id->certpool);
- hx509_context_free(&ctx->id->hx509ctx);
if (ctx->clientDHNonce) {
krb5_free_data(NULL, ctx->clientDHNonce);
x509_anchors = anchors;
}
+ if (flags & 4)
+ opt->opt_private->pk_init_ctx->anonymous = 1;
+
ret = _krb5_pk_load_id(context,
&opt->opt_private->pk_init_ctx->id,
- flags,
user_id,
x509_anchors,
pool,
}
if (opt->opt_private->pk_init_ctx->id->certs) {
- hx509_query *q = NULL;
- hx509_cert cert = NULL;
- hx509_context hx509ctx = opt->opt_private->pk_init_ctx->id->hx509ctx;
-
- ret = hx509_query_alloc(hx509ctx, &q);
- if (ret) {
- pk_copy_error(context, hx509ctx, ret,
- "Allocate query to find signing certificate");
- return ret;
- }
-
- hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY);
- hx509_query_match_option(q, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE);
-
- ret = find_cert(context, opt->opt_private->pk_init_ctx->id, q, &cert);
- hx509_query_free(hx509ctx, q);
- if (ret)
- return ret;
-
- opt->opt_private->pk_init_ctx->id->cert = cert;
+ _krb5_pk_set_user_id(context,
+ opt->opt_private->pk_init_ctx,
+ opt->opt_private->pk_init_ctx->id->certs);
} else
opt->opt_private->pk_init_ctx->id->cert = NULL;
if ((flags & 2) == 0) {
- hx509_context hx509ctx = opt->opt_private->pk_init_ctx->id->hx509ctx;
+ hx509_context hx509ctx = context->hx509ctx;
hx509_cert cert = opt->opt_private->pk_init_ctx->id->cert;
opt->opt_private->pk_init_ctx->keyex = USE_DH;
#endif
}
+krb5_error_code KRB5_LIB_FUNCTION
+_krb5_get_init_creds_opt_set_pkinit_user_certs(krb5_context context,
+ krb5_get_init_creds_opt *opt,
+ struct hx509_certs_data *certs)
+{
+#ifdef PKINIT
+ if (opt->opt_private == NULL) {
+ krb5_set_error_message(context, EINVAL,
+ N_("PKINIT: on non extendable opt", ""));
+ return EINVAL;
+ }
+ if (opt->opt_private->pk_init_ctx == NULL) {
+ krb5_set_error_message(context, EINVAL,
+ N_("PKINIT: on pkinit context", ""));
+ return EINVAL;
+ }
+
+ _krb5_pk_set_user_id(context, opt->opt_private->pk_init_ctx, certs);
+
+ return 0;
+#else
+ krb5_set_error_message(context, EINVAL,
+ N_("no support for PKINIT compiled in", ""));
+ return EINVAL;
+#endif
+}
+
#ifdef PKINIT
static int
_krb5_pk_enterprise_cert(krb5_context context,
const char *user_id,
krb5_const_realm realm,
- krb5_principal *principal)
+ krb5_principal *principal,
+ struct hx509_certs_data **res)
{
#ifdef PKINIT
krb5_error_code ret;
- hx509_context hx509ctx;
hx509_certs certs, result;
hx509_cert cert;
hx509_query *q;
char *name;
*principal = NULL;
+ if (res)
+ *res = NULL;
- if (user_id == NULL)
+ if (user_id == NULL) {
+ krb5_clear_error_message(context);
return ENOENT;
+ }
- ret = hx509_context_init(&hx509ctx);
- if (ret)
- return ret;
-
- ret = hx509_certs_init(hx509ctx, user_id, 0, NULL, &certs);
+ ret = hx509_certs_init(context->hx509ctx, user_id, 0, NULL, &certs);
if (ret) {
- pk_copy_error(context, hx509ctx, ret,
+ pk_copy_error(context, context->hx509ctx, ret,
"Failed to init cert certs");
return ret;
}
- ret = hx509_query_alloc(hx509ctx, &q);
+ ret = hx509_query_alloc(context->hx509ctx, &q);
if (ret) {
+ krb5_set_error_message(context, ret, "out of memory");
hx509_certs_free(&certs);
return ret;
}
hx509_query_match_eku(q, &asn1_oid_id_pkinit_ms_eku);
hx509_query_match_cmp_func(q, find_ms_san, NULL);
- ret = hx509_certs_filter(hx509ctx, certs, q, &result);
- hx509_query_free(hx509ctx, q);
+ ret = hx509_certs_filter(context->hx509ctx, certs, q, &result);
+ hx509_query_free(context->hx509ctx, q);
hx509_certs_free(&certs);
- if (ret)
+ if (ret) {
+ pk_copy_error(context, context->hx509ctx, ret,
+ "Failed to find PKINIT certificate");
return ret;
+ }
- ret = hx509_get_one_cert(hx509ctx, result, &cert);
+ ret = hx509_get_one_cert(context->hx509ctx, result, &cert);
hx509_certs_free(&result);
- if (ret)
- return ret;
+ if (ret) {
+ pk_copy_error(context, context->hx509ctx, ret,
+ "Failed to get one cert");
+ goto out;
+ }
- ret = get_ms_san(hx509ctx, cert, &name);
- if (ret)
- return ret;
+ ret = get_ms_san(context->hx509ctx, cert, &name);
+ if (ret) {
+ pk_copy_error(context, context->hx509ctx, ret,
+ "Failed to get MS SAN");
+ goto out;
+ }
ret = krb5_make_principal(context, principal, realm, name, NULL);
free(name);
- hx509_context_free(&hx509ctx);
if (ret)
- return ret;
+ goto out;
krb5_principal_set_type(context, *principal, KRB5_NT_ENTERPRISE_PRINCIPAL);
-
+
+ if (res) {
+ ret = hx509_certs_init(context->hx509ctx, "MEMORY:", 0, NULL, res);
+ if (ret) {
+ hx509_cert_free(cert);
+ goto out;
+ }
+
+ ret = hx509_certs_add(context->hx509ctx, *res, cert);
+ if (ret) {
+ hx509_certs_free(res);
+ goto out;
+ }
+ }
+
+ out:
+ hx509_cert_free(cert);
+
return ret;
#else
krb5_set_error_message(context, EINVAL,
princ_type(principal) = type;
}
+/**
+ * Get the type of the principal
+ *
+ * @param context A Kerberos context.
+ * @param principal principal to get the type for
+ *
+ * @return the type of principal
+ *
+ * @ingroup krb5_principal
+ */
+
int KRB5_LIB_FUNCTION
krb5_principal_get_type(krb5_context context,
krb5_const_principal principal)
return princ_type(principal);
}
+/**
+ * Get the realm of the principal
+ *
+ * @param context A Kerberos context.
+ * @param principal principal to get the realm for
+ *
+ * @return realm of the principal, don't free or use after krb5_principal is freed
+ *
+ * @ingroup krb5_principal
+ */
+
const char* KRB5_LIB_FUNCTION
krb5_principal_get_realm(krb5_context context,
krb5_const_principal principal)
return princ_num_comp(principal);
}
+/**
+ * Parse a name into a krb5_principal structure, flags controls the behavior.
+ *
+ * @param context Kerberos 5 context
+ * @param name name to parse into a Kerberos principal
+ * @param flags flags to control the behavior
+ * @param principal returned principal, free with krb5_free_principal().
+ *
+ * @return An krb5 error code, see krb5_get_error_message().
+ *
+ * @ingroup krb5_principal
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_parse_name_flags(krb5_context context,
const char *name,
return ret;
}
+/**
+ * Parse a name into a krb5_principal structure
+ *
+ * @param context Kerberos 5 context
+ * @param name name to parse into a Kerberos principal
+ * @param principal returned principal, free with krb5_free_principal().
+ *
+ * @return An krb5 error code, see krb5_get_error_message().
+ *
+ * @ingroup krb5_principal
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_parse_name(krb5_context context,
const char *name,
return 0;
}
+#ifndef HEIMDAL_SMALLER
+/**
+ * Build a principal using vararg style building
+ *
+ * @param context A Kerberos context.
+ * @param principal returned principal
+ * @param rlen length of realm
+ * @param realm realm name
+ * @param ... a list of components ended with NULL.
+ *
+ * @return An krb5 error code, see krb5_get_error_message().
+ *
+ * @ingroup krb5_principal
+ */
krb5_error_code KRB5_LIB_FUNCTION
krb5_build_principal(krb5_context context,
va_end(ap);
return ret;
}
+#endif
+
+/**
+ * Build a principal using vararg style building
+ *
+ * @param context A Kerberos context.
+ * @param principal returned principal
+ * @param realm realm name
+ * @param ... a list of components ended with NULL.
+ *
+ * @return An krb5 error code, see krb5_get_error_message().
+ *
+ * @ingroup krb5_principal
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_make_principal(krb5_context context,
+ krb5_principal *principal,
+ krb5_const_realm realm,
+ ...)
+{
+ krb5_error_code ret;
+ krb5_realm r = NULL;
+ va_list ap;
+ if(realm == NULL) {
+ ret = krb5_get_default_realm(context, &r);
+ if(ret)
+ return ret;
+ realm = r;
+ }
+ va_start(ap, realm);
+ ret = krb5_build_principal_va(context, principal, strlen(realm), realm, ap);
+ va_end(ap);
+ if(r)
+ free(r);
+ return ret;
+}
static krb5_error_code
append_component(krb5_context context, krb5_principal p,
return 0;
}
-krb5_error_code KRB5_LIB_FUNCTION
-krb5_make_principal(krb5_context context,
- krb5_principal *principal,
- krb5_const_realm realm,
- ...)
-{
- krb5_error_code ret;
- krb5_realm r = NULL;
- va_list ap;
- if(realm == NULL) {
- ret = krb5_get_default_realm(context, &r);
- if(ret)
- return ret;
- realm = r;
- }
- va_start(ap, realm);
- ret = krb5_build_principal_va(context, principal, strlen(realm), realm, ap);
- va_end(ap);
- if(r)
- free(r);
- return ret;
-}
krb5_error_code KRB5_LIB_FUNCTION
krb5_build_principal_va(krb5_context context,
return ret;
}
+/**
+ * Copy a principal
+ *
+ * @param context A Kerberos context.
+ * @param inprinc principal to copy
+ * @param outprinc copied principal, free with krb5_free_principal()
+ *
+ * @return An krb5 error code, see krb5_get_error_message().
+ *
+ * @ingroup krb5_principal
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_copy_principal(krb5_context context,
* @return non zero if equal, 0 if not
*
* @ingroup krb5_principal
+ * @see krb5_principal_compare()
+ * @see krb5_realm_compare()
*/
krb5_boolean KRB5_LIB_FUNCTION
}
+/**
+ * Compares the two principals, including realm of the principals and returns
+ * TRUE if they are the same and FALSE if not.
+ *
+ * @param context Kerberos 5 context
+ * @param princ1 first principal to compare
+ * @param princ2 second principal to compare
+ *
+ * @ingroup krb5_principal
+ * @see krb5_principal_compare_any_realm()
+ * @see krb5_realm_compare()
+ */
+
/*
* return TRUE iff princ1 == princ2
*/
return krb5_principal_compare_any_realm(context, princ1, princ2);
}
-/*
+/**
* return TRUE iff realm(princ1) == realm(princ2)
+ *
+ * @param context Kerberos 5 context
+ * @param princ1 first principal to compare
+ * @param princ2 second principal to compare
+ *
+ * @ingroup krb5_principal
+ * @see krb5_principal_compare_any_realm()
+ * @see krb5_principal_compare()
*/
krb5_boolean KRB5_LIB_FUNCTION
return strcmp(princ_realm(princ1), princ_realm(princ2)) == 0;
}
-/*
+/**
* return TRUE iff princ matches pattern
+ *
+ * @ingroup krb5_principal
*/
krb5_boolean KRB5_LIB_FUNCTION
{ NULL }
};
+/**
+ * Parse nametype string and return a nametype integer
+ *
+ * @ingroup krb5_principal
+ */
+
krb5_error_code
krb5_parse_nametype(krb5_context context, const char *str, int32_t *nametype)
{
int ret;
if(f == NULL) {
+ char buf[128];
ret = errno;
- krb5_set_error_message(context, ret, "open(%s): %s", id->name,
- strerror(ret));
+ strerror_r(ret, buf, sizeof(buf));
+ krb5_set_error_message(context, ret, "open(%s): %s", id->name, buf);
return ret;
}
tmp.stamp = auth_lifespan;
int ret;
if(remove(id->name) < 0) {
+ char buf[128];
ret = errno;
- krb5_set_error_message(context, ret, "remove(%s): %s", id->name,
- strerror(ret));
+ strerror_r(ret, buf, sizeof(buf));
+ krb5_set_error_message(context, ret, "remove(%s): %s", id->name, buf);
return ret;
}
return krb5_rc_close(context, id);
checksum_authenticator(rep, ent.data);
f = fopen(id->name, "r");
if(f == NULL) {
+ char buf[128];
ret = errno;
- krb5_set_error_message(context, ret, "open(%s): %s", id->name,
- strerror(ret));
+ strerror_r(ret, buf, sizeof(buf));
+ krb5_set_error_message(context, ret, "open(%s): %s", id->name, buf);
return ret;
}
rk_cloexec_file(f);
}
}
if(ferror(f)){
+ char buf[128];
ret = errno;
fclose(f);
+ strerror_r(ret, buf, sizeof(buf));
krb5_set_error_message(context, ret, "%s: %s",
- id->name, strerror(ret));
+ id->name, buf);
return ret;
}
fclose(f);
f = fopen(id->name, "a");
if(f == NULL) {
+ char buf[128];
+ strerror_r(errno, buf, sizeof(buf));
krb5_set_error_message(context, KRB5_RC_IO_UNKNOWN,
- "open(%s): %s", id->name,
- strerror(errno));
+ "open(%s): %s", id->name, buf);
return KRB5_RC_IO_UNKNOWN;
}
fwrite(&ent, 1, sizeof(ent), f);
*arg++ = msg;
}
if(context && do_errtext){
- const char *err_msg;
-
strlcat(xfmt, "%s", sizeof(xfmt));
err_str = krb5_get_error_message(context, code);
if (err_str != NULL) {
*arg = err_str;
} else {
- err_msg = krb5_get_err_text(context, code);
- if (err_msg)
- *arg = err_msg;
- else
- *arg= "<unknown error>";
+ *arg= "<unknown error>";
}
}
static void
open_pty(void)
{
+#ifdef _AIX
+ printf("implement open_pty\n");
+ exit(77);
+#endif
#if defined(HAVE_OPENPTY) || defined(__linux) || defined(__osf__) /* XXX */
if(openpty(&master, &slave, line, 0, 0) == 0)
return;
char * ROKEN_LIB_FUNCTION strerror(int);
#endif
+#if !defined(HAVE_STRERROR) && !defined(strerror)
+#define strerror_r rk_strerror_r
+int ROKEN_LIB_FUNCTION strerror_r(int, char *, size_t);
+#endif
+
+
#if !defined(HAVE_HSTRERROR) || defined(NEED_HSTRERROR_PROTO)
#ifndef HAVE_HSTRERROR
#define hstrerror rk_hstrerror
int rk_flock(int fd, int operation);
#endif /* HAVE_FLOCK */
-#ifdef SunOS
+#if defined(SunOS) || defined(_AIX)
#define dirfd(x) ((x)->dd_fd)
#endif
rk_timegm(struct tm *tm);
#endif
+#ifdef NEED_QSORT
+#define qsort rk_qsort
+void
+rk_qsort(void *, size_t, size_t, int (*)(const void *, const void *));
+#endif
+
#ifdef SOCKET_WRAPPER_REPLACE
#include <socket_wrapper.h>
#endif
#include <assert.h>
#include <stdlib.h>
#include <errno.h>
+#include <stdio.h>
+
+#include "roken.h"
#include "normalize_table.h"
static void
canonical_reorder(uint32_t *tmp, size_t tmp_len)
{
- unsigned i;
+ size_t i;
for (i = 0; i < tmp_len; ++i) {
int cc = _wind_combining_class(tmp[i]);
j < tmp_len && _wind_combining_class(tmp[j]);
++j)
;
- qsort(&tmp[i], j - i, sizeof(unsigned),
- cc_cmp);
+ qsort(&tmp[i], j - i, sizeof(tmp[0]), cc_cmp);
i = j;
}
}
uint32_t *tmp;
int ret;
+ if (in_len == 0) {
+ *out_len = 0;
+ return 0;
+ }
+
tmp_len = in_len * 4;
if (tmp_len < MAX_LENGTH_CANON)
tmp_len = MAX_LENGTH_CANON;
wind_profile_flags flags)
{
size_t tmp_len = in_len * 3;
- uint32_t *tmp = malloc(tmp_len * sizeof(uint32_t));
+ uint32_t *tmp;
int ret;
size_t olen;
+ if (in_len == 0) {
+ *out_len = 0;
+ return 0;
+ }
+
+ tmp = malloc(tmp_len * sizeof(uint32_t));
if (tmp == NULL)
return ENOMEM;