git ls-files -o|grep -v ^build/
fi
- name: Upload Install Tarball
- uses: actions/upload-artifact@v2
+ uses: actions/upload-artifact@v4
with:
name: Install Tarball
path: '~/heimdal-install-linux-${{ matrix.compiler }}.tgz'
- name: Upload Dist Tarball
- uses: actions/upload-artifact@v2
+ uses: actions/upload-artifact@v4
with:
name: Dist Tarball
path: 'build/heimdal-*.tar.gz'
- name: Upload Logs Tarball
- uses: actions/upload-artifact@v2
+ uses: actions/upload-artifact@v4
with:
name: Test Logs
path: '~/logs-linux-${{ matrix.compiler }}.tgz'
git ls-files -o|grep -v ^build/
fi
- name: Upload Install Tarball
- uses: actions/upload-artifact@v2
+ uses: actions/upload-artifact@v4
with:
name: Install Tarball
path: '~/heimdal-install-linux-${{ matrix.compiler }}.tgz'
- name: Upload Dist Tarball
- uses: actions/upload-artifact@v2
+ uses: actions/upload-artifact@v4
with:
name: Dist Tarball
path: 'build/heimdal-*.tar.gz'
- name: Upload Logs Tarball
- uses: actions/upload-artifact@v2
+ uses: actions/upload-artifact@v4
with:
name: Test Logs
path: '~/logs-linux-${{ matrix.compiler }}.tgz'
run: |
find build -name \*.trs|xargs grep -lw FAIL|sed -e 's/trs$/log/'|xargs cat
- name: Upload Install Tarball
- uses: actions/upload-artifact@v2
+ uses: actions/upload-artifact@v4
with:
name: Install Tarball
path: '~/heimdal-install-osx.tgz'
- name: Upload Artifacts
- uses: actions/upload-artifact@v2
+ uses: actions/upload-artifact@v4
with:
name: Upload Test Logs
path: '~/logs-osx.cpio'
run: |
find build -name \*.trs|xargs grep -lw FAIL|sed -e 's/trs$/log/'|xargs cat
- name: Upload Artifacts
- uses: actions/upload-artifact@v2
+ uses: actions/upload-artifact@v4
with:
name: Scan-Build Reports
path: '/tmp/scan-build*/'
run: |
find build -name \*.trs | sed -e 's/trs$/log/' | xargs cat
- name: Upload Logs Tarball
- uses: actions/upload-artifact@v2
+ uses: actions/upload-artifact@v4
with:
name: Test Logs
path: '~/logs-linux-${{ matrix.compiler }}.tgz'
run: |
find build -name \*.trs|xargs grep -lw FAIL | sed -e 's/trs$/log/' | xargs cat
- name: Upload Artifacts
- uses: actions/upload-artifact@v2
+ uses: actions/upload-artifact@v4
with:
name: Test Logs
path: '~/logs-linux-valgrind.tgz'
nmake /f NTMakefile APPVEYOR=1 MAKEINFO=makeinfo NO_INSTALLERS=1
nmake /f NTMakefile APPVEYOR=1 MAKEINFO=makeinfo NO_INSTALLERS=1 test
- name: Upload Artifacts
- uses: actions/upload-artifact@v2
+ uses: actions/upload-artifact@v4
with:
name: Objects
path: 'D:/a/heimdal/heimdal/out/'
WFLAGS += $(WFLAGS_LITE)
+AUTOMAKE_OPTIONS = subdir-objects
+
noinst_PROGRAMS = tcp_client tcp_server gssapi_server gssapi_client \
uu_server uu_client nt_gss_server nt_gss_client http_client \
kinit_auditdns
AC_REQUIRE([AC_SYS_LARGEFILE])dnl
dnl need to set this on the command line, since it might otherwise break
dnl with generated code, such as lex
-if test "$enable_largefile" != no -a "$ac_cv_sys_large_files" != no; then
- CPPFLAGS="$CPPFLAGS -D_LARGE_FILES=$ac_cv_sys_large_files"
-fi
-if test "$enable_largefile" != no -a "$ac_cv_sys_file_offset_bits" != no && test -n "$ac_cv_sys_file_offset_bits"; then
- CPPFLAGS="$CPPFLAGS -D_FILE_OFFSET_BITS=$ac_cv_sys_file_offset_bits"
+if test "$enable_largefile" != no; then
+ if test -n "$ac_cv_sys_large_files" && test "$ac_cv_sys_large_files" != no; then
+ CPPFLAGS="$CPPFLAGS -D_LARGE_FILES=$ac_cv_sys_large_files"
+ fi
+ if test -n "$ac_cv_sys_file_offset_bits" && test "$ac_cv_sys_file_offset_bits" != no; then
+ CPPFLAGS="$CPPFLAGS -D_FILE_OFFSET_BITS=$ac_cv_sys_file_offset_bits"
+ fi
+ if test -n "$ac_cv_sys_largefile_opts"; then
+ AS_CASE([$ac_cv_sys_largefile_opts],[-D_FILE_OFFSET_BITS=*|-D_LARGE_FILES=*],
+ [CPPFLAGS="$CPPFLAGS $ac_cv_sys_largefile_opts"])
+ fi
fi
])
@verbatim
-LibTomMath is hereby released into the Public Domain.
+ The LibTom license
+
+This is free and unencumbered software released into the public domain.
+
+Anyone is free to copy, modify, publish, use, compile, sell, or
+distribute this software, either in source code form or as a compiled
+binary, for any purpose, commercial or non-commercial, and by any
+means.
+
+In jurisdictions that recognize copyright laws, the author or authors
+of this software dedicate any and all copyright interest in the
+software to the public domain. We make this dedication for the benefit
+of the public at large and to the detriment of our heirs and
+successors. We intend this dedication to be an overt act of
+relinquishment in perpetuity of all present and future rights to this
+software under copyright law.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+For more information, please refer to <http://unlicense.org/>
@end verbatim
return matched;
}
+/**
+ * @brief Check to see if the certificate’s object SID matches the client’s.
+ *
+ * @param client[in] client hdb record
+ * @param cert_sid[in] SID of certificate used to sign the request.
+ *
+ * @return TRUE the certificate matches
+ * FALSE the certificate DOES NOT match
+ */
+static krb5_boolean
+match_object_sid(hdb_entry *client, ObjectSid *cert_sid)
+{
+ HDB_extension *ext = NULL;
+
+ ext = hdb_find_extension(client, choice_HDB_extension_data_object_sid);
+ if (ext == NULL) {
+ return FALSE;
+ }
+
+ /*
+ * Does the certificate’s object SID match the object SID for this client?
+ */
+ return der_heim_octet_string_cmp(&ext->data.u.object_sid, cert_sid) == 0;
+}
+
/**
* @brief Validate the certificate against the criteria outlined in KB5014754
*
memset(&mappings, 0, sizeof(mappings));
/*
- * If there is no extension or the enforcement mode is none
- * then there is nothing to do.
- */
+ * If there is no extension or the enforcement mode is none, don’t
+ * perform any certificate mapping or object SID checks.
+ */
ext = hdb_find_extension(client, choice_HDB_extension_data_cert_mappings);
if (ext == NULL) {
return 0;
goto out;
}
- /*
- * If there are no mappings then reject the logon
- */
- if (mappings.mappings == NULL) {
- ret = KRB5_KDC_ERR_CERTIFICATE_MISMATCH;
- krb5_set_error_message(
- context, ret, "Client has no certificate mappings");
- goto out;
- }
-
- for (i = 0, matched = FALSE; i < mappings.mappings->len && !matched; i++) {
- HDB_Ext_CertificateMapping *m = &mappings.mappings->val[i];
-
- strong_mapping = m->strong_mapping;
- /*
- * When enforcement mode is full only consider strong mappings
- */
- if (mappings.enforcement_mode == hdb_enf_mode_full && !strong_mapping) {
- continue;
- }
+ if (mappings.mappings != NULL) {
+ for (i = 0, matched = FALSE; i < mappings.mappings->len && !matched; i++) {
+ HDB_Ext_CertificateMapping *m = &mappings.mappings->val[i];
- if (m->issuer_name != NULL) {
- hx509_name issuer;
- ret = hx509_cert_get_issuer(*cert, &issuer);
- if (ret != 0) {
+ strong_mapping = m->strong_mapping;
+ /*
+ * When enforcement mode is full only consider strong mappings
+ */
+ if (mappings.enforcement_mode == hdb_enf_mode_full && !strong_mapping) {
continue;
}
- matched = match_name(context, &issuer, m->issuer_name);
- hx509_name_free(&issuer);
- if (!matched) {
- continue;
+
+ if (m->issuer_name != NULL) {
+ hx509_name issuer;
+ ret = hx509_cert_get_issuer(*cert, &issuer);
+ if (ret != 0) {
+ ret = 0;
+ continue;
+ }
+ matched = match_name(context, &issuer, m->issuer_name);
+ hx509_name_free(&issuer);
+ if (!matched) {
+ krb5_warnx(context, "PKINIT: Issuer name does not match");
+ continue;
+ }
}
- }
- if (m->subject_name != NULL) {
- hx509_name subject;
- ret = hx509_cert_get_subject(*cert, &subject);
- if (ret != 0) {
- continue;
+ if (m->subject_name != NULL) {
+ hx509_name subject;
+ ret = hx509_cert_get_subject(*cert, &subject);
+ if (ret != 0) {
+ ret = 0;
+ continue;
+ }
+ matched = match_name(context, &subject, m->subject_name);
+ hx509_name_free(&subject);
+ if (!matched) {
+ krb5_warnx(context, "PKINIT: Subject name does not match");
+ continue;
+ }
}
- matched = match_name(context, &subject, m->subject_name);
- hx509_name_free(&subject);
- if (!matched) {
- continue;
+ if (m->rfc822 != NULL) {
+ matched = match_rfc822_name(context, cert, m);
+ if (!matched) {
+ krb5_warnx(context, "PKINIT: RFC822 name does not match");
+ continue;
+ }
}
- }
- if (m->rfc822 != NULL) {
- matched = match_rfc822_name(context, cert, m);
- if (!matched) {
- continue;
+ if (m->ski != NULL) {
+ matched = match_subject_key_identifier(context, cert, m);
+ if (!matched) {
+ krb5_warnx(context, "PKINIT: Subject key identifier does not match");
+ continue;
+ }
}
- }
- if (m->ski != NULL) {
- matched = match_subject_key_identifier(context, cert, m);
- if (!matched) {
- continue;
+ if (m->public_key != NULL) {
+ matched = match_public_key(context, cert, m);
+ if (!matched) {
+ continue;
+ }
}
- }
- if (m->public_key != NULL) {
- matched = match_public_key(context, cert, m);
- if (!matched) {
- continue;
+ if (m->serial_number != NULL) {
+ matched = match_serial_number(cert, m);
+ if (!matched) {
+ krb5_warnx(context, "PKINIT: Serial number does not match");
+ continue;
+ }
}
}
- if (m->serial_number != NULL) {
- matched = match_serial_number(cert, m);
+ }
+
+ if (!matched || !strong_mapping) {
+ ObjectSid cert_sid;
+
+ ret = hx509_cert_get_object_sid(*cert, &cert_sid);
+ if (ret) {
+ ret = 0;
+ } else {
+ strong_mapping = TRUE;
+ matched = match_object_sid(client, &cert_sid);
+ free_ObjectSid(&cert_sid);
if (!matched) {
- continue;
+ krb5_warnx(context, "PKINIT: Object SID does not match");
}
}
}
KERB-TGS-REQ-IN,
KERB-TGS-REQ-OUT,
KERB-ARMOR-SERVICE-REPLY,
- KERB-ERROR-DATA
+ KERB-ERROR-DATA,
+ SidExtension
;
NAME-TYPE ::= INTEGER {
GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
+SidExtension ::= GeneralNames
+
id-x509-ce-keyUsage OBJECT IDENTIFIER ::= { id-x509-ce 15 }
KeyUsage ::= BIT STRING {
id-heim-ce-pkinit-princ-max-life OBJECT IDENTIFIER ::=
{ iso(1) member-body(2) se(752) su(43) heim-pkix(16) 4 }
+-- Microsoft extensions from MS-WCCE
+
+szOID-NTDS-CA-SECURITY-EXT OBJECT IDENTIFIER ::= {
+ iso(1) org(3) dod(6) internet(1) private(4) enterprise(1)
+ microsoft(311) directory-service(25) 2
+}
+
+szOID-NTDS-OBJECTSID OBJECT IDENTIFIER ::= {
+ iso(1) org(3) dod(6) internet(1) private(4) enterprise(1)
+ microsoft(311) directory-service(25) 2 1
+}
+
+ObjectSid ::= OCTET STRING
DistributionPointReasonFlags ::= BIT STRING {
unused (0),
&id id-pkix-on-pkinit-ms-san,
&Type AliasUTF8String
}
+on-ntds-objectsid _OTHER-NAME ::= {
+ &id szOID-NTDS-OBJECTSID,
+ &Type ObjectSid
+}
KnownOtherNameTypes _OTHER-NAME ::= {
on-xmppAddr
| on-permanentIdentifier
| on-krb5PrincipalName
| on-pkinit-ms-san
+ | on-ntds-objectsid
}
OtherName ::= OtherName{KnownOtherNameTypes}
HDB DEFINITIONS ::=
BEGIN
-IMPORTS EncryptionKey, KerberosTime, Principal FROM krb5;
+IMPORTS EncryptionKey, KerberosTime, Principal FROM krb5
+ ObjectSid FROM rfc2459;
hdb_db_format INTEGER ::= 2 -- format of database,
-- update when making changes
krb5-config[15] OCTET STRING,
key-trust[16] HDB-Ext-KeyTrust,
cert-mappings[17] HDB-Ext-CertificateMappings,
+ object-sid[18] ObjectSid,
...
},
...
#define HDB_F_GET_ANY ( HDB_F_GET_CLIENT | \
HDB_F_GET_SERVER | \
HDB_F_GET_KRBTGT ) /* fetch any of client,server,krbtgt */
-#define HDB_F_CANON 0x00020 /* want canonicalition */
+#define HDB_F_CANON 0x00020 /* want canonicalization */
#define HDB_F_ADMIN_DATA 0x00040 /* want data that kdc don't use */
#define HDB_F_KVNO_SPECIFIED 0x00080 /* we want a particular KVNO */
#define HDB_F_LIVE_CLNT_KVNOS 0x00200 /* we want all live keys for pre-auth */
/**
* @page page_cert The basic certificate
*
- * The basic hx509 cerificate object in hx509 is hx509_cert. The
+ * The basic hx509 certificate object in hx509 is hx509_cert. The
* hx509_cert object is representing one X509/PKIX certificate and
* associated attributes; like private key, friendly name, etc.
*
- * A hx509_cert object is usully found via the keyset interfaces (@ref
+ * A hx509_cert object is usually found via the keyset interfaces (@ref
* page_keyset), but its also possible to create a certificate
* directly from a parsed object with hx509_cert_init() and
* hx509_cert_init_data().
}
/**
- * Attach an revocation context to the verfication context, , makes an
+ * Attach an revocation context to the verification context, makes an
* reference to the revoke context, so the consumer can free the
* revoke context independent of the destruction of the verification
* context. If there is no revoke context, the verification process is
* set the current time will be used.
*
* @param ctx a verification context.
- * @param t the time the verifiation is using.
+ * @param t the time the verification is using.
*
*
* @ingroup hx509_verify
* builder is going to try.
*
* @param ctx a verification context
- * @param max_depth maxium depth of the certificate chain, include
+ * @param max_depth maximum depth of the certificate chain, include
* trust anchor.
*
* @ingroup hx509_verify
}
/**
- * Select strict RFC3280 verification of certificiates. This means
+ * Select strict RFC3280 verification of certificates. This means
* checking key usage on CA certificates, this will make version 1
- * certificiates unuseable.
+ * certificates unusable.
*
* @param ctx a verification context
* @param boolean if non zero, use strict verification.
eku, &size);
}
+static int
+find_extension_ntds_security_extension(const Certificate *subject,
+ SidExtension *sid_extension)
+{
+ const Extension *e;
+ size_t size;
+ size_t i = 0;
+ int ret;
+
+ memset(sid_extension, 0, sizeof(*sid_extension));
+
+ e = find_extension(subject, &asn1_oid_szOID_NTDS_CA_SECURITY_EXT, &i);
+ if (e == NULL)
+ return HX509_EXTENSION_NOT_FOUND;
+
+ ret = decode_SidExtension(e->extnValue.data,
+ e->extnValue.length,
+ sid_extension,
+ &size);
+ if (ret)
+ return ret;
+
+ if (size != e->extnValue.length)
+ return HX509_EXTRA_DATA_AFTER_STRUCTURE;
+
+ return ret;
+}
+
static int
add_to_list(hx509_octet_string_list *list, const heim_octet_string *entry)
{
/**
* Return the name of the base subject of the hx509 certificate. If
- * the certiicate is a verified proxy certificate, the this function
+ * the certificate is a verified proxy certificate, the this function
* return the base certificate (root of the proxy chain). If the proxy
* certificate is not verified with the base certificate
* HX509_PROXY_CERTIFICATE_NOT_CANONICALIZED is returned.
* @param p a hx509 certificate object.
* @param alg AlgorithmIdentifier, should be freed with
* free_AlgorithmIdentifier(). The algorithmidentifier is
- * typicly rsaEncryption, or id-ecPublicKey, or some other
+ * typically rsaEncryption, or id-ecPublicKey, or some other
* public key mechanism.
*
* @return An hx509 error code, see hx509_get_error_string().
}
/**
- * Get a copy of the Subect Unique ID
+ * Get a copy of the Subject Unique ID
*
* @param context a hx509_context
* @param p a hx509 certificate
return ret;
}
+/**
+ * Get a copy of the Object SID
+ *
+ * @param p a hx509 certificate
+ * @param sid the object SID returned, free with der_free_octet_string()
+ *
+ * @return An hx509 error code, see hx509_get_error_string(). The
+ * error code HX509_EXTENSION_NOT_FOUND is returned if the certificate
+ * doesn't have an object SID
+ *
+ * @ingroup hx509_cert
+ */
+
+HX509_LIB_FUNCTION int HX509_LIB_CALL
+hx509_cert_get_object_sid(hx509_cert p,
+ ObjectSid *sid)
+{
+ SidExtension sid_ext;
+ int ret;
+
+ ret = find_extension_ntds_security_extension(p->data, &sid_ext);
+ if (ret) {
+ return ret;
+ }
+
+ if (sid_ext.len != 1) {
+ return HX509_CMS_INVALID_DATA;
+ }
+
+ if (sid_ext.val[0].element != choice_GeneralName_otherName) {
+ return HX509_CMS_INVALID_DATA;
+ }
+
+ if (sid_ext.val[0].u.otherName._ioschoice_value.element !=
+ choice_OtherName_iosnum_szOID_NTDS_OBJECTSID)
+ {
+ return HX509_CMS_INVALID_DATA;
+ }
+
+ if (!sid_ext.val[0].u.otherName._ioschoice_value.u.on_ntds_objectsid) {
+ return HX509_CMS_INVALID_DATA;
+ }
+
+ return der_copy_octet_string(
+ sid_ext.val[0].u.otherName._ioschoice_value.u.on_ntds_objectsid,
+ sid);
+}
HX509_LIB_FUNCTION hx509_private_key HX509_LIB_CALL
_hx509_cert_private_key(hx509_cert p)
* @param peer info about the peer the message to send the message to,
* like what digest algorithm to use.
* @param anchors trust anchors that the client will use, used to
- * polulate the certificates included in the message
+ * populate the certificates included in the message
* @param pool certificates to use in try to build the path to the
* trust anchors.
* @param signed_data the output of the function, free with
hx509_cert_get_issuer;
hx509_cert_get_notAfter;
hx509_cert_get_notBefore;
+ hx509_cert_get_object_sid;
hx509_cert_get_pkinit_max_life;
hx509_cert_get_serialnumber;
hx509_cert_get_subject;