From 02b83c5762ab58213baecdbe53dfdc77eccc8e52 Mon Sep 17 00:00:00 2001 From: MSVSphere Packaging Team Date: Mon, 11 Dec 2023 16:23:26 +0300 Subject: [PATCH] import krb5-1.18.2-25.el8_8 --- ...tead-of-9-for-unkeyed-SHA-1-checksum.patch | 184 ++++ .../0153-Add-PAC-ticket-signature-APIs.patch | 840 ++++++++++++++++++ ...Factor-out-PAC-checksum-verification.patch | 258 ++++++ SOURCES/0155-Add-PAC-full-checksums.patch | 673 ++++++++++++++ ...rt-PAC-full-checksum-w-o-ticket-chec.patch | 140 +++ ...Fix-integer-overflows-in-PAC-parsing.patch | 14 +- SPECS/krb5.spec | 22 +- 7 files changed, 2121 insertions(+), 10 deletions(-) create mode 100644 SOURCES/0152-Use-14-instead-of-9-for-unkeyed-SHA-1-checksum.patch create mode 100644 SOURCES/0153-Add-PAC-ticket-signature-APIs.patch create mode 100644 SOURCES/0154-Factor-out-PAC-checksum-verification.patch create mode 100644 SOURCES/0155-Add-PAC-full-checksums.patch create mode 100644 SOURCES/0156-downstream-Support-PAC-full-checksum-w-o-ticket-chec.patch diff --git a/SOURCES/0152-Use-14-instead-of-9-for-unkeyed-SHA-1-checksum.patch b/SOURCES/0152-Use-14-instead-of-9-for-unkeyed-SHA-1-checksum.patch new file mode 100644 index 0000000..d23f854 --- /dev/null +++ b/SOURCES/0152-Use-14-instead-of-9-for-unkeyed-SHA-1-checksum.patch @@ -0,0 +1,184 @@ +From 9f3e127806d14b84d40abdfeae8fcd0daa1e6a4f Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Sat, 11 Dec 2021 01:25:34 -0500 +Subject: [PATCH] Use 14 instead of 9 for unkeyed SHA-1 checksum + +Although MIT krb5 had been using the value 9 for unkeyed SHA-1 since +its 1.0 release in 1996, RFC 3961 instead assigned this value to +rsa-md5-des3 (likely never used), and assigned the values 10 and 14 to +SHA-1. Heimdal and Microsoft use the value 14. Unkeyed SHA-1 almost +never appears on the wire, but has been seen in PKINIT asChecksum +fields in replies from Windows KDCs (despite the field being specified +as a keyed checksum). + +Define a new symbol CKSUMTYPE_SHA1 with the value 14, and use it where +we currently use CKSUMTYPE_NIST_SHA. Continue to allow the value 9 +for ABI compatibility. Remove the pkinit_clnt.c workaround as the +value 14 will now work without adjustment. + +ticket: 9040 (new) +--- + doc/appdev/refs/macros/index.rst | 1 + + src/include/krb5/krb5.hin | 6 ++++++ + src/lib/crypto/crypto_tests/t_cksums.c | 2 +- + src/lib/crypto/krb/cksumtypes.c | 6 ++++++ + src/lib/gssapi/mechglue/g_saslname.c | 3 +-- + src/lib/krb5/os/trace.c | 2 +- + src/plugins/kdb/test/kdb_test.c | 2 +- + src/plugins/preauth/pkinit/pkinit_clnt.c | 11 ++--------- + src/plugins/preauth/pkinit/pkinit_srv.c | 4 ++-- + 9 files changed, 21 insertions(+), 16 deletions(-) + +diff --git a/doc/appdev/refs/macros/index.rst b/doc/appdev/refs/macros/index.rst +index 788d094bff..001fb386a7 100644 +--- a/doc/appdev/refs/macros/index.rst ++++ b/doc/appdev/refs/macros/index.rst +@@ -42,6 +42,7 @@ Public + CKSUMTYPE_RSA_MD4_DES.rst + CKSUMTYPE_RSA_MD5.rst + CKSUMTYPE_RSA_MD5_DES.rst ++ CKSUMTYPE_SHA1.rst + ENCTYPE_AES128_CTS_HMAC_SHA1_96.rst + ENCTYPE_AES128_CTS_HMAC_SHA256_128.rst + ENCTYPE_AES256_CTS_HMAC_SHA1_96.rst +diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin +index d2cf1eba2a..a7060aa733 100644 +--- a/src/include/krb5/krb5.hin ++++ b/src/include/krb5/krb5.hin +@@ -449,6 +449,11 @@ typedef struct _krb5_crypto_iov { + #define ENCTYPE_CAMELLIA256_CTS_CMAC 0x001a /**< RFC 6803 */ + #define ENCTYPE_UNKNOWN 0x01ff + ++/* ++ * Historically we used the value 9 for unkeyed SHA-1. RFC 3961 assigns this ++ * value to rsa-md5-des3, which fortunately is unused. For ABI compatibility ++ * we allow either 9 or 14 for SHA-1. ++ */ + #define CKSUMTYPE_CRC32 0x0001 + #define CKSUMTYPE_RSA_MD4 0x0002 + #define CKSUMTYPE_RSA_MD4_DES 0x0003 +@@ -459,6 +464,7 @@ typedef struct _krb5_crypto_iov { + #define CKSUMTYPE_RSA_MD5_DES 0x0008 + #define CKSUMTYPE_NIST_SHA 0x0009 + #define CKSUMTYPE_HMAC_SHA1_DES3 0x000c /* @deprecated removed */ ++#define CKSUMTYPE_SHA1 0x000d /**< RFC 3962 */ + #define CKSUMTYPE_HMAC_SHA1_96_AES128 0x000f /**< RFC 3962. Used with + ENCTYPE_AES128_CTS_HMAC_SHA1_96 */ + #define CKSUMTYPE_HMAC_SHA1_96_AES256 0x0010 /**< RFC 3962. Used with +diff --git a/src/lib/crypto/crypto_tests/t_cksums.c b/src/lib/crypto/crypto_tests/t_cksums.c +index 84408fb68a..de5ed3a22b 100644 +--- a/src/lib/crypto/crypto_tests/t_cksums.c ++++ b/src/lib/crypto/crypto_tests/t_cksums.c +@@ -54,7 +54,7 @@ struct test { + }, + { + { KV5M_DATA, 0, "" }, +- CKSUMTYPE_NIST_SHA, 0, 0, { KV5M_DATA, 0, "" }, ++ CKSUMTYPE_SHA1, 0, 0, { KV5M_DATA, 0, "" }, + { KV5M_DATA, 20, + "\xDA\x39\xA3\xEE\x5E\x6B\x4B\x0D\x32\x55\xBF\xEF\x95\x60\x18\x90" + "\xAF\xD8\x07\x09" } +diff --git a/src/lib/crypto/krb/cksumtypes.c b/src/lib/crypto/krb/cksumtypes.c +index f5fbe8a2a7..25a3ffd2d2 100644 +--- a/src/lib/crypto/krb/cksumtypes.c ++++ b/src/lib/crypto/krb/cksumtypes.c +@@ -46,6 +46,12 @@ const struct krb5_cksumtypes krb5int_cksumtypes_list[] = { + krb5int_unkeyed_checksum, NULL, + 20, 20, CKSUM_UNKEYED }, + ++ { CKSUMTYPE_SHA1, ++ "sha", { 0 }, "SHA-1", ++ NULL, &krb5int_hash_sha1, ++ krb5int_unkeyed_checksum, NULL, ++ 20, 20, CKSUM_UNKEYED }, ++ + { CKSUMTYPE_HMAC_MD5_ARCFOUR, + "hmac-md5-rc4", { "hmac-md5-enc", "hmac-md5-earcfour" }, + "Microsoft HMAC MD5", +diff --git a/src/lib/gssapi/mechglue/g_saslname.c b/src/lib/gssapi/mechglue/g_saslname.c +index e25f9e0a53..2be0c8a69a 100644 +--- a/src/lib/gssapi/mechglue/g_saslname.c ++++ b/src/lib/gssapi/mechglue/g_saslname.c +@@ -58,8 +58,7 @@ oidToSaslName(OM_uint32 *minor, const gss_OID mech, + iov[2].data.length = sizeof(cksumBuf); + iov[2].data.data = (char *)cksumBuf; + +- *minor = krb5_k_make_checksum_iov(NULL, CKSUMTYPE_NIST_SHA, +- NULL, 0, iov, 3); ++ *minor = krb5_k_make_checksum_iov(NULL, CKSUMTYPE_SHA1, NULL, 0, iov, 3); + if (*minor != 0) + return GSS_S_FAILURE; + +diff --git a/src/lib/krb5/os/trace.c b/src/lib/krb5/os/trace.c +index e9b99f4ca0..abb8a3f21b 100644 +--- a/src/lib/krb5/os/trace.c ++++ b/src/lib/krb5/os/trace.c +@@ -93,7 +93,7 @@ hash_bytes(krb5_context context, const void *ptr, size_t len) + krb5_data d = make_data((void *) ptr, len); + char *s = NULL; + +- if (krb5_k_make_checksum(context, CKSUMTYPE_NIST_SHA, NULL, 0, &d, ++ if (krb5_k_make_checksum(context, CKSUMTYPE_SHA1, NULL, 0, &d, + &cksum) != 0) + return NULL; + if (cksum.length >= 2) +diff --git a/src/plugins/kdb/test/kdb_test.c b/src/plugins/kdb/test/kdb_test.c +index 95a6062e2a..38d371cb86 100644 +--- a/src/plugins/kdb/test/kdb_test.c ++++ b/src/plugins/kdb/test/kdb_test.c +@@ -205,7 +205,7 @@ make_keyblock(krb5_kvno kvno, krb5_enctype etype, int32_t salttype, + (int)salttype, princstr, (int)realm->length, realm->data) < 0) + abort(); + d = string2data(hashstr); +- check(krb5_c_make_checksum(NULL, CKSUMTYPE_NIST_SHA, NULL, 0, &d, &cksum)); ++ check(krb5_c_make_checksum(NULL, CKSUMTYPE_SHA1, NULL, 0, &d, &cksum)); + + /* Make the appropriate number of input bytes from the hash result. */ + for (pos = 0; pos < keybytes; pos += n) { +diff --git a/src/plugins/preauth/pkinit/pkinit_clnt.c b/src/plugins/preauth/pkinit/pkinit_clnt.c +index 9b991ffe05..021e5f0723 100644 +--- a/src/plugins/preauth/pkinit/pkinit_clnt.c ++++ b/src/plugins/preauth/pkinit/pkinit_clnt.c +@@ -119,8 +119,8 @@ pa_pkinit_gen_req(krb5_context context, + goto cleanup; + } + +- retval = krb5_c_make_checksum(context, CKSUMTYPE_NIST_SHA, NULL, 0, +- der_req, &cksum); ++ retval = krb5_c_make_checksum(context, CKSUMTYPE_SHA1, NULL, 0, der_req, ++ &cksum); + if (retval) + goto cleanup; + TRACE_PKINIT_CLIENT_REQ_CHECKSUM(context, &cksum); +@@ -701,13 +701,6 @@ pkinit_as_rep_parse(krb5_context context, + pkiDebug("failed to decode reply_key_pack\n"); + goto cleanup; + } +- /* +- * This is hack but Windows sends back SHA1 checksum +- * with checksum type of 14. There is currently no +- * checksum type of 14 defined. +- */ +- if (key_pack->asChecksum.checksum_type == 14) +- key_pack->asChecksum.checksum_type = CKSUMTYPE_NIST_SHA; + retval = krb5_c_make_checksum(context, + key_pack->asChecksum.checksum_type, + &key_pack->replyKey, +diff --git a/src/plugins/preauth/pkinit/pkinit_srv.c b/src/plugins/preauth/pkinit/pkinit_srv.c +index 3ae56c0641..3bff456f8f 100644 +--- a/src/plugins/preauth/pkinit/pkinit_srv.c ++++ b/src/plugins/preauth/pkinit/pkinit_srv.c +@@ -546,8 +546,8 @@ pkinit_server_verify_padata(krb5_context context, + goto cleanup; + } + der_req = cb->request_body(context, rock); +- retval = krb5_c_make_checksum(context, CKSUMTYPE_NIST_SHA, NULL, 0, +- der_req, &cksum); ++ retval = krb5_c_make_checksum(context, CKSUMTYPE_SHA1, NULL, 0, der_req, ++ &cksum); + if (retval) { + pkiDebug("unable to calculate AS REQ checksum\n"); + goto cleanup; +-- +2.39.1 + diff --git a/SOURCES/0153-Add-PAC-ticket-signature-APIs.patch b/SOURCES/0153-Add-PAC-ticket-signature-APIs.patch new file mode 100644 index 0000000..81df71c --- /dev/null +++ b/SOURCES/0153-Add-PAC-ticket-signature-APIs.patch @@ -0,0 +1,840 @@ +From d9ba43315f4a3e0fe2af9acbe47413ccb1f69af2 Mon Sep 17 00:00:00 2001 +From: Isaac Boukris +Date: Fri, 7 Jan 2022 13:46:24 -0500 +Subject: [PATCH] Add PAC ticket signature APIs + +Microsoft added a third PAC signature over the ticket to prevent +servers from setting the forwardable flag on evidence tickets. Add +new APIs to generate and verify ticket signatures, as well as defines +for this and other new PAC buffer types. Deprecate the old signing +functions as they cannot generate ticket signatures. Modify several +error returns to better match the protocol errors generated by Active +Directory. + +[ghudson@mit.edu: adjusted contracts for KDC requirements; simplified +and commented code changes; wrote commit message. rharwood@redhat.com +also did some work on this commit.] + +ticket: 9043 (new) +--- + doc/appdev/refs/api/index.rst | 2 + + doc/appdev/refs/macros/index.rst | 6 + + src/include/krb5/krb5.hin | 98 +++++++++++------ + src/lib/krb5/krb/deps | 5 +- + src/lib/krb5/krb/int-proto.h | 12 ++ + src/lib/krb5/krb/pac.c | 148 ++++++++++++++++++++++++- + src/lib/krb5/krb/pac_sign.c | 121 ++++++++++++++++++++ + src/lib/krb5/krb/t_pac.c | 182 +++++++++++++++++++++++++++++++ + src/lib/krb5/libkrb5.exports | 2 + + src/lib/krb5_32.def | 3 + + src/plugins/kdb/test/kdb_test.c | 6 +- + 11 files changed, 544 insertions(+), 41 deletions(-) + +diff --git a/doc/appdev/refs/api/index.rst b/doc/appdev/refs/api/index.rst +index 9e03fd386f..d12be47c3c 100644 +--- a/doc/appdev/refs/api/index.rst ++++ b/doc/appdev/refs/api/index.rst +@@ -223,6 +223,8 @@ Rarely used public interfaces + krb5_init_creds_step.rst + krb5_init_keyblock.rst + krb5_is_referral_realm.rst ++ krb5_kdc_sign_ticket.rst ++ krb5_kdc_verify_ticket.rst + krb5_kt_add_entry.rst + krb5_kt_end_seq_get.rst + krb5_kt_get_entry.rst +diff --git a/doc/appdev/refs/macros/index.rst b/doc/appdev/refs/macros/index.rst +index 001fb386a7..c6ea088742 100644 +--- a/doc/appdev/refs/macros/index.rst ++++ b/doc/appdev/refs/macros/index.rst +@@ -234,12 +234,18 @@ Public + KRB5_NT_UNKNOWN.rst + KRB5_NT_WELLKNOWN.rst + KRB5_NT_X500_PRINCIPAL.rst ++ KRB5_PAC_ATTRIBUTES_INFO.rst + KRB5_PAC_CLIENT_INFO.rst ++ KRB5_PAC_CLIENT_CLAIMS.rst + KRB5_PAC_CREDENTIALS_INFO.rst + KRB5_PAC_DELEGATION_INFO.rst ++ KRB5_PAC_DEVICE_CLAIMS.rst ++ KRB5_PAC_DEVICE_INFO.rst + KRB5_PAC_LOGON_INFO.rst + KRB5_PAC_PRIVSVR_CHECKSUM.rst ++ KRB5_PAC_REQUESTOR.rst + KRB5_PAC_SERVER_CHECKSUM.rst ++ KRB5_PAC_TICKET_CHECKSUM.rst + KRB5_PAC_UPN_DNS_INFO.rst + KRB5_PADATA_AFS3_SALT.rst + KRB5_PADATA_AP_REQ.rst +diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin +index a7060aa733..8e59628bd9 100644 +--- a/src/include/krb5/krb5.hin ++++ b/src/include/krb5/krb5.hin +@@ -1918,7 +1918,7 @@ krb5_verify_checksum(krb5_context context, krb5_cksumtype ctype, + #define KRB5_AUTHDATA_CAMMAC 96 + #define KRB5_AUTHDATA_WIN2K_PAC 128 + #define KRB5_AUTHDATA_ETYPE_NEGOTIATION 129 /**< RFC 4537 */ +-#define KRB5_AUTHDATA_SIGNTICKET 512 /**< formerly 142 in krb5 1.8 */ ++#define KRB5_AUTHDATA_SIGNTICKET 512 /**< @deprecated use PAC */ + #define KRB5_AUTHDATA_FX_ARMOR 71 + #define KRB5_AUTHDATA_AUTH_INDICATOR 97 + #define KRB5_AUTHDATA_AP_OPTIONS 143 +@@ -8181,6 +8181,12 @@ krb5_verify_authdata_kdc_issued(krb5_context context, + #define KRB5_PAC_CLIENT_INFO 10 /**< Client name and ticket info */ + #define KRB5_PAC_DELEGATION_INFO 11 /**< Constrained delegation info */ + #define KRB5_PAC_UPN_DNS_INFO 12 /**< User principal name and DNS info */ ++#define KRB5_PAC_CLIENT_CLAIMS 13 /**< Client claims information */ ++#define KRB5_PAC_DEVICE_INFO 14 /**< Device information */ ++#define KRB5_PAC_DEVICE_CLAIMS 15 /**< Device claims information */ ++#define KRB5_PAC_TICKET_CHECKSUM 16 /**< Ticket checksum */ ++#define KRB5_PAC_ATTRIBUTES_INFO 17 /**< PAC attributes */ ++#define KRB5_PAC_REQUESTOR 18 /**< PAC requestor SID */ + + struct krb5_pac_data; + /** PAC data structure to convey authorization information */ +@@ -8338,56 +8344,84 @@ krb5_pac_verify_ext(krb5_context context, const krb5_pac pac, + krb5_boolean with_realm); + + /** +- * Sign a PAC. ++ * Verify a PAC, possibly including ticket signature + * +- * @param [in] context Library context +- * @param [in] pac PAC handle +- * @param [in] authtime Expected timestamp +- * @param [in] principal Expected principal name (or NULL) +- * @param [in] server_key Key for server checksum +- * @param [in] privsvr_key Key for KDC checksum +- * @param [out] data Signed PAC encoding ++ * @param [in] context Library context ++ * @param [in] enc_tkt Ticket enc-part, possibly containing a PAC ++ * @param [in] server_princ Canonicalized name of ticket server ++ * @param [in] server Key to validate server checksum (or NULL) ++ * @param [in] privsvr Key to validate KDC checksum (or NULL) ++ * @param [out] pac_out Verified PAC (NULL if no PAC included) + * +- * This function signs @a pac using the keys @a server_key and @a privsvr_key +- * and returns the signed encoding in @a data. @a pac is modified to include +- * the server and KDC checksum buffers. Use krb5_free_data_contents() to free +- * @a data when it is no longer needed. ++ * If a PAC is present in @a enc_tkt, verify its signatures. If @a privsvr is ++ * not NULL and @a server_princ is not a krbtgt or kadmin/changepw service, ++ * require a ticket signature over @a enc_tkt in addition to the KDC signature. ++ * Place the verified PAC in @a pac_out. If an invalid PAC signature is found, ++ * return an error matching the Windows KDC protocol code for that condition as ++ * closely as possible. + * +- * @version New in 1.10 ++ * If no PAC is present in @a enc_tkt, set @a pac_out to NULL and return ++ * successfully. ++ * ++ * @note This function does not validate the PAC_CLIENT_INFO buffer. If a ++ * specific value is expected, the caller can make a separate call to ++ * krb5_pac_verify_ext() with a principal but no keys. ++ * ++ * @retval 0 Success; otherwise - Kerberos error codes ++ * ++ * @version New in 1.20 + */ + krb5_error_code KRB5_CALLCONV ++krb5_kdc_verify_ticket(krb5_context context, const krb5_enc_tkt_part *enc_tkt, ++ krb5_const_principal server_princ, ++ const krb5_keyblock *server, ++ const krb5_keyblock *privsvr, krb5_pac *pac_out); ++ ++/** @deprecated Use krb5_kdc_sign_ticket() instead. */ ++krb5_error_code KRB5_CALLCONV + krb5_pac_sign(krb5_context context, krb5_pac pac, krb5_timestamp authtime, + krb5_const_principal principal, const krb5_keyblock *server_key, + const krb5_keyblock *privsvr_key, krb5_data *data); + ++/** @deprecated Use krb5_kdc_sign_ticket() instead. */ ++krb5_error_code KRB5_CALLCONV ++krb5_pac_sign_ext(krb5_context context, krb5_pac pac, krb5_timestamp authtime, ++ krb5_const_principal principal, ++ const krb5_keyblock *server_key, ++ const krb5_keyblock *privsvr_key, krb5_boolean with_realm, ++ krb5_data *data); ++ + /** +- * Sign a PAC, possibly with a specified realm. ++ * Sign a PAC, possibly including a ticket signature + * + * @param [in] context Library context ++ * @param [in] enc_tkt The ticket for the signature + * @param [in] pac PAC handle +- * @param [in] authtime Expected timestamp +- * @param [in] principal Principal name (or NULL) +- * @param [in] server_key Key for server checksum +- * @param [in] privsvr_key Key for KDC checksum ++ * @param [in] server_princ Canonical ticket server name ++ * @param [in] client_princ PAC_CLIENT_INFO principal (or NULL) ++ * @param [in] server Key for server checksum ++ * @param [in] privsvr Key for KDC and ticket checksum + * @param [in] with_realm If true, include the realm of @a principal +- * @param [out] data Signed PAC encoding + * +- * This function is similar to krb5_pac_sign(), but adds a parameter +- * @a with_realm. If @a with_realm is true, the PAC_CLIENT_INFO field of the +- * signed PAC will include the realm of @a principal as well as the name. This +- * flag is necessary to generate PACs for cross-realm S4U2Self referrals. ++ * Sign @a pac using the keys @a server and @a privsvr. Include a ticket ++ * signature over @a enc_tkt if @a server_princ is not a TGS or kadmin/changepw ++ * principal name. Add the signed PAC's encoding to the authorization data of ++ * @a enc_tkt in the first slot, wrapped in an AD-IF-RELEVANT container. If @a ++ * client_princ is non-null, add a PAC_CLIENT_INFO buffer, including the realm ++ * if @a with_realm is true. + * +- * @version New in 1.17 ++ * @retval 0 on success, otherwise - Kerberos error codes ++ * ++ * @version New in 1.20 + */ + krb5_error_code KRB5_CALLCONV +-krb5_pac_sign_ext(krb5_context context, krb5_pac pac, krb5_timestamp authtime, +- krb5_const_principal principal, +- const krb5_keyblock *server_key, +- const krb5_keyblock *privsvr_key, krb5_boolean with_realm, +- krb5_data *data); ++krb5_kdc_sign_ticket(krb5_context context, krb5_enc_tkt_part *enc_tkt, ++ const krb5_pac pac, krb5_const_principal server_princ, ++ krb5_const_principal client_princ, ++ const krb5_keyblock *server, const krb5_keyblock *privsvr, ++ krb5_boolean with_realm); + +- +-/* ++/** + * Read client information from a PAC. + * + * @param [in] context Library context +diff --git a/src/lib/krb5/krb/deps b/src/lib/krb5/krb/deps +index 439ca02725..cd842b03cd 100644 +--- a/src/lib/krb5/krb/deps ++++ b/src/lib/krb5/krb/deps +@@ -709,7 +709,7 @@ pac.so pac.po $(OUTPRE)pac.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(top_srcdir)/include/k5-utf8.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ +- authdata.h pac.c ++ authdata.h int-proto.h pac.c + pac_sign.so pac_sign.po $(OUTPRE)pac_sign.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ +@@ -720,7 +720,8 @@ pac_sign.so pac_sign.po $(OUTPRE)pac_sign.$(OBJEXT): \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/k5-utf8.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ +- $(top_srcdir)/include/socket-utils.h authdata.h pac_sign.c ++ $(top_srcdir)/include/socket-utils.h authdata.h int-proto.h \ ++ pac_sign.c + padata.so padata.po $(OUTPRE)padata.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ +diff --git a/src/lib/krb5/krb/int-proto.h b/src/lib/krb5/krb/int-proto.h +index fe61bebf5b..453ed60c6c 100644 +--- a/src/lib/krb5/krb/int-proto.h ++++ b/src/lib/krb5/krb/int-proto.h +@@ -386,4 +386,16 @@ k5_get_proxy_cred_from_kdc(krb5_context context, krb5_flags options, + krb5_ccache ccache, krb5_creds *in_creds, + krb5_creds **out_creds); + ++/* Return true if mprinc will match any hostname in a host-based principal name ++ * (possibly due to ignore_acceptor_hostname) with krb5_sname_match(). */ ++krb5_boolean ++k5_sname_wildcard_host(krb5_context context, krb5_const_principal mprinc); ++ ++/* Guess the appropriate name-type for a principal based on the name. */ ++krb5_int32 ++k5_infer_principal_type(krb5_principal princ); ++ ++krb5_boolean ++k5_pac_should_have_ticket_signature(krb5_const_principal sprinc); ++ + #endif /* KRB5_INT_FUNC_PROTO__ */ +diff --git a/src/lib/krb5/krb/pac.c b/src/lib/krb5/krb/pac.c +index 1b9ef12276..6eb23d8090 100644 +--- a/src/lib/krb5/krb/pac.c ++++ b/src/lib/krb5/krb/pac.c +@@ -25,6 +25,7 @@ + */ + + #include "k5-int.h" ++#include "int-proto.h" + #include "authdata.h" + + #define MAX_BUFFERS 4096 +@@ -552,8 +553,10 @@ k5_pac_verify_server_checksum(krb5_context context, + checksum.checksum_type = load_32_le(p); + checksum.length = checksum_data.length - PAC_SIGNATURE_DATA_LENGTH; + checksum.contents = p + PAC_SIGNATURE_DATA_LENGTH; ++ if (checksum.checksum_type == CKSUMTYPE_SHA1) ++ return KRB5KDC_ERR_SUMTYPE_NOSUPP; + if (!krb5_c_is_keyed_cksum(checksum.checksum_type)) +- return KRB5KRB_AP_ERR_INAPP_CKSUM; ++ return KRB5KRB_ERR_GENERIC; + + pac_data.length = pac->data.length; + pac_data.data = k5memdup(pac->data.data, pac->data.length, &ret); +@@ -586,7 +589,7 @@ k5_pac_verify_server_checksum(krb5_context context, + } + + if (valid == FALSE) +- ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; ++ ret = KRB5KRB_AP_ERR_MODIFIED; + + return ret; + } +@@ -623,7 +626,7 @@ k5_pac_verify_kdc_checksum(krb5_context context, + checksum.length = privsvr_checksum.length - PAC_SIGNATURE_DATA_LENGTH; + checksum.contents = p + PAC_SIGNATURE_DATA_LENGTH; + if (!krb5_c_is_keyed_cksum(checksum.checksum_type)) +- return KRB5KRB_AP_ERR_INAPP_CKSUM; ++ return KRB5KRB_ERR_GENERIC; + + server_checksum.data += PAC_SIGNATURE_DATA_LENGTH; + server_checksum.length -= PAC_SIGNATURE_DATA_LENGTH; +@@ -635,11 +638,148 @@ k5_pac_verify_kdc_checksum(krb5_context context, + return ret; + + if (valid == FALSE) +- ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; ++ ret = KRB5KRB_AP_ERR_MODIFIED; + + return ret; + } + ++static krb5_error_code ++verify_ticket_checksum(krb5_context context, const krb5_pac pac, ++ const krb5_data *ticket, const krb5_keyblock *privsvr) ++{ ++ krb5_error_code ret; ++ krb5_checksum checksum; ++ krb5_data checksum_data; ++ krb5_boolean valid; ++ krb5_octet *p; ++ ++ ret = k5_pac_locate_buffer(context, pac, KRB5_PAC_TICKET_CHECKSUM, ++ &checksum_data); ++ if (ret != 0) ++ return KRB5KRB_AP_ERR_MODIFIED; ++ ++ if (checksum_data.length < PAC_SIGNATURE_DATA_LENGTH) ++ return KRB5_BAD_MSIZE; ++ ++ p = (krb5_octet *)checksum_data.data; ++ checksum.checksum_type = load_32_le(p); ++ checksum.length = checksum_data.length - PAC_SIGNATURE_DATA_LENGTH; ++ checksum.contents = p + PAC_SIGNATURE_DATA_LENGTH; ++ if (!krb5_c_is_keyed_cksum(checksum.checksum_type)) ++ return KRB5KRB_ERR_GENERIC; ++ ++ ret = krb5_c_verify_checksum(context, privsvr, ++ KRB5_KEYUSAGE_APP_DATA_CKSUM, ticket, ++ &checksum, &valid); ++ if (ret != 0) ++ return ret; ++ ++ return valid ? 0 : KRB5KRB_AP_ERR_MODIFIED; ++} ++ ++/* Per MS-PAC 2.8.3, tickets encrypted to TGS and password change principals ++ * should not have ticket signatures. */ ++krb5_boolean ++k5_pac_should_have_ticket_signature(krb5_const_principal sprinc) ++{ ++ if (IS_TGS_PRINC(sprinc)) ++ return FALSE; ++ if (sprinc->length == 2 && data_eq_string(sprinc->data[0], "kadmin") && ++ data_eq_string(sprinc->data[1], "changepw")) ++ return FALSE; ++ return TRUE; ++} ++ ++krb5_error_code KRB5_CALLCONV ++krb5_kdc_verify_ticket(krb5_context context, const krb5_enc_tkt_part *enc_tkt, ++ krb5_const_principal server_princ, ++ const krb5_keyblock *server, ++ const krb5_keyblock *privsvr, krb5_pac *pac_out) ++{ ++ krb5_error_code ret; ++ krb5_pac pac = NULL; ++ krb5_data *recoded_tkt = NULL; ++ krb5_authdata **authdata, *orig, **ifrel = NULL, **recoded_ifrel = NULL; ++ uint8_t z = 0; ++ krb5_authdata zpac = { KV5M_AUTHDATA, KRB5_AUTHDATA_WIN2K_PAC, 1, &z }; ++ size_t i, j; ++ ++ *pac_out = NULL; ++ ++ /* ++ * Find the position of the PAC in the ticket authdata. ifrel will be the ++ * decoded AD-IF-RELEVANT container at position i containing a PAC, and j ++ * will be the offset within the container. ++ */ ++ authdata = enc_tkt->authorization_data; ++ for (i = 0; authdata != NULL && authdata[i] != NULL; i++) { ++ if (authdata[i]->ad_type != KRB5_AUTHDATA_IF_RELEVANT) ++ continue; ++ ++ ret = krb5_decode_authdata_container(context, ++ KRB5_AUTHDATA_IF_RELEVANT, ++ authdata[i], &ifrel); ++ if (ret) ++ goto cleanup; ++ ++ for (j = 0; ifrel[j] != NULL; j++) { ++ if (ifrel[j]->ad_type == KRB5_AUTHDATA_WIN2K_PAC) ++ break; ++ } ++ if (ifrel[j] != NULL) ++ break; ++ ++ krb5_free_authdata(context, ifrel); ++ ifrel = NULL; ++ } ++ ++ /* Stop and return successfully if we didn't find a PAC. */ ++ if (ifrel == NULL) { ++ ret = 0; ++ goto cleanup; ++ } ++ ++ ret = krb5_pac_parse(context, ifrel[j]->contents, ifrel[j]->length, &pac); ++ if (ret) ++ goto cleanup; ++ ++ if (privsvr != NULL && k5_pac_should_have_ticket_signature(server_princ)) { ++ /* To check the PAC ticket signatures, re-encode the ticket with the ++ * PAC contents replaced by a single zero. */ ++ orig = ifrel[j]; ++ ifrel[j] = &zpac; ++ ret = krb5_encode_authdata_container(context, ++ KRB5_AUTHDATA_IF_RELEVANT, ++ ifrel, &recoded_ifrel); ++ ifrel[j] = orig; ++ if (ret) ++ goto cleanup; ++ orig = authdata[i]; ++ authdata[i] = recoded_ifrel[0]; ++ ret = encode_krb5_enc_tkt_part(enc_tkt, &recoded_tkt); ++ authdata[i] = orig; ++ if (ret) ++ goto cleanup; ++ ++ ret = verify_ticket_checksum(context, pac, recoded_tkt, privsvr); ++ if (ret) ++ goto cleanup; ++ } ++ ++ ret = krb5_pac_verify_ext(context, pac, enc_tkt->times.authtime, NULL, ++ server, privsvr, FALSE); ++ ++ *pac_out = pac; ++ pac = NULL; ++ ++cleanup: ++ krb5_pac_free(context, pac); ++ krb5_free_data(context, recoded_tkt); ++ krb5_free_authdata(context, ifrel); ++ krb5_free_authdata(context, recoded_ifrel); ++ return ret; ++} ++ + krb5_error_code KRB5_CALLCONV + krb5_pac_verify(krb5_context context, + const krb5_pac pac, +diff --git a/src/lib/krb5/krb/pac_sign.c b/src/lib/krb5/krb/pac_sign.c +index 12f0259b4f..0f9581abbb 100644 +--- a/src/lib/krb5/krb/pac_sign.c ++++ b/src/lib/krb5/krb/pac_sign.c +@@ -25,6 +25,7 @@ + */ + + #include "k5-int.h" ++#include "int-proto.h" + #include "authdata.h" + + /* draft-brezak-win2k-krb-authz-00 */ +@@ -286,3 +287,123 @@ krb5_pac_sign_ext(krb5_context context, krb5_pac pac, krb5_timestamp authtime, + + return 0; + } ++ ++/* Add a signature over der_enc_tkt in privsvr to pac. der_enc_tkt should be ++ * encoded with a dummy PAC authdata element containing a single zero byte. */ ++static krb5_error_code ++add_ticket_signature(krb5_context context, const krb5_pac pac, ++ krb5_data *der_enc_tkt, const krb5_keyblock *privsvr) ++{ ++ krb5_error_code ret; ++ krb5_data ticket_cksum; ++ krb5_cksumtype ticket_cksumtype; ++ krb5_crypto_iov iov[2]; ++ ++ /* Create zeroed buffer for checksum. */ ++ ret = k5_insert_checksum(context, pac, KRB5_PAC_TICKET_CHECKSUM, ++ privsvr, &ticket_cksumtype); ++ if (ret) ++ return ret; ++ ++ ret = k5_pac_locate_buffer(context, pac, KRB5_PAC_TICKET_CHECKSUM, ++ &ticket_cksum); ++ if (ret) ++ return ret; ++ ++ iov[0].flags = KRB5_CRYPTO_TYPE_DATA; ++ iov[0].data = *der_enc_tkt; ++ iov[1].flags = KRB5_CRYPTO_TYPE_CHECKSUM; ++ iov[1].data = make_data(ticket_cksum.data + PAC_SIGNATURE_DATA_LENGTH, ++ ticket_cksum.length - PAC_SIGNATURE_DATA_LENGTH); ++ ret = krb5_c_make_checksum_iov(context, ticket_cksumtype, privsvr, ++ KRB5_KEYUSAGE_APP_DATA_CKSUM, iov, 2); ++ if (ret) ++ return ret; ++ ++ store_32_le(ticket_cksumtype, ticket_cksum.data); ++ return 0; ++} ++ ++/* Set *out to an AD-IF-RELEVANT authdata element containing a PAC authdata ++ * element with contents pac_data. */ ++static krb5_error_code ++encode_pac_ad(krb5_context context, krb5_data *pac_data, krb5_authdata **out) ++{ ++ krb5_error_code ret; ++ krb5_authdata *container[2], **encoded_container = NULL; ++ krb5_authdata pac_ad = { KV5M_AUTHDATA, KRB5_AUTHDATA_WIN2K_PAC }; ++ uint8_t z = 0; ++ ++ pac_ad.contents = (pac_data != NULL) ? (uint8_t *)pac_data->data : &z; ++ pac_ad.length = (pac_data != NULL) ? pac_data->length : 1; ++ container[0] = &pac_ad; ++ container[1] = NULL; ++ ++ ret = krb5_encode_authdata_container(context, KRB5_AUTHDATA_IF_RELEVANT, ++ container, &encoded_container); ++ if (ret) ++ return ret; ++ ++ *out = encoded_container[0]; ++ free(encoded_container); ++ return 0; ++} ++ ++krb5_error_code KRB5_CALLCONV ++krb5_kdc_sign_ticket(krb5_context context, krb5_enc_tkt_part *enc_tkt, ++ const krb5_pac pac, krb5_const_principal server_princ, ++ krb5_const_principal client_princ, ++ const krb5_keyblock *server, const krb5_keyblock *privsvr, ++ krb5_boolean with_realm) ++{ ++ krb5_error_code ret; ++ krb5_data *der_enc_tkt = NULL, pac_data = empty_data(); ++ krb5_authdata **list, *pac_ad; ++ size_t count; ++ ++ /* Reallocate space for another authdata element in enc_tkt. */ ++ list = enc_tkt->authorization_data; ++ for (count = 0; list != NULL && list[count] != NULL; count++); ++ list = realloc(enc_tkt->authorization_data, (count + 2) * sizeof(*list)); ++ if (list == NULL) ++ return ENOMEM; ++ list[count] = NULL; ++ enc_tkt->authorization_data = list; ++ ++ /* Create a dummy PAC for ticket signing and make it the first element. */ ++ ret = encode_pac_ad(context, NULL, &pac_ad); ++ if (ret) ++ goto cleanup; ++ memmove(list + 1, list, (count + 1) * sizeof(*list)); ++ list[0] = pac_ad; ++ ++ if (k5_pac_should_have_ticket_signature(server_princ)) { ++ ret = encode_krb5_enc_tkt_part(enc_tkt, &der_enc_tkt); ++ if (ret) ++ goto cleanup; ++ ++ assert(privsvr != NULL); ++ ret = add_ticket_signature(context, pac, der_enc_tkt, privsvr); ++ if (ret) ++ goto cleanup; ++ } ++ ++ ret = krb5_pac_sign_ext(context, pac, enc_tkt->times.authtime, ++ client_princ, server, privsvr, with_realm, ++ &pac_data); ++ if (ret) ++ goto cleanup; ++ ++ /* Replace the dummy PAC with the signed real one. */ ++ ret = encode_pac_ad(context, &pac_data, &pac_ad); ++ if (ret) ++ goto cleanup; ++ free(list[0]->contents); ++ free(list[0]); ++ list[0] = pac_ad; ++ ++cleanup: ++ krb5_free_data(context, der_enc_tkt); ++ krb5_free_data_contents(context, &pac_data); ++ return ret; ++} +diff --git a/src/lib/krb5/krb/t_pac.c b/src/lib/krb5/krb/t_pac.c +index ccd165380d..173bde7bab 100644 +--- a/src/lib/krb5/krb/t_pac.c ++++ b/src/lib/krb5/krb/t_pac.c +@@ -605,6 +605,186 @@ check_pac(krb5_context context, int index, const unsigned char *pdata, + krb5_pac_free(context, pac); + } + ++static const krb5_keyblock ticket_sig_krbtgt_key = { ++ 0, ENCTYPE_AES256_CTS_HMAC_SHA1_96, ++ 32, U("\x7a\x58\x98\xd2\xaf\xa6\xaf\xc0\x6a\xce\x06\x04\x4b\xc2\x70\x84" ++ "\x9b\x8e\x0a\x6c\x4c\x07\xdc\x6f\xbb\x48\x43\xe1\xd2\xaa\x97\xf7") ++}; ++ ++static const krb5_keyblock ticket_sig_server_key = { ++ 0, ENCTYPE_ARCFOUR_HMAC, ++ 16, U("\xed\x23\x11\x20\x7a\x21\x44\x20\xbf\xc0\x8d\x36\xf7\xf6\xb2\x3e") ++}; ++ ++static const krb5_data ticket_data = { ++ .length = 972, .data = ++ "\x61\x82\x03\xC8\x30\x82\x03\xC4\xA0\x03\x02\x01\x05\xA1\x0A\x1B" ++ "\x08\x43\x44\x4F\x4D\x2E\x43\x4F\x4D\xA2\x0F\x30\x0D\xA0\x03\x02" ++ "\x01\x01\xA1\x06\x30\x04\x1B\x02\x73\x31\xA3\x82\x03\x9E\x30\x82" ++ "\x03\x9A\xA0\x03\x02\x01\x17\xA1\x03\x02\x01\x03\xA2\x82\x03\x8C" ++ "\x04\x82\x03\x88\x44\x31\x61\x20\x17\xC9\xFE\xBC\xAC\x46\xB5\x77" ++ "\xE9\x68\x04\x4C\x9B\x31\x91\x0C\xC1\xD4\xDD\xEF\xC7\x34\x20\x08" ++ "\x90\x91\xE8\x79\xE0\xB5\x03\x26\xA4\x65\xDE\xEC\x47\x03\x2A\x8F" ++ "\x61\xE7\x4D\x38\x5A\x42\x95\x5A\xF9\x2F\x41\x2C\x2A\x6E\x60\xA1" ++ "\xEB\x51\xB3\xBD\x4C\x00\x41\x2A\x44\x76\x08\x37\x1A\x51\xFD\x65" ++ "\x67\x7E\xBF\x3D\x90\x86\xE3\x9A\x54\x6B\x67\xA8\x08\x7A\x73\xCC" ++ "\xC3\xB7\x4B\xD5\x5C\x3A\x14\x6C\xC1\x5F\x54\x4B\x92\x55\xB4\xB7" ++ "\x92\x23\x3F\x53\x89\x47\x8E\x1F\x8B\xB9\xDB\x3B\x93\xE8\x70\xE4" ++ "\x24\xB8\x9D\xF0\x0E\x35\x28\xF8\x7A\x27\x5D\xF7\x25\x97\x9C\xF5" ++ "\x9F\x9F\x64\x04\xF2\xA3\xAB\x11\x15\xB6\xDA\x18\xD6\x46\xD5\xE6" ++ "\xB8\x08\xDE\x0A\x62\xFD\xF8\xAA\x52\x90\xD9\x67\x29\xB2\xCD\x06" ++ "\xB6\xB0\x50\x2B\x3F\x0F\xA3\xA5\xBF\xAA\x6E\x40\x03\xD6\x5F\x02" ++ "\xBC\xD8\x18\x47\x97\x09\xD7\xE4\x96\x3B\xCB\xEB\x92\x2C\x3C\x49" ++ "\xFF\x1F\x71\xE0\x52\x94\x0F\x8B\x9F\xB8\x2A\xBB\x9C\xE2\xA3\xDD" ++ "\x38\x89\xE2\xB1\x0B\x9E\x1F\x7A\xB3\xE3\xD2\xB0\x94\xDC\x87\xBE" ++ "\x37\xA6\xD3\xB3\x29\x35\x9A\x72\xC3\x7A\xF1\xA9\xE6\xC5\xD1\x26" ++ "\x83\x65\x44\x17\xBA\x55\xA8\x5E\x94\x26\xED\xE9\x8A\x93\x11\x5D" ++ "\x7E\x20\x1B\x9C\x15\x9E\x13\x37\x03\x4D\xDD\x99\x51\xD8\x66\x29" ++ "\x6A\xB9\xFB\x49\xFE\x52\x78\xDA\x86\x85\xA9\xA3\xB9\xEF\xEC\xAD" ++ "\x35\xA6\x8D\xAC\x0F\x75\x22\xBB\x0B\x49\x1C\x13\x52\x40\xC9\x52" ++ "\x69\x09\x54\xD1\x0F\x94\x3F\x22\x48\x67\xB0\x96\x28\xAA\xE6\x28" ++ "\xD9\x0C\x08\xEF\x51\xED\x15\x5E\xA2\x53\x59\xA5\x03\xB4\x06\x20" ++ "\x3D\xCC\xB4\xC5\xF8\x8C\x73\x67\xA3\x21\x3D\x19\xCD\xD4\x12\x28" ++ "\xD2\x93\xDE\x0D\xF0\x71\x10\x50\xD6\x33\x35\x04\x11\x64\x43\x39" ++ "\xC3\xDF\x96\xE3\x66\xE3\x85\xCA\xE7\x67\x14\x3A\xF0\x43\xAA\xBB" ++ "\xD4\x1D\xB5\x24\xB5\x74\x90\x25\xA7\x87\x7E\xDB\xD3\x83\x8A\x3A" ++ "\x69\xA8\x2D\xAF\xB7\xB8\xF3\xDC\x13\xAF\x45\x61\x3F\x59\x39\x7E" ++ "\x69\xDE\x0C\x04\xF1\x10\x6B\xB4\x56\xFA\x21\x9F\x72\x2B\x60\x86" ++ "\xE3\x23\x0E\xC4\x51\xF6\xBE\xD8\xE1\x5F\xEE\x73\x4C\x17\x4C\x2C" ++ "\x1B\xFB\x9F\x1F\x7A\x3B\x07\x5B\x8E\xF1\x01\xAC\xD6\x30\x94\x8A" ++ "\x5D\x22\x6F\x08\xCE\xED\x5E\xB6\xDB\x86\x8C\x87\xEB\x8D\x91\xFF" ++ "\x0A\x86\x30\xBD\xC0\xF8\x25\xE7\xAE\x24\x35\xF2\xFC\xE5\xFD\x1B" ++ "\xB0\x05\x4A\xA3\xE5\xEB\x2E\x05\xAD\x99\x67\x49\x87\xE6\xB3\x87" ++ "\x82\xA4\x59\xA7\x6E\xDD\xF2\xB6\x66\xE8\xF7\x70\xF5\xBD\xC9\x0E" ++ "\xFA\x9C\x79\x84\xD4\x9B\x05\x0E\xBB\xF5\xDB\xEF\xFC\xCC\x26\xF2" ++ "\x93\xCF\xD2\x04\x3C\xA9\x2C\x65\x42\x97\x86\xD8\x38\x0A\x1E\xF6" ++ "\xD6\xCA\x30\xB5\x1A\xEC\xFB\xBA\x3B\x84\x57\xB0\xFD\xFB\xE6\xBC" ++ "\xF2\x76\xF6\x4C\xBB\xAB\xB1\x31\xA1\x27\x7C\xE6\xE6\x81\xB6\xCE" ++ "\x84\x86\x40\xB6\x40\x33\xC4\xF8\xB4\x15\xCF\xAA\xA5\x51\x78\xB9" ++ "\x8B\x50\x25\xB2\x88\x86\x96\x72\x8C\x71\x4D\xB5\x3A\x94\x86\x77" ++ "\x0E\x95\x9B\x16\x93\xEF\x3A\x11\x79\xBA\x83\xF7\x74\xD3\x8D\xBA" ++ "\x15\xE1\x2C\x04\x57\xA8\x92\x1E\x9D\x00\x8E\x20\xFD\x30\x70\xE7" ++ "\xF5\x65\x2F\x19\x0C\x94\xBA\x03\x71\x12\x96\xCD\xC8\xB4\x96\xDB" ++ "\xCE\x19\xC2\xDF\x3C\xC2\xF6\x3D\x53\xED\x98\xA5\x41\x72\x2A\x22" ++ "\x7B\xF3\x2B\x17\x6C\xE1\x39\x7D\xAE\x9B\x11\xF9\xC1\xA6\x9E\x9F" ++ "\x89\x3C\x12\xAA\x94\x74\xA7\x4F\x70\xE8\xB9\xDE\x04\xF0\x9D\x39" ++ "\x24\x2D\x92\xE8\x46\x2D\x2E\xF0\x40\x66\x1A\xD9\x27\xF9\x98\xF1" ++ "\x81\x1D\x70\x62\x63\x30\x6D\xCD\x84\x04\x5F\xFA\x83\xD3\xEC\x8D" ++ "\x86\xFB\x40\x61\xC1\x8A\x45\xFF\x7B\xD9\xD4\x18\x61\x7F\x51\xE3" ++ "\xFC\x1E\x18\xF0\xAF\xC6\x18\x2C\xE1\x6D\x5D\xF9\x62\xFC\x20\xA3" ++ "\xB2\x8A\x5F\xE5\xBB\x29\x0F\x99\x63\x07\x88\x38\x3A\x3B\x73\x2A" ++ "\x6D\xDA\x3D\xA8\x0D\x8F\x56\x41\x89\x82\xE5\xB8\x61\x00\x64\x7D" ++ "\x17\x0C\xCE\x03\x55\x8F\xF4\x5B\x0D\x50\xF2\xEB\x05\x67\xBE\xDB" ++ "\x7B\x75\xC5\xEA\xA1\xAB\x1D\xB0\x3C\x6D\x42\x08\x0B\x9A\x45\x20" ++ "\xA8\x8F\xE5\x67\x47\x30\xDE\x93\x5F\x43\x05\xEB\xA8\x2D\x80\xF5" ++ "\x1A\xB8\x4A\x4E\x42\x2D\x0B\x7A\xDC\x46\x20\x2D\x13\x17\xDD\x4B" ++ "\x94\x96\xAA\x1F\x06\x0C\x1F\x62\x07\x9C\x40\xA1" ++}; ++ ++static void ++test_pac_ticket_signature(krb5_context context) ++{ ++ krb5_error_code ret; ++ krb5_ticket *ticket; ++ krb5_principal sprinc; ++ krb5_authdata **authdata1, **authdata2; ++ krb5_pac pac, pac2, pac3; ++ uint32_t *list; ++ size_t len, i; ++ krb5_data data; ++ ++ ret = krb5_decode_ticket(&ticket_data, &ticket); ++ if (ret) ++ err(context, ret, "while decoding ticket"); ++ ++ ret = krb5_decrypt_tkt_part(context, &ticket_sig_server_key, ticket); ++ if (ret) ++ err(context, ret, "while decrypting ticket"); ++ ++ ret = krb5_parse_name(context, "s1@CDOM.COM", &sprinc); ++ if (ret) ++ err(context, ret, "krb5_parse_name"); ++ ++ ret = krb5_kdc_verify_ticket(context, ticket->enc_part2, sprinc, ++ &ticket_sig_server_key, ++ &ticket_sig_krbtgt_key, &pac); ++ if (ret) ++ err(context, ret, "while verifying ticket"); ++ ++ /* In this test, the server is also the client. */ ++ ret = krb5_pac_verify(context, pac, ticket->enc_part2->times.authtime, ++ ticket->server, NULL, NULL); ++ if (ret) ++ err(context, ret, "while verifying PAC client info"); ++ ++ /* We know there is only a PAC in this test's ticket. */ ++ authdata1 = ticket->enc_part2->authorization_data; ++ ticket->enc_part2->authorization_data = NULL; ++ ++ ret = krb5_kdc_sign_ticket(context, ticket->enc_part2, pac, sprinc, ++ sprinc, &ticket_sig_server_key, ++ &ticket_sig_krbtgt_key, FALSE); ++ if (ret) ++ err(context, ret, "while signing ticket"); ++ ++ authdata2 = ticket->enc_part2->authorization_data; ++ assert(authdata2 != NULL); ++ assert(authdata2[1] == NULL); ++ ++ assert(authdata1[0]->length == authdata2[0]->length); ++ assert(memcmp(authdata1[0]->contents, authdata2[0]->contents, ++ authdata1[0]->length) == 0); ++ ++ /* Test adding signatures to a new PAC. */ ++ ret = krb5_pac_init(context, &pac2); ++ if (ret) ++ err(context, ret, "krb5_pac_init"); ++ ++ ret = krb5_pac_get_types(context, pac, &len, &list); ++ if (ret) ++ err(context, ret, "krb5_pac_get_types"); ++ ++ for (i = 0; i < len; i++) { ++ /* Skip server_cksum, privsvr_cksum, and ticket_cksum. */ ++ if (list[i] == 6 || list[i] == 7 || list[i] == 16) ++ continue; ++ ++ ret = krb5_pac_get_buffer(context, pac, list[i], &data); ++ if (ret) ++ err(context, ret, "krb5_pac_get_buffer"); ++ ++ ret = krb5_pac_add_buffer(context, pac2, list[i], &data); ++ if (ret) ++ err(context, ret, "krb5_pac_add_buffer"); ++ ++ krb5_free_data_contents(context, &data); ++ } ++ free(list); ++ ++ krb5_free_authdata(context, authdata1); ++ krb5_free_authdata(context, ticket->enc_part2->authorization_data); ++ ticket->enc_part2->authorization_data = NULL; ++ ++ ret = krb5_kdc_sign_ticket(context, ticket->enc_part2, pac2, sprinc, NULL, ++ &ticket_sig_server_key, &ticket_sig_krbtgt_key, ++ FALSE); ++ if (ret) ++ err(context, ret, "while signing ticket"); ++ ++ /* We can't compare the data since the order of the buffers may differ. */ ++ ret = krb5_kdc_verify_ticket(context, ticket->enc_part2, sprinc, ++ &ticket_sig_server_key, ++ &ticket_sig_krbtgt_key, &pac3); ++ if (ret) ++ err(context, ret, "while verifying ticket"); ++ ++ krb5_pac_free(context, pac); ++ krb5_pac_free(context, pac2); ++ krb5_pac_free(context, pac3); ++ krb5_free_principal(context, sprinc); ++ krb5_free_ticket(context, ticket); ++} ++ + int + main(int argc, char **argv) + { +@@ -618,6 +798,8 @@ main(int argc, char **argv) + if (ret) + err(NULL, 0, "krb5_init_contex"); + ++ test_pac_ticket_signature(context); ++ + ret = krb5_set_default_realm(context, "WIN2K3.THINKER.LOCAL"); + if (ret) + err(context, ret, "krb5_set_default_realm"); +diff --git a/src/lib/krb5/libkrb5.exports b/src/lib/krb5/libkrb5.exports +index 48ae46f5c4..28784ec67c 100644 +--- a/src/lib/krb5/libkrb5.exports ++++ b/src/lib/krb5/libkrb5.exports +@@ -462,6 +462,8 @@ krb5_is_permitted_enctype + krb5_is_referral_realm + krb5_is_thread_safe + krb5_kdc_rep_decrypt_proc ++krb5_kdc_sign_ticket ++krb5_kdc_verify_ticket + krb5_kt_add_entry + krb5_kt_client_default + krb5_kt_close +diff --git a/src/lib/krb5_32.def b/src/lib/krb5_32.def +index 209c6aaef5..8c3469a96c 100644 +--- a/src/lib/krb5_32.def ++++ b/src/lib/krb5_32.def +@@ -506,3 +506,6 @@ EXPORTS + ; new in 1.20 + krb5_marshal_credentials @472 + krb5_unmarshal_credentials @473 ++ k5_sname_compare @474 ; PRIVATE GSSAPI ++ krb5_kdc_sign_ticket @475 ; ++ krb5_kdc_verify_ticket @476 ; +diff --git a/src/plugins/kdb/test/kdb_test.c b/src/plugins/kdb/test/kdb_test.c +index 38d371cb86..7d033acae4 100644 +--- a/src/plugins/kdb/test/kdb_test.c ++++ b/src/plugins/kdb/test/kdb_test.c +@@ -675,7 +675,7 @@ verify_kdc_signature(krb5_context context, krb5_pac pac, + int tries; + + ret = krb5_pac_verify(context, pac, 0, NULL, NULL, tgt_key); +- if (ret != KRB5KRB_AP_ERR_BAD_INTEGRITY) ++ if (ret != KRB5KRB_AP_ERR_MODIFIED) + return ret; + + kvno = tgt->key_data[0].key_data_kvno - 1; +@@ -684,7 +684,7 @@ verify_kdc_signature(krb5_context context, krb5_pac pac, + for (tries = 2; tries > 0 && kvno > 0; tries--, kvno--) { + ret = krb5_dbe_find_enctype(context, tgt, -1, -1, kvno, &kd); + if (ret) +- return KRB5KRB_AP_ERR_BAD_INTEGRITY; ++ return KRB5KRB_AP_ERR_MODIFIED; + ret = krb5_dbe_decrypt_key_data(context, NULL, kd, &old_key, NULL); + if (ret) + return ret; +@@ -697,7 +697,7 @@ verify_kdc_signature(krb5_context context, krb5_pac pac, + kvno = kd->key_data_kvno - 1; + } + +- return KRB5KRB_AP_ERR_BAD_INTEGRITY; ++ return KRB5KRB_AP_ERR_MODIFIED; + } + + static krb5_error_code +-- +2.39.1 + diff --git a/SOURCES/0154-Factor-out-PAC-checksum-verification.patch b/SOURCES/0154-Factor-out-PAC-checksum-verification.patch new file mode 100644 index 0000000..1653853 --- /dev/null +++ b/SOURCES/0154-Factor-out-PAC-checksum-verification.patch @@ -0,0 +1,258 @@ +From ae7c326c3c074266d8c80d71561494d785172251 Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Fri, 14 Jan 2022 02:05:58 -0500 +Subject: [PATCH] Factor out PAC checksum verification + +Reduce code repetition in PAC checksum handling by adding a helper +function. Remove the unnecessary prefix on several function names. +--- + src/lib/krb5/krb/pac.c | 173 +++++++++++++---------------------------- + 1 file changed, 55 insertions(+), 118 deletions(-) + +diff --git a/src/lib/krb5/krb/pac.c b/src/lib/krb5/krb/pac.c +index 6eb23d8090..2f6ad4e1df 100644 +--- a/src/lib/krb5/krb/pac.c ++++ b/src/lib/krb5/krb/pac.c +@@ -493,10 +493,8 @@ k5_pac_validate_client(krb5_context context, + } + + static krb5_error_code +-k5_pac_zero_signature(krb5_context context, +- const krb5_pac pac, +- krb5_ui_4 type, +- krb5_data *data) ++zero_signature(krb5_context context, const krb5_pac pac, krb5_ui_4 type, ++ krb5_data *data) + { + PAC_INFO_BUFFER *buffer = NULL; + size_t i; +@@ -530,151 +528,89 @@ k5_pac_zero_signature(krb5_context context, + } + + static krb5_error_code +-k5_pac_verify_server_checksum(krb5_context context, +- const krb5_pac pac, +- const krb5_keyblock *server) ++verify_checksum(krb5_context context, const krb5_pac pac, uint32_t buffer_type, ++ const krb5_keyblock *key, krb5_keyusage usage, ++ const krb5_data *data) + { + krb5_error_code ret; +- krb5_data pac_data; /* PAC with zeroed checksums */ ++ krb5_data buffer; ++ krb5_cksumtype cksumtype; + krb5_checksum checksum; +- krb5_data checksum_data; + krb5_boolean valid; +- krb5_octet *p; ++ size_t cksumlen; + +- ret = k5_pac_locate_buffer(context, pac, KRB5_PAC_SERVER_CHECKSUM, +- &checksum_data); ++ ret = k5_pac_locate_buffer(context, pac, buffer_type, &buffer); + if (ret != 0) + return ret; +- +- if (checksum_data.length < PAC_SIGNATURE_DATA_LENGTH) ++ if (buffer.length < PAC_SIGNATURE_DATA_LENGTH) + return KRB5_BAD_MSIZE; + +- p = (krb5_octet *)checksum_data.data; +- checksum.checksum_type = load_32_le(p); +- checksum.length = checksum_data.length - PAC_SIGNATURE_DATA_LENGTH; +- checksum.contents = p + PAC_SIGNATURE_DATA_LENGTH; +- if (checksum.checksum_type == CKSUMTYPE_SHA1) ++ cksumtype = load_32_le(buffer.data); ++ if (buffer_type == KRB5_PAC_SERVER_CHECKSUM && cksumtype == CKSUMTYPE_SHA1) + return KRB5KDC_ERR_SUMTYPE_NOSUPP; +- if (!krb5_c_is_keyed_cksum(checksum.checksum_type)) ++ if (!krb5_c_is_keyed_cksum(cksumtype)) + return KRB5KRB_ERR_GENERIC; + +- pac_data.length = pac->data.length; +- pac_data.data = k5memdup(pac->data.data, pac->data.length, &ret); +- if (pac_data.data == NULL) +- return ret; +- +- /* Zero out both checksum buffers */ +- ret = k5_pac_zero_signature(context, pac, KRB5_PAC_SERVER_CHECKSUM, +- &pac_data); +- if (ret != 0) { +- free(pac_data.data); +- return ret; +- } +- +- ret = k5_pac_zero_signature(context, pac, KRB5_PAC_PRIVSVR_CHECKSUM, +- &pac_data); +- if (ret != 0) { +- free(pac_data.data); ++ /* There may be an RODCIdentifier trailer (see [MS-PAC] 2.8), so look up ++ * the length of the checksum by its type. */ ++ ret = krb5_c_checksum_length(context, cksumtype, &cksumlen); ++ if (ret) + return ret; +- } ++ if (cksumlen > buffer.length - PAC_SIGNATURE_DATA_LENGTH) ++ return KRB5_BAD_MSIZE; ++ checksum.checksum_type = cksumtype; ++ checksum.length = cksumlen; ++ checksum.contents = (uint8_t *)buffer.data + PAC_SIGNATURE_DATA_LENGTH; + +- ret = krb5_c_verify_checksum(context, server, +- KRB5_KEYUSAGE_APP_DATA_CKSUM, +- &pac_data, &checksum, &valid); ++ ret = krb5_c_verify_checksum(context, key, usage, data, &checksum, &valid); ++ return ret ? ret : (valid ? 0 : KRB5KRB_AP_ERR_MODIFIED); ++} + +- free(pac_data.data); ++static krb5_error_code ++verify_server_checksum(krb5_context context, const krb5_pac pac, ++ const krb5_keyblock *server) ++{ ++ krb5_error_code ret; ++ krb5_data copy; /* PAC with zeroed checksums */ + +- if (ret != 0) { ++ ret = krb5int_copy_data_contents(context, &pac->data, ©); ++ if (ret) + return ret; +- } + +- if (valid == FALSE) +- ret = KRB5KRB_AP_ERR_MODIFIED; ++ /* Zero out both checksum buffers */ ++ ret = zero_signature(context, pac, KRB5_PAC_SERVER_CHECKSUM, ©); ++ if (ret) ++ goto cleanup; ++ ret = zero_signature(context, pac, KRB5_PAC_PRIVSVR_CHECKSUM, ©); ++ if (ret) ++ goto cleanup; ++ ++ ret = verify_checksum(context, pac, KRB5_PAC_SERVER_CHECKSUM, server, ++ KRB5_KEYUSAGE_APP_DATA_CKSUM, ©); + ++cleanup: ++ free(copy.data); + return ret; + } + + static krb5_error_code +-k5_pac_verify_kdc_checksum(krb5_context context, +- const krb5_pac pac, +- const krb5_keyblock *privsvr) ++verify_kdc_checksum(krb5_context context, const krb5_pac pac, ++ const krb5_keyblock *privsvr) + { + krb5_error_code ret; +- krb5_data server_checksum, privsvr_checksum; +- krb5_checksum checksum; +- krb5_boolean valid; +- krb5_octet *p; +- +- ret = k5_pac_locate_buffer(context, pac, KRB5_PAC_PRIVSVR_CHECKSUM, +- &privsvr_checksum); +- if (ret != 0) +- return ret; +- +- if (privsvr_checksum.length < PAC_SIGNATURE_DATA_LENGTH) +- return KRB5_BAD_MSIZE; ++ krb5_data server_checksum; + + ret = k5_pac_locate_buffer(context, pac, KRB5_PAC_SERVER_CHECKSUM, + &server_checksum); +- if (ret != 0) ++ if (ret) + return ret; +- + if (server_checksum.length < PAC_SIGNATURE_DATA_LENGTH) + return KRB5_BAD_MSIZE; +- +- p = (krb5_octet *)privsvr_checksum.data; +- checksum.checksum_type = load_32_le(p); +- checksum.length = privsvr_checksum.length - PAC_SIGNATURE_DATA_LENGTH; +- checksum.contents = p + PAC_SIGNATURE_DATA_LENGTH; +- if (!krb5_c_is_keyed_cksum(checksum.checksum_type)) +- return KRB5KRB_ERR_GENERIC; +- + server_checksum.data += PAC_SIGNATURE_DATA_LENGTH; + server_checksum.length -= PAC_SIGNATURE_DATA_LENGTH; + +- ret = krb5_c_verify_checksum(context, privsvr, +- KRB5_KEYUSAGE_APP_DATA_CKSUM, +- &server_checksum, &checksum, &valid); +- if (ret != 0) +- return ret; +- +- if (valid == FALSE) +- ret = KRB5KRB_AP_ERR_MODIFIED; +- +- return ret; +-} +- +-static krb5_error_code +-verify_ticket_checksum(krb5_context context, const krb5_pac pac, +- const krb5_data *ticket, const krb5_keyblock *privsvr) +-{ +- krb5_error_code ret; +- krb5_checksum checksum; +- krb5_data checksum_data; +- krb5_boolean valid; +- krb5_octet *p; +- +- ret = k5_pac_locate_buffer(context, pac, KRB5_PAC_TICKET_CHECKSUM, +- &checksum_data); +- if (ret != 0) +- return KRB5KRB_AP_ERR_MODIFIED; +- +- if (checksum_data.length < PAC_SIGNATURE_DATA_LENGTH) +- return KRB5_BAD_MSIZE; +- +- p = (krb5_octet *)checksum_data.data; +- checksum.checksum_type = load_32_le(p); +- checksum.length = checksum_data.length - PAC_SIGNATURE_DATA_LENGTH; +- checksum.contents = p + PAC_SIGNATURE_DATA_LENGTH; +- if (!krb5_c_is_keyed_cksum(checksum.checksum_type)) +- return KRB5KRB_ERR_GENERIC; +- +- ret = krb5_c_verify_checksum(context, privsvr, +- KRB5_KEYUSAGE_APP_DATA_CKSUM, ticket, +- &checksum, &valid); +- if (ret != 0) +- return ret; +- +- return valid ? 0 : KRB5KRB_AP_ERR_MODIFIED; ++ return verify_checksum(context, pac, KRB5_PAC_PRIVSVR_CHECKSUM, privsvr, ++ KRB5_KEYUSAGE_APP_DATA_CKSUM, &server_checksum); + } + + /* Per MS-PAC 2.8.3, tickets encrypted to TGS and password change principals +@@ -761,7 +697,8 @@ krb5_kdc_verify_ticket(krb5_context context, const krb5_enc_tkt_part *enc_tkt, + if (ret) + goto cleanup; + +- ret = verify_ticket_checksum(context, pac, recoded_tkt, privsvr); ++ ret = verify_checksum(context, pac, KRB5_PAC_TICKET_CHECKSUM, privsvr, ++ KRB5_KEYUSAGE_APP_DATA_CKSUM, recoded_tkt); + if (ret) + goto cleanup; + } +@@ -804,13 +741,13 @@ krb5_pac_verify_ext(krb5_context context, + krb5_error_code ret; + + if (server != NULL) { +- ret = k5_pac_verify_server_checksum(context, pac, server); ++ ret = verify_server_checksum(context, pac, server); + if (ret != 0) + return ret; + } + + if (privsvr != NULL) { +- ret = k5_pac_verify_kdc_checksum(context, pac, privsvr); ++ ret = verify_kdc_checksum(context, pac, privsvr); + if (ret != 0) + return ret; + } +-- +2.39.1 + diff --git a/SOURCES/0155-Add-PAC-full-checksums.patch b/SOURCES/0155-Add-PAC-full-checksums.patch new file mode 100644 index 0000000..a83a008 --- /dev/null +++ b/SOURCES/0155-Add-PAC-full-checksums.patch @@ -0,0 +1,673 @@ +From 1159d1e6057b6bc5b2a83bd6c8fc9f5fe38816d8 Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Thu, 22 Dec 2022 03:05:23 -0500 +Subject: [PATCH] Add PAC full checksums + +A paper by Tom Tervoort noted that computing the PAC privsvr checksum +over only the server checksum is vulnerable to collision attacks +(CVE-2022-37967). In response, Microsoft has added a second KDC +checksum over the full contents of the PAC. Generate and verify full +KDC checksums in PACs for service tickets. Update the t_pac.c ticket +test case to use a ticket issued by a recent version of Active +Directory (provided by Stefan Metzmacher). + +ticket: 9084 (new) +--- + doc/appdev/refs/macros/index.rst | 1 + + src/include/krb5/krb5.hin | 1 + + src/lib/krb5/krb/pac.c | 92 +++++++++-------- + src/lib/krb5/krb/pac_sign.c | 146 +++++++++++++++----------- + src/lib/krb5/krb/t_pac.c | 171 ++++++++++++++++++------------- + src/tests/t_authdata.py | 5 +- + 6 files changed, 242 insertions(+), 174 deletions(-) + +diff --git a/doc/appdev/refs/macros/index.rst b/doc/appdev/refs/macros/index.rst +index c6ea088742..22ef2b2f42 100644 +--- a/doc/appdev/refs/macros/index.rst ++++ b/doc/appdev/refs/macros/index.rst +@@ -247,6 +247,7 @@ Public + KRB5_PAC_SERVER_CHECKSUM.rst + KRB5_PAC_TICKET_CHECKSUM.rst + KRB5_PAC_UPN_DNS_INFO.rst ++ KRB5_PAC_FULL_CHECKSUM.rst + KRB5_PADATA_AFS3_SALT.rst + KRB5_PADATA_AP_REQ.rst + KRB5_PADATA_AS_CHECKSUM.rst +diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin +index 8e59628bd9..12a1d441b8 100644 +--- a/src/include/krb5/krb5.hin ++++ b/src/include/krb5/krb5.hin +@@ -8187,6 +8187,7 @@ krb5_verify_authdata_kdc_issued(krb5_context context, + #define KRB5_PAC_TICKET_CHECKSUM 16 /**< Ticket checksum */ + #define KRB5_PAC_ATTRIBUTES_INFO 17 /**< PAC attributes */ + #define KRB5_PAC_REQUESTOR 18 /**< PAC requestor SID */ ++#define KRB5_PAC_FULL_CHECKSUM 19 /**< KDC full checksum */ + + struct krb5_pac_data; + /** PAC data structure to convey authorization information */ +diff --git a/src/lib/krb5/krb/pac.c b/src/lib/krb5/krb/pac.c +index 2f6ad4e1df..9c00178a28 100644 +--- a/src/lib/krb5/krb/pac.c ++++ b/src/lib/krb5/krb/pac.c +@@ -500,7 +500,8 @@ zero_signature(krb5_context context, const krb5_pac pac, krb5_ui_4 type, + size_t i; + + assert(type == KRB5_PAC_SERVER_CHECKSUM || +- type == KRB5_PAC_PRIVSVR_CHECKSUM); ++ type == KRB5_PAC_PRIVSVR_CHECKSUM || ++ type == KRB5_PAC_FULL_CHECKSUM); + assert(data->length >= pac->data.length); + + for (i = 0; i < pac->pac->cBuffers; i++) { +@@ -567,17 +568,17 @@ verify_checksum(krb5_context context, const krb5_pac pac, uint32_t buffer_type, + } + + static krb5_error_code +-verify_server_checksum(krb5_context context, const krb5_pac pac, +- const krb5_keyblock *server) ++verify_pac_checksums(krb5_context context, const krb5_pac pac, ++ krb5_boolean expect_full_checksum, ++ const krb5_keyblock *server, const krb5_keyblock *privsvr) + { + krb5_error_code ret; +- krb5_data copy; /* PAC with zeroed checksums */ ++ krb5_data copy, server_checksum; + ++ /* Make a copy of the PAC with zeroed out server and privsvr checksums. */ + ret = krb5int_copy_data_contents(context, &pac->data, ©); + if (ret) + return ret; +- +- /* Zero out both checksum buffers */ + ret = zero_signature(context, pac, KRB5_PAC_SERVER_CHECKSUM, ©); + if (ret) + goto cleanup; +@@ -585,32 +586,46 @@ verify_server_checksum(krb5_context context, const krb5_pac pac, + if (ret) + goto cleanup; + +- ret = verify_checksum(context, pac, KRB5_PAC_SERVER_CHECKSUM, server, +- KRB5_KEYUSAGE_APP_DATA_CKSUM, ©); ++ if (server != NULL) { ++ /* Verify the server checksum over the PAC copy. */ ++ ret = verify_checksum(context, pac, KRB5_PAC_SERVER_CHECKSUM, server, ++ KRB5_KEYUSAGE_APP_DATA_CKSUM, ©); ++ } + +-cleanup: +- free(copy.data); +- return ret; +-} ++ if (privsvr != NULL && expect_full_checksum) { ++ /* Zero the full checksum buffer in the copy and verify the full ++ * checksum over the copy with all three checksums zeroed. */ ++ ret = zero_signature(context, pac, KRB5_PAC_FULL_CHECKSUM, ©); ++ if (ret) ++ goto cleanup; ++ ret = verify_checksum(context, pac, KRB5_PAC_FULL_CHECKSUM, privsvr, ++ KRB5_KEYUSAGE_APP_DATA_CKSUM, ©); ++ if (ret) ++ goto cleanup; ++ } + +-static krb5_error_code +-verify_kdc_checksum(krb5_context context, const krb5_pac pac, +- const krb5_keyblock *privsvr) +-{ +- krb5_error_code ret; +- krb5_data server_checksum; ++ if (privsvr != NULL) { ++ /* Verify the privsvr checksum over the server checksum. */ ++ ret = k5_pac_locate_buffer(context, pac, KRB5_PAC_SERVER_CHECKSUM, ++ &server_checksum); ++ if (ret) ++ return ret; ++ if (server_checksum.length < PAC_SIGNATURE_DATA_LENGTH) ++ return KRB5_BAD_MSIZE; ++ server_checksum.data += PAC_SIGNATURE_DATA_LENGTH; ++ server_checksum.length -= PAC_SIGNATURE_DATA_LENGTH; + +- ret = k5_pac_locate_buffer(context, pac, KRB5_PAC_SERVER_CHECKSUM, +- &server_checksum); +- if (ret) +- return ret; +- if (server_checksum.length < PAC_SIGNATURE_DATA_LENGTH) +- return KRB5_BAD_MSIZE; +- server_checksum.data += PAC_SIGNATURE_DATA_LENGTH; +- server_checksum.length -= PAC_SIGNATURE_DATA_LENGTH; ++ ret = verify_checksum(context, pac, KRB5_PAC_PRIVSVR_CHECKSUM, privsvr, ++ KRB5_KEYUSAGE_APP_DATA_CKSUM, &server_checksum); ++ if (ret) ++ goto cleanup; ++ } ++ ++ pac->verified = TRUE; + +- return verify_checksum(context, pac, KRB5_PAC_PRIVSVR_CHECKSUM, privsvr, +- KRB5_KEYUSAGE_APP_DATA_CKSUM, &server_checksum); ++cleanup: ++ free(copy.data); ++ return ret; + } + + /* Per MS-PAC 2.8.3, tickets encrypted to TGS and password change principals +@@ -638,6 +653,7 @@ krb5_kdc_verify_ticket(krb5_context context, const krb5_enc_tkt_part *enc_tkt, + krb5_authdata **authdata, *orig, **ifrel = NULL, **recoded_ifrel = NULL; + uint8_t z = 0; + krb5_authdata zpac = { KV5M_AUTHDATA, KRB5_AUTHDATA_WIN2K_PAC, 1, &z }; ++ krb5_boolean is_service_tkt; + size_t i, j; + + *pac_out = NULL; +@@ -679,7 +695,8 @@ krb5_kdc_verify_ticket(krb5_context context, const krb5_enc_tkt_part *enc_tkt, + if (ret) + goto cleanup; + +- if (privsvr != NULL && k5_pac_should_have_ticket_signature(server_princ)) { ++ is_service_tkt = k5_pac_should_have_ticket_signature(server_princ); ++ if (privsvr != NULL && is_service_tkt) { + /* To check the PAC ticket signatures, re-encode the ticket with the + * PAC contents replaced by a single zero. */ + orig = ifrel[j]; +@@ -703,8 +720,9 @@ krb5_kdc_verify_ticket(krb5_context context, const krb5_enc_tkt_part *enc_tkt, + goto cleanup; + } + +- ret = krb5_pac_verify_ext(context, pac, enc_tkt->times.authtime, NULL, +- server, privsvr, FALSE); ++ ret = verify_pac_checksums(context, pac, is_service_tkt, server, privsvr); ++ if (ret) ++ goto cleanup; + + *pac_out = pac; + pac = NULL; +@@ -740,14 +758,8 @@ krb5_pac_verify_ext(krb5_context context, + { + krb5_error_code ret; + +- if (server != NULL) { +- ret = verify_server_checksum(context, pac, server); +- if (ret != 0) +- return ret; +- } +- +- if (privsvr != NULL) { +- ret = verify_kdc_checksum(context, pac, privsvr); ++ if (server != NULL || privsvr != NULL) { ++ ret = verify_pac_checksums(context, pac, FALSE, server, privsvr); + if (ret != 0) + return ret; + } +@@ -759,8 +771,6 @@ krb5_pac_verify_ext(krb5_context context, + return ret; + } + +- pac->verified = TRUE; +- + return 0; + } + +diff --git a/src/lib/krb5/krb/pac_sign.c b/src/lib/krb5/krb/pac_sign.c +index 0f9581abbb..8ea61ac17b 100644 +--- a/src/lib/krb5/krb/pac_sign.c ++++ b/src/lib/krb5/krb/pac_sign.c +@@ -187,26 +187,41 @@ k5_pac_encode_header(krb5_context context, krb5_pac pac) + return 0; + } + +-krb5_error_code KRB5_CALLCONV +-krb5_pac_sign(krb5_context context, krb5_pac pac, krb5_timestamp authtime, +- krb5_const_principal principal, const krb5_keyblock *server_key, +- const krb5_keyblock *privsvr_key, krb5_data *data) ++/* Find the buffer of type buftype in pac and write within it a checksum of ++ * type cksumtype over data. Set *cksum_out to the checksum. */ ++static krb5_error_code ++compute_pac_checksum(krb5_context context, krb5_pac pac, uint32_t buftype, ++ const krb5_keyblock *key, krb5_cksumtype cksumtype, ++ const krb5_data *data, krb5_data *cksum_out) + { +- return krb5_pac_sign_ext(context, pac, authtime, principal, server_key, +- privsvr_key, FALSE, data); ++ krb5_error_code ret; ++ krb5_data buf; ++ krb5_crypto_iov iov[2]; ++ ++ ret = k5_pac_locate_buffer(context, pac, buftype, &buf); ++ if (ret) ++ return ret; ++ ++ assert(buf.length > PAC_SIGNATURE_DATA_LENGTH); ++ *cksum_out = make_data(buf.data + PAC_SIGNATURE_DATA_LENGTH, ++ buf.length - PAC_SIGNATURE_DATA_LENGTH); ++ iov[0].flags = KRB5_CRYPTO_TYPE_DATA; ++ iov[0].data = *data; ++ iov[1].flags = KRB5_CRYPTO_TYPE_CHECKSUM; ++ iov[1].data = *cksum_out; ++ return krb5_c_make_checksum_iov(context, cksumtype, key, ++ KRB5_KEYUSAGE_APP_DATA_CKSUM, iov, 2); + } + +-krb5_error_code KRB5_CALLCONV +-krb5_pac_sign_ext(krb5_context context, krb5_pac pac, krb5_timestamp authtime, +- krb5_const_principal principal, +- const krb5_keyblock *server_key, +- const krb5_keyblock *privsvr_key, krb5_boolean with_realm, +- krb5_data *data) ++static krb5_error_code ++sign_pac(krb5_context context, krb5_pac pac, krb5_timestamp authtime, ++ krb5_const_principal principal, const krb5_keyblock *server_key, ++ const krb5_keyblock *privsvr_key, krb5_boolean with_realm, ++ krb5_boolean is_service_tkt, krb5_data *data) + { + krb5_error_code ret; +- krb5_data server_cksum, privsvr_cksum; ++ krb5_data full_cksum, server_cksum, privsvr_cksum; + krb5_cksumtype server_cksumtype, privsvr_cksumtype; +- krb5_crypto_iov iov[2]; + + data->length = 0; + data->data = NULL; +@@ -214,67 +229,53 @@ krb5_pac_sign_ext(krb5_context context, krb5_pac pac, krb5_timestamp authtime, + if (principal != NULL) { + ret = k5_insert_client_info(context, pac, authtime, principal, + with_realm); +- if (ret != 0) ++ if (ret) + return ret; + } + +- /* Create zeroed buffers for both checksums */ ++ /* Create zeroed buffers for all checksums. */ + ret = k5_insert_checksum(context, pac, KRB5_PAC_SERVER_CHECKSUM, + server_key, &server_cksumtype); +- if (ret != 0) ++ if (ret) + return ret; +- + ret = k5_insert_checksum(context, pac, KRB5_PAC_PRIVSVR_CHECKSUM, + privsvr_key, &privsvr_cksumtype); +- if (ret != 0) ++ if (ret) + return ret; ++ if (is_service_tkt) { ++ ret = k5_insert_checksum(context, pac, KRB5_PAC_FULL_CHECKSUM, ++ privsvr_key, &privsvr_cksumtype); ++ if (ret) ++ return ret; ++ } + +- /* Now, encode the PAC header so that the checksums will include it */ ++ /* Encode the PAC header so that the checksums will include it. */ + ret = k5_pac_encode_header(context, pac); +- if (ret != 0) +- return ret; +- +- /* Generate the server checksum over the entire PAC */ +- ret = k5_pac_locate_buffer(context, pac, KRB5_PAC_SERVER_CHECKSUM, +- &server_cksum); +- if (ret != 0) ++ if (ret) + return ret; + +- assert(server_cksum.length > PAC_SIGNATURE_DATA_LENGTH); +- +- iov[0].flags = KRB5_CRYPTO_TYPE_DATA; +- iov[0].data = pac->data; +- +- iov[1].flags = KRB5_CRYPTO_TYPE_CHECKSUM; +- iov[1].data.data = server_cksum.data + PAC_SIGNATURE_DATA_LENGTH; +- iov[1].data.length = server_cksum.length - PAC_SIGNATURE_DATA_LENGTH; ++ if (is_service_tkt) { ++ /* Generate a full KDC checksum over the whole PAC. */ ++ ret = compute_pac_checksum(context, pac, KRB5_PAC_FULL_CHECKSUM, ++ privsvr_key, privsvr_cksumtype, ++ &pac->data, &full_cksum); ++ if (ret) ++ return ret; ++ } + +- ret = krb5_c_make_checksum_iov(context, server_cksumtype, +- server_key, KRB5_KEYUSAGE_APP_DATA_CKSUM, +- iov, sizeof(iov)/sizeof(iov[0])); +- if (ret != 0) ++ /* Generate the server checksum over the whole PAC, including the full KDC ++ * checksum if we added one. */ ++ ret = compute_pac_checksum(context, pac, KRB5_PAC_SERVER_CHECKSUM, ++ server_key, server_cksumtype, &pac->data, ++ &server_cksum); ++ if (ret) + return ret; + +- /* Generate the privsvr checksum over the server checksum buffer */ +- ret = k5_pac_locate_buffer(context, pac, KRB5_PAC_PRIVSVR_CHECKSUM, ++ /* Generate the privsvr checksum over the server checksum buffer. */ ++ ret = compute_pac_checksum(context, pac, KRB5_PAC_PRIVSVR_CHECKSUM, ++ privsvr_key, privsvr_cksumtype, &server_cksum, + &privsvr_cksum); +- if (ret != 0) +- return ret; +- +- assert(privsvr_cksum.length > PAC_SIGNATURE_DATA_LENGTH); +- +- iov[0].flags = KRB5_CRYPTO_TYPE_DATA; +- iov[0].data.data = server_cksum.data + PAC_SIGNATURE_DATA_LENGTH; +- iov[0].data.length = server_cksum.length - PAC_SIGNATURE_DATA_LENGTH; +- +- iov[1].flags = KRB5_CRYPTO_TYPE_CHECKSUM; +- iov[1].data.data = privsvr_cksum.data + PAC_SIGNATURE_DATA_LENGTH; +- iov[1].data.length = privsvr_cksum.length - PAC_SIGNATURE_DATA_LENGTH; +- +- ret = krb5_c_make_checksum_iov(context, privsvr_cksumtype, +- privsvr_key, KRB5_KEYUSAGE_APP_DATA_CKSUM, +- iov, sizeof(iov)/sizeof(iov[0])); +- if (ret != 0) ++ if (ret) + return ret; + + data->data = k5memdup(pac->data.data, pac->data.length, &ret); +@@ -288,6 +289,26 @@ krb5_pac_sign_ext(krb5_context context, krb5_pac pac, krb5_timestamp authtime, + return 0; + } + ++krb5_error_code KRB5_CALLCONV ++krb5_pac_sign(krb5_context context, krb5_pac pac, krb5_timestamp authtime, ++ krb5_const_principal principal, const krb5_keyblock *server_key, ++ const krb5_keyblock *privsvr_key, krb5_data *data) ++{ ++ return sign_pac(context, pac, authtime, principal, server_key, ++ privsvr_key, FALSE, FALSE, data); ++} ++ ++krb5_error_code KRB5_CALLCONV ++krb5_pac_sign_ext(krb5_context context, krb5_pac pac, krb5_timestamp authtime, ++ krb5_const_principal principal, ++ const krb5_keyblock *server_key, ++ const krb5_keyblock *privsvr_key, krb5_boolean with_realm, ++ krb5_data *data) ++{ ++ return sign_pac(context, pac, authtime, principal, server_key, privsvr_key, ++ with_realm, FALSE, data); ++} ++ + /* Add a signature over der_enc_tkt in privsvr to pac. der_enc_tkt should be + * encoded with a dummy PAC authdata element containing a single zero byte. */ + static krb5_error_code +@@ -359,6 +380,7 @@ krb5_kdc_sign_ticket(krb5_context context, krb5_enc_tkt_part *enc_tkt, + krb5_error_code ret; + krb5_data *der_enc_tkt = NULL, pac_data = empty_data(); + krb5_authdata **list, *pac_ad; ++ krb5_boolean is_service_tkt; + size_t count; + + /* Reallocate space for another authdata element in enc_tkt. */ +@@ -377,7 +399,8 @@ krb5_kdc_sign_ticket(krb5_context context, krb5_enc_tkt_part *enc_tkt, + memmove(list + 1, list, (count + 1) * sizeof(*list)); + list[0] = pac_ad; + +- if (k5_pac_should_have_ticket_signature(server_princ)) { ++ is_service_tkt = k5_pac_should_have_ticket_signature(server_princ); ++ if (is_service_tkt) { + ret = encode_krb5_enc_tkt_part(enc_tkt, &der_enc_tkt); + if (ret) + goto cleanup; +@@ -388,9 +411,8 @@ krb5_kdc_sign_ticket(krb5_context context, krb5_enc_tkt_part *enc_tkt, + goto cleanup; + } + +- ret = krb5_pac_sign_ext(context, pac, enc_tkt->times.authtime, +- client_princ, server, privsvr, with_realm, +- &pac_data); ++ ret = sign_pac(context, pac, enc_tkt->times.authtime, client_princ, server, ++ privsvr, with_realm, is_service_tkt, &pac_data); + if (ret) + goto cleanup; + +diff --git a/src/lib/krb5/krb/t_pac.c b/src/lib/krb5/krb/t_pac.c +index 173bde7bab..81f1642ab0 100644 +--- a/src/lib/krb5/krb/t_pac.c ++++ b/src/lib/krb5/krb/t_pac.c +@@ -607,78 +607,102 @@ check_pac(krb5_context context, int index, const unsigned char *pdata, + + static const krb5_keyblock ticket_sig_krbtgt_key = { + 0, ENCTYPE_AES256_CTS_HMAC_SHA1_96, +- 32, U("\x7a\x58\x98\xd2\xaf\xa6\xaf\xc0\x6a\xce\x06\x04\x4b\xc2\x70\x84" +- "\x9b\x8e\x0a\x6c\x4c\x07\xdc\x6f\xbb\x48\x43\xe1\xd2\xaa\x97\xf7") ++ 32, U("\x03\x73\x81\xEC\x43\x96\x7B\xC2\xAC\x3D\xF5\x2A\xAE\x95\xA6\x8E" ++ "\xBE\x24\x58\xDB\xCE\x52\x28\x20\xAF\x5E\xB7\x04\xA2\x22\x71\x4F") + }; + + static const krb5_keyblock ticket_sig_server_key = { +- 0, ENCTYPE_ARCFOUR_HMAC, +- 16, U("\xed\x23\x11\x20\x7a\x21\x44\x20\xbf\xc0\x8d\x36\xf7\xf6\xb2\x3e") ++ 0, ENCTYPE_AES256_CTS_HMAC_SHA1_96, ++ 32, U("\x11\x4A\x84\xE3\x14\x8F\xAA\xB1\xFA\x7B\x53\x51\xB2\x8A\xC2\xF1" ++ "\xFD\x19\x6D\x61\xE0\xF3\xF2\x3E\x1F\xDB\xD3\xC1\x79\x7D\xC1\xEE") + }; + ++/* A ticket issued by an Active Directory KDC (Windows Server 2022), containing ++ * a PAC with a full checksum. */ + static const krb5_data ticket_data = { +- .length = 972, .data = +- "\x61\x82\x03\xC8\x30\x82\x03\xC4\xA0\x03\x02\x01\x05\xA1\x0A\x1B" +- "\x08\x43\x44\x4F\x4D\x2E\x43\x4F\x4D\xA2\x0F\x30\x0D\xA0\x03\x02" +- "\x01\x01\xA1\x06\x30\x04\x1B\x02\x73\x31\xA3\x82\x03\x9E\x30\x82" +- "\x03\x9A\xA0\x03\x02\x01\x17\xA1\x03\x02\x01\x03\xA2\x82\x03\x8C" +- "\x04\x82\x03\x88\x44\x31\x61\x20\x17\xC9\xFE\xBC\xAC\x46\xB5\x77" +- "\xE9\x68\x04\x4C\x9B\x31\x91\x0C\xC1\xD4\xDD\xEF\xC7\x34\x20\x08" +- "\x90\x91\xE8\x79\xE0\xB5\x03\x26\xA4\x65\xDE\xEC\x47\x03\x2A\x8F" +- "\x61\xE7\x4D\x38\x5A\x42\x95\x5A\xF9\x2F\x41\x2C\x2A\x6E\x60\xA1" +- "\xEB\x51\xB3\xBD\x4C\x00\x41\x2A\x44\x76\x08\x37\x1A\x51\xFD\x65" +- "\x67\x7E\xBF\x3D\x90\x86\xE3\x9A\x54\x6B\x67\xA8\x08\x7A\x73\xCC" +- "\xC3\xB7\x4B\xD5\x5C\x3A\x14\x6C\xC1\x5F\x54\x4B\x92\x55\xB4\xB7" +- "\x92\x23\x3F\x53\x89\x47\x8E\x1F\x8B\xB9\xDB\x3B\x93\xE8\x70\xE4" +- "\x24\xB8\x9D\xF0\x0E\x35\x28\xF8\x7A\x27\x5D\xF7\x25\x97\x9C\xF5" +- "\x9F\x9F\x64\x04\xF2\xA3\xAB\x11\x15\xB6\xDA\x18\xD6\x46\xD5\xE6" +- "\xB8\x08\xDE\x0A\x62\xFD\xF8\xAA\x52\x90\xD9\x67\x29\xB2\xCD\x06" +- "\xB6\xB0\x50\x2B\x3F\x0F\xA3\xA5\xBF\xAA\x6E\x40\x03\xD6\x5F\x02" +- "\xBC\xD8\x18\x47\x97\x09\xD7\xE4\x96\x3B\xCB\xEB\x92\x2C\x3C\x49" +- "\xFF\x1F\x71\xE0\x52\x94\x0F\x8B\x9F\xB8\x2A\xBB\x9C\xE2\xA3\xDD" +- "\x38\x89\xE2\xB1\x0B\x9E\x1F\x7A\xB3\xE3\xD2\xB0\x94\xDC\x87\xBE" +- "\x37\xA6\xD3\xB3\x29\x35\x9A\x72\xC3\x7A\xF1\xA9\xE6\xC5\xD1\x26" +- "\x83\x65\x44\x17\xBA\x55\xA8\x5E\x94\x26\xED\xE9\x8A\x93\x11\x5D" +- "\x7E\x20\x1B\x9C\x15\x9E\x13\x37\x03\x4D\xDD\x99\x51\xD8\x66\x29" +- "\x6A\xB9\xFB\x49\xFE\x52\x78\xDA\x86\x85\xA9\xA3\xB9\xEF\xEC\xAD" +- "\x35\xA6\x8D\xAC\x0F\x75\x22\xBB\x0B\x49\x1C\x13\x52\x40\xC9\x52" +- "\x69\x09\x54\xD1\x0F\x94\x3F\x22\x48\x67\xB0\x96\x28\xAA\xE6\x28" +- "\xD9\x0C\x08\xEF\x51\xED\x15\x5E\xA2\x53\x59\xA5\x03\xB4\x06\x20" +- "\x3D\xCC\xB4\xC5\xF8\x8C\x73\x67\xA3\x21\x3D\x19\xCD\xD4\x12\x28" +- "\xD2\x93\xDE\x0D\xF0\x71\x10\x50\xD6\x33\x35\x04\x11\x64\x43\x39" +- "\xC3\xDF\x96\xE3\x66\xE3\x85\xCA\xE7\x67\x14\x3A\xF0\x43\xAA\xBB" +- "\xD4\x1D\xB5\x24\xB5\x74\x90\x25\xA7\x87\x7E\xDB\xD3\x83\x8A\x3A" +- "\x69\xA8\x2D\xAF\xB7\xB8\xF3\xDC\x13\xAF\x45\x61\x3F\x59\x39\x7E" +- "\x69\xDE\x0C\x04\xF1\x10\x6B\xB4\x56\xFA\x21\x9F\x72\x2B\x60\x86" +- "\xE3\x23\x0E\xC4\x51\xF6\xBE\xD8\xE1\x5F\xEE\x73\x4C\x17\x4C\x2C" +- "\x1B\xFB\x9F\x1F\x7A\x3B\x07\x5B\x8E\xF1\x01\xAC\xD6\x30\x94\x8A" +- "\x5D\x22\x6F\x08\xCE\xED\x5E\xB6\xDB\x86\x8C\x87\xEB\x8D\x91\xFF" +- "\x0A\x86\x30\xBD\xC0\xF8\x25\xE7\xAE\x24\x35\xF2\xFC\xE5\xFD\x1B" +- "\xB0\x05\x4A\xA3\xE5\xEB\x2E\x05\xAD\x99\x67\x49\x87\xE6\xB3\x87" +- "\x82\xA4\x59\xA7\x6E\xDD\xF2\xB6\x66\xE8\xF7\x70\xF5\xBD\xC9\x0E" +- "\xFA\x9C\x79\x84\xD4\x9B\x05\x0E\xBB\xF5\xDB\xEF\xFC\xCC\x26\xF2" +- "\x93\xCF\xD2\x04\x3C\xA9\x2C\x65\x42\x97\x86\xD8\x38\x0A\x1E\xF6" +- "\xD6\xCA\x30\xB5\x1A\xEC\xFB\xBA\x3B\x84\x57\xB0\xFD\xFB\xE6\xBC" +- "\xF2\x76\xF6\x4C\xBB\xAB\xB1\x31\xA1\x27\x7C\xE6\xE6\x81\xB6\xCE" +- "\x84\x86\x40\xB6\x40\x33\xC4\xF8\xB4\x15\xCF\xAA\xA5\x51\x78\xB9" +- "\x8B\x50\x25\xB2\x88\x86\x96\x72\x8C\x71\x4D\xB5\x3A\x94\x86\x77" +- "\x0E\x95\x9B\x16\x93\xEF\x3A\x11\x79\xBA\x83\xF7\x74\xD3\x8D\xBA" +- "\x15\xE1\x2C\x04\x57\xA8\x92\x1E\x9D\x00\x8E\x20\xFD\x30\x70\xE7" +- "\xF5\x65\x2F\x19\x0C\x94\xBA\x03\x71\x12\x96\xCD\xC8\xB4\x96\xDB" +- "\xCE\x19\xC2\xDF\x3C\xC2\xF6\x3D\x53\xED\x98\xA5\x41\x72\x2A\x22" +- "\x7B\xF3\x2B\x17\x6C\xE1\x39\x7D\xAE\x9B\x11\xF9\xC1\xA6\x9E\x9F" +- "\x89\x3C\x12\xAA\x94\x74\xA7\x4F\x70\xE8\xB9\xDE\x04\xF0\x9D\x39" +- "\x24\x2D\x92\xE8\x46\x2D\x2E\xF0\x40\x66\x1A\xD9\x27\xF9\x98\xF1" +- "\x81\x1D\x70\x62\x63\x30\x6D\xCD\x84\x04\x5F\xFA\x83\xD3\xEC\x8D" +- "\x86\xFB\x40\x61\xC1\x8A\x45\xFF\x7B\xD9\xD4\x18\x61\x7F\x51\xE3" +- "\xFC\x1E\x18\xF0\xAF\xC6\x18\x2C\xE1\x6D\x5D\xF9\x62\xFC\x20\xA3" +- "\xB2\x8A\x5F\xE5\xBB\x29\x0F\x99\x63\x07\x88\x38\x3A\x3B\x73\x2A" +- "\x6D\xDA\x3D\xA8\x0D\x8F\x56\x41\x89\x82\xE5\xB8\x61\x00\x64\x7D" +- "\x17\x0C\xCE\x03\x55\x8F\xF4\x5B\x0D\x50\xF2\xEB\x05\x67\xBE\xDB" +- "\x7B\x75\xC5\xEA\xA1\xAB\x1D\xB0\x3C\x6D\x42\x08\x0B\x9A\x45\x20" +- "\xA8\x8F\xE5\x67\x47\x30\xDE\x93\x5F\x43\x05\xEB\xA8\x2D\x80\xF5" +- "\x1A\xB8\x4A\x4E\x42\x2D\x0B\x7A\xDC\x46\x20\x2D\x13\x17\xDD\x4B" +- "\x94\x96\xAA\x1F\x06\x0C\x1F\x62\x07\x9C\x40\xA1" ++ .length = 1307, .data = ++ "\x61\x82\x05\x17\x30\x82\x05\x13\xA0\x03\x02\x01\x05\xA1\x0F\x1B" ++ "\x0D\x57\x32\x30\x32\x32\x2D\x4C\x37\x2E\x42\x41\x53\x45\xA2\x2A" ++ "\x30\x28\xA0\x03\x02\x01\x01\xA1\x21\x30\x1F\x1B\x04\x63\x69\x66" ++ "\x73\x1B\x17\x77\x32\x30\x32\x32\x2D\x31\x31\x38\x2E\x77\x32\x30" ++ "\x32\x32\x2D\x6C\x37\x2E\x62\x61\x73\x65\xA3\x82\x04\xCD\x30\x82" ++ "\x04\xC9\xA0\x03\x02\x01\x12\xA1\x03\x02\x01\x05\xA2\x82\x04\xBB" ++ "\x04\x82\x04\xB7\x44\x5C\x7B\x5A\x3F\x2E\xA3\x50\x34\xDE\xB0\x69" ++ "\x23\x2D\x47\x89\x2C\xC0\xA3\xF9\xDD\x70\xAA\xA5\x1E\xFE\x74\xE5" ++ "\x19\xA2\x4F\x65\x6C\x9E\x00\xB4\x60\x00\x7C\x0C\x29\x43\x31\x99" ++ "\x77\x02\x73\xED\xB9\x40\xF5\xD2\xD1\xC9\x20\x0F\xE3\x38\xF9\xCC" ++ "\x5E\x2A\xBD\x1F\x91\x66\x1A\xD8\x2A\x80\x3C\x2C\x00\x3C\x1E\xC9" ++ "\x2A\x29\x19\x19\x96\x18\x54\x03\x97\x8F\x1D\x5F\xDB\xE9\x66\x68" ++ "\xCD\xB1\xD5\x00\x35\x69\x49\x45\xF1\x6A\x78\x7B\x37\x71\x87\x14" ++ "\x1C\x98\x4D\x69\xCB\x1B\xD8\xF5\xA3\xD8\x53\x4A\x75\x76\x62\xBA" ++ "\x6C\x3F\xEA\x8B\x97\x21\xCA\x8A\x46\x4B\x38\xDA\x09\x9F\x5A\xC8" ++ "\x38\xFF\x34\x97\x5B\xA2\xE5\xBA\xC9\x87\x17\xD8\x08\x05\x7A\x83" ++ "\x04\xD6\x02\x8E\x9B\x18\xB6\x40\x1A\xF7\x47\x25\x24\x3E\x37\x1E" ++ "\xF6\xC1\x3A\x1F\xCA\xB3\x43\x5A\xAE\x94\x83\x31\xAF\xFB\xEE\xED" ++ "\x46\x71\xEF\xE2\x37\x37\x15\xFE\x1B\x0B\x9E\xF8\x3E\x0C\x43\x96" ++ "\xB6\x0A\x04\x78\xF8\x5E\xAA\x33\x1F\xE2\x07\x5A\x8D\xC4\x4E\x32" ++ "\x6D\xD6\xA0\xC5\xEA\x3D\x12\x59\xD4\x41\x40\x4E\xA1\xD8\xBE\xED" ++ "\x17\xCB\x68\xCC\x59\xCB\x53\xB2\x0E\x58\x8A\xA9\x33\x7F\x6F\x2B" ++ "\x37\x89\x08\x44\xBA\xC7\x67\x17\xBB\x91\xF7\xC3\x0F\x00\xF8\xAA" ++ "\xA1\x33\xA6\x08\x47\xCA\xFA\xE8\x49\x27\x45\x46\xF1\xC1\xC3\x5F" ++ "\xE2\x45\x0A\x7D\x64\x52\x8C\x2E\xE1\xDE\xFF\xB2\x64\xEC\x69\x98" ++ "\x15\xDF\x9E\xB1\xEB\xD6\x9D\x08\x06\x4E\x73\xC1\x0B\x71\x21\x05" ++ "\x9E\xBC\xA2\x17\xCF\xB3\x70\xF4\xEF\xB8\x69\xA9\x94\x27\xFD\x5E" ++ "\x72\xB1\x2D\xD2\x20\x1B\x57\x80\xAB\x38\x97\xCF\x22\x68\x4F\xB8" ++ "\xB7\x17\x53\x25\x67\x0B\xED\xD1\x58\x20\x0D\x45\xF9\x09\xFA\xE7" ++ "\x61\x3E\xDB\xC2\x59\x7B\x3A\x3B\x59\x81\x51\xAA\xA4\x81\xF4\x96" ++ "\x3B\xE1\x6F\x6F\xF4\x8E\x68\x9E\xBA\x1E\x0F\xF2\x44\x68\x11\xFC" ++ "\x2B\x5F\xBE\xF2\xEA\x07\x80\xB9\xCA\x9E\x41\xBD\x2F\x81\xF5\x11" ++ "\x2A\x12\xF3\x4F\xD6\x12\x16\x0F\x21\x90\xF1\xD3\x1E\xF1\xA4\x94" ++ "\x46\xEA\x30\xF3\x84\x06\xC1\xA4\x51\xFC\x43\x35\xBD\xEF\x4D\x89" ++ "\x1D\xA5\x44\xB2\x69\xC4\x0F\xBF\x86\x01\x08\x44\x77\xD5\xB4\xB7" ++ "\x5C\x3F\xA7\xD4\x2F\x39\x73\x85\x88\xEE\xB1\x64\x1D\x80\x6C\xEE" ++ "\x6E\x31\x90\x92\x0D\xA1\xB7\xC4\x5C\xCC\xEE\x91\xC8\xCB\x11\x2D" ++ "\x4A\x1A\x7D\x43\x8F\xEB\x60\x09\xED\x1B\x07\x58\xBE\xBC\xBD\x29" ++ "\xF3\xB3\xA3\x4F\xC5\x8A\x30\x33\xB9\xA9\x9F\x43\x08\x27\x15\xC4" ++ "\x9C\x5D\x8E\xBD\x5C\x05\xC6\x05\x9C\x87\x60\x08\x1E\xE2\x52\xB8" ++ "\x45\x8D\x28\xB6\x2C\x15\x46\x74\x9F\x0E\xAA\x6B\x70\x3A\x2A\x55" ++ "\x45\x26\xB2\x58\x4D\x35\xA6\xF1\x96\xBE\x60\xB2\x71\x7B\xF8\x54" ++ "\xB9\x90\x21\x8E\xB9\x0F\x35\x98\x5E\x88\xEB\x1A\x53\xB4\x59\x7F" ++ "\xAF\x69\x1C\x61\x67\xF4\xF6\xBD\xAC\x24\xCD\xB7\xA9\x67\xE8\xA1" ++ "\x83\x85\x5F\x11\x74\x1F\xF7\x4C\x78\x36\xEF\x50\x74\x88\x58\x4B" ++ "\x1A\x9F\x84\x9A\x9A\x05\x92\xEC\x1D\xD5\xF3\xC4\x95\x51\x28\xE2" ++ "\x3F\x32\x87\xB2\xFD\x21\x27\x66\xE4\x6B\x85\x2F\xDC\x7B\xC0\x22" ++ "\xEB\x7A\x94\x20\x5A\x7B\xD3\x7A\xB9\x5B\xF8\x1A\x5A\x84\x4E\xA1" ++ "\x73\x41\x53\xD2\x60\xF7\x7C\xEE\x68\x59\x85\x80\xFC\x3D\x70\x4B" ++ "\x04\x32\xE7\xF2\xFD\xBD\xB3\xD9\x21\xE2\x37\x56\xA2\x16\xCC\xDE" ++ "\x8A\xD3\xBC\x71\xEF\x58\x19\x0E\x45\x8A\x5B\x53\xD6\x77\x30\x6A" ++ "\xA7\xF8\x68\x06\x4E\x07\xCA\xCE\x30\xD7\x35\xAB\x1A\xC7\x18\xD4" ++ "\xC6\x2F\x1A\xFF\xE9\x7A\x94\x0B\x76\x5E\x7E\x29\x0C\xE6\xD3\x3B" ++ "\x5B\x44\x96\xA8\xF1\x29\x23\x95\xD9\x79\xB3\x39\xFC\x76\xED\xE1" ++ "\x1E\x67\x4E\xF7\xE8\x7B\x7A\x12\x9E\xD8\x4B\x35\x09\x0A\xF2\xC1" ++ "\x63\x5B\xEE\xFD\x2A\xC2\xA6\x66\x30\x3C\x1F\x95\xAF\x65\x22\x95" ++ "\x14\x1D\xF5\xD5\xDC\x38\x79\x35\x1C\xCD\x24\x47\xE0\xFD\x08\xC8" ++ "\xF4\x15\x55\x9F\xD9\xC7\xAC\x3F\x67\xB3\x4F\xEB\x26\x7C\x8E\xD6" ++ "\x74\xB3\x0A\xCD\xE7\xFA\xBE\x7E\xA3\x3E\xEC\x61\x50\x77\x52\x56" ++ "\xCF\x90\x5D\x48\xFB\xD4\x2C\x6C\x61\x8B\xDD\x2B\xF5\x92\x1F\x30" ++ "\xBF\x3F\x80\x0D\x31\xDB\xB2\x0B\x7D\x84\xE3\xA6\x42\x7F\x00\x38" ++ "\x44\x02\xC5\xB8\xD9\x58\x29\x9D\x68\x5C\x32\x8B\x76\xAE\xED\x15" ++ "\xF9\x7C\xAE\x7B\xB6\x8E\xD6\x54\x24\xFF\xFA\x87\x05\xEF\x15\x08" ++ "\x5E\x4B\x21\xA2\x2F\x49\xE7\x0F\xC3\xD0\xB9\x49\x22\xEF\xD5\xCA" ++ "\xB2\x11\xF2\x17\xB6\x77\x24\x68\x76\xB2\x07\xF8\x0A\x73\xDD\x65" ++ "\x9C\x75\x64\xF7\xA1\xC6\x23\x08\x84\x72\x3E\x54\x2E\xEB\x9B\x40" ++ "\xA6\x83\x87\xEB\xB5\x00\x40\x4F\xE1\x72\x2A\x59\x3A\x06\x60\x29" ++ "\x7E\x25\x2F\xD8\x80\x40\x8C\x59\xCA\xCF\x8E\x44\xE4\x2D\x84\x7E" ++ "\xCB\xFD\x1E\x3B\xD5\xFF\x9A\xB9\x66\x93\x6D\x5E\xC8\xB7\x13\x26" ++ "\xD6\x38\x1B\x2B\xE1\x87\x96\x05\xD5\xF3\xAB\x68\xF7\x12\x62\x2C" ++ "\x58\xC1\xC9\x85\x3C\x72\xF1\x26\xEE\xC0\x09\x5F\x1D\x4B\xAC\x01" ++ "\x41\xC8\x12\xF8\xF3\x93\x43\x41\xFF\xEC\x0B\x80\xE2\xEE\x20\x85" ++ "\x25\xCD\x6C\x30\x8C\x0D\x24\x2E\xBA\x19\xEA\x28\x7F\xCF\xD5\x10" ++ "\x5C\xE9\xB2\x9D\x5F\x16\xE4\xC0\xF3\xCC\xD9\x68\x4A\x05\x08\x70" ++ "\x17\x26\xC8\x5C\x4A\xBF\x94\x6A\x0E\xD5\xDA\x67\x47\x4B\xAF\x44" ++ "\xE3\x94\xAA\x05\xDB\xA2\x49\x74\xFA\x5C\x69\xAB\x44\xB7\xF7\xBA" ++ "\xAE\x7A\x23\x87\xEB\x54\x7E\x80\xF1\x5B\x60\xA5\x93\xE5\xD4\x24" ++ "\x84\xF7\x0A\x16\x10\xBE\xE9\x4D\xD8\x6B\x15\x40\x5D\x74\xDA\x1B" ++ "\xFF\x2E\x4D\x17\x9D\x35\xF7\x0D\xCF\x66\x38\x0D\x8A\xE4\xDD\x6B" ++ "\xE1\x0F\x1F\xBD\xFD\x4F\x30\x37\x3F\x96\xB4\x92\x54\xD3\x9A\x7A" ++ "\xD1\x5B\x5B\xA9\x54\x16\xE6\x24\xAB\xD4\x23\x39\x7D\xD2\xC7\x09" ++ "\xFA\xD4\x86\x55\x4D\x60\xC2\x87\x67\x6B\xE6" + }; + + static void +@@ -686,7 +710,7 @@ test_pac_ticket_signature(krb5_context context) + { + krb5_error_code ret; + krb5_ticket *ticket; +- krb5_principal sprinc; ++ krb5_principal cprinc, sprinc; + krb5_authdata **authdata1, **authdata2; + krb5_pac pac, pac2, pac3; + uint32_t *list; +@@ -701,7 +725,13 @@ test_pac_ticket_signature(krb5_context context) + if (ret) + err(context, ret, "while decrypting ticket"); + +- ret = krb5_parse_name(context, "s1@CDOM.COM", &sprinc); ++ ret = krb5_parse_name(context, "administrator@W2022-L7.BASE", &cprinc); ++ if (ret) ++ err(context, ret, "krb5_parse_name"); ++ ++ ret = krb5_parse_name(context, ++ "cifs/w2022-118.w2022-l7.base@W2022-L7.BASE", ++ &sprinc); + if (ret) + err(context, ret, "krb5_parse_name"); + +@@ -713,7 +743,7 @@ test_pac_ticket_signature(krb5_context context) + + /* In this test, the server is also the client. */ + ret = krb5_pac_verify(context, pac, ticket->enc_part2->times.authtime, +- ticket->server, NULL, NULL); ++ cprinc, NULL, NULL); + if (ret) + err(context, ret, "while verifying PAC client info"); + +@@ -722,7 +752,7 @@ test_pac_ticket_signature(krb5_context context) + ticket->enc_part2->authorization_data = NULL; + + ret = krb5_kdc_sign_ticket(context, ticket->enc_part2, pac, sprinc, +- sprinc, &ticket_sig_server_key, ++ cprinc, &ticket_sig_server_key, + &ticket_sig_krbtgt_key, FALSE); + if (ret) + err(context, ret, "while signing ticket"); +@@ -781,6 +811,7 @@ test_pac_ticket_signature(krb5_context context) + krb5_pac_free(context, pac); + krb5_pac_free(context, pac2); + krb5_pac_free(context, pac3); ++ krb5_free_principal(context, cprinc); + krb5_free_principal(context, sprinc); + krb5_free_ticket(context, ticket); + } +diff --git a/src/tests/t_authdata.py b/src/tests/t_authdata.py +index 4fbdbec052..b0666c3b81 100644 +--- a/src/tests/t_authdata.py ++++ b/src/tests/t_authdata.py +@@ -11,7 +11,7 @@ realm = K5Realm(krb5_conf=conf) + # container. + mark('baseline authdata') + out = realm.run(['./adata', realm.host_princ]) +-if '?512: ' not in out or '^-42: Hello' not in out: ++if '?128: [6, 7, 10, 16, 19]' not in out or '^-42: Hello' not in out: + fail('expected authdata not seen for basic request') + + # Requested authdata is copied into the ticket, with KDC-only types +@@ -239,6 +239,9 @@ realm.run(['./s4u2proxy', usercache, 'service/2']) + out = realm.run(['./adata', '-p', realm.user_princ, 'service/2']) + if '+97: [indcl]' not in out or '[inds1]' in out: + fail('correct auth-indicator not seen for S4U2Proxy req') ++# Make sure a PAC with an S4U_DELEGATION_INFO(11) buffer is included. ++if '?128: [1, 6, 7, 10, 11, 16, 19]' not in out: ++ fail('PAC with delegation info not seen for S4U2Proxy req') + + # Get another S4U2Proxy ticket including request-authdata. + realm.run(['./s4u2proxy', usercache, 'service/2', '-2', 'proxy_ad']) +-- +2.39.1 + diff --git a/SOURCES/0156-downstream-Support-PAC-full-checksum-w-o-ticket-chec.patch b/SOURCES/0156-downstream-Support-PAC-full-checksum-w-o-ticket-chec.patch new file mode 100644 index 0000000..84ca96c --- /dev/null +++ b/SOURCES/0156-downstream-Support-PAC-full-checksum-w-o-ticket-chec.patch @@ -0,0 +1,140 @@ +From 3e40a47cee51fb855c71d425eb572253b6fc41eb Mon Sep 17 00:00:00 2001 +From: Julien Rische +Date: Fri, 24 Mar 2023 16:22:06 +0100 +Subject: [PATCH] [downstream] Support PAC full checksum w/o ticket checksum + +--- + doc/appdev/refs/api/index.rst | 1 + + src/include/krb5/krb5.hin | 38 +++++++++++++++++++++++++++++++++++ + src/lib/krb5/krb/pac.c | 10 ++++++++- + src/lib/krb5/krb/pac_sign.c | 17 ++++++++++++++++ + src/lib/krb5/libkrb5.exports | 1 + + 5 files changed, 66 insertions(+), 1 deletion(-) + +diff --git a/doc/appdev/refs/api/index.rst b/doc/appdev/refs/api/index.rst +index d12be47c3c..ff813108bb 100644 +--- a/doc/appdev/refs/api/index.rst ++++ b/doc/appdev/refs/api/index.rst +@@ -248,6 +248,7 @@ Rarely used public interfaces + krb5_os_localaddr.rst + krb5_pac_add_buffer.rst + krb5_pac_free.rst ++ krb5_pac_full_sign_compat.rst + krb5_pac_get_buffer.rst + krb5_pac_get_types.rst + krb5_pac_init.rst +diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin +index 12a1d441b8..dbe87561c5 100644 +--- a/src/include/krb5/krb5.hin ++++ b/src/include/krb5/krb5.hin +@@ -8392,6 +8392,44 @@ krb5_pac_sign_ext(krb5_context context, krb5_pac pac, krb5_timestamp authtime, + const krb5_keyblock *privsvr_key, krb5_boolean with_realm, + krb5_data *data); + ++/** ++ * Compatibility function used by IPA if the 1.20 KDB diver API is not ++ * available. It generates PAC signatures, including the extended KDC one when ++ * relevant. ++ * ++ * It is similar to krb5_kdc_sign_ticket(), except it will not generate the ++ * PAC ticket signature, and therefore does not expect encrypted ticket part as ++ * parameter. ++ * ++ * @param [in] context Library context ++ * @param [in] pac PAC handle ++ * @param [in] authtime Expected timestamp ++ * @param [in] client_princ Client principal name (or NULL) ++ * @param [in] server_princ Server principal name ++ * @param [in] server_key Key for server checksum ++ * @param [in] privsvr_key Key for KDC checksum ++ * @param [in] with_realm If true, include the realm of @a client_princ ++ * @param [out] data Signed PAC encoding ++ * ++ * This function signs @a pac using the keys @a server_key and @a privsvr_key ++ * and returns the signed encoding in @a data. @a pac is modified to include ++ * the server and KDC checksum buffers. Use krb5_free_data_contents() to free ++ * @a data when it is no longer needed. ++ * ++ * If @a with_realm is true, the PAC_CLIENT_INFO field of the signed PAC will ++ * include the realm of @a client_princ as well as the name. This flag is ++ * necessary to generate PACs for cross-realm S4U2Self referrals. ++ */ ++krb5_error_code KRB5_CALLCONV ++krb5_pac_full_sign_compat(krb5_context context, krb5_pac pac, ++ krb5_timestamp authtime, ++ krb5_const_principal client_princ, ++ krb5_const_principal server_princ, ++ const krb5_keyblock *server_key, ++ const krb5_keyblock *privsvr_key, ++ krb5_boolean with_realm, ++ krb5_data *data); ++ + /** + * Sign a PAC, possibly including a ticket signature + * +diff --git a/src/lib/krb5/krb/pac.c b/src/lib/krb5/krb/pac.c +index 9c00178a28..b7fa064100 100644 +--- a/src/lib/krb5/krb/pac.c ++++ b/src/lib/krb5/krb/pac.c +@@ -757,9 +757,17 @@ krb5_pac_verify_ext(krb5_context context, + krb5_boolean with_realm) + { + krb5_error_code ret; ++ krb5_boolean has_full_chksum; + + if (server != NULL || privsvr != NULL) { +- ret = verify_pac_checksums(context, pac, FALSE, server, privsvr); ++ /* Fail only if full checksum is present and invalid. ++ * Proceed if absent. ++ */ ++ ret = k5_pac_locate_buffer(context, pac, KRB5_PAC_FULL_CHECKSUM, NULL); ++ has_full_chksum = ret != ENOENT; ++ ++ ret = verify_pac_checksums(context, pac, has_full_chksum, server, ++ privsvr); + if (ret != 0) + return ret; + } +diff --git a/src/lib/krb5/krb/pac_sign.c b/src/lib/krb5/krb/pac_sign.c +index 8ea61ac17b..7c3a86d8eb 100644 +--- a/src/lib/krb5/krb/pac_sign.c ++++ b/src/lib/krb5/krb/pac_sign.c +@@ -309,6 +309,23 @@ krb5_pac_sign_ext(krb5_context context, krb5_pac pac, krb5_timestamp authtime, + with_realm, FALSE, data); + } + ++krb5_error_code KRB5_CALLCONV ++krb5_pac_full_sign_compat(krb5_context context, krb5_pac pac, ++ krb5_timestamp authtime, ++ krb5_const_principal client_princ, ++ krb5_const_principal server_princ, ++ const krb5_keyblock *server_key, ++ const krb5_keyblock *privsvr_key, ++ krb5_boolean with_realm, ++ krb5_data *data) ++{ ++ krb5_boolean is_service_tkt; ++ ++ is_service_tkt = k5_pac_should_have_ticket_signature(server_princ); ++ return sign_pac(context, pac, authtime, client_princ, server_key, ++ privsvr_key, with_realm, is_service_tkt, data); ++} ++ + /* Add a signature over der_enc_tkt in privsvr to pac. der_enc_tkt should be + * encoded with a dummy PAC authdata element containing a single zero byte. */ + static krb5_error_code +diff --git a/src/lib/krb5/libkrb5.exports b/src/lib/krb5/libkrb5.exports +index 28784ec67c..ac94e0c236 100644 +--- a/src/lib/krb5/libkrb5.exports ++++ b/src/lib/krb5/libkrb5.exports +@@ -508,6 +508,7 @@ krb5_os_localaddr + krb5_overridekeyname + krb5_pac_add_buffer + krb5_pac_free ++krb5_pac_full_sign_compat + krb5_pac_get_buffer + krb5_pac_get_types + krb5_pac_init +-- +2.39.2 + diff --git a/SOURCES/Fix-integer-overflows-in-PAC-parsing.patch b/SOURCES/Fix-integer-overflows-in-PAC-parsing.patch index f44c35a..df97b8d 100644 --- a/SOURCES/Fix-integer-overflows-in-PAC-parsing.patch +++ b/SOURCES/Fix-integer-overflows-in-PAC-parsing.patch @@ -1,4 +1,4 @@ -From 21d7d94a16ed0be6e1fb101679bf9446b1163d44 Mon Sep 17 00:00:00 2001 +From d2477aa606ad590ca4097941bb6c2e1955b2a8c8 Mon Sep 17 00:00:00 2001 From: Greg Hudson Date: Mon, 17 Oct 2022 20:25:11 -0400 Subject: [PATCH] Fix integer overflows in PAC parsing @@ -32,18 +32,18 @@ target_version: 1.19-next 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/lib/krb5/krb/pac.c b/src/lib/krb5/krb/pac.c -index 950beda657..2e844d499b 100644 +index 950beda657..1b9ef12276 100644 --- a/src/lib/krb5/krb/pac.c +++ b/src/lib/krb5/krb/pac.c -@@ -29,6 +29,8 @@ - - /* draft-brezak-win2k-krb-authz-00 */ +@@ -27,6 +27,8 @@ + #include "k5-int.h" + #include "authdata.h" +#define MAX_BUFFERS 4096 + + /* draft-brezak-win2k-krb-authz-00 */ + /* - * Add a buffer to the provided PAC and update header. - */ @@ -316,6 +318,9 @@ krb5_pac_parse(krb5_context context, if (version != 0) return EINVAL; diff --git a/SPECS/krb5.spec b/SPECS/krb5.spec index 6ef94c0..e45c8f2 100644 --- a/SPECS/krb5.spec +++ b/SPECS/krb5.spec @@ -18,7 +18,7 @@ Summary: The Kerberos network authentication system Name: krb5 Version: 1.18.2 # for prerelease, should be e.g., 0.% {prerelease}.1% { ?dist } (without spaces) -Release: 22%{?dist} +Release: 25%{?dist} # lookaside-cached sources; two downloads and a build artifact Source0: https://web.mit.edu/kerberos/dist/krb5/1.18/krb5-%{version}%{prerelease}.tar.gz @@ -94,6 +94,11 @@ Patch148: downstream-Fix-dejagnu-unit-tests-directory-name-for-RPC-lib.patch Patch149: krb5-krad-larger-attrs.patch Patch150: krb5-krad-remote.patch Patch151: Fix-integer-overflows-in-PAC-parsing.patch +Patch152: 0152-Use-14-instead-of-9-for-unkeyed-SHA-1-checksum.patch +Patch153: 0153-Add-PAC-ticket-signature-APIs.patch +Patch154: 0154-Factor-out-PAC-checksum-verification.patch +Patch155: 0155-Add-PAC-full-checksums.patch +Patch156: 0156-downstream-Support-PAC-full-checksum-w-o-ticket-chec.patch License: MIT URL: http://web.mit.edu/kerberos/www/ @@ -704,9 +709,20 @@ exit 0 %{_libdir}/libkadm5srv_mit.so.* %changelog -* Tue Nov 08 2022 Julien Rische - 1. +* Tue Jun 06 2023 Julien Rische - 1.18.2-25 +- Bump release number + +* Fri Mar 24 2023 Julien Rische - 1.18.2-24 +- Support PAC with KDC extended signature and without ticket signature +- Resolves: rhbz#2211390 + +* Tue Feb 14 2023 Julien Rische - 1.18.2-23 +- Add support for MS-PAC extended KDC signature (CVE-2022-37967) +- Resolves: rhbz#2169477 + +* Tue Nov 08 2022 Julien Rische - 1.18.2-22 - Fix integer overflows in PAC parsing (CVE-2022-42898) -- Resolves: rhbz#2140967 +- Resolves: rhbz#2140968 * Fri Jul 01 2022 Julien Rische - 1.18.2-21 - Backport fix of memory use after free during libkrad cleanup