summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTimothy Pearson <kb9vqf@pearsoncomputing.net>2015-09-29 12:06:18 -0500
committerTimothy Pearson <kb9vqf@pearsoncomputing.net>2015-09-29 12:06:18 -0500
commitd9172dad3c94e373c944d6f4e7a06262ed0329a1 (patch)
treef29728c2a51a382711e0727248098e1221572a53
parentc70ce69a08815fb4da81b2a85fc4a2a10d469cab (diff)
downloadlibtdeldap-d9172dad.tar.gz
libtdeldap-d9172dad.zip
Add PKI subject mapping to user principals
Fix long-standing inability to clear user principal attribute fields
-rw-r--r--src/libtdeldap.cpp91
1 files changed, 90 insertions, 1 deletions
diff --git a/src/libtdeldap.cpp b/src/libtdeldap.cpp
index 690cee9..37cc76b 100644
--- a/src/libtdeldap.cpp
+++ b/src/libtdeldap.cpp
@@ -51,9 +51,30 @@
extern "C" {
#include <hdb.h>
+ #include <hdb_asn1.h>
#include <kadm5/admin.h>
#include <kadm5/private.h>
#include <kadm5/kadm5-private.h>
+
+ // ========================================================================
+ // Taken from asn1-common.h and slightly modified for C++ compilability
+ // ========================================================================
+ #define ASN1_MALLOC_ENCODE_HDB(T, B, BL, S, L, R) \
+ do { \
+ (BL) = length_##T((S)); \
+ (B) = (unsigned char*)malloc((BL)); \
+ if((B) == NULL) { \
+ (R) = ENOMEM; \
+ } else { \
+ (R) = encode_##T(((unsigned char*)(B)) + (BL) - 1, (BL), \
+ (S), (L)); \
+ if((R) != 0) { \
+ free((B)); \
+ (B) = NULL; \
+ } \
+ } \
+ } while (0)
+ // ========================================================================
}
#include "libtdeldap.h"
@@ -930,6 +951,14 @@ void add_single_attribute_operation(LDAPMod **mods, int *i, TQString attr, TQStr
mods[*i]->mod_values = values;
(*i)++;
}
+ else {
+ char **values = (char**)malloc(sizeof(char*));
+ values[0] = NULL;
+ mods[*i]->mod_op = LDAP_MOD_REPLACE;
+ mods[*i]->mod_type = strdup(attr.ascii());
+ mods[*i]->mod_values = values;
+ (*i)++;
+ }
}
void add_single_binary_attribute_operation(LDAPMod **mods, int *i, TQString attr, TQByteArray &ba) {
@@ -1023,9 +1052,68 @@ int LDAPManager::updateUserInfo(LDAPUserInfo user, TQString *errstr) {
return -1;
}
else {
+ // Create certificate ACL extension data
+ TQString pkinit_acl_subject = TQString::null;
+ PKICertificateEntryList::Iterator it;
+ for (it = user.pkiCertificates.begin(); it != user.pkiCertificates.end(); ++it) {
+ PKICertificateEntry certificateData = *it;
+
+ TQCString ssldata(certificateData.second);
+ ssldata[certificateData.second.size()] = 0;
+ ssldata.replace("-----BEGIN CERTIFICATE-----", "");
+ ssldata.replace("-----END CERTIFICATE-----", "");
+ ssldata.replace("\n", "");
+ KSSLCertificate* cert = KSSLCertificate::fromString(ssldata);
+ if (cert) {
+ bool expired = false;
+ if (TQDateTime::currentDateTime(Qt::UTC) > cert->getQDTNotAfter()) {
+ expired = true;
+ }
+
+ if ((certificateData.first == PKICertificateStatus::Revoked) || expired) {
+ continue;
+ }
+ else {
+ // NOTE
+ // At this time Heimdal only appears to support one certificate ACL string
+ // Use the last valid certificate subject when creating that string
+ TQStringList reversedSubjectChunks;
+ TQStringList subjectChunks = TQStringList::split("/", cert->getSubject());
+ for (TQStringList::Iterator it = subjectChunks.begin(); it != subjectChunks.end(); it++) {
+ reversedSubjectChunks.prepend(*it);
+ }
+ pkinit_acl_subject = reversedSubjectChunks.join(",");
+ }
+ }
+ }
+ TQByteArray acl_asn1_data;
+ if (pkinit_acl_subject != "") {
+ krb5_error_code krb5_ret;
+ HDB_extension extended_attributes;
+ memset(&extended_attributes, 0, sizeof(extended_attributes));
+ extended_attributes.mandatory = true;
+ extended_attributes.data.element = HDB_extension::HDB_extension_data::choice_HDB_extension_data_pkinit_acl;
+ HDB_Ext_PKINIT_acl* pkinit_acl = &extended_attributes.data.u.pkinit_acl;
+ pkinit_acl->val = (HDB_Ext_PKINIT_acl::HDB_Ext_PKINIT_acl_val*)malloc(sizeof(pkinit_acl->val[0]));
+ pkinit_acl->len = 1;
+ pkinit_acl->val->subject = const_cast<char*>(pkinit_acl_subject.ascii());
+ pkinit_acl->val->issuer = NULL;
+ pkinit_acl->val->anchor = NULL;
+ unsigned char *asn1_encoding_buf;
+ size_t initial_size = 0;
+ size_t resultant_size = 0;
+ ASN1_MALLOC_ENCODE_HDB(HDB_extension, asn1_encoding_buf, initial_size, &extended_attributes, &resultant_size, krb5_ret);
+ if (initial_size == resultant_size) {
+ acl_asn1_data.resize(resultant_size);
+ memcpy(acl_asn1_data.data(), asn1_encoding_buf, resultant_size);
+ }
+ free(pkinit_acl->val);
+ free(asn1_encoding_buf);
+ }
+
// Assemble the LDAPMod structure
// We will replace any existing attributes with the new values
- int number_of_parameters = 40; // 40 primary attributes
+ int number_of_parameters = 49; // 49 primary attributes
LDAPMod *mods[number_of_parameters+1];
set_up_attribute_operations(mods, number_of_parameters);
@@ -1087,6 +1175,7 @@ int LDAPManager::updateUserInfo(LDAPUserInfo user, TQString *errstr) {
add_single_attribute_operation(mods, &i, "businessCategory", user.businessCategory);
add_single_attribute_operation(mods, &i, "carLicense", user.carLicense);
add_single_attribute_operation(mods, &i, "notes", user.notes);
+ add_single_binary_attribute_operation(mods, &i, "krb5ExtendedAttributes", acl_asn1_data);
LDAPMod *prevterm = mods[i];
mods[i] = NULL;