summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--daemons/configure.ac10
-rw-r--r--daemons/ipa-sam/ipa_sam.c172
2 files changed, 177 insertions, 5 deletions
diff --git a/daemons/configure.ac b/daemons/configure.ac
index d3b6b19d1..14dc04e58 100644
--- a/daemons/configure.ac
+++ b/daemons/configure.ac
@@ -252,6 +252,16 @@ AC_CHECK_LIB([wbclient],
[$SAMBA40EXTRA_LIBPATH])
AC_SUBST(WBCLIENT_LIBS)
+AC_CHECK_LIB([pdb],
+ [make_pdb_method],
+ [HAVE_LIBPDB=1],
+ [AC_MSG_ERROR([libpdb does not have make_pdb_method])],
+ [$SAMBA40EXTRA_LIBPATH])
+AC_CHECK_LIB([pdb],[pdb_enum_upn_suffixes],
+ [AC_DEFINE([HAVE_PDB_ENUM_UPN_SUFFIXES], [1], [Ability to enumerate UPN suffixes])],
+ [AC_MSG_WARN([libpdb does not have pdb_enum_upn_suffixes, no support for realm domains in ipasam])],
+ [$SAMBA40EXTRA_LIBPATH])
+
dnl ---------------------------------------------------------------------------
dnl - Check for check unit test framework http://check.sourceforge.net/
dnl ---------------------------------------------------------------------------
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;
}