summaryrefslogtreecommitdiffstats
path: root/daemons/ipa-sam/ipa_sam.c
diff options
context:
space:
mode:
Diffstat (limited to 'daemons/ipa-sam/ipa_sam.c')
-rw-r--r--daemons/ipa-sam/ipa_sam.c172
1 files changed, 167 insertions, 5 deletions
diff --git a/daemons/ipa-sam/ipa_sam.c b/daemons/ipa-sam/ipa_sam.c
index dd3ad617b..1783ca345 100644
--- a/daemons/ipa-sam/ipa_sam.c
+++ b/daemons/ipa-sam/ipa_sam.c
@@ -1,6 +1,7 @@
#define HAVE_IMMEDIATE_STRUCTURES 1
#define LDAP_DEPRECATED 1
+#include "config.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
@@ -167,6 +168,12 @@ struct ipasam_privates {
struct sss_idmap_ctx *idmap_ctx;
};
+
+static NTSTATUS ipasam_get_domain_name(struct ldapsam_privates *ldap_state,
+ TALLOC_CTX *mem_ctx,
+ char **domain_name);
+
+
static void *idmap_talloc(size_t size, void *pvt)
{
return talloc_size(pvt, size);
@@ -295,6 +302,53 @@ static LDAP *priv2ld(struct ldapsam_privates *priv)
return priv->smbldap_state->ldap_struct;
}
+/*
+ * get_attribute_values() returns array of all values of the attribute
+ * allocated over mem_ctx
+ */
+static char **get_attribute_values(TALLOC_CTX *mem_ctx, LDAP *ldap_struct,
+ LDAPMessage *entry, const char *attribute, int *num_values)
+{
+ struct berval **values;
+ int count, i;
+ char **result = NULL;
+ size_t conv_size;
+
+ if (attribute == NULL || entry == NULL) {
+ return NULL;
+ }
+
+ values = ldap_get_values_len(ldap_struct, entry, attribute);
+ if (values == NULL) {
+ DEBUG(10, ("Attribute [%s] not found.\n", attribute));
+ return NULL;
+ }
+
+ /* Note that if we've got any values, count would be > 0 */
+ count = ldap_count_values_len(values);
+ result = talloc_array(mem_ctx, char *, count);
+ if (result == NULL) {
+ goto done;
+ }
+
+ *num_values = count;
+ for (i = 0; i < count; i++) {
+ if (!convert_string_talloc(result, CH_UTF8, CH_UNIX,
+ values[i]->bv_val, values[i]->bv_len,
+ &result[i], &conv_size)) {
+ DEBUG(10, ("Failed to convert %dth value of [%s] out of %d.\n",
+ i, attribute, count));
+ talloc_free(result);
+ result = NULL;
+ goto done;
+ }
+ }
+
+done:
+ ldap_value_free_len(values);
+ return result;
+}
+
static char *get_single_attribute(TALLOC_CTX *mem_ctx, LDAP *ldap_struct,
LDAPMessage *entry, const char *attribute)
{
@@ -3250,9 +3304,8 @@ static struct pdb_domain_info *pdb_ipasam_get_domain_info(struct pdb_methods *pd
goto fail;
}
- /* TODO: read dns_domain, dns_forest and guid from LDAP */
- info->dns_domain = strlower_talloc(info, ldap_state->ipasam_privates->realm);
- if (info->dns_domain == NULL) {
+ status = ipasam_get_domain_name(ldap_state, info, &info->dns_domain);
+ if (!NT_STATUS_IS_OK(status) || (info->dns_domain == NULL)) {
goto fail;
}
info->dns_forest = talloc_strdup(info, info->dns_domain);
@@ -3464,7 +3517,7 @@ static NTSTATUS ipasam_get_base_dn(struct smbldap_state *smbldap_state,
static NTSTATUS ipasam_get_domain_name(struct ldapsam_privates *ldap_state,
TALLOC_CTX *mem_ctx,
- const char **domain_name)
+ char **domain_name)
{
int ret;
LDAPMessage *result;
@@ -3572,6 +3625,110 @@ static NTSTATUS ipasam_get_realm(struct ldapsam_privates *ldap_state,
return NT_STATUS_OK;
}
+#ifdef HAVE_PDB_ENUM_UPN_SUFFIXES
+static NTSTATUS ipasam_enum_upn_suffixes(struct pdb_methods *pdb_methods,
+ TALLOC_CTX *mem_ctx,
+ uint32_t *num_suffixes,
+ char ***suffixes)
+{
+ int ret;
+ LDAPMessage *result;
+ LDAPMessage *entry = NULL;
+ int count, i;
+ char *realmdomains_dn = NULL;
+ char **domains = NULL;
+ struct ldapsam_privates *ldap_state;
+ struct smbldap_state *smbldap_state;
+ const char *attr_list[] = {
+ "associatedDomain",
+ NULL
+ };
+
+ if ((suffixes == NULL) || (num_suffixes == NULL)) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ ldap_state = (struct ldapsam_privates *)pdb_methods->private_data;
+ smbldap_state = ldap_state->smbldap_state;
+
+ realmdomains_dn = talloc_asprintf(mem_ctx, "cn=Realm Domains,cn=ipa,cn=etc,%s",
+ ldap_state->ipasam_privates->base_dn);
+ if (realmdomains_dn == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ ret = smbldap_search(smbldap_state,
+ realmdomains_dn,
+ LDAP_SCOPE_BASE,
+ "objectclass=domainRelatedObject", attr_list, 0,
+ &result);
+ if (ret != LDAP_SUCCESS) {
+ DEBUG(1, ("Failed to get list of realm domains: %s\n",
+ ldap_err2string (ret)));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ count = ldap_count_entries(smbldap_state->ldap_struct, result);
+ if (count != 1) {
+ DEBUG(1, ("Unexpected number of results [%d] for realm domains "
+ "search.\n", count));
+ ldap_msgfree(result);
+ return NT_STATUS_OK;
+ }
+
+ entry = ldap_first_entry(smbldap_state->ldap_struct, result);
+ if (entry == NULL) {
+ DEBUG(0, ("Could not get domainRelatedObject entry\n"));
+ ldap_msgfree(result);
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ domains = get_attribute_values(mem_ctx, smbldap_state->ldap_struct, entry,
+ "associatedDomain", &count);
+ if (domains == NULL) {
+ ldap_msgfree(result);
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ /* Since associatedDomain has attributeType MUST, there must be at least one domain */
+ for (i = 0; i < count ; i++) {
+ if (strcmp(ldap_state->domain_name, domains[i]) == 0) {
+ break;
+ }
+ }
+
+ if (i < count) {
+ /* If we found our primary domain in the list and it is alone, exit with empty list */
+ if (count == 1) {
+ ldap_msgfree(result);
+ talloc_free(domains);
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ talloc_free(domains[i]);
+
+ /* if i is not last element, move everything down */
+ if (i != (count - 1)) {
+ memcpy(domains + i, domains + i + 1, sizeof(char *) * (count - i - 1));
+ }
+
+ /* we don't resize whole list, only reduce number of elements in it
+ * since sizing down a single pointer will not reduce memory usage in talloc
+ */
+ *suffixes = domains;
+ *num_suffixes = count - 1;
+ } else {
+ /* There is no our primary domain in the list */
+ *suffixes = domains;
+ *num_suffixes = count;
+ }
+
+ ldap_msgfree(result);
+ return NT_STATUS_OK;
+}
+#endif /* HAVE_PDB_ENUM_UPN_SUFFIXES */
+
+
#define SECRETS_DOMAIN_SID "SECRETS/SID"
static char *sec_key(TALLOC_CTX *mem_ctx, const char *d)
{
@@ -4030,7 +4187,7 @@ static NTSTATUS pdb_init_ipasam(struct pdb_methods **pdb_method,
}
status = ipasam_get_domain_name(ldap_state, ldap_state,
- &ldap_state->domain_name);
+ (char**) &ldap_state->domain_name);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0, ("Failed to get domain name.\n"));
return status;
@@ -4150,6 +4307,11 @@ static NTSTATUS pdb_init_ipasam(struct pdb_methods **pdb_method,
(*pdb_method)->set_trusted_domain = ipasam_set_trusted_domain;
(*pdb_method)->del_trusted_domain = ipasam_del_trusted_domain;
(*pdb_method)->enum_trusted_domains = ipasam_enum_trusted_domains;
+#ifdef HAVE_PDB_ENUM_UPN_SUFFIXES
+ (*pdb_method)->enum_upn_suffixes = ipasam_enum_upn_suffixes;
+ DEBUG(1, ("pdb_init_ipasam: support for pdb_enum_upn_suffixes "
+ "enabled for domain %s\n", ldap_state->domain_name));
+#endif
return NT_STATUS_OK;
}