summaryrefslogtreecommitdiff
path: root/source3/passdb/pdb_ipa.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/passdb/pdb_ipa.c')
-rw-r--r--source3/passdb/pdb_ipa.c434
1 files changed, 434 insertions, 0 deletions
diff --git a/source3/passdb/pdb_ipa.c b/source3/passdb/pdb_ipa.c
index 34eee5efa9..24513ccf8c 100644
--- a/source3/passdb/pdb_ipa.c
+++ b/source3/passdb/pdb_ipa.c
@@ -22,6 +22,17 @@
#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;
}