diff options
Diffstat (limited to 'source4/heimdal')
59 files changed, 1168 insertions, 646 deletions
diff --git a/source4/heimdal/README b/source4/heimdal/README index f130698597..d2c4eba8ce 100644 --- a/source4/heimdal/README +++ b/source4/heimdal/README @@ -1,12 +1,12 @@ 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: diff --git a/source4/heimdal/kdc/kerberos5.c b/source4/heimdal/kdc/kerberos5.c index 0a9d4a5ca4..fb88aa9f8f 100644 --- a/source4/heimdal/kdc/kerberos5.c +++ b/source4/heimdal/kdc/kerberos5.c @@ -261,6 +261,7 @@ _kdc_encode_reply(krb5_context context, 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) { @@ -272,8 +273,9 @@ _kdc_encode_reply(krb5_context context, 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) { @@ -286,8 +288,9 @@ _kdc_encode_reply(krb5_context context, 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; } @@ -301,8 +304,9 @@ _kdc_encode_reply(krb5_context context, 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; } @@ -311,8 +315,9 @@ _kdc_encode_reply(krb5_context context, 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) { @@ -323,9 +328,10 @@ _kdc_encode_reply(krb5_context context, } 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) { @@ -341,7 +347,7 @@ _kdc_encode_reply(krb5_context context, } 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, @@ -351,8 +357,9 @@ _kdc_encode_reply(krb5_context context, } 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) { @@ -980,8 +987,9 @@ _kdc_as_rep(krb5_context context, 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; } @@ -990,8 +998,9 @@ _kdc_as_rep(krb5_context context, 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; } @@ -1135,8 +1144,9 @@ _kdc_as_rep(krb5_context context, 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; } @@ -1154,6 +1164,8 @@ _kdc_as_rep(krb5_context context, */ 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) @@ -1161,9 +1173,8 @@ _kdc_as_rep(krb5_context context, 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, @@ -1757,7 +1768,7 @@ _kdc_as_rep(krb5_context context, 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) diff --git a/source4/heimdal/kdc/krb5tgs.c b/source4/heimdal/kdc/krb5tgs.c index c3b0aaa89e..4f587cf1b6 100644 --- a/source4/heimdal/kdc/krb5tgs.c +++ b/source4/heimdal/kdc/krb5tgs.c @@ -671,6 +671,8 @@ tgs_make_reply(krb5_context context, 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, @@ -823,10 +825,14 @@ tgs_make_reply(krb5_context context, 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]); @@ -927,7 +933,8 @@ tgs_make_reply(krb5_context context, 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); @@ -988,8 +995,9 @@ tgs_check_authenticator(krb5_context context, /* 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) { @@ -1001,9 +1009,10 @@ tgs_check_authenticator(krb5_context context, } 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, @@ -1015,9 +1024,10 @@ tgs_check_authenticator(krb5_context 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); @@ -1077,7 +1087,9 @@ tgs_parse_request(krb5_context context, 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; @@ -1087,16 +1099,20 @@ tgs_parse_request(krb5_context context, 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; } @@ -1115,14 +1131,15 @@ tgs_parse_request(krb5_context context, 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; @@ -1184,8 +1201,9 @@ tgs_parse_request(krb5_context context, 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; } @@ -1219,41 +1237,49 @@ tgs_parse_request(krb5_context context, 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, @@ -1377,6 +1403,8 @@ tgs_build_reply(krb5_context 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, @@ -1495,7 +1523,7 @@ server_lookup: NULL, &server); if(ret){ - const char *new_rlm; + const char *new_rlm, *msg; Realm req_rlm; krb5_realm *realms; @@ -1543,9 +1571,10 @@ server_lookup: } 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; @@ -1554,7 +1583,7 @@ server_lookup: 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 @@ -1574,8 +1603,9 @@ server_lookup: 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); } /* @@ -1656,9 +1686,11 @@ server_lookup: 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; } @@ -1671,9 +1703,11 @@ server_lookup: &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; } @@ -1709,10 +1743,11 @@ server_lookup: 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; } @@ -1725,10 +1760,11 @@ server_lookup: 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; } @@ -1866,11 +1902,13 @@ server_lookup: 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; } @@ -1950,6 +1988,8 @@ server_lookup: b, client_principal, tgt, + replykey, + rk_is_subkey, ekey, &sessionkey, kvno, @@ -2016,6 +2056,8 @@ _kdc_tgs_rep(krb5_context context, 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; @@ -2043,7 +2085,9 @@ _kdc_tgs_rep(krb5_context context, &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); @@ -2056,6 +2100,8 @@ _kdc_tgs_rep(krb5_context context, &req->req_body, krbtgt, krbtgt_etype, + replykey, + rk_is_subkey, ticket, data, from, @@ -2076,6 +2122,8 @@ _kdc_tgs_rep(krb5_context context, } out: + if (replykey) + krb5_free_keyblock(context, replykey); if(ret && data->data == NULL){ krb5_mk_error(context, ret, diff --git a/source4/heimdal/kdc/kx509.c b/source4/heimdal/kdc/kx509.c index 8f7f3a27fb..eb757bb578 100644 --- a/source4/heimdal/kdc/kx509.c +++ b/source4/heimdal/kdc/kx509.c @@ -143,7 +143,6 @@ build_certificate(krb5_context context, krb5_principal principal, krb5_data *certificate) { - hx509_context hxctx = NULL; hx509_ca_tbs tbs = NULL; hx509_env env = NULL; hx509_cert cert = NULL; @@ -155,11 +154,7 @@ build_certificate(krb5_context context, 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; @@ -168,14 +163,14 @@ build_certificate(krb5_context context, 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; @@ -184,8 +179,8 @@ build_certificate(krb5_context context, 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", @@ -194,7 +189,7 @@ build_certificate(krb5_context context, } } - ret = hx509_ca_tbs_init(hxctx, &tbs); + ret = hx509_ca_tbs_init(context->hx509ctx, &tbs); if (ret) goto out; @@ -214,7 +209,7 @@ build_certificate(krb5_context context, 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; @@ -224,21 +219,21 @@ build_certificate(krb5_context context, 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, @@ -248,25 +243,23 @@ build_certificate(krb5_context context, 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) @@ -275,8 +268,6 @@ out: 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; } diff --git a/source4/heimdal/kdc/misc.c b/source4/heimdal/kdc/misc.c index e016183615..9a3f254640 100644 --- a/source4/heimdal/kdc/misc.c +++ b/source4/heimdal/kdc/misc.c @@ -80,8 +80,9 @@ _kdc_db_fetch(krb5_context context, 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; } diff --git a/source4/heimdal/kdc/pkinit.c b/source4/heimdal/kdc/pkinit.c index 0d00ef2173..7bb32eb577 100644 --- a/source4/heimdal/kdc/pkinit.c +++ b/source4/heimdal/kdc/pkinit.c @@ -517,7 +517,7 @@ _kdc_pk_rd_padata(krb5_context context, goto out; } - ret = hx509_certs_init(kdc_identity->hx509ctx, + ret = hx509_certs_init(context->hx509ctx, "MEMORY:trust-anchors", 0, NULL, &trust_anchors); if (ret) { @@ -525,7 +525,7 @@ _kdc_pk_rd_padata(krb5_context context, 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); @@ -540,18 +540,18 @@ _kdc_pk_rd_padata(krb5_context context, 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"); @@ -618,7 +618,7 @@ _kdc_pk_rd_padata(krb5_context 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); @@ -645,7 +645,7 @@ _kdc_pk_rd_padata(krb5_context context, 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"); @@ -657,24 +657,24 @@ _kdc_pk_rd_padata(krb5_context context, &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); } @@ -719,7 +719,7 @@ _kdc_pk_rd_padata(krb5_context context, 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, @@ -730,7 +730,7 @@ _kdc_pk_rd_padata(krb5_context context, &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); @@ -738,7 +738,7 @@ _kdc_pk_rd_padata(krb5_context context, } 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); } @@ -843,7 +843,7 @@ _kdc_pk_rd_padata(krb5_context context, } 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); @@ -851,7 +851,7 @@ _kdc_pk_rd_padata(krb5_context context, } 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); @@ -861,11 +861,11 @@ _kdc_pk_rd_padata(krb5_context context, } } 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); @@ -1016,7 +1016,7 @@ pk_mk_pa_reply_enckey(krb5_context context, 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; @@ -1024,15 +1024,15 @@ pk_mk_pa_reply_enckey(krb5_context context, 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, @@ -1060,7 +1060,7 @@ pk_mk_pa_reply_enckey(krb5_context context, 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, @@ -1172,7 +1172,7 @@ pk_mk_pa_reply_dh(krb5_context context, * filled in above */ - ret = hx509_query_alloc(kdc_identity->hx509ctx, &q); + ret = hx509_query_alloc(context->hx509ctx, &q); if (ret) goto out; @@ -1180,15 +1180,15 @@ pk_mk_pa_reply_dh(krb5_context context, 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, @@ -1509,7 +1509,7 @@ _kdc_pk_mk_pa_reply(krb5_context context, goto out_ocsp; } - ret = hx509_ocsp_verify(kdc_identity->hx509ctx, + ret = hx509_ocsp_verify(context->hx509ctx, kdc_time, kdc_cert, 0, @@ -1580,9 +1580,10 @@ match_rfc_san(krb5_context context, 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) { @@ -1644,6 +1645,12 @@ match_ms_upn_san(krb5_context context, 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); @@ -1697,7 +1704,7 @@ _kdc_pk_check_client(krb5_context context, return 0; } - ret = hx509_cert_get_base_subject(kdc_identity->hx509ctx, + ret = hx509_cert_get_base_subject(context->hx509ctx, cp->cert, &name); if (ret) @@ -1718,7 +1725,7 @@ _kdc_pk_check_client(krb5_context context, 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); @@ -1737,7 +1744,7 @@ _kdc_pk_check_client(krb5_context context, 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) { @@ -1746,7 +1753,7 @@ _kdc_pk_check_client(krb5_context context, return 0; } ret = match_ms_upn_san(context, config, - kdc_identity->hx509ctx, + context->hx509ctx, cp->cert, clientdb, client); @@ -1944,7 +1951,6 @@ _kdc_pk_initialize(krb5_context context, ret = _krb5_pk_load_id(context, &kdc_identity, - 0, user_id, anchors, pool, @@ -1962,7 +1968,7 @@ _kdc_pk_initialize(krb5_context context, 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; @@ -1972,13 +1978,13 @@ _kdc_pk_initialize(krb5_context context, 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; diff --git a/source4/heimdal/kdc/windc.c b/source4/heimdal/kdc/windc.c index ab844e346c..0ef9cdb7ab 100644 --- a/source4/heimdal/kdc/windc.c +++ b/source4/heimdal/kdc/windc.c @@ -55,7 +55,7 @@ krb5_kdc_windc_init(krb5_context context) 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); diff --git a/source4/heimdal/kdc/windc_plugin.h b/source4/heimdal/kdc/windc_plugin.h index c7efb7b852..0ec8e066c7 100644 --- a/source4/heimdal/kdc/windc_plugin.h +++ b/source4/heimdal/kdc/windc_plugin.h @@ -72,6 +72,7 @@ typedef krb5_error_code #define KRB5_WINDC_PLUGING_MINOR 4 +#define KRB5_WINDC_PLUGIN_MINOR 4 typedef struct krb5plugin_windc_ftable { int minor_version; diff --git a/source4/heimdal/kuser/kinit.c b/source4/heimdal/kuser/kinit.c index dd122b5ce7..809d399336 100644 --- a/source4/heimdal/kuser/kinit.c +++ b/source4/heimdal/kuser/kinit.c @@ -40,6 +40,7 @@ struct krb5_dh_moduli; struct AlgorithmIdentifier; struct _krb5_krb_auth_data; +struct hx509_certs_data; #include <krb5-private.h> #ifndef NO_NTLM @@ -76,6 +77,7 @@ int fcache_version; 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; @@ -246,10 +248,15 @@ do_524init(krb5_context context, krb5_ccache ccache, 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; } @@ -415,7 +422,7 @@ get_new_tickets(krb5_context context, 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 @@ -467,7 +474,7 @@ get_new_tickets(krb5_context context, 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, @@ -481,6 +488,8 @@ get_new_tickets(krb5_context context, 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) @@ -488,14 +497,14 @@ get_new_tickets(krb5_context context, 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); } @@ -543,7 +552,7 @@ get_new_tickets(krb5_context context, 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, @@ -796,17 +805,20 @@ main (int argc, char **argv) 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 { diff --git a/source4/heimdal/lib/asn1/asn1parse.y b/source4/heimdal/lib/asn1/asn1parse.y index 7975fe4f6b..3835744bbd 100644 --- a/source4/heimdal/lib/asn1/asn1parse.y +++ b/source4/heimdal/lib/asn1/asn1parse.y @@ -687,6 +687,11 @@ RestrictedCharactedStringType: kw_GeneralString $$ = 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, diff --git a/source4/heimdal/lib/asn1/der_get.c b/source4/heimdal/lib/asn1/der_get.c index aee565040f..5a062fb339 100644 --- a/source4/heimdal/lib/asn1/der_get.c +++ b/source4/heimdal/lib/asn1/der_get.c @@ -305,7 +305,7 @@ der_get_octet_string_ber (const unsigned char *p, size_t len, void *ptr; ptr = realloc(data->data, data->length + datalen); - if (ptr == NULL) { + if (ptr == NULL && data->length + datalen != 0) { e = ENOMEM; goto out; } @@ -354,21 +354,23 @@ der_get_heim_integer (const unsigned char *p, size_t len, 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; diff --git a/source4/heimdal/lib/asn1/gen.c b/source4/heimdal/lib/asn1/gen.c index e156c7cefb..780c18b36f 100644 --- a/source4/heimdal/lib/asn1/gen.c +++ b/source4/heimdal/lib/asn1/gen.c @@ -494,6 +494,9 @@ define_asn1 (int level, Type *t) case TGeneralString: fprintf (headerfile, "GeneralString"); break; + case TTeletexString: + fprintf (headerfile, "TeletexString"); + break; case TTag: { const char *classnames[] = { "UNIVERSAL ", "APPLICATION ", "" /* CONTEXT */, "PRIVATE " }; @@ -685,6 +688,10 @@ define_type (int level, const char *name, Type *t, int typedefp, int preservep) 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; diff --git a/source4/heimdal/lib/asn1/gen_copy.c b/source4/heimdal/lib/asn1/gen_copy.c index 5042ed64ed..f28647d19a 100644 --- a/source4/heimdal/lib/asn1/gen_copy.c +++ b/source4/heimdal/lib/asn1/gen_copy.c @@ -184,6 +184,9 @@ copy_type (const char *from, const char *to, const Type *t, int preserve) 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; diff --git a/source4/heimdal/lib/asn1/gen_decode.c b/source4/heimdal/lib/asn1/gen_decode.c index cf7f0b05dc..327de4c98c 100644 --- a/source4/heimdal/lib/asn1/gen_decode.c +++ b/source4/heimdal/lib/asn1/gen_decode.c @@ -67,6 +67,7 @@ is_primitive_type(int type) case TEnumerated: case TGeneralizedTime: case TGeneralString: + case TTeletexString: case TOID: case TUTCTime: case TUTF8String: @@ -109,6 +110,11 @@ find_tag (const Type *t, *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; @@ -489,6 +495,9 @@ decode_type (const char *name, const Type *t, int optional, 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; @@ -621,7 +630,7 @@ decode_type (const char *name, const Type *t, int optional, 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" @@ -703,6 +712,7 @@ generate_type_decode (const Symbol *s) case TOID: case TGeneralizedTime: case TGeneralString: + case TTeletexString: case TUTF8String: case TPrintableString: case TIA5String: @@ -734,7 +744,7 @@ generate_type_decode (const Symbol *s) 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" diff --git a/source4/heimdal/lib/asn1/gen_encode.c b/source4/heimdal/lib/asn1/gen_encode.c index 1f8078a0ee..012d4677f4 100644 --- a/source4/heimdal/lib/asn1/gen_encode.c +++ b/source4/heimdal/lib/asn1/gen_encode.c @@ -383,6 +383,10 @@ encode_type (const char *name, const Type *t, const char *tmpstr) encode_primitive ("general_string", name); constructed = 0; break; + case TTeletexString: + encode_primitive ("general_string", name); + constructed = 0; + break; case TTag: { char *tname; int c; @@ -521,6 +525,7 @@ generate_type_encode (const Symbol *s) case TOctetString: case TGeneralizedTime: case TGeneralString: + case TTeletexString: case TUTCTime: case TUTF8String: case TPrintableString: diff --git a/source4/heimdal/lib/asn1/gen_free.c b/source4/heimdal/lib/asn1/gen_free.c index fac1f6da5d..48fe8cd787 100644 --- a/source4/heimdal/lib/asn1/gen_free.c +++ b/source4/heimdal/lib/asn1/gen_free.c @@ -145,6 +145,9 @@ free_type (const char *name, const Type *t, int preserve) case TGeneralString: free_primitive ("general_string", name); break; + case TTeletexString: + free_primitive ("general_string", name); + break; case TUTF8String: free_primitive ("utf8string", name); break; diff --git a/source4/heimdal/lib/asn1/gen_length.c b/source4/heimdal/lib/asn1/gen_length.c index 7f9755e2da..e1f045c4c5 100644 --- a/source4/heimdal/lib/asn1/gen_length.c +++ b/source4/heimdal/lib/asn1/gen_length.c @@ -219,6 +219,9 @@ length_type (const char *name, const Type *t, 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; diff --git a/source4/heimdal/lib/asn1/rfc2459.asn1 b/source4/heimdal/lib/asn1/rfc2459.asn1 index 51cac55cc0..9794ca1514 100644 --- a/source4/heimdal/lib/asn1/rfc2459.asn1 +++ b/source4/heimdal/lib/asn1/rfc2459.asn1 @@ -150,11 +150,9 @@ AttributeType ::= OBJECT IDENTIFIER AttributeValue ::= heim_any -TeletexStringx ::= [UNIVERSAL 20] IMPLICIT OCTET STRING - DirectoryString ::= CHOICE { ia5String IA5String, - teletexString TeletexStringx, + teletexString TeletexString, printableString PrintableString, universalString UniversalString, utf8String UTF8String, diff --git a/source4/heimdal/lib/asn1/symbol.h b/source4/heimdal/lib/asn1/symbol.h index 3a0f807980..a39c8f4651 100644 --- a/source4/heimdal/lib/asn1/symbol.h +++ b/source4/heimdal/lib/asn1/symbol.h @@ -44,6 +44,7 @@ enum typetype { TChoice, TEnumerated, TGeneralString, + TTeletexString, TGeneralizedTime, TIA5String, TInteger, diff --git a/source4/heimdal/lib/com_err/com_right.h b/source4/heimdal/lib/com_err/com_right.h index 46aec001ad..e13855abad 100644 --- a/source4/heimdal/lib/com_err/com_right.h +++ b/source4/heimdal/lib/com_err/com_right.h @@ -52,6 +52,7 @@ struct et_list { 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 *); diff --git a/source4/heimdal/lib/com_err/error.c b/source4/heimdal/lib/com_err/error.c index 6b12c00c7a..d4a42ac5de 100644 --- a/source4/heimdal/lib/com_err/error.c +++ b/source4/heimdal/lib/com_err/error.c @@ -49,16 +49,26 @@ 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; } diff --git a/source4/heimdal/lib/gssapi/krb5/init_sec_context.c b/source4/heimdal/lib/gssapi/krb5/init_sec_context.c index 1954c101c7..7f84efe354 100644 --- a/source4/heimdal/lib/gssapi/krb5/init_sec_context.c +++ b/source4/heimdal/lib/gssapi/krb5/init_sec_context.c @@ -297,13 +297,12 @@ do_delegation (krb5_context context, 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; @@ -610,12 +609,11 @@ init_auth_restart 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); diff --git a/source4/heimdal/lib/hcrypto/evp-cc.c b/source4/heimdal/lib/hcrypto/evp-cc.c index 1bf8ca8af9..15b3479f8e 100644 --- a/source4/heimdal/lib/hcrypto/evp-cc.c +++ b/source4/heimdal/lib/hcrypto/evp-cc.c @@ -296,6 +296,7 @@ EVP_cc_aes_256_cbc(void) * */ +#ifdef COMMONCRYPTO_SUPPORTS_RC2 static int cc_rc2_cbc_init(EVP_CIPHER_CTX *ctx, const unsigned char * key, @@ -305,6 +306,7 @@ cc_rc2_cbc_init(EVP_CIPHER_CTX *ctx, 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 @@ -318,6 +320,7 @@ cc_rc2_cbc_init(EVP_CIPHER_CTX *ctx, const EVP_CIPHER * EVP_cc_rc2_cbc(void) { +#ifdef COMMONCRYPTO_SUPPORTS_RC2 static const EVP_CIPHER rc2_cbc = { 0, kCCBlockSizeRC2, @@ -334,6 +337,9 @@ EVP_cc_rc2_cbc(void) NULL }; return &rc2_cbc; +#else + return NULL; +#endif } /** @@ -348,6 +354,7 @@ EVP_cc_rc2_cbc(void) const EVP_CIPHER * EVP_cc_rc2_40_cbc(void) { +#ifdef COMMONCRYPTO_SUPPORTS_RC2 static const EVP_CIPHER rc2_40_cbc = { 0, kCCBlockSizeRC2, @@ -364,6 +371,9 @@ EVP_cc_rc2_40_cbc(void) NULL }; return &rc2_40_cbc; +#else + return NULL; +#endif } @@ -379,6 +389,7 @@ EVP_cc_rc2_40_cbc(void) const EVP_CIPHER * EVP_cc_rc2_64_cbc(void) { +#ifdef COMMONCRYPTO_SUPPORTS_RC2 static const EVP_CIPHER rc2_64_cbc = { 0, kCCBlockSizeRC2, @@ -395,6 +406,9 @@ EVP_cc_rc2_64_cbc(void) NULL }; return &rc2_64_cbc; +#else + return NULL; +#endif } /** diff --git a/source4/heimdal/lib/hcrypto/hmac.c b/source4/heimdal/lib/hcrypto/hmac.c index 282dc38113..dcd836d0be 100644 --- a/source4/heimdal/lib/hcrypto/hmac.c +++ b/source4/heimdal/lib/hcrypto/hmac.c @@ -121,7 +121,8 @@ HMAC_Init_ex(HMAC_CTX *ctx, 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)); diff --git a/source4/heimdal/lib/hcrypto/rand-unix.c b/source4/heimdal/lib/hcrypto/rand-unix.c index 2bfa265fa4..fcad39f1de 100644 --- a/source4/heimdal/lib/hcrypto/rand-unix.c +++ b/source4/heimdal/lib/hcrypto/rand-unix.c @@ -95,8 +95,10 @@ unix_bytes(unsigned char *outdata, int size) 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) { diff --git a/source4/heimdal/lib/hdb/ext.c b/source4/heimdal/lib/hdb/ext.c index 8248098dc5..a8a882c6b2 100644 --- a/source4/heimdal/lib/hdb/ext.c +++ b/source4/heimdal/lib/hdb/ext.c @@ -281,12 +281,11 @@ hdb_entry_get_password(krb5_context context, HDB *db, 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) { @@ -314,13 +313,13 @@ hdb_entry_get_password(krb5_context context, HDB *db, 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) { @@ -330,14 +329,17 @@ hdb_entry_get_password(krb5_context context, HDB *db, 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 diff --git a/source4/heimdal/lib/hdb/hdb.c b/source4/heimdal/lib/hdb/hdb.c index c5d91b8f9d..fa70c7778d 100644 --- a/source4/heimdal/lib/hdb/hdb.c +++ b/source4/heimdal/lib/hdb/hdb.c @@ -59,7 +59,7 @@ * */ - +const int hdb_interface_version = HDB_INTERFACE_VERSION; static struct hdb_method methods[] = { #if HAVE_DB1 || HAVE_DB3 diff --git a/source4/heimdal/lib/hdb/hdb.h b/source4/heimdal/lib/hdb/hdb.h index 8eba864fd3..f34c9fb36e 100644 --- a/source4/heimdal/lib/hdb/hdb.h +++ b/source4/heimdal/lib/hdb/hdb.h @@ -53,6 +53,7 @@ enum hdb_lockop{ HDB_RLOCK, HDB_WLOCK }; #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 @@ -245,6 +246,8 @@ struct hdb_method { krb5_error_code (*create)(krb5_context, HDB **, const char *filename); }; +extern const int hdb_interface_version; + #include <hdb-protos.h> #endif /* __HDB_H__ */ diff --git a/source4/heimdal/lib/hx509/ca.c b/source4/heimdal/lib/hx509/ca.c index 552a869809..8ec6eae22a 100644 --- a/source4/heimdal/lib/hx509/ca.c +++ b/source4/heimdal/lib/hx509/ca.c @@ -692,7 +692,7 @@ add_utf8_san(hx509_context context, 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; diff --git a/source4/heimdal/lib/hx509/cert.c b/source4/heimdal/lib/hx509/cert.c index 7eaf6eb3c8..ebf02a99e3 100644 --- a/source4/heimdal/lib/hx509/cert.c +++ b/source4/heimdal/lib/hx509/cert.c @@ -283,6 +283,7 @@ hx509_cert_init_data(hx509_context context, 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; @@ -445,7 +446,7 @@ hx509_verify_attach_anchors(hx509_verify_ctx ctx, hx509_certs set) { if (ctx->trust_anchors) hx509_certs_free(&ctx->trust_anchors); - ctx->trust_anchors = _hx509_certs_ref(set); + ctx->trust_anchors = hx509_certs_ref(set); } /** @@ -1926,9 +1927,9 @@ hx509_verify_path(hx509_context context, * */ 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) @@ -3451,3 +3452,66 @@ out: 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; +} diff --git a/source4/heimdal/lib/hx509/error.c b/source4/heimdal/lib/hx509/error.c index 45813efb38..fc3cf90b32 100644 --- a/source4/heimdal/lib/hx509/error.c +++ b/source4/heimdal/lib/hx509/error.c @@ -67,8 +67,10 @@ free_error_string(hx509_error msg) 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; + } } /** @@ -91,6 +93,9 @@ hx509_set_error_stringv(hx509_context context, int flags, int code, { hx509_error msg; + if (context == NULL) + return; + msg = calloc(1, sizeof(*msg)); if (msg == NULL) { hx509_clear_error_string(context); diff --git a/source4/heimdal/lib/hx509/file.c b/source4/heimdal/lib/hx509/file.c index 674d2706ce..56e25766ef 100644 --- a/source4/heimdal/lib/hx509/file.c +++ b/source4/heimdal/lib/hx509/file.c @@ -66,7 +66,7 @@ _hx509_write_file(const char *fn, const void *data, size_t length) */ 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); } @@ -82,7 +82,7 @@ hx509_pem_write(hx509_context context, const char *type, #define ENCODE_LINE_LENGTH 54 - header(f, "BEGIN", type); + print_pem_stamp(f, "BEGIN", type); while (headers) { fprintf(f, "%s: %s\n%s", @@ -110,7 +110,7 @@ hx509_pem_write(hx509_context context, const char *type, free(line); } - header(f, "END", type); + print_pem_stamp(f, "END", type); return 0; } @@ -121,14 +121,14 @@ hx509_pem_write(hx509_context context, const char *type, 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; @@ -164,10 +164,10 @@ hx509_pem_free_header(hx509_pem_header *headers) */ 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; } diff --git a/source4/heimdal/lib/hx509/keyset.c b/source4/heimdal/lib/hx509/keyset.c index c4f035ab87..4a96cff530 100644 --- a/source4/heimdal/lib/hx509/keyset.c +++ b/source4/heimdal/lib/hx509/keyset.c @@ -198,7 +198,7 @@ hx509_certs_store(hx509_context context, hx509_certs -_hx509_certs_ref(hx509_certs certs) +hx509_certs_ref(hx509_certs certs) { if (certs == NULL) return NULL; diff --git a/source4/heimdal/lib/hx509/ks_file.c b/source4/heimdal/lib/hx509/ks_file.c index 3955820aef..f137b84641 100644 --- a/source4/heimdal/lib/hx509/ks_file.c +++ b/source4/heimdal/lib/hx509/ks_file.c @@ -367,7 +367,7 @@ file_init_common(hx509_context context, 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; @@ -380,15 +380,15 @@ file_init_common(hx509_context context, 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; @@ -401,10 +401,10 @@ file_init_common(hx509_context context, 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; } @@ -412,25 +412,25 @@ file_init_common(hx509_context context, 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) { @@ -461,7 +461,7 @@ file_init_common(hx509_context context, } } - 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; @@ -470,17 +470,17 @@ file_init_common(hx509_context context, 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); @@ -507,10 +507,10 @@ file_init_der(hx509_context context, 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; } @@ -558,20 +558,20 @@ static int 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; } @@ -579,24 +579,24 @@ file_store(hx509_context context, 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 @@ -605,8 +605,8 @@ file_iter_end(hx509_context context, 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 @@ -615,8 +615,8 @@ file_getkeys(hx509_context context, 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 @@ -625,8 +625,8 @@ file_addkey(hx509_context context, 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 = { diff --git a/source4/heimdal/lib/hx509/lock.c b/source4/heimdal/lib/hx509/lock.c index 219a301928..07e9d36125 100644 --- a/source4/heimdal/lib/hx509/lock.c +++ b/source4/heimdal/lib/hx509/lock.c @@ -214,10 +214,12 @@ hx509_lock_prompt(hx509_lock lock, hx509_prompt *prompt) 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 diff --git a/source4/heimdal/lib/hx509/name.c b/source4/heimdal/lib/hx509/name.c index c5844f98cc..b544ecb7ff 100644 --- a/source4/heimdal/lib/hx509/name.c +++ b/source4/heimdal/lib/hx509/name.c @@ -243,11 +243,7 @@ _hx509_Name_to_string(const Name *n, char **str) 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; @@ -279,8 +275,7 @@ _hx509_Name_to_string(const Name *n, char **str) 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); } @@ -341,7 +336,7 @@ dsstringprep(const DirectoryString *ds, uint32_t **rname, size_t *rlen) 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); @@ -930,12 +925,12 @@ hx509_general_name_unparse(GeneralName *name, char **str) 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: @@ -990,12 +985,12 @@ hx509_general_name_unparse(GeneralName *name, char **str) 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: diff --git a/source4/heimdal/lib/hx509/revoke.c b/source4/heimdal/lib/hx509/revoke.c index 74f2d74679..21140b3c7e 100644 --- a/source4/heimdal/lib/hx509/revoke.c +++ b/source4/heimdal/lib/hx509/revoke.c @@ -1004,17 +1004,17 @@ hx509_ocsp_request(hx509_context context, 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) { diff --git a/source4/heimdal/lib/hx509/sel.c b/source4/heimdal/lib/hx509/sel.c index c5e760569a..5932ce84c3 100644 --- a/source4/heimdal/lib/hx509/sel.c +++ b/source4/heimdal/lib/hx509/sel.c @@ -176,7 +176,6 @@ _hx509_expr_eval(hx509_context context, hx509_env env, struct hx_expr *expr) default: _hx509_abort("hx509 eval expr with unknown op: %d", (int)expr->op); } - return 0; } void diff --git a/source4/heimdal/lib/krb5/auth_context.c b/source4/heimdal/lib/krb5/auth_context.c index bfc183d168..dfb9f6a0e3 100644 --- a/source4/heimdal/lib/krb5/auth_context.c +++ b/source4/heimdal/lib/krb5/auth_context.c @@ -171,10 +171,10 @@ krb5_auth_con_genaddrs(krb5_context context, 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); @@ -189,9 +189,10 @@ krb5_auth_con_genaddrs(krb5_context context, 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); diff --git a/source4/heimdal/lib/krb5/build_auth.c b/source4/heimdal/lib/krb5/build_auth.c index bf77fd4e77..a845e0ac33 100644 --- a/source4/heimdal/lib/krb5/build_auth.c +++ b/source4/heimdal/lib/krb5/build_auth.c @@ -100,35 +100,30 @@ make_etypelist(krb5_context context, } 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; @@ -137,33 +132,43 @@ krb5_build_authenticator (krb5_context context, 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) @@ -175,7 +180,7 @@ krb5_build_authenticator (krb5_context context, ret = krb5_encrypt (context, crypto, usage /* KRB5_KU_AP_REQ_AUTH */, - buf + buf_size - len, + buf, len, result); krb5_crypto_destroy(context, crypto); @@ -183,20 +188,9 @@ krb5_build_authenticator (krb5_context context, 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; } diff --git a/source4/heimdal/lib/krb5/context.c b/source4/heimdal/lib/krb5/context.c index 8bf8b79022..79e1000fd0 100644 --- a/source4/heimdal/lib/krb5/context.c +++ b/source4/heimdal/lib/krb5/context.c @@ -304,6 +304,12 @@ krb5_init_context(krb5_context *context) 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); @@ -816,31 +822,6 @@ krb5_get_default_in_tkt_etypes(krb5_context context, } /** - * 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. * * @param context kerberos context to add the ets too diff --git a/source4/heimdal/lib/krb5/crypto.c b/source4/heimdal/lib/krb5/crypto.c index bdcdb2ea0a..68233c290d 100644 --- a/source4/heimdal/lib/krb5/crypto.c +++ b/source4/heimdal/lib/krb5/crypto.c @@ -2058,7 +2058,7 @@ evp_encrypt(krb5_context context, 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, diff --git a/source4/heimdal/lib/krb5/error_string.c b/source4/heimdal/lib/krb5/error_string.c index 829c080a55..d2661dcaf5 100644 --- a/source4/heimdal/lib/krb5/error_string.c +++ b/source4/heimdal/lib/krb5/error_string.c @@ -104,6 +104,68 @@ krb5_vset_error_message (krb5_context context, krb5_error_code ret, 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, @@ -155,7 +217,6 @@ krb5_have_error_string(krb5_context context) 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); @@ -172,10 +233,13 @@ krb5_get_error_message(krb5_context context, krb5_error_code code) 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; @@ -199,3 +263,31 @@ krb5_free_error_message(krb5_context context, const char *msg) { 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; +} diff --git a/source4/heimdal/lib/krb5/fcache.c b/source4/heimdal/lib/krb5/fcache.c index f8e74f1ddc..cda15e483b 100644 --- a/source4/heimdal/lib/krb5/fcache.c +++ b/source4/heimdal/lib/krb5/fcache.c @@ -95,13 +95,15 @@ _krb5_xlock(krb5_context context, int fd, krb5_boolean exclusive, 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; } @@ -127,12 +129,14 @@ _krb5_xunlock(krb5_context context, int fd) 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; } @@ -369,9 +373,11 @@ fcc_open(krb5_context context, 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); @@ -431,9 +437,11 @@ fcc_initialize(krb5_context context, 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; } @@ -485,9 +493,11 @@ fcc_store_cred(krb5_context context, 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; @@ -875,12 +885,13 @@ fcc_move(krb5_context context, krb5_ccache from, krb5_ccache to) 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 */ diff --git a/source4/heimdal/lib/krb5/generate_seq_number.c b/source4/heimdal/lib/krb5/generate_seq_number.c index 2764f1a914..b7bd8b99f8 100644 --- a/source4/heimdal/lib/krb5/generate_seq_number.c +++ b/source4/heimdal/lib/krb5/generate_seq_number.c @@ -38,23 +38,11 @@ krb5_generate_seq_number(krb5_context context, 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; } diff --git a/source4/heimdal/lib/krb5/generate_subkey.c b/source4/heimdal/lib/krb5/generate_subkey.c index efb6cce288..003a66ac01 100644 --- a/source4/heimdal/lib/krb5/generate_subkey.c +++ b/source4/heimdal/lib/krb5/generate_subkey.c @@ -33,13 +33,18 @@ #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, diff --git a/source4/heimdal/lib/krb5/get_cred.c b/source4/heimdal/lib/krb5/get_cred.c index 10417f1a52..63152bbfa6 100644 --- a/source4/heimdal/lib/krb5/get_cred.c +++ b/source4/heimdal/lib/krb5/get_cred.c @@ -32,6 +32,7 @@ */ #include <krb5_locl.h> +#include <assert.h> /* * Take the `body' and encode it into `padata' using the credentials @@ -79,7 +80,7 @@ static krb5_error_code 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; @@ -101,7 +102,7 @@ set_auth_data (krb5_context context, 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); @@ -111,7 +112,6 @@ set_auth_data (krb5_context context, krb5_encrypt_EncryptedData(context, crypto, KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY, - /* KRB5_KU_TGS_REQ_AUTH_DAT_SESSION? */ buf, len, 0, @@ -143,7 +143,9 @@ init_tgs_req (krb5_context context, 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; @@ -238,60 +240,39 @@ init_tgs_req (krb5_context context, } } - { - 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); @@ -349,17 +330,12 @@ decrypt_tkt_with_subkey (krb5_context context, 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; @@ -370,6 +346,17 @@ decrypt_tkt_with_subkey (krb5_context context, &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; @@ -549,7 +536,7 @@ get_cred_kdc(krb5_context context, out_creds, &krbtgt->session, NULL, - KRB5_KU_TGS_REP_ENC_PART_SESSION, + 0, &krbtgt->addresses, nonce, eflags, @@ -574,10 +561,8 @@ out: 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; } @@ -898,6 +883,12 @@ get_cred_kdc_referral(krb5_context context, 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)); @@ -1087,6 +1078,12 @@ krb5_get_credentials_with_flags(krb5_context context, 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) { @@ -1282,6 +1279,12 @@ krb5_get_creds(krb5_context context, 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); @@ -1289,7 +1292,10 @@ krb5_get_creds(krb5_context context, if (ret) return ret; - options = opt->options; + if (opt) + options = opt->options; + else + options = 0; flags.i = 0; *out_creds = NULL; @@ -1301,7 +1307,7 @@ krb5_get_creds(krb5_context context, return ENOMEM; } - if (opt->enctype) { + if (opt && opt->enctype) { in_creds.session.keytype = opt->enctype; options |= KRB5_TC_MATCH_KEYTYPE; } @@ -1312,7 +1318,7 @@ krb5_get_creds(krb5_context context, */ 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 diff --git a/source4/heimdal/lib/krb5/get_for_creds.c b/source4/heimdal/lib/krb5/get_for_creds.c index 19e48173df..8c58dae187 100644 --- a/source4/heimdal/lib/krb5/get_for_creds.c +++ b/source4/heimdal/lib/krb5/get_for_creds.c @@ -137,13 +137,12 @@ krb5_fwd_tgt_creds (krb5_context context, 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; diff --git a/source4/heimdal/lib/krb5/krb5_locl.h b/source4/heimdal/lib/krb5/krb5_locl.h index 71dc1327c6..d436215769 100644 --- a/source4/heimdal/lib/krb5/krb5_locl.h +++ b/source4/heimdal/lib/krb5/krb5_locl.h @@ -136,6 +136,8 @@ struct sockaddr_dl; #include <door.h> #endif +#include <com_err.h> + #include <roken.h> #include <parse_time.h> #include <base64.h> @@ -151,6 +153,7 @@ struct sockaddr_dl; struct send_to_kdc; /* XXX glue for pkinit */ +struct hx509_certs_data; struct krb5_pk_identity; struct krb5_pk_cert; struct ContentInfo; @@ -265,6 +268,9 @@ typedef struct krb5_context_data { #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}" @@ -295,7 +301,6 @@ typedef struct krb5_context_data { #ifdef PKINIT struct krb5_pk_identity { - hx509_context hx509ctx; hx509_verify_ctx verify_ctx; hx509_certs certs; hx509_cert cert; diff --git a/source4/heimdal/lib/krb5/mk_error.c b/source4/heimdal/lib/krb5/mk_error.c index f623fc495b..0de30e4ddb 100644 --- a/source4/heimdal/lib/krb5/mk_error.c +++ b/source4/heimdal/lib/krb5/mk_error.c @@ -44,6 +44,7 @@ krb5_mk_error(krb5_context context, int *client_usec, krb5_data *reply) { + const char *e_text2 = NULL; KRB_ERROR msg; krb5_timestamp sec; int32_t usec; @@ -62,7 +63,7 @@ krb5_mk_error(krb5_context context, /* 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; @@ -82,6 +83,8 @@ krb5_mk_error(krb5_context context, } 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) diff --git a/source4/heimdal/lib/krb5/mk_req_ext.c b/source4/heimdal/lib/krb5/mk_req_ext.c index d130272aa1..03fc93b02f 100644 --- a/source4/heimdal/lib/krb5/mk_req_ext.c +++ b/source4/heimdal/lib/krb5/mk_req_ext.c @@ -123,12 +123,11 @@ _krb5_mk_req_internal(krb5_context context, 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) diff --git a/source4/heimdal/lib/krb5/pkinit.c b/source4/heimdal/lib/krb5/pkinit.c index 2f6d7854a5..f6457aa5c9 100644 --- a/source4/heimdal/lib/krb5/pkinit.c +++ b/source4/heimdal/lib/krb5/pkinit.c @@ -74,6 +74,7 @@ struct krb5_pk_init_ctx_data { unsigned int require_krbtgt_otherName:1; unsigned int require_hostname_match:1; unsigned int trustedCertifiers:1; + unsigned int anonymous:1; }; static void @@ -193,15 +194,15 @@ find_cert(krb5_context context, struct krb5_pk_identity *id, 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; @@ -221,7 +222,7 @@ create_signature(krb5_context context, 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, @@ -233,7 +234,7 @@ create_signature(krb5_context context, 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; } @@ -596,7 +597,7 @@ build_auth_pack(krb5_context context, 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) @@ -756,7 +757,7 @@ pk_mk_padata(krb5_context context, 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, @@ -806,6 +807,12 @@ _krb5_pk_mk_padata(krb5_context context, 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", @@ -873,7 +880,7 @@ pk_verify_sign(krb5_context context, *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, @@ -884,7 +891,7 @@ pk_verify_sign(krb5_context context, 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; } @@ -896,9 +903,9 @@ pk_verify_sign(krb5_context context, 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; } @@ -1040,7 +1047,7 @@ pk_verify_host(krb5_context context, 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, @@ -1052,7 +1059,7 @@ pk_verify_host(krb5_context context, 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); @@ -1102,7 +1109,7 @@ pk_verify_host(krb5_context context, 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, @@ -1145,7 +1152,7 @@ pk_rd_pa_reply_enckey(krb5_context context, 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, @@ -1155,7 +1162,7 @@ pk_rd_pa_reply_enckey(krb5_context context, &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; } @@ -1167,8 +1174,26 @@ pk_rd_pa_reply_enckey(krb5_context context, 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, @@ -1700,10 +1725,44 @@ hx_pass_prompter(void *data, const hx509_prompt *prompter) 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, @@ -1713,7 +1772,6 @@ _krb5_pk_load_id(krb5_context context, char *password) { struct krb5_pk_identity *id = NULL; - hx509_lock lock = NULL; struct prompter p; int ret; @@ -1725,12 +1783,6 @@ _krb5_pk_load_id(krb5_context context, 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)); @@ -1740,33 +1792,34 @@ _krb5_pk_load_id(krb5_context context, 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; } @@ -1774,26 +1827,26 @@ _krb5_pk_load_id(krb5_context context, 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; @@ -1802,30 +1855,30 @@ _krb5_pk_load_id(krb5_context context, } 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; } @@ -1840,14 +1893,11 @@ _krb5_pk_load_id(krb5_context context, 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; } @@ -2204,7 +2254,6 @@ _krb5_get_init_creds_opt_free_pkinit(krb5_get_init_creds_opt *opt) 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); @@ -2275,9 +2324,11 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context, 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, @@ -2292,31 +2343,14 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context, } 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; @@ -2353,6 +2387,33 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context, #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 @@ -2404,34 +2465,35 @@ krb5_error_code KRB5_LIB_FUNCTION _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; } @@ -2441,29 +2503,54 @@ _krb5_pk_enterprise_cert(krb5_context context, 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, diff --git a/source4/heimdal/lib/krb5/principal.c b/source4/heimdal/lib/krb5/principal.c index 1483d59f9d..d854113a43 100644 --- a/source4/heimdal/lib/krb5/principal.c +++ b/source4/heimdal/lib/krb5/principal.c @@ -106,6 +106,17 @@ krb5_principal_set_type(krb5_context context, 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) @@ -113,6 +124,17 @@ krb5_principal_get_type(krb5_context context, 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) @@ -148,6 +170,19 @@ krb5_principal_get_num_comp(krb5_context context, 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, @@ -337,6 +372,18 @@ exit: 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, @@ -630,6 +677,20 @@ krb5_principal_set_realm(krb5_context context, 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, @@ -645,6 +706,43 @@ 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, @@ -730,28 +828,6 @@ build_principal(krb5_context context, 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, @@ -789,6 +865,18 @@ krb5_build_principal_ext(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, @@ -821,6 +909,8 @@ 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 @@ -854,6 +944,19 @@ _krb5_principal_compare_PrincipalName(krb5_context context, } +/** + * 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 */ @@ -868,8 +971,16 @@ krb5_principal_compare(krb5_context context, 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 @@ -880,8 +991,10 @@ krb5_realm_compare(krb5_context context, return strcmp(princ_realm(princ1), princ_realm(princ2)) == 0; } -/* +/** * return TRUE iff princ matches pattern + * + * @ingroup krb5_principal */ krb5_boolean KRB5_LIB_FUNCTION @@ -1418,6 +1531,12 @@ static const struct { { 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) { diff --git a/source4/heimdal/lib/krb5/replay.c b/source4/heimdal/lib/krb5/replay.c index be484c29dc..0cad91e437 100644 --- a/source4/heimdal/lib/krb5/replay.c +++ b/source4/heimdal/lib/krb5/replay.c @@ -133,9 +133,10 @@ krb5_rc_initialize(krb5_context context, 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; @@ -158,9 +159,10 @@ krb5_rc_destroy(krb5_context context, 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); @@ -208,9 +210,10 @@ krb5_rc_store(krb5_context context, 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); @@ -226,18 +229,21 @@ krb5_rc_store(krb5_context context, } } 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); diff --git a/source4/heimdal/lib/krb5/warn.c b/source4/heimdal/lib/krb5/warn.c index 05239186ec..886a1fe981 100644 --- a/source4/heimdal/lib/krb5/warn.c +++ b/source4/heimdal/lib/krb5/warn.c @@ -59,19 +59,13 @@ _warnerr(krb5_context context, int do_errtext, *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>"; } } diff --git a/source4/heimdal/lib/roken/rkpty.c b/source4/heimdal/lib/roken/rkpty.c index 2776c1318b..6043e2b815 100644 --- a/source4/heimdal/lib/roken/rkpty.c +++ b/source4/heimdal/lib/roken/rkpty.c @@ -93,6 +93,10 @@ caught_signal(int signo) 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; diff --git a/source4/heimdal/lib/roken/roken.h.in b/source4/heimdal/lib/roken/roken.h.in index 2bd471736c..6fc533c697 100644 --- a/source4/heimdal/lib/roken/roken.h.in +++ b/source4/heimdal/lib/roken/roken.h.in @@ -306,6 +306,12 @@ int ROKEN_LIB_FUNCTION getdtablesize(void); 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 @@ -476,7 +482,7 @@ unsigned short ROKEN_LIB_FUNCTION bswap16(unsigned short); int rk_flock(int fd, int operation); #endif /* HAVE_FLOCK */ -#ifdef SunOS +#if defined(SunOS) || defined(_AIX) #define dirfd(x) ((x)->dd_fd) #endif @@ -799,6 +805,12 @@ time_t ROKEN_LIB_FUNCTION 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 diff --git a/source4/heimdal/lib/wind/normalize.c b/source4/heimdal/lib/wind/normalize.c index 4c70a52932..102c577e66 100644 --- a/source4/heimdal/lib/wind/normalize.c +++ b/source4/heimdal/lib/wind/normalize.c @@ -39,6 +39,9 @@ #include <assert.h> #include <stdlib.h> #include <errno.h> +#include <stdio.h> + +#include "roken.h" #include "normalize_table.h" @@ -173,7 +176,7 @@ cc_cmp(const void *a, const void *b) 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]); @@ -183,8 +186,7 @@ canonical_reorder(uint32_t *tmp, size_t tmp_len) 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; } } @@ -280,6 +282,11 @@ _wind_stringprep_normalize(const uint32_t *in, size_t in_len, 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; diff --git a/source4/heimdal/lib/wind/stringprep.c b/source4/heimdal/lib/wind/stringprep.c index a991f20cfb..ec4657665e 100644 --- a/source4/heimdal/lib/wind/stringprep.c +++ b/source4/heimdal/lib/wind/stringprep.c @@ -58,10 +58,16 @@ wind_stringprep(const uint32_t *in, size_t in_len, 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; |