summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Bokovoy <abokovoy@redhat.com>2013-03-22 17:30:41 +0200
committerAlexander Bokovoy <abokovoy@redhat.com>2013-03-25 18:45:22 +0200
commitf400d55eaec99b3e5440e90b6a6d055e26529e7e (patch)
tree8a3fe196b9d2240212689fb2fbd203b9197df92a
parente6e37187fe2fb0f16abba94671931791c73ef177 (diff)
downloadfreeipa-trusts-master.tar.gz
freeipa-trusts-master.tar.xz
freeipa-trusts-master.zip
ipasam: add enumeration of UPN suffixes based on the realm domainstrusts-master
PASSDB API in Samba adds support for specifying UPN suffixes. The change in ipasam will allow to pass through list of realm domains as UPN suffixes so that Active Directory domain controller will be able to recognize non-primary UPN suffixes as belonging to IPA and properly find our KDC for cross-realm TGT. Since Samba already returns primary DNS domain separately, filter it out from list of UPN suffixes. Also enclose provider of UPN suffixes into #ifdef to support both Samba with and without pdb_enum_upn_suffixes(). Part of https://fedorahosted.org/freeipa/ticket/2848
-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;
}