s3-ipasam: implement {get,set,del}_trusted_domain
authorSumit Bose <sbose@redhat.com>
Fri, 16 Jul 2010 09:01:49 +0000 (11:01 +0200)
committerGünther Deschner <gd@samba.org>
Wed, 16 Feb 2011 10:34:45 +0000 (11:34 +0100)
Signed-off-by: Günther Deschner <gd@samba.org>
source3/include/smbldap.h
source3/passdb/pdb_ipa.c

index e651182e31adb6baaada010731f3fc907c42a8a4..90df78e7acfb6f2728381c3c7435943587b78148 100644 (file)
@@ -41,6 +41,7 @@ struct smbldap_state;
 #define LDAP_OBJ_SID_ENTRY             "sambaSidEntry"
 #define LDAP_OBJ_TRUST_PASSWORD         "sambaTrustPassword"
 #define LDAP_OBJ_TRUSTDOM_PASSWORD      "sambaTrustedDomainPassword"
+#define LDAP_OBJ_TRUSTED_DOMAIN                "sambaTrustedDomain"
 
 #define LDAP_OBJ_ACCOUNT               "account"
 #define LDAP_OBJ_POSIXACCOUNT          "posixAccount"
index 34eee5efa9c5ef6085badb788bbc2319a95022d0..24513ccf8c6f0757e11dc10111206f1ee0b0f153 100644 (file)
 
 #include "smbldap.h"
 
+#define LDAP_TRUST_CONTAINER "ou=system"
+#define LDAP_ATTRIBUTE_CN "cn"
+#define LDAP_ATTRIBUTE_TRUST_TYPE "sambaTrustType"
+#define LDAP_ATTRIBUTE_TRUST_ATTRIBUTES "sambaTrustAttributes"
+#define LDAP_ATTRIBUTE_TRUST_DIRECTION "sambaTrustDirection"
+#define LDAP_ATTRIBUTE_TRUST_PARTNER "sambaTrustPartner"
+#define LDAP_ATTRIBUTE_FLAT_NAME "sambaFlatName"
+#define LDAP_ATTRIBUTE_TRUST_AUTH_OUTGOING "sambaTrustAuthOutgoing"
+#define LDAP_ATTRIBUTE_TRUST_AUTH_INCOMING "sambaTrustAuthIncoming"
+#define LDAP_ATTRIBUTE_SECURITY_IDENTIFIER "sambaSecurityIdentifier"
+
 static bool ipasam_get_trusteddom_pw(struct pdb_methods *methods,
                                     const char *domain,
                                     char** pwd,
@@ -53,6 +64,425 @@ static NTSTATUS ipasam_enum_trusteddoms(struct pdb_methods *methods,
        return NT_STATUS_NOT_IMPLEMENTED;
 }
 
+static char *trusted_domain_dn(struct ldapsam_privates *ldap_state,
+                              const char *domain)
+{
+       return talloc_asprintf(talloc_tos(), "%s=%s,%s,%s",
+                              LDAP_ATTRIBUTE_CN, domain,
+                              LDAP_TRUST_CONTAINER, ldap_state->domain_dn);
+}
+
+static char *trusted_domain_base_dn(struct ldapsam_privates *ldap_state)
+{
+       return talloc_asprintf(talloc_tos(), "%s,%s",
+                              LDAP_TRUST_CONTAINER, ldap_state->domain_dn);
+}
+
+static bool get_trusted_domain_int(struct ldapsam_privates *ldap_state,
+                                  TALLOC_CTX *mem_ctx,
+                                  const char *domain, LDAPMessage **entry)
+{
+       int rc;
+       char *filter = NULL;
+       char *base_dn = NULL;
+       LDAPMessage *result = NULL;
+       uint32_t num_result;
+
+       filter = talloc_asprintf(talloc_tos(),
+                                "(&(objectClass=%s)(|(sambaFlatName=%s)(cn=%s)(sambaTrustPartner=%s)))",
+                                LDAP_OBJ_TRUSTED_DOMAIN, domain, domain, domain);
+       if (filter == NULL) {
+               return false;
+       }
+
+       base_dn = trusted_domain_base_dn(ldap_state);
+       if (base_dn == NULL) {
+               TALLOC_FREE(filter);
+               return false;
+       }
+
+       rc = smbldap_search(ldap_state->smbldap_state, base_dn,
+                           LDAP_SCOPE_SUBTREE, filter, NULL, 0, &result);
+       TALLOC_FREE(filter);
+       TALLOC_FREE(base_dn);
+
+       if (result != NULL) {
+               talloc_autofree_ldapmsg(mem_ctx, result);
+       }
+
+       if (rc == LDAP_NO_SUCH_OBJECT) {
+               *entry = NULL;
+               return true;
+       }
+
+       if (rc != LDAP_SUCCESS) {
+               return false;
+       }
+
+       num_result = ldap_count_entries(priv2ld(ldap_state), result);
+
+       if (num_result > 1) {
+               DEBUG(1, ("get_trusted_domain_int: more than one "
+                         "%s object for domain '%s'?!\n",
+                         LDAP_OBJ_TRUSTED_DOMAIN, domain));
+               return false;
+       }
+
+       if (num_result == 0) {
+               DEBUG(1, ("get_trusted_domain_int: no "
+                         "%s object for domain %s.\n",
+                         LDAP_OBJ_TRUSTED_DOMAIN, domain));
+               *entry = NULL;
+       } else {
+               *entry = ldap_first_entry(priv2ld(ldap_state), result);
+       }
+
+       return true;
+}
+
+static bool get_uint32_t_from_ldap_msg(struct ldapsam_privates *ldap_state,
+                                      LDAPMessage *entry,
+                                      const char *attr,
+                                      uint32_t *val)
+{
+       char *dummy;
+       long int l;
+       char *endptr;
+
+       dummy = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry,
+                                               attr, talloc_tos());
+       if (dummy == NULL) {
+               DEBUG(9, ("Attribute %s not present.\n", attr));
+               *val = 0;
+               return true;
+       }
+
+       l = strtoul(dummy, &endptr, 10);
+       TALLOC_FREE(dummy);
+
+       if (l < 0 || l > UINT32_MAX || *endptr != '\0') {
+               return false;
+       }
+
+       *val = l;
+
+       return true;
+}
+
+static void get_data_blob_from_ldap_msg(TALLOC_CTX *mem_ctx,
+                                       struct ldapsam_privates *ldap_state,
+                                       LDAPMessage *entry, const char *attr,
+                                       DATA_BLOB *_blob)
+{
+       char *dummy;
+       DATA_BLOB blob;
+
+       dummy = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry, attr,
+                                               talloc_tos());
+       if (dummy == NULL) {
+               DEBUG(9, ("Attribute %s not present.\n", attr));
+               ZERO_STRUCTP(_blob);
+       } else {
+               blob = base64_decode_data_blob(dummy);
+               if (blob.length == 0) {
+                       ZERO_STRUCTP(_blob);
+               } else {
+                       _blob->length = blob.length;
+                       _blob->data = talloc_steal(mem_ctx, blob.data);
+               }
+       }
+       TALLOC_FREE(dummy);
+}
+
+static bool fill_pdb_trusted_domain(TALLOC_CTX *mem_ctx,
+                                   struct ldapsam_privates *ldap_state,
+                                   LDAPMessage *entry,
+                                   struct pdb_trusted_domain **_td)
+{
+       char *dummy;
+       bool res;
+       struct pdb_trusted_domain *td;
+
+       if (entry == NULL) {
+               return false;
+       }
+
+       td = talloc_zero(mem_ctx, struct pdb_trusted_domain);
+       if (td == NULL) {
+               return false;
+       }
+
+       /* All attributes are MAY */
+
+       dummy = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry,
+                                               LDAP_ATTRIBUTE_SECURITY_IDENTIFIER,
+                                               talloc_tos());
+       if (dummy == NULL) {
+               DEBUG(9, ("Attribute %s not present.\n",
+                         LDAP_ATTRIBUTE_SECURITY_IDENTIFIER));
+               ZERO_STRUCT(td->security_identifier);
+       } else {
+               res = string_to_sid(&td->security_identifier, dummy);
+               TALLOC_FREE(dummy);
+               if (!res) {
+                       return false;
+               }
+       }
+
+       get_data_blob_from_ldap_msg(td, ldap_state, entry,
+                                   LDAP_ATTRIBUTE_TRUST_AUTH_INCOMING,
+                                   &td->trust_auth_incoming);
+
+       get_data_blob_from_ldap_msg(td, ldap_state, entry,
+                                   LDAP_ATTRIBUTE_TRUST_AUTH_OUTGOING,
+                                   &td->trust_auth_outgoing);
+
+       td->netbios_name = smbldap_talloc_single_attribute(priv2ld(ldap_state),
+                                                          entry,
+                                                          LDAP_ATTRIBUTE_FLAT_NAME,
+                                                          td);
+       if (td->netbios_name == NULL) {
+               DEBUG(9, ("Attribute %s not present.\n",
+                         LDAP_ATTRIBUTE_FLAT_NAME));
+       }
+
+       td->domain_name = smbldap_talloc_single_attribute(priv2ld(ldap_state),
+                                                         entry,
+                                                         LDAP_ATTRIBUTE_TRUST_PARTNER,
+                                                         td);
+       if (td->domain_name == NULL) {
+               DEBUG(9, ("Attribute %s not present.\n",
+                         LDAP_ATTRIBUTE_TRUST_PARTNER));
+       }
+
+       res = get_uint32_t_from_ldap_msg(ldap_state, entry,
+                                        LDAP_ATTRIBUTE_TRUST_DIRECTION,
+                                        &td->trust_direction);
+       if (!res) {
+               return false;
+       }
+
+       res = get_uint32_t_from_ldap_msg(ldap_state, entry,
+                                        LDAP_ATTRIBUTE_TRUST_ATTRIBUTES,
+                                        &td->trust_attributes);
+       if (!res) {
+               return false;
+       }
+
+       res = get_uint32_t_from_ldap_msg(ldap_state, entry,
+                                        LDAP_ATTRIBUTE_TRUST_TYPE,
+                                        &td->trust_type);
+       if (!res) {
+               return false;
+       }
+
+       *_td = td;
+
+       return true;
+}
+
+static NTSTATUS ipasam_get_trusted_domain(struct pdb_methods *methods,
+                                         TALLOC_CTX *mem_ctx,
+                                         const char *domain,
+                                         struct pdb_trusted_domain **td)
+{
+       struct ldapsam_privates *ldap_state =
+               (struct ldapsam_privates *)methods->private_data;
+       LDAPMessage *entry = NULL;
+
+       DEBUG(10, ("ipasam_get_trusted_domain called for domain %s\n", domain));
+
+       if (!get_trusted_domain_int(ldap_state, talloc_tos(), domain, &entry)) {
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+       if (entry == NULL) {
+               DEBUG(5, ("ipasam_get_trusted_domain: no such trusted domain: "
+                         "%s\n", domain));
+               return NT_STATUS_NO_SUCH_DOMAIN;
+       }
+
+       if (!fill_pdb_trusted_domain(mem_ctx, ldap_state, entry, td)) {
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+
+       return NT_STATUS_OK;
+}
+
+static bool smbldap_make_mod_uint32_t(LDAP *ldap_struct, LDAPMessage *entry,
+                                     LDAPMod ***mods, const char *attribute,
+                                     const uint32_t val)
+{
+       char *dummy;
+
+       dummy = talloc_asprintf(talloc_tos(), "%lu", (unsigned long) val);
+       if (dummy == NULL) {
+               return false;
+       }
+       smbldap_make_mod(ldap_struct, entry, mods, attribute, dummy);
+       TALLOC_FREE(dummy);
+
+       return true;
+}
+
+static bool smbldap_make_mod_blob(LDAP *ldap_struct, LDAPMessage *entry,
+                                 LDAPMod ***mods, const char *attribute,
+                                 DATA_BLOB blob)
+{
+       char *dummy;
+
+       dummy = base64_encode_data_blob(talloc_tos(), blob);
+       if (dummy == NULL) {
+               return false;
+       }
+
+       smbldap_make_mod(ldap_struct, entry, mods, attribute, dummy);
+       TALLOC_FREE(dummy);
+
+       return true;
+}
+
+static NTSTATUS ipasam_set_trusted_domain(struct pdb_methods *methods,
+                                         const char* domain,
+                                         const struct pdb_trusted_domain *td)
+{
+       struct ldapsam_privates *ldap_state =
+               (struct ldapsam_privates *)methods->private_data;
+       LDAPMessage *entry = NULL;
+       LDAPMod **mods;
+       bool res;
+       char *trusted_dn = NULL;
+       int ret;
+
+       DEBUG(10, ("ipasam_set_trusted_domain called for domain %s\n", domain));
+
+       res = get_trusted_domain_int(ldap_state, talloc_tos(), domain, &entry);
+       if (!res) {
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+
+       mods = NULL;
+       smbldap_make_mod(priv2ld(ldap_state), entry, &mods, "objectClass",
+                        LDAP_OBJ_TRUSTED_DOMAIN);
+
+       if (td->netbios_name != NULL) {
+               smbldap_make_mod(priv2ld(ldap_state), entry, &mods,
+                                LDAP_ATTRIBUTE_FLAT_NAME,
+                                td->netbios_name);
+       }
+
+       if (td->domain_name != NULL) {
+               smbldap_make_mod(priv2ld(ldap_state), entry, &mods,
+                                LDAP_ATTRIBUTE_TRUST_PARTNER,
+                                td->domain_name);
+       }
+
+       if (!is_null_sid(&td->security_identifier)) {
+               smbldap_make_mod(priv2ld(ldap_state), entry, &mods,
+                                LDAP_ATTRIBUTE_SECURITY_IDENTIFIER,
+                                sid_string_tos(&td->security_identifier));
+       }
+
+       if (td->trust_type != 0) {
+               res = smbldap_make_mod_uint32_t(priv2ld(ldap_state), entry,
+                                               &mods, LDAP_ATTRIBUTE_TRUST_TYPE,
+                                               td->trust_type);
+               if (!res) {
+                       return NT_STATUS_UNSUCCESSFUL;
+               }
+       }
+
+       if (td->trust_attributes != 0) {
+               res = smbldap_make_mod_uint32_t(priv2ld(ldap_state), entry,
+                                               &mods,
+                                               LDAP_ATTRIBUTE_TRUST_ATTRIBUTES,
+                                               td->trust_attributes);
+               if (!res) {
+                       return NT_STATUS_UNSUCCESSFUL;
+               }
+       }
+
+       if (td->trust_direction != 0) {
+               res = smbldap_make_mod_uint32_t(priv2ld(ldap_state), entry,
+                                               &mods,
+                                               LDAP_ATTRIBUTE_TRUST_DIRECTION,
+                                               td->trust_direction);
+               if (!res) {
+                       return NT_STATUS_UNSUCCESSFUL;
+               }
+       }
+
+       if (td->trust_auth_outgoing.data != NULL) {
+               res = smbldap_make_mod_blob(priv2ld(ldap_state), entry,
+                                           &mods,
+                                           LDAP_ATTRIBUTE_TRUST_AUTH_OUTGOING,
+                                           td->trust_auth_outgoing);
+               if (!res) {
+                       return NT_STATUS_UNSUCCESSFUL;
+               }
+       }
+
+       if (td->trust_auth_incoming.data != NULL) {
+               res = smbldap_make_mod_blob(priv2ld(ldap_state), entry,
+                                           &mods,
+                                           LDAP_ATTRIBUTE_TRUST_AUTH_INCOMING,
+                                           td->trust_auth_incoming);
+               if (!res) {
+                       return NT_STATUS_UNSUCCESSFUL;
+               }
+       }
+
+       talloc_autofree_ldapmod(talloc_tos(), mods);
+
+       trusted_dn = trusted_domain_dn(ldap_state, domain);
+       if (trusted_dn == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       if (entry == NULL) {
+               ret = smbldap_add(ldap_state->smbldap_state, trusted_dn, mods);
+       } else {
+               ret = smbldap_modify(ldap_state->smbldap_state, trusted_dn, mods);
+       }
+
+       if (ret != LDAP_SUCCESS) {
+               DEBUG(1, ("error writing trusted domain data!\n"));
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+       return NT_STATUS_OK;
+}
+
+static NTSTATUS ipasam_del_trusted_domain(struct pdb_methods *methods,
+                                         const char *domain)
+{
+       int ret;
+       struct ldapsam_privates *ldap_state =
+               (struct ldapsam_privates *)methods->private_data;
+       LDAPMessage *entry = NULL;
+       const char *dn;
+
+       if (!get_trusted_domain_int(ldap_state, talloc_tos(), domain, &entry)) {
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+
+       if (entry == NULL) {
+               DEBUG(5, ("ipasam_del_trusted_domain: no such trusted domain: "
+                         "%s\n", domain));
+               return NT_STATUS_NO_SUCH_DOMAIN;
+       }
+
+       dn = smbldap_talloc_dn(talloc_tos(), priv2ld(ldap_state), entry);
+       if (dn == NULL) {
+               DEBUG(0,("ipasam_del_trusted_domain: Out of memory!\n"));
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       ret = smbldap_delete(ldap_state->smbldap_state, dn);
+       if (ret != LDAP_SUCCESS) {
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+
+       return NT_STATUS_OK;
+}
+
 static NTSTATUS pdb_init_IPA_ldapsam(struct pdb_methods **pdb_method, const char *location)
 {
        struct ldapsam_privates *ldap_state;
@@ -69,6 +499,10 @@ static NTSTATUS pdb_init_IPA_ldapsam(struct pdb_methods **pdb_method, const char
        (*pdb_method)->del_trusteddom_pw = ipasam_del_trusteddom_pw;
        (*pdb_method)->enum_trusteddoms = ipasam_enum_trusteddoms;
 
+       (*pdb_method)->get_trusted_domain = ipasam_get_trusted_domain;
+       (*pdb_method)->set_trusted_domain = ipasam_set_trusted_domain;
+       (*pdb_method)->del_trusted_domain = ipasam_del_trusted_domain;
+
        return nt_status;
 }