From 21460dfc14acdeef69b6cd910da80f261316be63 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 2 Oct 2010 16:32:56 +1000 Subject: s4:heimdal: import lorikeet-heimdal-201010022046 (commit 1bea031b9404b14114b0272ecbe56e60c567af5c) --- source4/heimdal/cf/make-proto.pl | 2 +- source4/heimdal/kdc/digest.c | 10 ++-- source4/heimdal/kdc/kerberos5.c | 4 +- source4/heimdal/kdc/krb5tgs.c | 8 +-- source4/heimdal/kdc/misc.c | 24 ++++++--- source4/heimdal/lib/asn1/der_locl.h | 1 + source4/heimdal/lib/asn1/der_put.c | 12 ++--- source4/heimdal/lib/asn1/timegm.c | 62 +++++++++++++++++++---- source4/heimdal/lib/hcrypto/evp-hcrypto.c | 46 +++++++++++++++++ source4/heimdal/lib/hcrypto/evp-hcrypto.h | 4 ++ source4/heimdal/lib/hcrypto/evp.c | 30 +++++++++++ source4/heimdal/lib/hcrypto/evp.h | 4 ++ source4/heimdal/lib/hcrypto/hash.h | 6 +++ source4/heimdal/lib/hcrypto/rsa-ltm.c | 13 +++-- source4/heimdal/lib/hcrypto/sha.h | 26 ++++++++++ source4/heimdal/lib/hdb/hdb-keytab.c | 19 +++++-- source4/heimdal/lib/hdb/hdb.h | 12 ++++- source4/heimdal/lib/hdb/keytab.c | 16 ++++-- source4/heimdal/lib/hx509/crypto.c | 76 +++++++++++++++++++++++++--- source4/heimdal/lib/krb5/context.c | 24 ++++----- source4/heimdal/lib/krb5/crypto.c | 48 +++++++++++------- source4/heimdal/lib/krb5/init_creds_pw.c | 11 ++++ source4/heimdal/lib/krb5/krbhst.c | 83 ++++++++++++++++--------------- source4/heimdal/lib/roken/roken.h.in | 2 +- 24 files changed, 418 insertions(+), 125 deletions(-) (limited to 'source4/heimdal') diff --git a/source4/heimdal/cf/make-proto.pl b/source4/heimdal/cf/make-proto.pl index 12c6d07f5e5..566534f2471 100644 --- a/source4/heimdal/cf/make-proto.pl +++ b/source4/heimdal/cf/make-proto.pl @@ -12,7 +12,7 @@ my $debug = 0; my $oproto = 1; my $private_func_re = "^_"; -do Getopts('x:m:o:p:dqE:R:P:') || die "foo"; +Getopts('x:m:o:p:dqE:R:P:') || die "foo"; if($opt_d) { $debug = 1; diff --git a/source4/heimdal/kdc/digest.c b/source4/heimdal/kdc/digest.c index 1a383fa205c..70b45c2af6f 100644 --- a/source4/heimdal/kdc/digest.c +++ b/source4/heimdal/kdc/digest.c @@ -177,7 +177,7 @@ get_password_entry(krb5_context context, return ret; ret = _kdc_db_fetch(context, config, clientprincipal, - HDB_F_GET_CLIENT, &db, &user); + HDB_F_GET_CLIENT, NULL, &db, &user); krb5_free_principal(context, clientprincipal); if (ret) return ret; @@ -292,7 +292,7 @@ _kdc_do_digest(krb5_context context, krb5_clear_error_message(context); ret = _kdc_db_fetch(context, config, principal, - HDB_F_GET_SERVER, NULL, &server); + HDB_F_GET_SERVER, NULL, NULL, &server); if (ret) goto out; @@ -314,7 +314,7 @@ _kdc_do_digest(krb5_context context, } ret = _kdc_db_fetch(context, config, principal, - HDB_F_GET_CLIENT, NULL, &client); + HDB_F_GET_CLIENT, NULL, NULL, &client); krb5_free_principal(context, principal); if (ret) goto out; @@ -874,7 +874,7 @@ _kdc_do_digest(krb5_context context, goto failed; ret = _kdc_db_fetch(context, config, clientprincipal, - HDB_F_GET_CLIENT, NULL, &user); + HDB_F_GET_CLIENT, NULL, NULL, &user); krb5_free_principal(context, clientprincipal); if (ret) { krb5_set_error_message(context, ret, @@ -1158,7 +1158,7 @@ _kdc_do_digest(krb5_context context, goto failed; ret = _kdc_db_fetch(context, config, clientprincipal, - HDB_F_GET_CLIENT, NULL, &user); + HDB_F_GET_CLIENT, NULL, NULL, &user); krb5_free_principal(context, clientprincipal); if (ret) { krb5_set_error_message(context, ret, "NTLM user %s not in database", diff --git a/source4/heimdal/kdc/kerberos5.c b/source4/heimdal/kdc/kerberos5.c index 9fb0998a2aa..40e597befb5 100644 --- a/source4/heimdal/kdc/kerberos5.c +++ b/source4/heimdal/kdc/kerberos5.c @@ -988,7 +988,7 @@ _kdc_as_rep(krb5_context context, */ ret = _kdc_db_fetch(context, config, client_princ, - HDB_F_GET_CLIENT | flags, 0, + HDB_F_GET_CLIENT | flags, NULL, &clientdb, &client); if(ret){ const char *msg = krb5_get_error_message(context, ret); @@ -1000,7 +1000,7 @@ _kdc_as_rep(krb5_context context, ret = _kdc_db_fetch(context, config, server_princ, HDB_F_GET_SERVER|HDB_F_GET_KRBTGT, - 0, NULL, &server); + NULL, NULL, &server); if(ret){ const char *msg = krb5_get_error_message(context, ret); kdc_log(context, config, 0, "UNKNOWN -- %s: %s", server_name, msg); diff --git a/source4/heimdal/kdc/krb5tgs.c b/source4/heimdal/kdc/krb5tgs.c index 23f9674bef2..71d99e2bee0 100644 --- a/source4/heimdal/kdc/krb5tgs.c +++ b/source4/heimdal/kdc/krb5tgs.c @@ -351,7 +351,7 @@ check_PAC(krb5_context context, *signedpath = 1; ret = _krb5_pac_sign(context, pac, tkt->authtime, client_principal, - server_key, krbtgt_key, rspac); + server_key, krbtgt_sign_key, rspac); } krb5_pac_free(context, pac); @@ -1563,7 +1563,7 @@ tgs_build_reply(krb5_context context, server_lookup: ret = _kdc_db_fetch(context, config, sp, HDB_F_GET_SERVER | HDB_F_CANON, - 0, NULL, &server); + NULL, NULL, &server); if(ret){ const char *new_rlm, *msg; @@ -1624,7 +1624,7 @@ server_lookup: } ret = _kdc_db_fetch(context, config, cp, HDB_F_GET_CLIENT | HDB_F_CANON, - 0, &clientdb, &client); + NULL, &clientdb, &client); if(ret) { const char *krbtgt_realm, *msg; @@ -1845,7 +1845,7 @@ server_lookup: krb5_pac p = NULL; krb5_data_free(&rspac); ret = _kdc_db_fetch(context, config, client_principal, HDB_F_GET_CLIENT | HDB_F_CANON, - 0, &s4u2self_impersonated_clientdb, &s4u2self_impersonated_client); + NULL, &s4u2self_impersonated_clientdb, &s4u2self_impersonated_client); if (ret) { const char *msg; diff --git a/source4/heimdal/kdc/misc.c b/source4/heimdal/kdc/misc.c index 30807484638..9feb99cdbc0 100644 --- a/source4/heimdal/kdc/misc.c +++ b/source4/heimdal/kdc/misc.c @@ -47,7 +47,7 @@ _kdc_db_fetch(krb5_context context, hdb_entry_ex *ent; krb5_error_code ret; int i; - unsigned kvno; + unsigned kvno = 0; if (kvno_ptr) { kvno = *kvno_ptr; @@ -91,12 +91,22 @@ _kdc_db_fetch(krb5_context context, continue; } - ret = config->db[i]->hdb_fetch(context, - config->db[i], - principal, - flags | HDB_F_DECRYPT, - kvno, - ent); + if (config->db[i]->hdb_fetch_kvno) { + ret = config->db[i]->hdb_fetch_kvno(context, + config->db[i], + principal, + flags | HDB_F_DECRYPT, + kvno, + ent); + } else { + flags &= ~HDB_F_KVNO_SPECIFIED; + ret = config->db[i]->hdb_fetch(context, + config->db[i], + principal, + flags | HDB_F_DECRYPT, + ent); + } + krb5_free_principal(context, enterprise_principal); config->db[i]->hdb_close(context, config->db[i]); diff --git a/source4/heimdal/lib/asn1/der_locl.h b/source4/heimdal/lib/asn1/der_locl.h index 0f65c50a223..a086e18fa4a 100644 --- a/source4/heimdal/lib/asn1/der_locl.h +++ b/source4/heimdal/lib/asn1/der_locl.h @@ -56,6 +56,7 @@ #include "asn1-template.h" time_t _der_timegm (struct tm *); +struct tm * _der_gmtime(time_t t, struct tm *); size_t _heim_len_unsigned (unsigned); size_t _heim_len_int (int); diff --git a/source4/heimdal/lib/asn1/der_put.c b/source4/heimdal/lib/asn1/der_put.c index c8192f25fe5..b8101458ad4 100644 --- a/source4/heimdal/lib/asn1/der_put.c +++ b/source4/heimdal/lib/asn1/der_put.c @@ -426,22 +426,22 @@ der_put_length_and_tag (unsigned char *p, size_t len, size_t len_val, int _heim_time2generalizedtime (time_t t, heim_octet_string *s, int gtimep) { - struct tm *tm; + struct tm tm; const size_t len = gtimep ? 15 : 13; s->data = malloc(len + 1); if (s->data == NULL) return ENOMEM; s->length = len; - tm = gmtime (&t); + _der_gmtime(t, &tm); if (gtimep) snprintf (s->data, len + 1, "%04d%02d%02d%02d%02d%02dZ", - tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, - tm->tm_hour, tm->tm_min, tm->tm_sec); + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec); else snprintf (s->data, len + 1, "%02d%02d%02d%02d%02d%02dZ", - tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday, - tm->tm_hour, tm->tm_min, tm->tm_sec); + tm.tm_year % 100, tm.tm_mon + 1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec); return 0; } diff --git a/source4/heimdal/lib/asn1/timegm.c b/source4/heimdal/lib/asn1/timegm.c index 83f0e33fb8f..b5694784138 100644 --- a/source4/heimdal/lib/asn1/timegm.c +++ b/source4/heimdal/lib/asn1/timegm.c @@ -42,6 +42,10 @@ is_leap(unsigned y) return (y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0); } +static const unsigned ndays[2][12] ={ + {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, + {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}}; + /* * This is a simplifed version of timegm(3) that doesn't accept out of * bound values that timegm(3) normally accepts but those are not @@ -51,9 +55,8 @@ is_leap(unsigned y) time_t _der_timegm (struct tm *tm) { - static const unsigned ndays[2][12] ={ - {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, - {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}}; + time_t res = 0; + unsigned i; if (tm->tm_year < 0) return -1; @@ -68,10 +71,51 @@ _der_timegm (struct tm *tm) if (tm->tm_sec < 0 || tm->tm_sec > 59) return -1; - /* now call to the libc timegm(). This code used to do the - * calculation itself, but that calculation didn't account for the - * difference between UTC and GMT, which is 24 seconds in 2010. That - * caused a mutual authentication failure - */ - return timegm(tm); + for (i = 70; i < tm->tm_year; ++i) + res += is_leap(i) ? 366 : 365; + + for (i = 0; i < tm->tm_mon; ++i) + res += ndays[is_leap(tm->tm_year)][i]; + res += tm->tm_mday - 1; + res *= 24; + res += tm->tm_hour; + res *= 60; + res += tm->tm_min; + res *= 60; + res += tm->tm_sec; + return res; +} + +struct tm * +_der_gmtime(time_t t, struct tm *tm) +{ + time_t secday = t % (3600 * 24); + time_t days = t / (3600 * 24); + + memset(tm, 0, sizeof(*tm)); + + tm->tm_sec = secday % 60; + tm->tm_min = (secday % 3600) / 60; + tm->tm_hour = secday / 3600; + + tm->tm_year = 70; + while(1) { + unsigned dayinyear = (is_leap(tm->tm_year) ? 366 : 365); + if (days < dayinyear) + break; + tm->tm_year += 1; + days -= dayinyear; + } + tm->tm_mon = 0; + + while (1) { + unsigned daysinmonth = ndays[is_leap(tm->tm_year)][tm->tm_mon]; + if (days < daysinmonth) + break; + days -= daysinmonth; + tm->tm_mon++; + } + tm->tm_mday = days + 1; + + return tm; } diff --git a/source4/heimdal/lib/hcrypto/evp-hcrypto.c b/source4/heimdal/lib/hcrypto/evp-hcrypto.c index 9e063545e16..bf37b42edca 100644 --- a/source4/heimdal/lib/hcrypto/evp-hcrypto.c +++ b/source4/heimdal/lib/hcrypto/evp-hcrypto.c @@ -289,6 +289,52 @@ EVP_hcrypto_sha256(void) return &sha256; } +/** + * The message digest SHA384 - hcrypto + * + * @return the message digest type. + * + * @ingroup hcrypto_evp + */ + +const EVP_MD * +EVP_hcrypto_sha384(void) +{ + static const struct hc_evp_md sha384 = { + 48, + 128, + sizeof(SHA384_CTX), + (hc_evp_md_init)SHA384_Init, + (hc_evp_md_update)SHA384_Update, + (hc_evp_md_final)SHA384_Final, + NULL + }; + return &sha384; +} + +/** + * The message digest SHA512 - hcrypto + * + * @return the message digest type. + * + * @ingroup hcrypto_evp + */ + +const EVP_MD * +EVP_hcrypto_sha512(void) +{ + static const struct hc_evp_md sha512 = { + 64, + 128, + sizeof(SHA512_CTX), + (hc_evp_md_init)SHA512_Init, + (hc_evp_md_update)SHA512_Update, + (hc_evp_md_final)SHA512_Final, + NULL + }; + return &sha512; +} + /** * The message digest SHA1 - hcrypto * diff --git a/source4/heimdal/lib/hcrypto/evp-hcrypto.h b/source4/heimdal/lib/hcrypto/evp-hcrypto.h index 7915046bdce..b7876c67c8a 100644 --- a/source4/heimdal/lib/hcrypto/evp-hcrypto.h +++ b/source4/heimdal/lib/hcrypto/evp-hcrypto.h @@ -42,6 +42,8 @@ #define EVP_hcrypto_md5 hc_EVP_hcrypto_md5 #define EVP_hcrypto_sha1 hc_EVP_hcrypto_sha1 #define EVP_hcrypto_sha256 hc_EVP_hcrypto_sha256 +#define EVP_hcrypto_sha384 hc_EVP_hcrypto_sha384 +#define EVP_hcrypto_sha512 hc_EVP_hcrypto_sha512 #define EVP_hcrypto_des_cbc hc_EVP_hcrypto_des_cbc #define EVP_hcrypto_des_ede3_cbc hc_EVP_hcrypto_des_ede3_cbc #define EVP_hcrypto_aes_128_cbc hc_EVP_hcrypto_aes_128_cbc @@ -70,6 +72,8 @@ const EVP_MD * EVP_hcrypto_md4(void); const EVP_MD * EVP_hcrypto_md5(void); const EVP_MD * EVP_hcrypto_sha1(void); const EVP_MD * EVP_hcrypto_sha256(void); +const EVP_MD * EVP_hcrypto_sha384(void); +const EVP_MD * EVP_hcrypto_sha512(void); const EVP_CIPHER * EVP_hcrypto_rc4(void); const EVP_CIPHER * EVP_hcrypto_rc4_40(void); diff --git a/source4/heimdal/lib/hcrypto/evp.c b/source4/heimdal/lib/hcrypto/evp.c index da1a8940be8..7bd066fd5dc 100644 --- a/source4/heimdal/lib/hcrypto/evp.c +++ b/source4/heimdal/lib/hcrypto/evp.c @@ -360,6 +360,36 @@ EVP_sha256(void) return EVP_DEF_OP(HCRYPTO_DEF_PROVIDER, sha256); } +/** + * The message digest SHA384 + * + * @return the message digest type. + * + * @ingroup hcrypto_evp + */ + +const EVP_MD * +EVP_sha384(void) +{ + hcrypto_validate(); + return EVP_DEF_OP(HCRYPTO_DEF_PROVIDER, sha384); +} + +/** + * The message digest SHA512 + * + * @return the message digest type. + * + * @ingroup hcrypto_evp + */ + +const EVP_MD * +EVP_sha512(void) +{ + hcrypto_validate(); + return EVP_DEF_OP(HCRYPTO_DEF_PROVIDER, sha512); +} + /** * The message digest SHA1 * diff --git a/source4/heimdal/lib/hcrypto/evp.h b/source4/heimdal/lib/hcrypto/evp.h index 03ec175d597..c56eedec45b 100644 --- a/source4/heimdal/lib/hcrypto/evp.h +++ b/source4/heimdal/lib/hcrypto/evp.h @@ -96,6 +96,8 @@ #define EVP_sha hc_EVP_sha #define EVP_sha1 hc_EVP_sha1 #define EVP_sha256 hc_EVP_sha256 +#define EVP_sha384 hc_EVP_sha384 +#define EVP_sha512 hc_EVP_sha512 #define PKCS5_PBKDF2_HMAC_SHA1 hc_PKCS5_PBKDF2_HMAC_SHA1 #define EVP_BytesToKey hc_EVP_BytesToKey #define EVP_get_cipherbyname hc_EVP_get_cipherbyname @@ -225,6 +227,8 @@ HC_DEPRECATED_CRYPTO const EVP_MD *EVP_md5(void); const EVP_MD *EVP_sha(void); const EVP_MD *EVP_sha1(void); const EVP_MD *EVP_sha256(void); +const EVP_MD *EVP_sha384(void); +const EVP_MD *EVP_sha512(void); const EVP_CIPHER * EVP_aes_128_cbc(void); const EVP_CIPHER * EVP_aes_192_cbc(void); diff --git a/source4/heimdal/lib/hcrypto/hash.h b/source4/heimdal/lib/hcrypto/hash.h index cfec9cf3f34..498e5b1af01 100644 --- a/source4/heimdal/lib/hcrypto/hash.h +++ b/source4/heimdal/lib/hcrypto/hash.h @@ -66,4 +66,10 @@ cshift (uint32_t x, unsigned int n) return CRAYFIX((x << n) | (x >> (32 - n))); } +static inline uint64_t +cshift64 (uint64_t x, unsigned int n) +{ + return ((uint64_t)x << (uint64_t)n) | ((uint64_t)x >> ((uint64_t)64 - (uint64_t)n)); +} + #endif /* __hash_h__ */ diff --git a/source4/heimdal/lib/hcrypto/rsa-ltm.c b/source4/heimdal/lib/hcrypto/rsa-ltm.c index ad3686e403c..f4828104b65 100644 --- a/source4/heimdal/lib/hcrypto/rsa-ltm.c +++ b/source4/heimdal/lib/hcrypto/rsa-ltm.c @@ -398,7 +398,7 @@ ltm_rsa_private_decrypt(int flen, const unsigned char* from, if (flen > size) return -2; - mp_init_multi(&in, &n, &e, &out, &bi, &b, NULL); + mp_init_multi(&in, &n, &e, &out, &b, &bi, NULL); BN2mpz(&n, rsa->n); BN2mpz(&e, rsa->e); @@ -479,7 +479,7 @@ ltm_rsa_private_decrypt(int flen, const unsigned char* from, memmove(to, ptr, size); out: - mp_clear_multi(&e, &n, &in, &out, NULL); + mp_clear_multi(&e, &n, &in, &out, &b, &bi, NULL); return size; } @@ -518,7 +518,9 @@ ltm_rsa_generate_key(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb) ret = -1; - mp_init_multi(&el, &p, &q, &n, &n, &d, &dmp1, &dmq1, &iqmp, &t1, &t2, &t3, NULL); + mp_init_multi(&el, &p, &q, &n, &d, + &dmp1, &dmq1, &iqmp, + &t1, &t2, &t3, NULL); BN2mpz(&el, e); @@ -588,8 +590,9 @@ ltm_rsa_generate_key(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb) ret = 1; out: - mp_clear_multi(&el, &p, &q, &n, &d, &dmp1, - &dmq1, &iqmp, &t1, &t2, &t3, NULL); + mp_clear_multi(&el, &p, &q, &n, &d, + &dmp1, &dmq1, &iqmp, + &t1, &t2, &t3, NULL); return ret; } diff --git a/source4/heimdal/lib/hcrypto/sha.h b/source4/heimdal/lib/hcrypto/sha.h index 39e33cf8d0a..a1f5a993189 100644 --- a/source4/heimdal/lib/hcrypto/sha.h +++ b/source4/heimdal/lib/hcrypto/sha.h @@ -80,4 +80,30 @@ void SHA256_Init (SHA256_CTX *); void SHA256_Update (SHA256_CTX *, const void *, size_t); void SHA256_Final (void *, SHA256_CTX *); +/* + * SHA-2 512 + */ + +#define SHA512_DIGEST_LENGTH 64 + +struct hc_sha512state { + uint64_t sz[2]; + uint64_t counter[8]; + unsigned char save[128]; +}; + +typedef struct hc_sha512state SHA512_CTX; + +void SHA512_Init (SHA512_CTX *); +void SHA512_Update (SHA512_CTX *, const void *, size_t); +void SHA512_Final (void *, SHA512_CTX *); + +#define SHA384_DIGEST_LENGTH 48 + +typedef struct hc_sha512state SHA384_CTX; + +void SHA384_Init (SHA384_CTX *); +void SHA384_Update (SHA384_CTX *, const void *, size_t); +void SHA384_Final (void *, SHA384_CTX *); + #endif /* HEIM_SHA_H */ diff --git a/source4/heimdal/lib/hdb/hdb-keytab.c b/source4/heimdal/lib/hdb/hdb-keytab.c index 1b74eab2529..393981e47d8 100644 --- a/source4/heimdal/lib/hdb/hdb-keytab.c +++ b/source4/heimdal/lib/hdb/hdb-keytab.c @@ -117,13 +117,18 @@ hkt_open(krb5_context context, HDB * db, int flags, mode_t mode) } static krb5_error_code -hkt_fetch(krb5_context context, HDB * db, krb5_const_principal principal, - unsigned flags, hdb_entry_ex * entry) +hkt_fetch_kvno(krb5_context context, HDB * db, krb5_const_principal principal, + unsigned flags, unsigned kvno, hdb_entry_ex * entry) { hdb_keytab k = (hdb_keytab)db->hdb_db; krb5_error_code ret; krb5_keytab_entry ktentry; + if (!(flags & HDB_F_KVNO_SPECIFIED)) { + /* Preserve previous behaviour if no kvno specified */ + kvno = 0; + } + memset(&ktentry, 0, sizeof(ktentry)); entry->entry.flags.server = 1; @@ -143,7 +148,7 @@ hkt_fetch(krb5_context context, HDB * db, krb5_const_principal principal, * enctypes should work. */ - ret = krb5_kt_get_entry(context, k->keytab, principal, 0, 0, &ktentry); + ret = krb5_kt_get_entry(context, k->keytab, principal, kvno, 0, &ktentry); if (ret) { ret = HDB_ERR_NOENTRY; goto out; @@ -165,6 +170,13 @@ hkt_fetch(krb5_context context, HDB * db, krb5_const_principal principal, return ret; } +static krb5_error_code +hkt_fetch(krb5_context context, HDB * db, krb5_const_principal principal, + unsigned flags, hdb_entry_ex * entry) +{ + return hkt_fetch_kvno(context, db, principal, flags & ~HDB_F_KVNO_SPECIFIED, 0, entry); +} + static krb5_error_code hkt_store(krb5_context context, HDB * db, unsigned flags, hdb_entry_ex * entry) @@ -210,6 +222,7 @@ hdb_keytab_create(krb5_context context, HDB ** db, const char *arg) (*db)->hdb_open = hkt_open; (*db)->hdb_close = hkt_close; (*db)->hdb_fetch = hkt_fetch; + (*db)->hdb_fetch_kvno = hkt_fetch_kvno; (*db)->hdb_store = hkt_store; (*db)->hdb_remove = NULL; (*db)->hdb_firstkey = hkt_firstkey; diff --git a/source4/heimdal/lib/hdb/hdb.h b/source4/heimdal/lib/hdb/hdb.h index ca67d2ddd83..bcd190caa31 100644 --- a/source4/heimdal/lib/hdb/hdb.h +++ b/source4/heimdal/lib/hdb/hdb.h @@ -123,8 +123,18 @@ typedef struct HDB{ * should be fetch: client, server, krbtgt. */ krb5_error_code (*hdb_fetch)(krb5_context, struct HDB*, - krb5_const_principal, unsigned, unsigned, + krb5_const_principal, unsigned, hdb_entry_ex*); + /** + * Fetch an entry from the backend + * + * Fetch an entry from the backend, flags are what type of entry + * should be fetch: client, server, krbtgt. + * knvo (if specified and flags HDB_F_KVNO_SPECIFIED set) is the kvno to get + */ + krb5_error_code (*hdb_fetch_kvno)(krb5_context, struct HDB*, + krb5_const_principal, unsigned, unsigned, + hdb_entry_ex*); /** * Store an entry to database */ diff --git a/source4/heimdal/lib/hdb/keytab.c b/source4/heimdal/lib/hdb/keytab.c index efaed7f420f..b8cc0d47ee8 100644 --- a/source4/heimdal/lib/hdb/keytab.c +++ b/source4/heimdal/lib/hdb/keytab.c @@ -210,10 +210,18 @@ hdb_get_entry(krb5_context context, (*db->hdb_destroy)(context, db); goto out2; } - ret = (*db->hdb_fetch)(context, db, principal, - HDB_F_DECRYPT| - HDB_F_GET_CLIENT|HDB_F_GET_SERVER|HDB_F_GET_KRBTGT, - 0, &ent); + + if (*db->hdb_fetch_kvno) { + ret = (*db->hdb_fetch_kvno)(context, db, principal, + HDB_F_DECRYPT|HDB_F_KVNO_SPECIFIED| + HDB_F_GET_CLIENT|HDB_F_GET_SERVER|HDB_F_GET_KRBTGT, + kvno, &ent); + } else { + ret = (*db->hdb_fetch)(context, db, principal, + HDB_F_DECRYPT| + HDB_F_GET_CLIENT|HDB_F_GET_SERVER|HDB_F_GET_KRBTGT, + &ent); + } if(ret == HDB_ERR_NOENTRY) { ret = KRB5_KT_NOTFOUND; diff --git a/source4/heimdal/lib/hx509/crypto.c b/source4/heimdal/lib/hx509/crypto.c index c2e5e70748f..de7717af029 100644 --- a/source4/heimdal/lib/hx509/crypto.c +++ b/source4/heimdal/lib/hx509/crypto.c @@ -659,7 +659,11 @@ rsa_create_signature(hx509_context context, else sig_oid = signer->signature_alg; - if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_SHA256WITHRSAENCRYPTION) == 0) { + if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_SHA512WITHRSAENCRYPTION) == 0) { + digest_alg = hx509_signature_sha512(); + } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_SHA384WITHRSAENCRYPTION) == 0) { + digest_alg = hx509_signature_sha384(); + } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_SHA256WITHRSAENCRYPTION) == 0) { digest_alg = hx509_signature_sha256(); } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_SHA1WITHRSAENCRYPTION) == 0) { digest_alg = hx509_signature_sha1(); @@ -1241,6 +1245,32 @@ static const struct signature_alg pkcs1_rsa_sha1_alg = { rsa_create_signature }; +static const struct signature_alg rsa_with_sha512_alg = { + "rsa-with-sha512", + ASN1_OID_ID_PKCS1_SHA512WITHRSAENCRYPTION, + &_hx509_signature_rsa_with_sha512_data, + ASN1_OID_ID_PKCS1_RSAENCRYPTION, + &_hx509_signature_sha512_data, + PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK, + 0, + NULL, + rsa_verify_signature, + rsa_create_signature +}; + +static const struct signature_alg rsa_with_sha384_alg = { + "rsa-with-sha384", + ASN1_OID_ID_PKCS1_SHA384WITHRSAENCRYPTION, + &_hx509_signature_rsa_with_sha384_data, + ASN1_OID_ID_PKCS1_RSAENCRYPTION, + &_hx509_signature_sha384_data, + PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK, + 0, + NULL, + rsa_verify_signature, + rsa_create_signature +}; + static const struct signature_alg rsa_with_sha256_alg = { "rsa-with-sha256", ASN1_OID_ID_PKCS1_SHA256WITHRSAENCRYPTION, @@ -1306,6 +1336,32 @@ static const struct signature_alg dsa_sha1_alg = { /* create_signature */ NULL, }; +static const struct signature_alg sha512_alg = { + "sha-512", + ASN1_OID_ID_SHA512, + &_hx509_signature_sha512_data, + NULL, + NULL, + SIG_DIGEST, + 0, + EVP_sha512, + evp_md_verify_signature, + evp_md_create_signature +}; + +static const struct signature_alg sha384_alg = { + "sha-384", + ASN1_OID_ID_SHA512, + &_hx509_signature_sha384_data, + NULL, + NULL, + SIG_DIGEST, + 0, + EVP_sha384, + evp_md_verify_signature, + evp_md_create_signature +}; + static const struct signature_alg sha256_alg = { "sha-256", ASN1_OID_ID_SHA256, @@ -1355,6 +1411,8 @@ static const struct signature_alg *sig_algs[] = { &ecdsa_with_sha256_alg, &ecdsa_with_sha1_alg, #endif + &rsa_with_sha512_alg, + &rsa_with_sha384_alg, &rsa_with_sha256_alg, &rsa_with_sha1_alg, &rsa_with_sha1_alg_secsig, @@ -1362,6 +1420,8 @@ static const struct signature_alg *sig_algs[] = { &rsa_with_md5_alg, &heim_rsa_pkcs1_x509, &dsa_sha1_alg, + &sha512_alg, + &sha384_alg, &sha256_alg, &sha1_alg, &md5_alg, @@ -2460,7 +2520,7 @@ hx509_crypto_encrypt(hx509_crypto crypto, heim_octet_string **ciphertext) { EVP_CIPHER_CTX evp; - size_t padsize; + size_t padsize, bsize; int ret; *ciphertext = NULL; @@ -2488,14 +2548,16 @@ hx509_crypto_encrypt(hx509_crypto crypto, } assert(crypto->flags & PADDING_FLAGS); + + bsize = EVP_CIPHER_block_size(crypto->c); + padsize = 0; + if (crypto->flags & PADDING_NONE) { - padsize = 0; + if (bsize != 1 && (length % bsize) != 0) + return HX509_CMS_PADDING_ERROR; } else if (crypto->flags & PADDING_PKCS7) { - if (EVP_CIPHER_block_size(crypto->c) == 1) { - } else { - int bsize = EVP_CIPHER_block_size(crypto->c); + if (bsize != 1) padsize = bsize - (length % bsize); - } } (*ciphertext)->length = length + padsize; diff --git a/source4/heimdal/lib/krb5/context.c b/source4/heimdal/lib/krb5/context.c index 0897c5e7a09..f68ab46cec9 100644 --- a/source4/heimdal/lib/krb5/context.c +++ b/source4/heimdal/lib/krb5/context.c @@ -104,6 +104,18 @@ init_context_from_config_file(krb5_context context) INIT_FIELD(context, string, http_proxy, NULL, "http_proxy"); + ret = krb5_config_get_bool_default(context, NULL, FALSE, + "libdefaults", + "allow_weak_crypto", NULL); + if (ret) { + krb5_enctype_enable(context, ETYPE_DES_CBC_CRC); + krb5_enctype_enable(context, ETYPE_DES_CBC_MD4); + krb5_enctype_enable(context, ETYPE_DES_CBC_MD5); + krb5_enctype_enable(context, ETYPE_DES_CBC_NONE); + krb5_enctype_enable(context, ETYPE_DES_CFB64_NONE); + krb5_enctype_enable(context, ETYPE_DES_PCBC_NONE); + } + ret = set_etypes (context, "default_etypes", &tmptypes); if(ret) return ret; @@ -194,18 +206,6 @@ init_context_from_config_file(krb5_context context) context->default_cc_name = NULL; context->default_cc_name_set = 0; - ret = krb5_config_get_bool_default(context, NULL, FALSE, - "libdefaults", - "allow_weak_crypto", NULL); - if (ret) { - krb5_enctype_enable(context, ETYPE_DES_CBC_CRC); - krb5_enctype_enable(context, ETYPE_DES_CBC_MD4); - krb5_enctype_enable(context, ETYPE_DES_CBC_MD5); - krb5_enctype_enable(context, ETYPE_DES_CBC_NONE); - krb5_enctype_enable(context, ETYPE_DES_CFB64_NONE); - krb5_enctype_enable(context, ETYPE_DES_PCBC_NONE); - } - s = krb5_config_get_strings(context, NULL, "logging", "krb5", NULL); if(s) { char **p; diff --git a/source4/heimdal/lib/krb5/crypto.c b/source4/heimdal/lib/krb5/crypto.c index 47f910260e3..2502cc672f5 100644 --- a/source4/heimdal/lib/krb5/crypto.c +++ b/source4/heimdal/lib/krb5/crypto.c @@ -1847,9 +1847,11 @@ verify_checksum(krb5_context context, } if(ct->checksumsize != cksum->checksum.length) { krb5_clear_error_message (context); - krb5_set_error_message (context, KRB5KRB_AP_ERR_BAD_INTEGRITY, - N_("Decrypt integrity check failed for checksum type %s, length was %u, expected %u", ""), - ct->name, (unsigned)cksum->checksum.length, (unsigned)ct->checksumsize); + krb5_set_error_message(context, KRB5KRB_AP_ERR_BAD_INTEGRITY, + N_("Decrypt integrity check failed for checksum type %s, " + "length was %u, expected %u", ""), + ct->name, (unsigned)cksum->checksum.length, + (unsigned)ct->checksumsize); return KRB5KRB_AP_ERR_BAD_INTEGRITY; /* XXX */ } @@ -1857,18 +1859,18 @@ verify_checksum(krb5_context context, if(keyed_checksum) { struct checksum_type *kct; if (crypto == NULL) { - krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, - N_("Checksum type %s is keyed but no " - "crypto context (key) was passed in", ""), - ct->name); + krb5_set_error_message(context, KRB5_PROG_SUMTYPE_NOSUPP, + N_("Checksum type %s is keyed but no " + "crypto context (key) was passed in", ""), + ct->name); return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */ } kct = crypto->et->keyed_checksum; if (kct != NULL && kct->type != ct->type) { - krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, - N_("Checksum type %s is keyed, but " - "the key type %s passed didnt have that checksum " - "type as the keyed type", ""), + krb5_set_error_message(context, KRB5_PROG_SUMTYPE_NOSUPP, + N_("Checksum type %s is keyed, but " + "the key type %s passed didnt have that checksum " + "type as the keyed type", ""), ct->name, crypto->et->name); return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */ } @@ -1878,13 +1880,20 @@ verify_checksum(krb5_context context, return ret; } else dkey = NULL; + + /* + * If checksum have a verify function, lets use that instead of + * calling ->checksum and then compare result. + */ + if(ct->verify) { ret = (*ct->verify)(context, dkey, data, len, usage, cksum); - if (ret == KRB5KRB_AP_ERR_BAD_INTEGRITY) { - krb5_set_error_message (context, KRB5KRB_AP_ERR_BAD_INTEGRITY, - N_("Decrypt integrity check failed for checksum type %s, key type %s", ""), - ct->name, crypto->et->name); - } + if (ret) + krb5_set_error_message(context, ret, + N_("Decrypt integrity check failed for checksum " + "type %s, key type %s", ""), + ct->name, crypto->et->name); + return ret; } ret = krb5_data_alloc (&c.checksum, ct->checksumsize); @@ -1900,10 +1909,11 @@ verify_checksum(krb5_context context, if(c.checksum.length != cksum->checksum.length || ct_memcmp(c.checksum.data, cksum->checksum.data, c.checksum.length)) { krb5_clear_error_message (context); - krb5_set_error_message (context, KRB5KRB_AP_ERR_BAD_INTEGRITY, - N_("Decrypt integrity check failed for checksum type %s, key type %s", ""), - ct->name, crypto->et->name); ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; + krb5_set_error_message(context, ret, + N_("Decrypt integrity check failed for checksum " + "type %s, key type %s", ""), + ct->name, crypto->et->name); } else { ret = 0; } diff --git a/source4/heimdal/lib/krb5/init_creds_pw.c b/source4/heimdal/lib/krb5/init_creds_pw.c index 869687aa63b..29b882d0531 100644 --- a/source4/heimdal/lib/krb5/init_creds_pw.c +++ b/source4/heimdal/lib/krb5/init_creds_pw.c @@ -1418,6 +1418,17 @@ krb5_init_creds_set_service(krb5_context context, if (ret) return ret; } + + /* + * This is for Windows RODC that are picky about what name type + * the server principal have, and the really strange part is that + * they are picky about the AS-REQ name type and not the TGS-REQ + * later. Oh well. + */ + + if (krb5_principal_is_krbtgt(context, principal)) + krb5_principal_set_type(context, principal, KRB5_NT_SRV_INST); + krb5_free_principal(context, ctx->cred.server); ctx->cred.server = principal; diff --git a/source4/heimdal/lib/krb5/krbhst.c b/source4/heimdal/lib/krb5/krbhst.c index d8646f0537a..7d111578481 100644 --- a/source4/heimdal/lib/krb5/krbhst.c +++ b/source4/heimdal/lib/krb5/krbhst.c @@ -356,61 +356,66 @@ make_hints(struct addrinfo *hints, int proto) } } -/* - * return an `struct addrinfo *' in `ai' corresponding to the information - * in `host'. free:ing is handled by krb5_krbhst_free. +/** + * Return an `struct addrinfo *' for a KDC host. + * + * Returns an the struct addrinfo in in that corresponds to the + * information in `host'. free:ing is handled by krb5_krbhst_free, so + * the returned ai must not be released. + * + * @ingroup krb5 */ KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_krbhst_get_addrinfo(krb5_context context, krb5_krbhst_info *host, struct addrinfo **ai) { - struct addrinfo hints; - char portstr[NI_MAXSERV]; - int ret; + int ret = 0; if (host->ai == NULL) { - make_hints(&hints, host->proto); - hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV; + struct addrinfo hints; + char portstr[NI_MAXSERV]; + char *hostname = host->hostname; + snprintf (portstr, sizeof(portstr), "%d", host->port); + make_hints(&hints, host->proto); + + /** + * First try this as an IP address, this allows us to add a + * dot at the end to stop using the search domains. + */ + + hints.ai_flags |= AI_NUMERICHOST | AI_NUMERICSERV; - /* First try this as an IP address - the flags we have set - * will prevent it from looking up a name */ ret = getaddrinfo(host->hostname, portstr, &hints, &host->ai); - if (ret == 0) { - *ai = host->ai; - return 0; + if (ret == 0) + goto out; + + /** + * If the hostname contains a dot, assumes it's a FQDN and + * don't use search domains since that might be painfully slow + * when machine is disconnected from that network. + */ + + hints.ai_flags &= ~(AI_NUMERICHOST); + + if (strchr(hostname, '.') && hostname[strlen(hostname) - 1] != '.') { + ret = asprintf(&hostname, "%s.", host->hostname); + if (ret < 0 || hostname == NULL) + return ENOMEM; } - hints.ai_flags &= ~AI_NUMERICHOST; - - /* Now that we know it's not an IP, we can manipulate - it as a dotted-name, to add a final . if we think - it's a fully qualified DNS name */ - if (strchr(host->hostname, '.') && - host->hostname[strlen(host->hostname)-1] != '.') { - char *hostname_dot = NULL; - - /* avoid expansion of search domains from resolv.conf - - these can be very slow if the DNS server is not up - for the searched domain */ - hostname_dot = malloc(strlen(host->hostname)+2); - if (hostname_dot) { - strcpy(hostname_dot, host->hostname); - hostname_dot[strlen(host->hostname)] = '.'; - hostname_dot[strlen(host->hostname)+1] = 0; - } - ret = getaddrinfo(hostname_dot?hostname_dot:host->hostname, portstr, &hints, &host->ai); - if (hostname_dot) - free(hostname_dot); - } else { - ret = getaddrinfo(host->hostname, portstr, &hints, &host->ai); + ret = getaddrinfo(hostname, portstr, &hints, &host->ai); + if (hostname != host->hostname) + free(hostname); + if (ret) { + ret = krb5_eai_to_heim_errno(ret, errno); + goto out; } - if (ret) - return krb5_eai_to_heim_errno(ret, errno); } + out: *ai = host->ai; - return 0; + return ret; } static krb5_boolean diff --git a/source4/heimdal/lib/roken/roken.h.in b/source4/heimdal/lib/roken/roken.h.in index d6e9024bd08..0c0dd200350 100644 --- a/source4/heimdal/lib/roken/roken.h.in +++ b/source4/heimdal/lib/roken/roken.h.in @@ -1072,7 +1072,7 @@ void rk_qsort(void *, size_t, size_t, int (*)(const void *, const void *)); #endif -#if defined(__linux__) && defined(SOCK_CLOEXEC) && !defined(SOCKET_WRAPPER_REPLACE) +#if defined(__linux__) && defined(SOCK_CLOEXEC) && !defined(SOCKET_WRAPPER_REPLACE) && !defined(__SOCKET_WRAPPER_H__) #undef socket #define socket(_fam,_type,_prot) rk_socket(_fam,_type,_prot) int ROKEN_LIB_FUNCTION rk_socket(int, int, int); -- cgit