#define LDAP_VIRTUAL_DN_ATTR "dn" //!< 'Virtual' attribute which maps to the DN of the object.
+#define LDAP_SERVER_NOTIFICATION_OID "1.2.840.113556.1.4.528" //!< OID of Active Directory control for
+ //!< persistent search.
+#define LDAP_SERVER_SHOW_DELETED_OID "1.2.840.113556.1.4.417" //!< OID of Active Directory control which
+ //!< enables searching for deleted objects.
+
typedef enum {
LDAP_EXT_UNSUPPORTED, //!< Unsupported extension.
LDAP_EXT_BINDNAME, //!< Specifies the user DN or name for an LDAP bind.
FR_LDAP_DIRECTORY_UNBOUND_ID //!< Directory server is Unbound ID
} fr_ldap_directory_type_t;
+typedef enum {
+ FR_LDAP_SYNC_NONE = 0, //!< No support for LDAP sync
+ FR_LDAP_SYNC_RFC4533, //!< Directory supports RFC 4533
+ FR_LDAP_SYNC_ACTIVE_DIRECTORY, //!< Directory supports AD style persistent search.
+ FR_LDAP_SYNC_PERSISTENT_SEARCH //!< Directory supports persistent search
+} fr_ldap_sync_type_t;
+
/** LDAP connection handle states
*
*/
bool cleartext_password; //!< Whether the server will return the user's plaintext
///< password.
+
+ fr_ldap_sync_type_t sync_type; //! <What kind of LDAP sync this directory supports.
} fr_ldap_directory_t;
/** Connection configuration
/*
* directory.c - Get directory capabilities from the remote server
*/
+#define LDAP_DIRECTORY_ATTRS { "vendorname", \
+ "vendorversion", \
+ "isGlobalCatalogReady", \
+ "objectClass", \
+ "orcldirectoryversion", \
+ "supportedControl", \
+ NULL }
+
+int fr_ldap_directory_result_parse(fr_ldap_directory_t *directory, LDAP *handle,
+ LDAPMessage *result, char const *name);
+
int fr_ldap_trunk_directory_alloc_async(TALLOC_CTX *ctx, fr_ldap_thread_trunk_t *ttrunk);
+int fr_ldap_conn_directory_alloc_async(fr_ldap_connection_t *ldap_conn);
+
/*
* edir.c - Edirectory integrations
*/
};
static size_t fr_ldap_directory_type_table_len = NUM_ELEMENTS(fr_ldap_directory_type_table);
-static int ldap_directory_result_parse(fr_ldap_directory_t *directory, LDAP *handle,
- LDAPMessage *result, char const *name)
+int fr_ldap_directory_result_parse(fr_ldap_directory_t *directory, LDAP *handle,
+ LDAPMessage *result, char const *name)
{
int entry_cnt, i, num, ldap_errno;
LDAPMessage *entry;
if (directory->vendor_str) {
if (strcasestr(directory->vendor_str, "International Business Machines")) {
- directory->type = FR_LDAP_DIRECTORY_EDIRECTORY;
+ directory->type = FR_LDAP_DIRECTORY_IBM;
}
goto found;
break;
}
+ /*
+ * Evaluate what type of sync the directory supports
+ */
+ values = ldap_get_values_len(handle, entry, "supportedControl");
+ if (values) {
+ num = ldap_count_values_len(values);
+ for (i = 0; i < num; i++) {
+ if (strncmp(LDAP_CONTROL_SYNC, values[i]->bv_val, values[i]->bv_len) == 0) {
+ INFO("Directory supports RFC 4533");
+ directory->sync_type = FR_LDAP_SYNC_RFC4533;
+ break;
+ }
+ if (strncmp(LDAP_SERVER_NOTIFICATION_OID, values[i]->bv_val, values[i]->bv_len) == 0) {
+ INFO("Directory supports LDAP_SERVER_NOTIFICATION_OID");
+ directory->sync_type = FR_LDAP_SYNC_ACTIVE_DIRECTORY;
+ break;
+ }
+ if (strncmp(LDAP_CONTROL_PERSIST_REQUEST, values[i]->bv_val, values[i]->bv_len) == 0) {
+ INFO("Directory supports persistent search");
+ directory->sync_type = FR_LDAP_SYNC_PERSISTENT_SEARCH;
+ break;
+ }
+ }
+ ldap_value_free_len(values);
+ } else {
+ WARN("No supportedControl returned by LDAP server");
+ }
+
return 0;
}
fr_ldap_config_t const *config = query->ldap_conn->config;
fr_ldap_directory_t *directory = talloc_get_type_abort(rctx, fr_ldap_directory_t);
- (void)ldap_directory_result_parse(directory, handle, result, config->name);
+ (void)fr_ldap_directory_result_parse(directory, handle, result, config->name);
}
/** Async extract useful information from the rootDSE of the LDAP server
*/
int fr_ldap_trunk_directory_alloc_async(TALLOC_CTX *ctx, fr_ldap_thread_trunk_t *ttrunk)
{
- static char const *attrs[] = { "vendorname",
- "vendorversion",
- "isGlobalCatalogReady",
- "objectClass",
- "orcldirectoryversion",
- NULL };
fr_ldap_query_t *query;
+ static char const *attrs[] = LDAP_DIRECTORY_ATTRS;
ttrunk->directory = talloc_zero(ctx, fr_ldap_directory_t);
if (!ttrunk->directory) return -1;
return 0;
}
+
+/** Async extract useful information from the rootDSE of the LDAP server
+ *
+ * This version is for a single connection rather than a connection trunk
+ *
+ * @param[in] ldap_conn connection to be queried
+ * @return
+ * - message ID on success
+ * < 0 on failure
+ */
+int fr_ldap_conn_directory_alloc_async(fr_ldap_connection_t *ldap_conn)
+{
+ int msgid;
+ static char const *attrs[] = LDAP_DIRECTORY_ATTRS;
+
+ ldap_conn->directory = talloc_zero(ldap_conn, fr_ldap_directory_t);
+ if (!ldap_conn->directory) return -1;
+
+ if (fr_ldap_search_async(&msgid, NULL, &ldap_conn, "", LDAP_SCOPE_BASE, "(objectclass=*)", attrs,
+ NULL, NULL) != LDAP_PROC_SUCCESS) return -1;
+
+ return msgid;
+}