| |
@@ -0,0 +1,834 @@
|
| |
+ From 7c9fc678b08a9fb53155a1acc3e2a817c5b13da4 Mon Sep 17 00:00:00 2001
|
| |
+ From: Isaac Boukris <iboukris@gmail.com>
|
| |
+ 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 | 7 ++
|
| |
+ 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 | 2 +
|
| |
+ src/plugins/kdb/test/kdb_test.c | 6 +-
|
| |
+ 11 files changed, 538 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 4bf64e7dfa..a872b69bcf 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 f8778075fc..5fe2a29f20 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
|
| |
+ @@ -8186,6 +8186,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 */
|
| |
+ @@ -8343,56 +8349,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 ab3cc3e5a4..485cf30dab 100644
|
| |
+ --- a/src/lib/krb5/krb/deps
|
| |
+ +++ b/src/lib/krb5/krb/deps
|
| |
+ @@ -710,7 +710,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 \
|
| |
+ @@ -721,7 +721,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 2fde08d1ae..b62f9049f0 100644
|
| |
+ --- a/src/lib/krb5/krb/int-proto.h
|
| |
+ +++ b/src/lib/krb5/krb/int-proto.h
|
| |
+ @@ -391,4 +391,11 @@ k5_get_proxy_cred_from_kdc(krb5_context context, krb5_flags options,
|
| |
+ 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 df6e2ffbe6..0ff4f191d6 100644
|
| |
+ --- a/src/lib/krb5/libkrb5.exports
|
| |
+ +++ b/src/lib/krb5/libkrb5.exports
|
| |
+ @@ -464,6 +464,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 cf690dbe42..b1610974b1 100644
|
| |
+ --- a/src/lib/krb5_32.def
|
| |
+ +++ b/src/lib/krb5_32.def
|
| |
+ @@ -508,3 +508,5 @@ EXPORTS
|
| |
+ 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 2e02e2141f..495bec42ad 100644
|
| |
+ --- a/src/plugins/kdb/test/kdb_test.c
|
| |
+ +++ b/src/plugins/kdb/test/kdb_test.c
|
| |
+ @@ -700,7 +700,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;
|
| |
+ @@ -709,7 +709,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;
|
| |
+ @@ -722,7 +722,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.2
|
| |
+
|
| |
Resolves: rhbz#2182135