From cb95154a6f6a0ecbc9d5f3535b4e0bf9fb474e30 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 16 May 2023 17:07:07 +1200 Subject: [PATCH 1/8] hdb: Make maximum ticket lifetime and renew time signed integers This allows for negative lifetimes to be encoded, and fits in better with our use elsewhere of time_t, which in POSIX is a signed integer type. Signed-off-by: Joseph Sutton --- lib/hdb/hdb.asn1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/hdb/hdb.asn1 b/lib/hdb/hdb.asn1 index 49318c8113..c0d8373208 100644 --- a/lib/hdb/hdb.asn1 +++ b/lib/hdb/hdb.asn1 @@ -233,8 +233,8 @@ HDB_entry ::= SEQUENCE { valid-start[5] KerberosTime OPTIONAL, valid-end[6] KerberosTime OPTIONAL, pw-end[7] KerberosTime OPTIONAL, - max-life[8] INTEGER (0..4294967295) OPTIONAL, - max-renew[9] INTEGER (0..4294967295) OPTIONAL, + max-life[8] INTEGER (-2147483648..2147483647) OPTIONAL, + max-renew[9] INTEGER (-2147483648..2147483647) OPTIONAL, flags[10] HDBFlags, etypes[11] HDB-EncTypeList OPTIONAL, generation[12] GENERATION OPTIONAL, From aa075bfe5e5d000e4b716545d3e30e2c21f4aeaf Mon Sep 17 00:00:00 2001 From: Nicolas Williams Date: Wed, 21 Jan 2026 17:33:19 -0600 Subject: [PATCH 2/8] kadmin: Make maximum ticket lifetime and renew time signed integers --- kadmin/load.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/kadmin/load.c b/kadmin/load.c index f62f8b96dc..9e757ac237 100644 --- a/kadmin/load.c +++ b/kadmin/load.c @@ -118,7 +118,7 @@ parse_time_string_alloc (time_t **t, const char *s) */ static int -parse_integer(unsigned int *u, const char *s) +parse_unsigned(unsigned int *u, const char *s) { if(strcmp(s, "-") == 0) return 0; @@ -128,17 +128,26 @@ parse_integer(unsigned int *u, const char *s) } static int -parse_integer_alloc (unsigned int **u, const char *s) +parse_int(int *u, const char *s) { - unsigned int tmp; - int ret; + if(strcmp(s, "-") == 0) + return 0; + if (sscanf(s, "%u", u) != 1) + return -1; + return 1; +} + +static int +parse_int_alloc(int **u, const char *s) +{ + int tmp, ret; *u = NULL; - ret = parse_integer (&tmp, s); + ret = parse_int(&tmp, s); if (ret == 1) { - *u = malloc (sizeof (**u)); + *u = malloc(sizeof (**u)); if (*u == NULL) - krb5_errx (context, 1, "malloc: out of memory"); + krb5_errx(context, 1, "malloc: out of memory"); **u = tmp; } return ret; @@ -278,9 +287,9 @@ parse_hdbflags2int(HDBFlags *f, const char *s) int ret; unsigned int tmp; - ret = parse_integer (&tmp, s); + ret = parse_unsigned(&tmp, s); if (ret == 1) - *f = int2HDBFlags (tmp); + *f = int2HDBFlags(tmp); return ret; } @@ -560,7 +569,7 @@ doit(const char *filename, int mergep) continue; } - if (parse_integer_alloc (&ent.max_life, e.max_life) == -1) { + if (parse_int_alloc(&ent.max_life, e.max_life) == -1) { fprintf (stderr, "%s:%d:error parsing lifetime (%s)\n", filename, lineno, e.max_life); hdb_free_entry (context, db, &ent); @@ -568,7 +577,7 @@ doit(const char *filename, int mergep) continue; } - if (parse_integer_alloc (&ent.max_renew, e.max_renew) == -1) { + if (parse_int_alloc(&ent.max_renew, e.max_renew) == -1) { fprintf (stderr, "%s:%d:error parsing lifetime (%s)\n", filename, lineno, e.max_renew); hdb_free_entry (context, db, &ent); From 2390273f3cf9615e6e0c6643308b67620a58f48a Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Tue, 16 May 2023 17:10:09 +1200 Subject: [PATCH 3/8] kdc: Always apply maximum ticket lifetime and renew time when non-NULL This allows a lifetime of zero to work. Signed-off-by: Joseph Sutton --- kdc/kerberos5.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/kdc/kerberos5.c b/kdc/kerberos5.c index bb64f54ee1..62bf016c17 100644 --- a/kdc/kerberos5.c +++ b/kdc/kerberos5.c @@ -2547,11 +2547,11 @@ _kdc_as_rep(astgs_request_t r) */ if (r->pa_max_life > 0) t = rk_time_add(start, min(rk_time_sub(t, start), r->pa_max_life)); - else if (r->client->max_life && *r->client->max_life) + else if (r->client->max_life) t = rk_time_add(start, min(rk_time_sub(t, start), *r->client->max_life)); - if (r->server->max_life && *r->server->max_life) + if (r->server->max_life) t = rk_time_add(start, min(rk_time_sub(t, start), *r->server->max_life)); @@ -2582,10 +2582,10 @@ _kdc_as_rep(astgs_request_t r) t = *b->rtime; if(t == 0) t = MAX_TIME; - if(r->client->max_renew && *r->client->max_renew) + if(r->client->max_renew) t = rk_time_add(start, min(rk_time_sub(t, start), *r->client->max_renew)); - if(r->server->max_renew && *r->server->max_renew) + if(r->server->max_renew) t = rk_time_add(start, min(rk_time_sub(t, start), *r->server->max_renew)); #if 0 From eab1a243a2e04abdaf0cd1cbc19220b36de7375f Mon Sep 17 00:00:00 2001 From: Nicolas Williams Date: Wed, 21 Jan 2026 18:06:30 -0600 Subject: [PATCH 4/8] hdb: Get LDAP backend building again --- lib/hdb/hdb-ldap.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/lib/hdb/hdb-ldap.c b/lib/hdb/hdb-ldap.c index 902426d127..b4c0b72232 100644 --- a/lib/hdb/hdb-ldap.c +++ b/lib/hdb/hdb-ldap.c @@ -79,7 +79,7 @@ struct hdbldapdb { * */ -static char * krb5kdcentry_attrs[] = { +static const char * krb5kdcentry_attrs[] = { "cn", "createTimestamp", "creatorsName", @@ -107,7 +107,7 @@ static char * krb5kdcentry_attrs[] = { NULL }; -static char *krb5principal_attrs[] = { +static const char *krb5principal_attrs[] = { "cn", "createTimestamp", "creatorsName", @@ -384,6 +384,8 @@ static int bervalstrcmp(struct berval *v, const char *str) { size_t len = strlen(str); + if (v->bv_val == NULL) + return 1; return (v->bv_len == len) && strncasecmp(str, (char *)v->bv_val, len) == 0; } @@ -788,7 +790,8 @@ LDAP_dn2principal(krb5_context context, HDB * db, const char *dn, goto out; rc = ldap_search_ext_s(HDB2LDAP(db), dn, LDAP_SCOPE_SUBTREE, - filter, krb5principal_attrs, 0, + /* XXX strict aliasing violation */ + filter, (char **)rk_UNCONST(krb5principal_attrs), 0, NULL, NULL, NULL, 0, &res); if (check_ldap(context, db, rc)) { @@ -905,7 +908,8 @@ LDAP__lookup_princ(krb5_context context, rc = ldap_search_ext_s(HDB2LDAP(db), HDB2BASE(db), LDAP_SCOPE_SUBTREE, filter, - krb5kdcentry_attrs, 0, + /* XXX strict aliasing violation */ + (char **)rk_UNCONST(krb5kdcentry_attrs), 0, NULL, NULL, NULL, 0, msg); if (check_ldap(context, db, rc)) { @@ -941,7 +945,8 @@ LDAP__lookup_princ(krb5_context context, goto out; rc = ldap_search_ext_s(HDB2LDAP(db), HDB2BASE(db), LDAP_SCOPE_SUBTREE, - filter, krb5kdcentry_attrs, 0, + /* XXX strict aliasing violation */ + filter, (char **)rk_UNCONST(krb5kdcentry_attrs), 0, NULL, NULL, NULL, 0, msg); if (check_ldap(context, db, rc)) { @@ -1578,7 +1583,8 @@ LDAP_firstkey(krb5_context context, HDB *db, unsigned flags, ret = ldap_search_ext(HDB2LDAP(db), HDB2BASE(db), LDAP_SCOPE_SUBTREE, "(|(objectClass=krb5Principal)(objectClass=sambaSamAccount))", - krb5kdcentry_attrs, 0, + /* XXX strict aliasing violation */ + (char **)rk_UNCONST(krb5kdcentry_attrs), 0, NULL, NULL, NULL, 0, &msgid); if (ret != LDAP_SUCCESS || msgid < 0) return HDB_ERR_NOENTRY; @@ -1605,7 +1611,7 @@ LDAP__connect(krb5_context context, HDB * db) * credentials instead of empty credentials you will get a SASL * bind in progress message. */ - struct berval bv = { 0, "" }; + struct berval bv = { 0, 0 }; const char *sasl_method = "EXTERNAL"; const char *bind_dn = NULL; From 3b1430cf5144edc6cbca93ce3ae63ff36a13fdb5 Mon Sep 17 00:00:00 2001 From: Nicolas Williams Date: Wed, 21 Jan 2026 18:06:51 -0600 Subject: [PATCH 5/8] kdc: Get altsecid_gss_preauth_authorize building --- kdc/altsecid_gss_preauth_authorizer.c | 39 ++++++++++++++------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/kdc/altsecid_gss_preauth_authorizer.c b/kdc/altsecid_gss_preauth_authorizer.c index 17d3ee31bf..6a2161bf55 100644 --- a/kdc/altsecid_gss_preauth_authorizer.c +++ b/kdc/altsecid_gss_preauth_authorizer.c @@ -179,8 +179,8 @@ ad_connect(krb5_context context, struct rk_resource_record *rr; char *domain; - asprintf(&domain, "_ldap._tcp.%s", realm); - if (domain == NULL) { + if (asprintf(&domain, "_ldap._tcp.%s", realm) == -1 || + domain == NULL) { ret = krb5_enomem(context); goto out; } @@ -224,8 +224,8 @@ ad_connect(krb5_context context, LDAP *ld; char *url = NULL; - asprintf(&url, "ldap://%s:%d", servers[i].server, servers[i].port); - if (url == NULL) { + if (asprintf(&url, "ldap://%s:%d", servers[i].server, servers[i].port) == -1 || + url == NULL) { ret = krb5_enomem(context); goto out; } @@ -281,6 +281,7 @@ ad_lookup(krb5_context context, krb5_principal *canon_principal, kdc_data_t *requestor_sid) { + static const char *attrs[] = { "sAMAccountName", "objectSid", NULL }; krb5_error_code ret; OM_uint32 minor; const char *mech_type_str, *p; @@ -288,8 +289,7 @@ ad_lookup(krb5_context context, gss_buffer_desc initiator_name_buf = GSS_C_EMPTY_BUFFER; LDAPMessage *m = NULL, *m0; char *basedn = NULL; - int lret; - char *attrs[] = { "sAMAccountName", "objectSid", NULL }; + int lret, aret; struct berval **values = NULL; *canon_principal = NULL; @@ -309,20 +309,20 @@ ad_lookup(krb5_context context, goto out; if ((p = strrchr(mech_type_str, '-')) != NULL) { - asprintf(&filter, "(&(objectClass=user)" - "(|(altSecurityIdentities=%.*s:%.*s)(altSecurityIdentities=%s:%.*s)))", - (int)(p - mech_type_str), mech_type_str, - (int)initiator_name_buf.length, (char *)initiator_name_buf.value, - mech_type_str, - (int)initiator_name_buf.length, - (char *)initiator_name_buf.value); + aret = asprintf(&filter, "(&(objectClass=user)" + "(|(altSecurityIdentities=%.*s:%.*s)(altSecurityIdentities=%s:%.*s)))", + (int)(p - mech_type_str), mech_type_str, + (int)initiator_name_buf.length, (char *)initiator_name_buf.value, + mech_type_str, + (int)initiator_name_buf.length, + (char *)initiator_name_buf.value); } else { - asprintf(&filter, "(&(objectClass=user)(altSecurityIdentities=%s:%.*s))", - mech_type_str, - (int)initiator_name_buf.length, - (char *)initiator_name_buf.value); + aret = asprintf(&filter, "(&(objectClass=user)(altSecurityIdentities=%s:%.*s))", + mech_type_str, + (int)initiator_name_buf.length, + (char *)initiator_name_buf.value); } - if (filter == NULL) + if (aret == -1 || filter == NULL) goto enomem; lret = ldap_domain2dn(realm, &basedn); @@ -330,7 +330,8 @@ ad_lookup(krb5_context context, goto out; lret = ldap_search_ext_s(server->ld, basedn, LDAP_SCOPE_SUBTREE, - filter, attrs, 0, + /* XXX strict aliasing violation */ + filter, (char **)rk_UNCONST(attrs), 0, NULL, NULL, NULL, 1, &m); if (lret == LDAP_SIZELIMIT_EXCEEDED) ret = KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE; From 023d7f9d9a06173d2d925b1978d6f7adceb3b894 Mon Sep 17 00:00:00 2001 From: Nicolas Williams Date: Wed, 21 Jan 2026 18:08:39 -0600 Subject: [PATCH 6/8] kdc: Make MAX_TIME INT32_MAX always This just to be consistent with the new max value of HDB_entry's max_life. 68 years is long enough. --- kdc/kerberos5.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kdc/kerberos5.c b/kdc/kerberos5.c index 62bf016c17..f780103d04 100644 --- a/kdc/kerberos5.c +++ b/kdc/kerberos5.c @@ -37,16 +37,16 @@ #if SIZEOF_TIME_T == 4 #define MAX_TIME ((time_t)INT32_MAX) #elif SIZEOF_TIME_T == 8 -#define MAX_TIME ((time_t)INT64_MAX) +#define MAX_TIME ((time_t)INT32_MAX) #else #error "Unexpected sizeof(time_t)" #endif #else #if SIZEOF_TIME_T == 4 -#define MAX_TIME ((time_t)UINT32_MAX) +#define MAX_TIME ((time_t)INT32_MAX) #else -#define MAX_TIME ((time_t)UINT64_MAX) +#define MAX_TIME ((time_t)INT32_MAX) #endif #endif From d10f153d6942103eb933e0027f8b52c6a2104830 Mon Sep 17 00:00:00 2001 From: Nicolas Williams Date: Wed, 21 Jan 2026 18:21:20 -0600 Subject: [PATCH 7/8] NEWS: Add upgrade/downgrade considerations to release notes --- NEWS | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 0be68430a3..57fcbf9edb 100644 --- a/NEWS +++ b/NEWS @@ -128,7 +128,17 @@ Features removed: Feature removal warnings: - - 1DES and RC4 may be remove in Heimdal 8.2 + - 1DES and RC4 may be removed in Heimdal 8.2 + + Upgrade considerations: + + - Due to a change in HDB schema operators should check that Heimdal 8.x can + dump HDBs modified by Heimdal 7.x before upgrading from 7.x to 8.x. + + Downgrade considerations: + + - Due to a change in HDB schema operators should check that Heimdal 7.x can + dump HDBs modified by Heimdal 8.x before downgrading from 8.x to 7.x. Release Notes - Heimdal - Version Heimdal 7.8 From 4111c8dfd7663fdc1085a7c59e49d74f682670dd Mon Sep 17 00:00:00 2001 From: Nicolas Williams Date: Wed, 21 Jan 2026 18:21:32 -0600 Subject: [PATCH 8/8] NEWS: Fix formatting --- NEWS | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/NEWS b/NEWS index 57fcbf9edb..3963590e95 100644 --- a/NEWS +++ b/NEWS @@ -1,8 +1,7 @@ -Partial news for a future Heimdal 8.0 release -- but NOTE WELL that this is NOT -a release at this time! +Release Notes - Heimdal - Version Heimdal 8.0 (future) -Bug fixes + Bug fixes: - Errors found by the Coverity static analysis. - Errors found by the LLVM scan-build static analyzer. @@ -11,7 +10,7 @@ Bug fixes - iprop bugs, race conditions, and performance - Many misc. bugs -Defaults changes: + Defaults changes: - Default enctypes set to: aes256-cts-hmac-sha1-96 aes256-cts-hmac-sha384-192. - 1DES now disabled by default in the build configuration. @@ -19,7 +18,7 @@ Defaults changes: (Use `--with-3des=no` to disable 3DES.) (Use `--with-arcfour` to disable RC4.) -Features: + Features: - OpenSSL 3 support (hcrypto has been removed). - OpenSSL 3 provider support, including propq (e.g., for enabling FIPS) and @@ -119,14 +118,14 @@ Features: - Improved plugin interfaces. - roken: Add secure_getenv() and issuid(), use them extensively. -Features removed: + Features removed: - NTLM support. - "digest" server functionality in KDC (for NTLM). - OTP. - libhcrypto. -Feature removal warnings: + Feature removal warnings: - 1DES and RC4 may be removed in Heimdal 8.2