return 0;
}
+/**
+ * @brief Does data contain a value?
+ *
+ * @param[in] data pointer to a krb5_data structure
+ *
+ * @return TRUE data contains data
+ * FALSE data is NULL, or contains no data1:w
+ */
+static krb5_boolean krb5_data_not_empty(const krb5_data *data) {
+
+ if (data == NULL) {
+ return FALSE;
+ }
+
+ if (data->length == 0 || data->data == NULL) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ * @brief Allocate a new krb5_data struct and copy the contents of src
+ *
+ * @param[in] The source krb5_data structure
+ *
+ * @return A pointer the new krb5_data structure
+ * OR NULL if unable to allocate memory
+ *
+ * @note this allocates a new krb5_data structure and space for the
+ * contents of src, it should be freed by calling free_krb5_data
+ */
+static krb5_data *copy_krb5_data(const krb5_data *src) {
+
+ krb5_data *dest = malloc(sizeof(*dest));
+
+ if (dest == NULL) {
+ return NULL;
+ }
+
+ dest->data = malloc(src->length);
+ if (dest->data == NULL) {
+ SAFE_FREE(dest);
+ return NULL;
+ }
+
+ memcpy(dest->data, src->data, src->length);
+ dest->length = src->length;
+ return dest;
+}
+
+/**
+* @brief Convert a single sdb_certificate_mapping to
+* the corresponding HDB_Ext_CertificateMapping
+*
+* @param s[in] certificate mappings in sdb form
+* @param h[out] the HDB_Ext_Certificate mapping to populate
+*
+* @return 0 no error
+* ENOMEM unable to allocate memory
+*
+* @note memory is allocated on the HDB_Ext_CertificateMapping
+* and it needs to be freed by calling free_HDB_Ext_CertificateMapping
+* This also needs to be done in the event of an error.
+*
+*/
+static int sdb_cert_mapping_to_hdb_key_trust_val(
+ const struct sdb_certificate_mapping *m,
+ struct HDB_Ext_CertificateMapping *h)
+{
+ h->strong_mapping = m->strong_mapping;
+ if (krb5_data_not_empty(&m->subject_name)) {
+ h->subject_name = copy_krb5_data(&m->subject_name);
+ if (h->subject_name == NULL) {
+ return ENOMEM;
+ }
+ }
+ if (krb5_data_not_empty(&m->issuer_name)) {
+ h->issuer_name = copy_krb5_data(&m->issuer_name);
+ if (h->issuer_name == NULL) {
+ return ENOMEM;
+ }
+ }
+ if (krb5_data_not_empty(&m->serial_number)) {
+ h->serial_number = copy_krb5_data(&m->serial_number);
+ if (h->serial_number == NULL) {
+ return ENOMEM;
+ }
+ }
+ if (krb5_data_not_empty(&m->public_key)) {
+ h->public_key = copy_krb5_data(&m->public_key);
+ if (h->public_key == NULL) {
+ return ENOMEM;
+ }
+ }
+ if (krb5_data_not_empty(&m->rfc822)) {
+ h->rfc822 = copy_krb5_data(&m->rfc822);
+ if (h->rfc822 == NULL) {
+ return ENOMEM;
+ }
+ }
+ if (krb5_data_not_empty(&m->ski)) {
+ h->ski = copy_krb5_data(&m->ski);
+ if (h->ski == NULL) {
+ return ENOMEM;
+ }
+ }
+ return 0;
+}
+
+/**
+* @brief Convert the sdb certificate mappings to a HDB_Ext_CertificateMapping
+*
+* @param s[in] The certificate mappings to be used
+* @param h[out] The converted mappings
+*
+* @return 0 if there are no errors
+* ENOMEM unable to allocate memory
+*
+* @note The HDB_Ext_CertificateMappings may not contain any mappings, this
+* can happen when:
+* - Enforcement mode is none
+* - Or the user is not permitted to use PKINIT when the enforcement
+* mode is compatibility or strong.
+*
+* @note Memory is allocated and will need to be freed with a call
+* to free_HDB_Ext_CertificateMappings
+*
+* @note h must be initialised to zero and have no associated allocated
+* memory
+*
+*/
+static int sdb_certificate_mappings_to_hdb_ext(
+ const struct sdb_certificate_mappings *m,
+ HDB_Ext_CertificateMappings *h)
+{
+ int ret = 0;
+ size_t i = 0;
+
+ h->enforcement_mode = m->enforcement_mode;
+ h->valid_certificate_start= m->valid_certificate_start;
+
+ if (m->mappings != NULL) {
+ h->mappings = malloc
+ (sizeof(struct HDB_Ext_CertificateMappings_mappings));
+ if (h->mappings == NULL) {
+ return ENOMEM;
+ }
+ h->mappings->len = 0;
+ h->mappings->val =calloc(
+ m->len,sizeof(struct HDB_Ext_CertificateMapping));
+ if (h->mappings->val == NULL) {
+ SAFE_FREE(h->mappings);
+ return ENOMEM;
+ }
+ for (i = 0; i < m->len; i++) {
+ ret = sdb_cert_mapping_to_hdb_key_trust_val(
+ &m->mappings[i], &h->mappings->val[i]);
+ if (ret != 0) {
+ free_HDB_Ext_CertificateMapping(
+ &h->mappings->val[i]);
+ free_HDB_Ext_CertificateMappings(h);
+ return ret;
+ }
+ h->mappings->len++;
+ }
+ }
+ return ret;
+}
+
+
int sdb_entry_to_hdb_entry(krb5_context context,
const struct sdb_entry *s,
hdb_entry *h)
{
struct samba_kdc_entry *ske = s->skdc_entry;
struct HDB_Ext_KeyTrust kt = {};
+ struct HDB_Ext_CertificateMappings cm = {};
unsigned int i;
int rc;
goto error;
}
+ rc = sdb_certificate_mappings_to_hdb_ext(&s->mappings, &cm);
+ if (rc != 0) {
+ goto error;
+ }
+ {
+ HDB_extension ext = {};
+ ext.mandatory = FALSE;
+ ext.data.element = choice_HDB_extension_data_cert_mappings;
+ ext.data.u.cert_mappings = cm;
+ rc = hdb_replace_extension(context, h, &ext);
+ free_HDB_Ext_CertificateMappings(&cm);
+ if (rc != 0) {
+ goto error;
+ }
+ }
+
h->context = ske;
if (ske != NULL) {
ske->kdc_entry = h;
#include "../sdb_to_hdb.c"
#include "hdb_asn1.h"
+#include "util/data_blob.h"
+
+#define assert_empty(a)\
+ _assert_int_equal((0), (a)->length, __FILE__, __LINE__);\
+ _assert_true(!(cast_ptr_to_largest_integral_type(a)), #a, \
+ __FILE__, __LINE__)
/*
* Test that an empty sdb_pub_key is handled without error and that
free(out.pub_key.data);
}
+/*
+ * Ensure that sdb_cert_mapping_to_hdb_key_trust_val handles an
+ * empty sdb_certificate_mapping
+ */
+static void cert_map_empty_sdb_mapping(void **state)
+{
+ struct sdb_certificate_mapping m = {};
+ struct HDB_Ext_CertificateMapping h = {};
+ int ret = 0;
+
+ ret = sdb_cert_mapping_to_hdb_key_trust_val(&m, &h);
+
+ assert_int_equal(0, ret);
+ assert_false(h.strong_mapping);
+ assert_null(h.serial_number);
+ assert_null(h.rfc822);
+ assert_null(h.ski);
+ assert_null(h.issuer_name);
+ assert_null(h.subject_name);
+ assert_null(h.public_key);
+
+ free_HDB_Ext_CertificateMapping(&h);
+}
+
+/*
+ * Ensure that sdb_cert_mapping_to_hdb_key_trust_val correctly maps the
+ * subject_name
+ */
+static void cert_map_subject_name_mapping(void **state)
+{
+ struct sdb_certificate_mapping m = {};
+ struct HDB_Ext_CertificateMapping h = {};
+ int ret = 0;
+ DATA_BLOB subject_name = data_blob_string_const("DN=SubjectName");
+
+ m.subject_name.data = subject_name.data;
+ m.subject_name.length = subject_name.length;
+ m.strong_mapping = FALSE;
+
+ ret = sdb_cert_mapping_to_hdb_key_trust_val(&m, &h);
+
+ assert_int_equal(0, ret);
+
+ assert_non_null(h.subject_name);
+ assert_memory_equal(
+ subject_name.data, h.subject_name->data, subject_name.length);
+ assert_int_equal(subject_name.length, h.subject_name->length);
+
+ assert_false(h.strong_mapping);
+
+ assert_null(h.serial_number);
+ assert_null(h.rfc822);
+ assert_null(h.ski);
+ assert_null(h.issuer_name);
+ assert_null(h.public_key);
+
+ free_HDB_Ext_CertificateMapping(&h);
+}
+
+/*
+ * Ensure that sdb_cert_mapping_to_hdb_key_trust_val correctly maps the
+ * issuer_name
+ */
+static void cert_map_issuer_name_mapping(void **state)
+{
+ struct sdb_certificate_mapping m = {};
+ struct HDB_Ext_CertificateMapping h = {};
+ int ret = 0;
+ DATA_BLOB issuer_name =
+ data_blob_string_const("DC=local,DC=samba,CN=Things");
+
+ m.issuer_name.data = issuer_name.data;
+ m.issuer_name.length = issuer_name.length;
+ m.strong_mapping = TRUE;
+
+ ret = sdb_cert_mapping_to_hdb_key_trust_val(&m, &h);
+
+ assert_int_equal(0, ret);
+
+ assert_non_null(h.issuer_name);
+ assert_memory_equal(
+ issuer_name.data, h.issuer_name->data, issuer_name.length);
+ assert_int_equal(issuer_name.length, h.issuer_name->length);
+
+ assert_true(h.strong_mapping);
+
+ assert_null(h.serial_number);
+ assert_null(h.rfc822);
+ assert_null(h.ski);
+ assert_null(h.subject_name);
+ assert_null(h.public_key);
+
+ free_HDB_Ext_CertificateMapping(&h);
+}
+
+
+/*
+ * Ensure that sdb_cert_mapping_to_hdb_key_trust_val correctly maps the
+ * serial_number
+ */
+static void cert_map_serial_number_mapping(void **state)
+{
+ struct sdb_certificate_mapping m = {};
+ struct HDB_Ext_CertificateMapping h = {};
+ int ret = 0;
+ DATA_BLOB serial_number =
+ data_blob_string_const("1234BACXXXXXX");
+
+ m.serial_number.data = serial_number.data;
+ m.serial_number.length = serial_number.length;
+
+ ret = sdb_cert_mapping_to_hdb_key_trust_val(&m, &h);
+
+ assert_int_equal(0, ret);
+
+ assert_non_null(h.serial_number);
+ assert_memory_equal(
+ serial_number.data, h.serial_number->data, serial_number.length);
+ assert_int_equal(serial_number.length, h.serial_number->length);
+
+ assert_false(h.strong_mapping);
+
+ assert_null(h.rfc822);
+ assert_null(h.ski);
+ assert_null(h.issuer_name);
+ assert_null(h.subject_name);
+ assert_null(h.public_key);
+
+ free_HDB_Ext_CertificateMapping(&h);
+}
+
+/*
+ * Ensure that sdb_cert_mapping_to_hdb_key_trust_val correctly maps the
+ * public_key
+ */
+static void cert_map_public_key_mapping(void **state)
+{
+ struct sdb_certificate_mapping m = {};
+ struct HDB_Ext_CertificateMapping h = {};
+ int ret = 0;
+ DATA_BLOB public_key =
+ data_blob_string_const("abcdefghij");
+
+ m.public_key.data = public_key.data;
+ m.public_key.length = public_key.length;
+
+ ret = sdb_cert_mapping_to_hdb_key_trust_val(&m, &h);
+
+ assert_int_equal(0, ret);
+
+ assert_non_null(h.public_key);
+ assert_memory_equal(
+ public_key.data, h.public_key->data, public_key.length);
+ assert_int_equal(public_key.length, h.public_key->length);
+
+ assert_false(h.strong_mapping);
+
+ assert_null(h.serial_number);
+ assert_null(h.rfc822);
+ assert_null(h.ski);
+ assert_null(h.issuer_name);
+ assert_null(h.subject_name);
+
+ free_HDB_Ext_CertificateMapping(&h);
+}
+
+/*
+ * Ensure that sdb_cert_mapping_to_hdb_key_trust_val correctly maps the
+ * RFC822 (email address)
+ */
+static void cert_map_RFC822_mapping(void **state)
+{
+ struct sdb_certificate_mapping m = {};
+ struct HDB_Ext_CertificateMapping h = {};
+ int ret = 0;
+ DATA_BLOB rfc822 =
+ data_blob_string_const("test@test.org");
+
+ m.rfc822.data = rfc822.data;
+ m.rfc822.length = rfc822.length;
+
+ ret = sdb_cert_mapping_to_hdb_key_trust_val(&m, &h);
+
+ assert_int_equal(0, ret);
+
+ assert_non_null(h.rfc822);
+ assert_memory_equal(
+ rfc822.data, h.rfc822->data, rfc822.length);
+ assert_int_equal(rfc822.length, h.rfc822->length);
+
+ assert_false(h.strong_mapping);
+
+ assert_null(h.serial_number);
+ assert_null(h.ski);
+ assert_null(h.issuer_name);
+ assert_null(h.subject_name);
+ assert_null(h.public_key);
+
+ free_HDB_Ext_CertificateMapping(&h);
+}
+
+/*
+ * Ensure that sdb_cert_mapping_to_hdb_key_trust_val correctly maps the
+ * SKI (Subject Key Identifier)
+ */
+static void cert_map_ski_mapping(void **state)
+{
+ struct sdb_certificate_mapping m = {};
+ struct HDB_Ext_CertificateMapping h = {};
+ int ret = 0;
+ DATA_BLOB ski =
+ data_blob_string_const("cdef123455");
+
+ m.ski.data = ski.data;
+ m.ski.length = ski.length;
+
+ ret = sdb_cert_mapping_to_hdb_key_trust_val(&m, &h);
+
+ assert_int_equal(0, ret);
+
+ assert_non_null(h.ski);
+ assert_memory_equal(
+ ski.data, h.ski->data, ski.length);
+ assert_int_equal(ski.length, h.ski->length);
+
+ assert_false(h.strong_mapping);
+
+ assert_null(h.serial_number);
+ assert_null(h.rfc822);
+ assert_null(h.issuer_name);
+ assert_null(h.subject_name);
+ assert_null(h.public_key);
+
+ free_HDB_Ext_CertificateMapping(&h);
+}
+
+/*
+ * Ensure that sdb_cert_mapping_to_hdb_key_trust_val correctly maps
+ * all values if provided
+ */
+static void cert_map_all(void **state)
+{
+ struct sdb_certificate_mapping m = {};
+ struct HDB_Ext_CertificateMapping h = {};
+ int ret = 0;
+ DATA_BLOB issuer_name =
+ data_blob_string_const("DC=local,DC=samba,CN=Things");
+ DATA_BLOB subject_name = data_blob_string_const("DN=SubjectName");
+ DATA_BLOB serial_number =
+ data_blob_string_const("1234BACXXXXXX");
+ DATA_BLOB public_key =
+ data_blob_string_const("abcdefghij");
+ DATA_BLOB rfc822 =
+ data_blob_string_const("test@test.org");
+ DATA_BLOB ski =
+ data_blob_string_const("cdef123455");
+
+ m.ski.data = ski.data;
+ m.ski.length = ski.length;
+
+ m.rfc822.data = rfc822.data;
+ m.rfc822.length = rfc822.length;
+
+ m.public_key.data = public_key.data;
+ m.public_key.length = public_key.length;
+
+ m.serial_number.data = serial_number.data;
+ m.serial_number.length = serial_number.length;
+
+ m.subject_name.data = subject_name.data;
+ m.subject_name.length = subject_name.length;
+
+ m.issuer_name.data = issuer_name.data;
+ m.issuer_name.length = issuer_name.length;
+
+ ret = sdb_cert_mapping_to_hdb_key_trust_val(&m, &h);
+
+ assert_int_equal(0, ret);
+
+ assert_memory_equal(
+ issuer_name.data, h.issuer_name->data, issuer_name.length);
+ assert_int_equal(issuer_name.length, h.issuer_name->length);
+
+ assert_memory_equal(
+ serial_number.data, h.serial_number->data, serial_number.length);
+ assert_int_equal(serial_number.length, h.serial_number->length);
+
+ assert_memory_equal(
+ rfc822.data, h.rfc822->data, rfc822.length);
+ assert_int_equal(rfc822.length, h.rfc822->length);
+
+ assert_memory_equal(
+ ski.data, h.ski->data, ski.length);
+ assert_int_equal(ski.length, h.ski->length);
+
+ assert_memory_equal(
+ subject_name.data, h.subject_name->data, subject_name.length);
+ assert_int_equal(subject_name.length, h.subject_name->length);
+
+ assert_memory_equal(
+ public_key.data, h.public_key->data, public_key.length);
+ assert_int_equal(public_key.length, h.public_key->length);
+
+ free_HDB_Ext_CertificateMapping(&h);
+}
+
+static void cert_mappings_empty_sdb(void **state)
+{
+ struct sdb_certificate_mappings m = {};
+ HDB_Ext_CertificateMappings h = {};
+ int ret = 0;
+
+ ret = sdb_certificate_mappings_to_hdb_ext(&m, &h);
+ assert_int_equal(0, ret);
+
+ assert_null(h.mappings);
+ assert_int_equal(0, h.valid_certificate_start);
+ assert_int_equal(0, h.enforcement_mode);
+
+ free_HDB_Ext_CertificateMappings(&h);
+}
+
+
+static void cert_mappings_one_mapping(void **state)
+{
+ struct sdb_certificate_mappings m = {};
+ struct sdb_certificate_mapping cm = {};
+ HDB_Ext_CertificateMappings h = {};
+ int ret = 0;
+
+ DATA_BLOB ski =
+ data_blob_string_const("cdef123455");
+
+ cm.ski.data = ski.data;
+ cm.ski.length = ski.length;
+ cm.strong_mapping = TRUE;
+
+ m.enforcement_mode = 2;
+ m.valid_certificate_start = 100;
+
+ m.len = 1;
+ m.mappings = &cm;
+
+
+ ret = sdb_certificate_mappings_to_hdb_ext(&m, &h);
+ assert_int_equal(0, ret);
+
+ assert_non_null(h.mappings);
+ assert_int_equal(100, h.valid_certificate_start);
+ assert_int_equal(2, h.enforcement_mode);
+
+ free_HDB_Ext_CertificateMappings(&h);
+}
+
+static void cert_mappings_two_mappings(void **state)
+{
+ struct sdb_certificate_mappings m = {};
+ struct sdb_certificate_mapping cm1 = {};
+ struct sdb_certificate_mapping cm2 = {};
+ HDB_Ext_CertificateMappings h = {};
+ struct sdb_certificate_mapping mappings[] = {cm1, cm2};
+ int ret = 0;
+
+ DATA_BLOB ski =
+ data_blob_string_const("cdef123455");
+ DATA_BLOB rfc822 =
+ data_blob_string_const("test@test.org");
+
+ cm1.ski.data = ski.data;
+ cm1.ski.length = ski.length;
+ cm1.strong_mapping = TRUE;
+
+ cm2.rfc822.data = rfc822.data;
+ cm2.rfc822.length = rfc822.length;
+ cm2.strong_mapping = FALSE;
+
+ m.enforcement_mode = 2;
+ m.valid_certificate_start = 100;
+
+ m.len = 2;
+ m.mappings = mappings;
+
+
+ ret = sdb_certificate_mappings_to_hdb_ext(&m, &h);
+ assert_int_equal(0, ret);
+
+ assert_non_null(h.mappings);
+ assert_int_equal(100, h.valid_certificate_start);
+ assert_int_equal(2, h.enforcement_mode);
+
+ free_HDB_Ext_CertificateMappings(&h);
+}
int main(int argc, const char **argv)
{
const struct CMUnitTest tests[] = {
cmocka_unit_test(empty_key),
cmocka_unit_test(test_leading_bit_handling),
cmocka_unit_test(test_no_leading_bit),
+ cmocka_unit_test(cert_map_empty_sdb_mapping),
+ cmocka_unit_test(cert_map_subject_name_mapping),
+ cmocka_unit_test(cert_map_issuer_name_mapping),
+ cmocka_unit_test(cert_map_serial_number_mapping),
+ cmocka_unit_test(cert_map_public_key_mapping),
+ cmocka_unit_test(cert_map_RFC822_mapping),
+ cmocka_unit_test(cert_map_ski_mapping),
+ cmocka_unit_test(cert_map_all),
+ cmocka_unit_test(cert_mappings_empty_sdb),
+ cmocka_unit_test(cert_mappings_one_mapping),
+ cmocka_unit_test(cert_mappings_two_mappings),
};
cmocka_set_message_output(CM_OUTPUT_SUBUNIT);