X-Git-Url: http://git.samba.org/?a=blobdiff_plain;f=source3%2Fpassdb%2Fpdb_ads.c;h=3ddf4f2dc0f1d65a8a0f1851e5a5de2e99389c82;hb=26225d3e798892b39b3c238b0bee465bffac6550;hp=9471f1ae712b3aa9294cf1a3cbbecacdfb99174d;hpb=275ca400db7a287a08288e2235b1deb929cea2a3;p=amitay%2Fsamba.git diff --git a/source3/passdb/pdb_ads.c b/source3/passdb/pdb_ads.c index 9471f1ae712..3ddf4f2dc0f 100644 --- a/source3/passdb/pdb_ads.c +++ b/source3/passdb/pdb_ads.c @@ -19,21 +19,42 @@ #include "includes.h" -static NTSTATUS pdb_ads_getsampwsid(struct pdb_methods *m, - struct samu *sam_acct, - const DOM_SID *sid); -static bool pdb_ads_gid_to_sid(struct pdb_methods *m, gid_t gid, - DOM_SID *sid); - - struct pdb_ads_state { + struct sockaddr_un socket_address; struct tldap_context *ld; struct dom_sid domainsid; + struct GUID domainguid; char *domaindn; char *configdn; char *netbiosname; }; +struct pdb_ads_samu_private { + char *dn; + struct tldap_message *ldapmsg; +}; + +static NTSTATUS pdb_ads_getsampwsid(struct pdb_methods *m, + struct samu *sam_acct, + const DOM_SID *sid); +static bool pdb_ads_gid_to_sid(struct pdb_methods *m, gid_t gid, + DOM_SID *sid); +static bool pdb_ads_dnblob2sid(struct pdb_ads_state *state, DATA_BLOB *dnblob, + struct dom_sid *psid); +static NTSTATUS pdb_ads_sid2dn(struct pdb_ads_state *state, + const struct dom_sid *sid, + TALLOC_CTX *mem_ctx, char **pdn); +static struct tldap_context *pdb_ads_ld(struct pdb_ads_state *state); +static int pdb_ads_search_fmt(struct pdb_ads_state *state, const char *base, + int scope, const char *attrs[], int num_attrs, + int attrsonly, + TALLOC_CTX *mem_ctx, struct tldap_message ***res, + const char *fmt, ...); +static NTSTATUS pdb_ads_getsamupriv(struct pdb_ads_state *state, + const char *filter, + TALLOC_CTX *mem_ctx, + struct pdb_ads_samu_private **presult); + static bool pdb_ads_pull_time(struct tldap_message *msg, const char *attr, time_t *ptime) { @@ -53,42 +74,73 @@ static gid_t pdb_ads_sid2gid(const struct dom_sid *sid) return rid; } -struct pdb_ads_samu_private { - char *dn; - struct tldap_message *ldapmsg; -}; +static char *pdb_ads_domaindn2dns(TALLOC_CTX *mem_ctx, char *dn) +{ + char *result, *p; + + result = talloc_string_sub2(mem_ctx, dn, "DC=", "", false, false, + true); + if (result == NULL) { + return NULL; + } + + while ((p = strchr_m(result, ',')) != NULL) { + *p = '.'; + } + + return result; +} -static struct samu *pdb_ads_init_guest(TALLOC_CTX *mem_ctx, - struct pdb_methods *m) +static struct pdb_domain_info *pdb_ads_get_domain_info( + struct pdb_methods *m, TALLOC_CTX *mem_ctx) { struct pdb_ads_state *state = talloc_get_type_abort( m->private_data, struct pdb_ads_state); - struct dom_sid guest_sid; - struct samu *guest; - NTSTATUS status; - - sid_compose(&guest_sid, &state->domainsid, DOMAIN_USER_RID_GUEST); + struct pdb_domain_info *info; + struct tldap_message *rootdse; + char *tmp; - guest = samu_new(mem_ctx); - if (guest == NULL) { + info = talloc(mem_ctx, struct pdb_domain_info); + if (info == NULL) { return NULL; } + info->name = talloc_strdup(info, state->netbiosname); + if (info->name == NULL) { + goto fail; + } + info->dns_domain = pdb_ads_domaindn2dns(info, state->domaindn); + if (info->dns_domain == NULL) { + goto fail; + } - status = pdb_ads_getsampwsid(m, guest, &guest_sid); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(10, ("Could not init guest account: %s\n", - nt_errstr(status))); - TALLOC_FREE(guest); - return NULL; + rootdse = tldap_rootdse(state->ld); + tmp = tldap_talloc_single_attribute(rootdse, "rootDomainNamingContext", + talloc_tos()); + if (tmp == NULL) { + goto fail; + } + info->dns_forest = pdb_ads_domaindn2dns(info, tmp); + TALLOC_FREE(tmp); + if (info->dns_forest == NULL) { + goto fail; } - return guest; + info->sid = state->domainsid; + info->guid = state->domainguid; + return info; + +fail: + TALLOC_FREE(info); + return NULL; } static struct pdb_ads_samu_private *pdb_ads_get_samu_private( struct pdb_methods *m, struct samu *sam) { + struct pdb_ads_state *state = talloc_get_type_abort( + m->private_data, struct pdb_ads_state); struct pdb_ads_samu_private *result; - uint32_t rid; + char *sidstr, *filter; + NTSTATUS status; result = (struct pdb_ads_samu_private *) pdb_get_backend_private_data(sam, m); @@ -98,63 +150,48 @@ static struct pdb_ads_samu_private *pdb_ads_get_samu_private( result, struct pdb_ads_samu_private); } - /* - * This is now a weirdness of the passdb API. For the guest user we - * are not asked first. - */ - sid_peek_rid(pdb_get_user_sid(sam), &rid); + sidstr = sid_binstring(talloc_tos(), pdb_get_user_sid(sam)); + if (sidstr == NULL) { + return NULL; + } - if (rid == DOMAIN_USER_RID_GUEST) { - struct samu *guest = pdb_ads_init_guest(talloc_tos(), m); + filter = talloc_asprintf( + talloc_tos(), "(&(objectsid=%s)(objectclass=user))", sidstr); + TALLOC_FREE(sidstr); + if (filter == NULL) { + return NULL; + } - if (guest == NULL) { - return NULL; - } - result = talloc_get_type_abort( - pdb_get_backend_private_data(guest, m), - struct pdb_ads_samu_private); - pdb_set_backend_private_data( - sam, talloc_move(sam, &result), NULL, m, PDB_SET); - TALLOC_FREE(guest); - return talloc_get_type_abort( - pdb_get_backend_private_data(sam, m), - struct pdb_ads_samu_private); + status = pdb_ads_getsamupriv(state, filter, sam, &result); + TALLOC_FREE(filter); + if (!NT_STATUS_IS_OK(status)) { + return NULL; } - return NULL; + return result; } -static NTSTATUS pdb_ads_init_sam_from_ads(struct pdb_methods *m, - struct samu *sam, - struct tldap_message *entry) +static NTSTATUS pdb_ads_init_sam_from_priv(struct pdb_methods *m, + struct samu *sam, + struct pdb_ads_samu_private *priv) { struct pdb_ads_state *state = talloc_get_type_abort( m->private_data, struct pdb_ads_state); TALLOC_CTX *frame = talloc_stackframe(); - struct pdb_ads_samu_private *priv; NTSTATUS status = NT_STATUS_INTERNAL_DB_CORRUPTION; + struct tldap_message *entry = priv->ldapmsg; char *str; time_t tmp_time; struct dom_sid sid; uint64_t n; DATA_BLOB blob; - priv = talloc(sam, struct pdb_ads_samu_private); - if (priv == NULL) { - return NT_STATUS_NO_MEMORY; - } - if (!tldap_entry_dn(entry, &priv->dn)) { - TALLOC_FREE(priv); - return NT_STATUS_INTERNAL_DB_CORRUPTION; - } - str = tldap_talloc_single_attribute(entry, "samAccountName", sam); if (str == NULL) { DEBUG(10, ("no samAccountName\n")); goto fail; } pdb_set_username(sam, str, PDB_SET); - TALLOC_FREE(str); if (pdb_ads_pull_time(entry, "lastLogon", &tmp_time)) { pdb_set_logon_time(sam, tmp_time, PDB_SET); @@ -166,13 +203,7 @@ static NTSTATUS pdb_ads_init_sam_from_ads(struct pdb_methods *m, pdb_set_pass_last_set_time(sam, tmp_time, PDB_SET); } if (pdb_ads_pull_time(entry, "accountExpires", &tmp_time)) { - pdb_set_pass_last_set_time(sam, tmp_time, PDB_SET); - } - - str = tldap_talloc_single_attribute(entry, "samAccoutName", - talloc_tos()); - if (str != NULL) { - pdb_set_username(sam, str, PDB_SET); + pdb_set_kickoff_time(sam, tmp_time, PDB_SET); } str = tldap_talloc_single_attribute(entry, "displayName", @@ -219,7 +250,7 @@ static NTSTATUS pdb_ads_init_sam_from_ads(struct pdb_methods *m, DEBUG(10, ("Could not pull userAccountControl\n")); goto fail; } - pdb_set_acct_ctrl(sam, ads_uf2acb(n), PDB_SET); + pdb_set_acct_ctrl(sam, ds_uf2acb(n), PDB_SET); if (tldap_get_single_valueblob(entry, "unicodePwd", &blob)) { if (blob.length != NT_HASH_LEN) { @@ -244,10 +275,6 @@ static NTSTATUS pdb_ads_init_sam_from_ads(struct pdb_methods *m, pdb_set_group_sid(sam, &sid, PDB_SET); } - - priv->ldapmsg = talloc_move(priv, &entry); - pdb_set_backend_private_data(sam, priv, NULL, m, PDB_SET); - status = NT_STATUS_OK; fail: TALLOC_FREE(frame); @@ -261,6 +288,7 @@ static bool pdb_ads_init_ads_from_sam(struct pdb_ads_state *state, struct samu *sam) { bool ret = true; + DATA_BLOB blob; /* TODO: All fields :-) */ @@ -268,21 +296,45 @@ static bool pdb_ads_init_ads_from_sam(struct pdb_ads_state *state, existing, mem_ctx, pnum_mods, pmods, "displayName", "%s", pdb_get_fullname(sam)); - ret &= tldap_make_mod_blob( - existing, mem_ctx, pnum_mods, pmods, "unicodePwd", - data_blob_const(pdb_get_nt_passwd(sam), NT_HASH_LEN)); + blob = data_blob_const(pdb_get_nt_passwd(sam), NT_HASH_LEN); + if (blob.data != NULL) { + ret &= tldap_add_mod_blobs(mem_ctx, pmods, TLDAP_MOD_REPLACE, + "unicodePwd", 1, &blob); + } + + blob = data_blob_const(pdb_get_lanman_passwd(sam), NT_HASH_LEN); + if (blob.data != NULL) { + ret &= tldap_add_mod_blobs(mem_ctx, pmods, TLDAP_MOD_REPLACE, + "dBCSPwd", 1, &blob); + } + + ret &= tldap_make_mod_fmt( + existing, mem_ctx, pnum_mods, pmods, "userAccountControl", + "%d", ds_acb2uf(pdb_get_acct_ctrl(sam))); + + ret &= tldap_make_mod_fmt( + existing, mem_ctx, pnum_mods, pmods, "homeDirectory", + "%s", pdb_get_homedir(sam)); - ret &= tldap_make_mod_blob( - existing, mem_ctx, pnum_mods, pmods, "dBCSPwd", - data_blob_const(pdb_get_lanman_passwd(sam), NT_HASH_LEN)); + ret &= tldap_make_mod_fmt( + existing, mem_ctx, pnum_mods, pmods, "homeDrive", + "%s", pdb_get_dir_drive(sam)); + + ret &= tldap_make_mod_fmt( + existing, mem_ctx, pnum_mods, pmods, "scriptPath", + "%s", pdb_get_logon_script(sam)); + + ret &= tldap_make_mod_fmt( + existing, mem_ctx, pnum_mods, pmods, "profilePath", + "%s", pdb_get_profile_path(sam)); return ret; } -static NTSTATUS pdb_ads_getsampwfilter(struct pdb_methods *m, - struct pdb_ads_state *state, - struct samu *sam_acct, - const char *filter) +static NTSTATUS pdb_ads_getsamupriv(struct pdb_ads_state *state, + const char *filter, + TALLOC_CTX *mem_ctx, + struct pdb_ads_samu_private **presult) { const char * attrs[] = { "lastLogon", "lastLogoff", "pwdLastSet", "accountExpires", @@ -294,23 +346,66 @@ static NTSTATUS pdb_ads_getsampwfilter(struct pdb_methods *m, "unicodePwd", "dBCSPwd" }; struct tldap_message **users; int rc, count; + struct pdb_ads_samu_private *result; - rc = tldap_search_fmt(state->ld, state->domaindn, TLDAP_SCOPE_SUB, - attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), - &users, "%s", filter); + result = talloc(mem_ctx, struct pdb_ads_samu_private); + if (result == NULL) { + return NT_STATUS_NO_MEMORY; + } + + rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB, + attrs, ARRAY_SIZE(attrs), 0, result, + &users, "%s", filter); if (rc != TLDAP_SUCCESS) { DEBUG(10, ("ldap_search failed %s\n", - tldap_errstr(debug_ctx(), state->ld, rc))); + tldap_errstr(talloc_tos(), state->ld, rc))); + TALLOC_FREE(result); return NT_STATUS_LDAP(rc); } count = talloc_array_length(users); if (count != 1) { DEBUG(10, ("Expected 1 user, got %d\n", count)); + TALLOC_FREE(result); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + result->ldapmsg = users[0]; + if (!tldap_entry_dn(result->ldapmsg, &result->dn)) { + DEBUG(10, ("Could not extract dn\n")); + TALLOC_FREE(result); return NT_STATUS_INTERNAL_DB_CORRUPTION; } - return pdb_ads_init_sam_from_ads(m, sam_acct, users[0]); + *presult = result; + return NT_STATUS_OK; +} + +static NTSTATUS pdb_ads_getsampwfilter(struct pdb_methods *m, + struct pdb_ads_state *state, + struct samu *sam_acct, + const char *filter) +{ + struct pdb_ads_samu_private *priv; + NTSTATUS status; + + status = pdb_ads_getsamupriv(state, filter, sam_acct, &priv); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("pdb_ads_getsamupriv failed: %s\n", + nt_errstr(status))); + return status; + } + + status = pdb_ads_init_sam_from_priv(m, sam_acct, priv); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("pdb_ads_init_sam_from_priv failed: %s\n", + nt_errstr(status))); + TALLOC_FREE(priv); + return status; + } + + pdb_set_backend_private_data(sam_acct, priv, NULL, m, PDB_SET); + return NT_STATUS_OK; } static NTSTATUS pdb_ads_getsampwnam(struct pdb_methods *m, @@ -355,6 +450,7 @@ static NTSTATUS pdb_ads_create_user(struct pdb_methods *m, { struct pdb_ads_state *state = talloc_get_type_abort( m->private_data, struct pdb_ads_state); + struct tldap_context *ld; const char *attrs[1] = { "objectSid" }; struct tldap_mod *mods = NULL; int num_mods = 0; @@ -370,6 +466,11 @@ static NTSTATUS pdb_ads_create_user(struct pdb_methods *m, return NT_STATUS_NO_MEMORY; } + ld = pdb_ads_ld(state); + if (ld == NULL) { + return NT_STATUS_LDAP(TLDAP_SERVER_DOWN); + } + /* TODO: Create machines etc */ ok = true; @@ -382,21 +483,23 @@ static NTSTATUS pdb_ads_create_user(struct pdb_methods *m, return NT_STATUS_NO_MEMORY; } - rc = tldap_add(state->ld, dn, num_mods, mods, NULL, NULL); + + rc = tldap_add(ld, dn, num_mods, mods, NULL, 0, NULL, 0); if (rc != TLDAP_SUCCESS) { DEBUG(10, ("ldap_add failed %s\n", - tldap_errstr(debug_ctx(), state->ld, rc))); + tldap_errstr(talloc_tos(), ld, rc))); TALLOC_FREE(dn); return NT_STATUS_LDAP(rc); } - rc = tldap_search_fmt(state->ld, state->domaindn, TLDAP_SCOPE_SUB, - attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &user, - "(&(objectclass=user)(samaccountname=%s))", - name); + rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB, + attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), + &user, + "(&(objectclass=user)(samaccountname=%s))", + name); if (rc != TLDAP_SUCCESS) { DEBUG(10, ("Could not find just created user %s: %s\n", - name, tldap_errstr(debug_ctx(), state->ld, rc))); + name, tldap_errstr(talloc_tos(), state->ld, rc))); TALLOC_FREE(dn); return NT_STATUS_LDAP(rc); } @@ -426,13 +529,27 @@ static NTSTATUS pdb_ads_delete_user(struct pdb_methods *m, { struct pdb_ads_state *state = talloc_get_type_abort( m->private_data, struct pdb_ads_state); - struct pdb_ads_samu_private *priv = pdb_ads_get_samu_private(m, sam); + NTSTATUS status; + struct tldap_context *ld; + char *dn; int rc; - rc = tldap_delete(state->ld, priv->dn, NULL, NULL); + ld = pdb_ads_ld(state); + if (ld == NULL) { + return NT_STATUS_LDAP(TLDAP_SERVER_DOWN); + } + + status = pdb_ads_sid2dn(state, pdb_get_user_sid(sam), talloc_tos(), + &dn); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + rc = tldap_delete(ld, dn, NULL, 0, NULL, 0); + TALLOC_FREE(dn); if (rc != TLDAP_SUCCESS) { - DEBUG(10, ("ldap_delete for %s failed: %s\n", priv->dn, - tldap_errstr(debug_ctx(), state->ld, rc))); + DEBUG(10, ("ldap_delete for %s failed: %s\n", dn, + tldap_errstr(talloc_tos(), ld, rc))); return NT_STATUS_LDAP(rc); } return NT_STATUS_OK; @@ -450,23 +567,34 @@ static NTSTATUS pdb_ads_update_sam_account(struct pdb_methods *m, struct pdb_ads_state *state = talloc_get_type_abort( m->private_data, struct pdb_ads_state); struct pdb_ads_samu_private *priv = pdb_ads_get_samu_private(m, sam); + struct tldap_context *ld; struct tldap_mod *mods = NULL; int rc, num_mods = 0; + ld = pdb_ads_ld(state); + if (ld == NULL) { + return NT_STATUS_LDAP(TLDAP_SERVER_DOWN); + } + if (!pdb_ads_init_ads_from_sam(state, priv->ldapmsg, talloc_tos(), &num_mods, &mods, sam)) { return NT_STATUS_NO_MEMORY; } - rc = tldap_modify(state->ld, priv->dn, num_mods, mods, NULL, NULL); + if (num_mods == 0) { + /* Nothing to do, just return success */ + return NT_STATUS_OK; + } + + rc = tldap_modify(ld, priv->dn, num_mods, mods, NULL, 0, + NULL, 0); + TALLOC_FREE(mods); if (rc != TLDAP_SUCCESS) { DEBUG(10, ("ldap_modify for %s failed: %s\n", priv->dn, - tldap_errstr(debug_ctx(), state->ld, rc))); + tldap_errstr(talloc_tos(), ld, rc))); return NT_STATUS_LDAP(rc); } - TALLOC_FREE(mods); - return NT_STATUS_OK; } @@ -502,17 +630,17 @@ static NTSTATUS pdb_ads_getgrfilter(struct pdb_methods *m, GROUP_MAP *map, uint32_t grouptype; int rc; - rc = tldap_search_fmt(state->ld, state->domaindn, TLDAP_SCOPE_SUB, - attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), - &group, "%s", filter); + rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB, + attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), + &group, "%s", filter); if (rc != TLDAP_SUCCESS) { DEBUG(10, ("ldap_search failed %s\n", - tldap_errstr(debug_ctx(), state->ld, rc))); + tldap_errstr(talloc_tos(), state->ld, rc))); return NT_STATUS_LDAP(rc); } if (talloc_array_length(group) != 1) { DEBUG(10, ("Expected 1 user, got %d\n", - talloc_array_length(group))); + (int)talloc_array_length(group))); return NT_STATUS_INTERNAL_DB_CORRUPTION; } @@ -608,6 +736,7 @@ static NTSTATUS pdb_ads_create_dom_group(struct pdb_methods *m, TALLOC_CTX *frame = talloc_stackframe(); struct pdb_ads_state *state = talloc_get_type_abort( m->private_data, struct pdb_ads_state); + struct tldap_context *ld; const char *attrs[1] = { "objectSid" }; int num_mods = 0; struct tldap_mod *mods = NULL; @@ -617,6 +746,11 @@ static NTSTATUS pdb_ads_create_dom_group(struct pdb_methods *m, int rc; bool ok = true; + ld = pdb_ads_ld(state); + if (ld == NULL) { + return NT_STATUS_LDAP(TLDAP_SERVER_DOWN); + } + dn = talloc_asprintf(talloc_tos(), "cn=%s,cn=users,%s", name, state->domaindn); if (dn == NULL) { @@ -638,21 +772,21 @@ static NTSTATUS pdb_ads_create_dom_group(struct pdb_methods *m, return NT_STATUS_NO_MEMORY; } - rc = tldap_add(state->ld, dn, num_mods, mods, NULL, NULL); + rc = tldap_add(ld, dn, num_mods, mods, NULL, 0, NULL, 0); if (rc != TLDAP_SUCCESS) { DEBUG(10, ("ldap_add failed %s\n", - tldap_errstr(debug_ctx(), state->ld, rc))); + tldap_errstr(talloc_tos(), state->ld, rc))); TALLOC_FREE(frame); return NT_STATUS_LDAP(rc); } - rc = tldap_search_fmt( - state->ld, state->domaindn, TLDAP_SCOPE_SUB, + rc = pdb_ads_search_fmt( + state, state->domaindn, TLDAP_SCOPE_SUB, attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &alias, "(&(objectclass=group)(samaccountname=%s))", name); if (rc != TLDAP_SUCCESS) { DEBUG(10, ("Could not find just created alias %s: %s\n", - name, tldap_errstr(debug_ctx(), state->ld, rc))); + name, tldap_errstr(talloc_tos(), state->ld, rc))); TALLOC_FREE(frame); return NT_STATUS_LDAP(rc); } @@ -679,7 +813,60 @@ static NTSTATUS pdb_ads_create_dom_group(struct pdb_methods *m, static NTSTATUS pdb_ads_delete_dom_group(struct pdb_methods *m, TALLOC_CTX *mem_ctx, uint32 rid) { - return NT_STATUS_NOT_IMPLEMENTED; + struct pdb_ads_state *state = talloc_get_type_abort( + m->private_data, struct pdb_ads_state); + struct tldap_context *ld; + struct dom_sid sid; + char *sidstr; + struct tldap_message **msg; + char *dn; + int rc; + + sid_compose(&sid, &state->domainsid, rid); + + sidstr = sid_binstring(talloc_tos(), &sid); + NT_STATUS_HAVE_NO_MEMORY(sidstr); + + rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB, + NULL, 0, 0, talloc_tos(), &msg, + ("(&(objectSid=%s)(objectClass=group))"), + sidstr); + TALLOC_FREE(sidstr); + if (rc != TLDAP_SUCCESS) { + DEBUG(10, ("ldap_search failed %s\n", + tldap_errstr(talloc_tos(), state->ld, rc))); + return NT_STATUS_LDAP(rc); + } + + switch talloc_array_length(msg) { + case 0: + return NT_STATUS_NO_SUCH_GROUP; + case 1: + break; + default: + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + if (!tldap_entry_dn(msg[0], &dn)) { + TALLOC_FREE(msg); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + ld = pdb_ads_ld(state); + if (ld == NULL) { + TALLOC_FREE(msg); + return NT_STATUS_LDAP(TLDAP_SERVER_DOWN); + } + + rc = tldap_delete(ld, dn, NULL, 0, NULL, 0); + TALLOC_FREE(msg); + if (rc != TLDAP_SUCCESS) { + DEBUG(10, ("ldap_delete failed: %s\n", + tldap_errstr(talloc_tos(), state->ld, rc))); + return NT_STATUS_LDAP(rc); + } + + return NT_STATUS_OK; } static NTSTATUS pdb_ads_add_group_mapping_entry(struct pdb_methods *m, @@ -713,10 +900,62 @@ static NTSTATUS pdb_ads_enum_group_mapping(struct pdb_methods *m, static NTSTATUS pdb_ads_enum_group_members(struct pdb_methods *m, TALLOC_CTX *mem_ctx, const DOM_SID *group, - uint32 **pp_member_rids, - size_t *p_num_members) + uint32 **pmembers, + size_t *pnum_members) { - return NT_STATUS_NOT_IMPLEMENTED; + struct pdb_ads_state *state = talloc_get_type_abort( + m->private_data, struct pdb_ads_state); + const char *attrs[1] = { "member" }; + char *sidstr; + struct tldap_message **msg; + int i, rc, num_members; + DATA_BLOB *blobs; + uint32_t *members; + + sidstr = sid_binstring(talloc_tos(), group); + NT_STATUS_HAVE_NO_MEMORY(sidstr); + + rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB, + attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), + &msg, "(objectsid=%s)", sidstr); + TALLOC_FREE(sidstr); + if (rc != TLDAP_SUCCESS) { + DEBUG(10, ("ldap_search failed %s\n", + tldap_errstr(talloc_tos(), state->ld, rc))); + return NT_STATUS_LDAP(rc); + } + switch talloc_array_length(msg) { + case 0: + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + break; + case 1: + break; + default: + return NT_STATUS_INTERNAL_DB_CORRUPTION; + break; + } + + if (!tldap_entry_values(msg[0], "member", &num_members, &blobs)) { + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + members = talloc_array(mem_ctx, uint32_t, num_members); + if (members == NULL) { + return NT_STATUS_NO_MEMORY; + } + + for (i=0; ild, state->domaindn, TLDAP_SCOPE_SUB, + rc = pdb_ads_search_fmt( + state, state->domaindn, TLDAP_SCOPE_SUB, attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &groups, "(&(member=%s)(grouptype=%d)(objectclass=group))", priv->dn, GTYPE_SECURITY_GLOBAL_GROUP); if (rc != TLDAP_SUCCESS) { DEBUG(10, ("ldap_search failed %s\n", - tldap_errstr(debug_ctx(), state->ld, rc))); + tldap_errstr(talloc_tos(), state->ld, rc))); return NT_STATUS_LDAP(rc); } @@ -787,18 +1026,79 @@ static NTSTATUS pdb_ads_set_unix_primary_group(struct pdb_methods *m, return NT_STATUS_NOT_IMPLEMENTED; } +static NTSTATUS pdb_ads_mod_groupmem(struct pdb_methods *m, + TALLOC_CTX *mem_ctx, + uint32 grouprid, uint32 memberrid, + int mod_op) +{ + struct pdb_ads_state *state = talloc_get_type_abort( + m->private_data, struct pdb_ads_state); + TALLOC_CTX *frame = talloc_stackframe(); + struct tldap_context *ld; + struct dom_sid groupsid, membersid; + char *groupdn, *memberdn; + struct tldap_mod *mods; + int rc; + NTSTATUS status; + + ld = pdb_ads_ld(state); + if (ld == NULL) { + return NT_STATUS_LDAP(TLDAP_SERVER_DOWN); + } + + sid_compose(&groupsid, &state->domainsid, grouprid); + sid_compose(&membersid, &state->domainsid, memberrid); + + status = pdb_ads_sid2dn(state, &groupsid, talloc_tos(), &groupdn); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); + return NT_STATUS_NO_SUCH_GROUP; + } + status = pdb_ads_sid2dn(state, &membersid, talloc_tos(), &memberdn); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); + return NT_STATUS_NO_SUCH_USER; + } + + mods = NULL; + + if (!tldap_add_mod_str(talloc_tos(), &mods, mod_op, + "member", memberdn)) { + TALLOC_FREE(frame); + return NT_STATUS_NO_MEMORY; + } + + rc = tldap_modify(ld, groupdn, 1, mods, NULL, 0, NULL, 0); + TALLOC_FREE(frame); + if (rc != TLDAP_SUCCESS) { + DEBUG(10, ("ldap_modify failed: %s\n", + tldap_errstr(talloc_tos(), state->ld, rc))); + if (rc == TLDAP_TYPE_OR_VALUE_EXISTS) { + return NT_STATUS_MEMBER_IN_GROUP; + } + if (rc == TLDAP_NO_SUCH_ATTRIBUTE) { + return NT_STATUS_MEMBER_NOT_IN_GROUP; + } + return NT_STATUS_LDAP(rc); + } + + return NT_STATUS_OK; +} + static NTSTATUS pdb_ads_add_groupmem(struct pdb_methods *m, TALLOC_CTX *mem_ctx, uint32 group_rid, uint32 member_rid) { - return NT_STATUS_NOT_IMPLEMENTED; + return pdb_ads_mod_groupmem(m, mem_ctx, group_rid, member_rid, + TLDAP_MOD_ADD); } static NTSTATUS pdb_ads_del_groupmem(struct pdb_methods *m, TALLOC_CTX *mem_ctx, uint32 group_rid, uint32 member_rid) { - return NT_STATUS_NOT_IMPLEMENTED; + return pdb_ads_mod_groupmem(m, mem_ctx, group_rid, member_rid, + TLDAP_MOD_DELETE); } static NTSTATUS pdb_ads_create_alias(struct pdb_methods *m, @@ -807,6 +1107,7 @@ static NTSTATUS pdb_ads_create_alias(struct pdb_methods *m, TALLOC_CTX *frame = talloc_stackframe(); struct pdb_ads_state *state = talloc_get_type_abort( m->private_data, struct pdb_ads_state); + struct tldap_context *ld; const char *attrs[1] = { "objectSid" }; int num_mods = 0; struct tldap_mod *mods = NULL; @@ -816,6 +1117,11 @@ static NTSTATUS pdb_ads_create_alias(struct pdb_methods *m, int rc; bool ok = true; + ld = pdb_ads_ld(state); + if (ld == NULL) { + return NT_STATUS_LDAP(TLDAP_SERVER_DOWN); + } + dn = talloc_asprintf(talloc_tos(), "cn=%s,cn=users,%s", name, state->domaindn); if (dn == NULL) { @@ -837,21 +1143,21 @@ static NTSTATUS pdb_ads_create_alias(struct pdb_methods *m, return NT_STATUS_NO_MEMORY; } - rc = tldap_add(state->ld, dn, num_mods, mods, NULL, NULL); + rc = tldap_add(ld, dn, num_mods, mods, NULL, 0, NULL, 0); if (rc != TLDAP_SUCCESS) { DEBUG(10, ("ldap_add failed %s\n", - tldap_errstr(debug_ctx(), state->ld, rc))); + tldap_errstr(talloc_tos(), state->ld, rc))); TALLOC_FREE(frame); return NT_STATUS_LDAP(rc); } - rc = tldap_search_fmt( - state->ld, state->domaindn, TLDAP_SCOPE_SUB, + rc = pdb_ads_search_fmt( + state, state->domaindn, TLDAP_SCOPE_SUB, attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &alias, "(&(objectclass=group)(samaccountname=%s))", name); if (rc != TLDAP_SUCCESS) { DEBUG(10, ("Could not find just created alias %s: %s\n", - name, tldap_errstr(debug_ctx(), state->ld, rc))); + name, tldap_errstr(talloc_tos(), state->ld, rc))); TALLOC_FREE(frame); return NT_STATUS_LDAP(rc); } @@ -880,31 +1186,37 @@ static NTSTATUS pdb_ads_delete_alias(struct pdb_methods *m, { struct pdb_ads_state *state = talloc_get_type_abort( m->private_data, struct pdb_ads_state); + struct tldap_context *ld; struct tldap_message **alias; char *sidstr, *dn; int rc; + ld = pdb_ads_ld(state); + if (ld == NULL) { + return NT_STATUS_LDAP(TLDAP_SERVER_DOWN); + } + sidstr = sid_binstring(talloc_tos(), sid); if (sidstr == NULL) { return NT_STATUS_NO_MEMORY; } - rc = tldap_search_fmt(state->ld, state->domaindn, TLDAP_SCOPE_SUB, - NULL, 0, 0, talloc_tos(), &alias, - "(&(objectSid=%s)(objectclass=group)" - "(|(grouptype=%d)(grouptype=%d)))", - sidstr, GTYPE_SECURITY_BUILTIN_LOCAL_GROUP, - GTYPE_SECURITY_DOMAIN_LOCAL_GROUP); + rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB, + NULL, 0, 0, talloc_tos(), &alias, + "(&(objectSid=%s)(objectclass=group)" + "(|(grouptype=%d)(grouptype=%d)))", + sidstr, GTYPE_SECURITY_BUILTIN_LOCAL_GROUP, + GTYPE_SECURITY_DOMAIN_LOCAL_GROUP); TALLOC_FREE(sidstr); if (rc != TLDAP_SUCCESS) { DEBUG(10, ("ldap_search failed: %s\n", - tldap_errstr(debug_ctx(), state->ld, rc))); + tldap_errstr(talloc_tos(), state->ld, rc))); TALLOC_FREE(dn); return NT_STATUS_LDAP(rc); } if (talloc_array_length(alias) != 1) { DEBUG(10, ("Expected 1 alias, got %d\n", - talloc_array_length(alias))); + (int)talloc_array_length(alias))); return NT_STATUS_INTERNAL_DB_CORRUPTION; } if (!tldap_entry_dn(alias[0], &dn)) { @@ -913,10 +1225,10 @@ static NTSTATUS pdb_ads_delete_alias(struct pdb_methods *m, return NT_STATUS_INTERNAL_ERROR; } - rc = tldap_delete(state->ld, dn, NULL, NULL); + rc = tldap_delete(ld, dn, NULL, 0, NULL, 0); if (rc != TLDAP_SUCCESS) { DEBUG(10, ("ldap_delete failed: %s\n", - tldap_errstr(debug_ctx(), state->ld, rc))); + tldap_errstr(talloc_tos(), state->ld, rc))); TALLOC_FREE(dn); return NT_STATUS_LDAP(rc); } @@ -924,18 +1236,84 @@ static NTSTATUS pdb_ads_delete_alias(struct pdb_methods *m, return NT_STATUS_OK; } -static NTSTATUS pdb_ads_get_aliasinfo(struct pdb_methods *m, - const DOM_SID *sid, - struct acct_info *info) -{ - return NT_STATUS_NOT_IMPLEMENTED; -} - static NTSTATUS pdb_ads_set_aliasinfo(struct pdb_methods *m, const DOM_SID *sid, struct acct_info *info) { - return NT_STATUS_NOT_IMPLEMENTED; + struct pdb_ads_state *state = talloc_get_type_abort( + m->private_data, struct pdb_ads_state); + struct tldap_context *ld; + const char *attrs[3] = { "objectSid", "description", + "samAccountName" }; + struct tldap_message **msg; + char *sidstr, *dn; + int rc; + struct tldap_mod *mods; + int num_mods; + bool ok; + + ld = pdb_ads_ld(state); + if (ld == NULL) { + return NT_STATUS_LDAP(TLDAP_SERVER_DOWN); + } + + sidstr = sid_binstring(talloc_tos(), sid); + NT_STATUS_HAVE_NO_MEMORY(sidstr); + + rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB, + attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), + &msg, "(&(objectSid=%s)(objectclass=group)" + "(|(grouptype=%d)(grouptype=%d)))", + sidstr, GTYPE_SECURITY_BUILTIN_LOCAL_GROUP, + GTYPE_SECURITY_DOMAIN_LOCAL_GROUP); + TALLOC_FREE(sidstr); + if (rc != TLDAP_SUCCESS) { + DEBUG(10, ("ldap_search failed %s\n", + tldap_errstr(talloc_tos(), state->ld, rc))); + return NT_STATUS_LDAP(rc); + } + switch talloc_array_length(msg) { + case 0: + return NT_STATUS_NO_SUCH_ALIAS; + case 1: + break; + default: + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + if (!tldap_entry_dn(msg[0], &dn)) { + TALLOC_FREE(msg); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + mods = NULL; + num_mods = 0; + ok = true; + + ok &= tldap_make_mod_fmt( + msg[0], msg, &num_mods, &mods, "description", + "%s", info->acct_desc); + ok &= tldap_make_mod_fmt( + msg[0], msg, &num_mods, &mods, "samAccountName", + "%s", info->acct_name); + if (!ok) { + TALLOC_FREE(msg); + return NT_STATUS_NO_MEMORY; + } + if (num_mods == 0) { + /* no change */ + TALLOC_FREE(msg); + return NT_STATUS_OK; + } + + rc = tldap_modify(ld, dn, num_mods, mods, NULL, 0, NULL, 0); + TALLOC_FREE(msg); + if (rc != TLDAP_SUCCESS) { + DEBUG(10, ("ldap_modify failed: %s\n", + tldap_errstr(talloc_tos(), state->ld, rc))); + return NT_STATUS_LDAP(rc); + } + return NT_STATUS_OK; } static NTSTATUS pdb_ads_sid2dn(struct pdb_ads_state *state, @@ -949,13 +1327,13 @@ static NTSTATUS pdb_ads_sid2dn(struct pdb_ads_state *state, sidstr = sid_binstring(talloc_tos(), sid); NT_STATUS_HAVE_NO_MEMORY(sidstr); - rc = tldap_search_fmt(state->ld, state->domaindn, TLDAP_SCOPE_SUB, - NULL, 0, 0, talloc_tos(), &msg, - "(objectsid=%s)", sidstr); + rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB, + NULL, 0, 0, talloc_tos(), &msg, + "(objectsid=%s)", sidstr); TALLOC_FREE(sidstr); if (rc != TLDAP_SUCCESS) { DEBUG(10, ("ldap_search failed %s\n", - tldap_errstr(debug_ctx(), state->ld, rc))); + tldap_errstr(talloc_tos(), state->ld, rc))); return NT_STATUS_LDAP(rc); } @@ -989,12 +1367,18 @@ static NTSTATUS pdb_ads_mod_aliasmem(struct pdb_methods *m, { struct pdb_ads_state *state = talloc_get_type_abort( m->private_data, struct pdb_ads_state); + struct tldap_context *ld; TALLOC_CTX *frame = talloc_stackframe(); struct tldap_mod *mods; int rc; char *aliasdn, *memberdn; NTSTATUS status; + ld = pdb_ads_ld(state); + if (ld == NULL) { + return NT_STATUS_LDAP(TLDAP_SERVER_DOWN); + } + status = pdb_ads_sid2dn(state, alias, talloc_tos(), &aliasdn); if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("pdb_ads_sid2dn (%s) failed: %s\n", @@ -1018,11 +1402,11 @@ static NTSTATUS pdb_ads_mod_aliasmem(struct pdb_methods *m, return NT_STATUS_NO_MEMORY; } - rc = tldap_modify(state->ld, aliasdn, 1, mods, NULL, NULL); + rc = tldap_modify(ld, aliasdn, 1, mods, NULL, 0, NULL, 0); TALLOC_FREE(frame); if (rc != TLDAP_SUCCESS) { DEBUG(10, ("ldap_modify failed: %s\n", - tldap_errstr(debug_ctx(), state->ld, rc))); + tldap_errstr(talloc_tos(), state->ld, rc))); if (rc == TLDAP_TYPE_OR_VALUE_EXISTS) { return NT_STATUS_MEMBER_IN_ALIAS; } @@ -1049,7 +1433,7 @@ static NTSTATUS pdb_ads_del_aliasmem(struct pdb_methods *m, return pdb_ads_mod_aliasmem(m, alias, member, TLDAP_MOD_DELETE); } -static bool pdb_ads_dnblob2sid(struct tldap_context *ld, DATA_BLOB *dnblob, +static bool pdb_ads_dnblob2sid(struct pdb_ads_state *state, DATA_BLOB *dnblob, struct dom_sid *psid) { const char *attrs[1] = { "objectSid" }; @@ -1064,9 +1448,9 @@ static bool pdb_ads_dnblob2sid(struct tldap_context *ld, DATA_BLOB *dnblob, false)) { return false; } - rc = tldap_search_fmt(ld, dn, TLDAP_SCOPE_BASE, - attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), - &msg, "(objectclass=*)"); + rc = pdb_ads_search_fmt(state, dn, TLDAP_SCOPE_BASE, + attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), + &msg, "(objectclass=*)"); TALLOC_FREE(dn); if (talloc_array_length(msg) != 1) { DEBUG(10, ("Got %d objects, expected one\n", @@ -1098,13 +1482,13 @@ static NTSTATUS pdb_ads_enum_aliasmem(struct pdb_methods *m, sidstr = sid_binstring(talloc_tos(), alias); NT_STATUS_HAVE_NO_MEMORY(sidstr); - rc = tldap_search_fmt(state->ld, state->domaindn, TLDAP_SCOPE_SUB, - attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &msg, - "(objectsid=%s)", sidstr); + rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB, + attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), + &msg, "(objectsid=%s)", sidstr); TALLOC_FREE(sidstr); if (rc != TLDAP_SUCCESS) { DEBUG(10, ("ldap_search failed %s\n", - tldap_errstr(debug_ctx(), state->ld, rc))); + tldap_errstr(talloc_tos(), state->ld, rc))); return NT_STATUS_LDAP(rc); } switch talloc_array_length(msg) { @@ -1128,7 +1512,7 @@ static NTSTATUS pdb_ads_enum_aliasmem(struct pdb_methods *m, } for (i=0; ild, &blobs[i], &members[i])) { + if (!pdb_ads_dnblob2sid(state, &blobs[i], &members[i])) { TALLOC_FREE(members); return NT_STATUS_INTERNAL_DB_CORRUPTION; } @@ -1144,20 +1528,171 @@ static NTSTATUS pdb_ads_enum_alias_memberships(struct pdb_methods *m, const DOM_SID *domain_sid, const DOM_SID *members, size_t num_members, - uint32 **pp_alias_rids, - size_t *p_num_alias_rids) + uint32_t **palias_rids, + size_t *pnum_alias_rids) { - return NT_STATUS_NOT_IMPLEMENTED; + struct pdb_ads_state *state = talloc_get_type_abort( + m->private_data, struct pdb_ads_state); + const char *attrs[1] = { "objectSid" }; + struct tldap_message **msg; + uint32_t *alias_rids = NULL; + size_t num_alias_rids = 0; + int i, rc, count; + bool got_members = false; + char *filter; + NTSTATUS status; + + /* + * TODO: Get the filter right so that we only get the aliases from + * either the SAM or BUILTIN + */ + + filter = talloc_asprintf(talloc_tos(), + "(&(|(grouptype=%d)(grouptype=%d))" + "(objectclass=group)(|", + GTYPE_SECURITY_BUILTIN_LOCAL_GROUP, + GTYPE_SECURITY_DOMAIN_LOCAL_GROUP); + if (filter == NULL) { + return NT_STATUS_NO_MEMORY; + } + + for (i=0; idomaindn, TLDAP_SCOPE_SUB, + attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), + &msg, "%s))", filter); + TALLOC_FREE(filter); + if (rc != TLDAP_SUCCESS) { + DEBUG(10, ("tldap_search failed %s\n", + tldap_errstr(talloc_tos(), state->ld, rc))); + return NT_STATUS_LDAP(rc); + } + + count = talloc_array_length(msg); + if (count == 0) { + goto done; + } + + alias_rids = talloc_array(mem_ctx, uint32_t, count); + if (alias_rids == NULL) { + TALLOC_FREE(msg); + return NT_STATUS_NO_MEMORY; + } + + for (i=0; iprivate_data, struct pdb_ads_state); + const char *attrs[2] = { "sAMAccountType", "sAMAccountName" }; + int i, num_mapped; + + if (num_rids == 0) { + return NT_STATUS_NONE_MAPPED; + } + + num_mapped = 0; + + for (i=0; idomaindn, + TLDAP_SCOPE_SUB, attrs, + ARRAY_SIZE(attrs), 0, talloc_tos(), + &msg, "(objectsid=%s)", sidstr); + TALLOC_FREE(sidstr); + if (rc != TLDAP_SUCCESS) { + DEBUG(10, ("ldap_search failed %s\n", + tldap_errstr(talloc_tos(), state->ld, rc))); + continue; + } + + switch talloc_array_length(msg) { + case 0: + DEBUG(10, ("rid %d not found\n", (int)rids[i])); + continue; + case 1: + break; + default: + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + names[i] = tldap_talloc_single_attribute( + msg[0], "samAccountName", talloc_tos()); + if (names[i] == NULL) { + DEBUG(10, ("no samAccountName\n")); + continue; + } + if (!tldap_pull_uint32(msg[0], "samAccountType", &attr)) { + DEBUG(10, ("no samAccountType")); + continue; + } + lsa_attrs[i] = ds_atype_map(attr); + num_mapped += 1; + } + + if (num_mapped == 0) { + return NT_STATUS_NONE_MAPPED; + } + if (num_mapped < num_rids) { + return STATUS_SOME_UNMAPPED; + } + return NT_STATUS_OK; } static NTSTATUS pdb_ads_lookup_names(struct pdb_methods *m, @@ -1171,16 +1706,18 @@ static NTSTATUS pdb_ads_lookup_names(struct pdb_methods *m, } static NTSTATUS pdb_ads_get_account_policy(struct pdb_methods *m, - int policy_index, uint32 *value) + enum pdb_policy_type type, + uint32_t *value) { - return account_policy_get(policy_index, value) + return account_policy_get(type, value) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; } static NTSTATUS pdb_ads_set_account_policy(struct pdb_methods *m, - int policy_index, uint32 value) + enum pdb_policy_type type, + uint32_t value) { - return account_policy_set(policy_index, value) + return account_policy_set(type, value) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; } @@ -1254,13 +1791,13 @@ static bool pdb_ads_search_filter(struct pdb_methods *m, return false; } - rc = tldap_search_fmt( - state->ld, state->domaindn, TLDAP_SCOPE_SUB, + rc = pdb_ads_search_fmt( + state, state->domaindn, TLDAP_SCOPE_SUB, attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &users, "%s", filter); if (rc != TLDAP_SUCCESS) { DEBUG(10, ("ldap_search_ext_s failed: %s\n", - tldap_errstr(debug_ctx(), state->ld, rc))); + tldap_errstr(talloc_tos(), state->ld, rc))); return false; } @@ -1380,12 +1917,6 @@ static bool pdb_ads_search_aliases(struct pdb_methods *m, return true; } -static bool pdb_ads_uid_to_rid(struct pdb_methods *m, uid_t uid, - uint32 *rid) -{ - return false; -} - static bool pdb_ads_uid_to_sid(struct pdb_methods *m, uid_t uid, DOM_SID *sid) { @@ -1425,8 +1956,8 @@ static bool pdb_ads_sid_to_id(struct pdb_methods *m, const DOM_SID *sid, return false; } - rc = tldap_search_fmt( - state->ld, state->domaindn, TLDAP_SCOPE_SUB, + rc = pdb_ads_search_fmt( + state, state->domaindn, TLDAP_SCOPE_SUB, NULL, 0, 0, talloc_tos(), &msg, "(&(objectsid=%s)(objectclass=user))", sidstr); if ((rc == TLDAP_SUCCESS) && (talloc_array_length(msg) > 0)) { @@ -1436,8 +1967,8 @@ static bool pdb_ads_sid_to_id(struct pdb_methods *m, const DOM_SID *sid, return true; } - rc = tldap_search_fmt( - state->ld, state->domaindn, TLDAP_SCOPE_SUB, + rc = pdb_ads_search_fmt( + state, state->domaindn, TLDAP_SCOPE_SUB, NULL, 0, 0, talloc_tos(), &msg, "(&(objectsid=%s)(objectclass=group))", sidstr); if ((rc == TLDAP_SUCCESS) && (talloc_array_length(msg) > 0)) { @@ -1451,9 +1982,9 @@ static bool pdb_ads_sid_to_id(struct pdb_methods *m, const DOM_SID *sid, return false; } -static bool pdb_ads_rid_algorithm(struct pdb_methods *m) +static uint32_t pdb_ads_capabilities(struct pdb_methods *m) { - return false; + return PDB_CAP_STORE_RIDS | PDB_CAP_ADS; } static bool pdb_ads_new_rid(struct pdb_methods *m, uint32 *rid) @@ -1487,12 +2018,15 @@ static NTSTATUS pdb_ads_enum_trusteddoms(struct pdb_methods *m, uint32 *num_domains, struct trustdom_info ***domains) { - return NT_STATUS_NOT_IMPLEMENTED; + *num_domains = 0; + *domains = NULL; + return NT_STATUS_OK; } static void pdb_ads_init_methods(struct pdb_methods *m) { m->name = "ads"; + m->get_domain_info = pdb_ads_get_domain_info; m->getsampwnam = pdb_ads_getsampwnam; m->getsampwsid = pdb_ads_getsampwsid; m->create_user = pdb_ads_create_user; @@ -1518,7 +2052,7 @@ static void pdb_ads_init_methods(struct pdb_methods *m) m->del_groupmem = pdb_ads_del_groupmem; m->create_alias = pdb_ads_create_alias; m->delete_alias = pdb_ads_delete_alias; - m->get_aliasinfo = pdb_ads_get_aliasinfo; + m->get_aliasinfo = pdb_default_get_aliasinfo; m->set_aliasinfo = pdb_ads_set_aliasinfo; m->add_aliasmem = pdb_ads_add_aliasmem; m->del_aliasmem = pdb_ads_del_aliasmem; @@ -1532,11 +2066,10 @@ static void pdb_ads_init_methods(struct pdb_methods *m) m->search_users = pdb_ads_search_users; m->search_groups = pdb_ads_search_groups; m->search_aliases = pdb_ads_search_aliases; - m->uid_to_rid = pdb_ads_uid_to_rid; m->uid_to_sid = pdb_ads_uid_to_sid; m->gid_to_sid = pdb_ads_gid_to_sid; m->sid_to_id = pdb_ads_sid_to_id; - m->rid_algorithm = pdb_ads_rid_algorithm; + m->capabilities = pdb_ads_capabilities; m->new_rid = pdb_ads_new_rid; m->get_trusteddom_pw = pdb_ads_get_trusteddom_pw; m->set_trusteddom_pw = pdb_ads_set_trusteddom_pw; @@ -1553,56 +2086,141 @@ static void free_private_data(void **vp) return; } -static NTSTATUS pdb_ads_connect(struct pdb_ads_state *state, - const char *location) +/* + this is used to catch debug messages from events +*/ +static void s3_tldap_debug(void *context, enum tldap_debug_level level, + const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3,0); + +static void s3_tldap_debug(void *context, enum tldap_debug_level level, + const char *fmt, va_list ap) +{ + int samba_level = -1; + char *s = NULL; + switch (level) { + case TLDAP_DEBUG_FATAL: + samba_level = 0; + break; + case TLDAP_DEBUG_ERROR: + samba_level = 1; + break; + case TLDAP_DEBUG_WARNING: + samba_level = 2; + break; + case TLDAP_DEBUG_TRACE: + samba_level = 11; + break; + + }; + if (vasprintf(&s, fmt, ap) == -1) { + return; + } + DEBUG(samba_level, ("tldap: %s", s)); + free(s); +} + +static struct tldap_context *pdb_ads_ld(struct pdb_ads_state *state) { - const char *rootdse_attrs[2] = { - "defaultNamingContext", "configurationNamingContext" }; - const char *domain_attrs[1] = { "objectSid" }; - const char *ncname_attrs[1] = { "netbiosname" }; - struct tldap_message **rootdse, **domain, **ncname; - TALLOC_CTX *frame = talloc_stackframe(); - struct sockaddr_un sunaddr; NTSTATUS status; - int num_domains; - int fd, rc; + int fd; - ZERO_STRUCT(sunaddr); - sunaddr.sun_family = AF_UNIX; - strncpy(sunaddr.sun_path, location, sizeof(sunaddr.sun_path) - 1); + if (tldap_connection_ok(state->ld)) { + return state->ld; + } + TALLOC_FREE(state->ld); - status = open_socket_out((struct sockaddr_storage *)(void *)&sunaddr, - 0, 0, &fd); + status = open_socket_out( + (struct sockaddr_storage *)(void *)&state->socket_address, + 0, 0, &fd); if (!NT_STATUS_IS_OK(status)) { - DEBUG(10, ("Could not connect to %s: %s\n", location, - nt_errstr(status))); - goto done; + DEBUG(10, ("Could not connect to %s: %s\n", + state->socket_address.sun_path, nt_errstr(status))); + return NULL; } + set_blocking(fd, false); + state->ld = tldap_context_create(state, fd); if (state->ld == NULL) { close(fd); - status = NT_STATUS_NO_MEMORY; + return NULL; + } + tldap_set_debug(state->ld, s3_tldap_debug, NULL); + + return state->ld; +} + +int pdb_ads_search_fmt(struct pdb_ads_state *state, const char *base, + int scope, const char *attrs[], int num_attrs, + int attrsonly, + TALLOC_CTX *mem_ctx, struct tldap_message ***res, + const char *fmt, ...) +{ + struct tldap_context *ld; + va_list ap; + int ret; + + ld = pdb_ads_ld(state); + if (ld == NULL) { + return TLDAP_SERVER_DOWN; + } + + va_start(ap, fmt); + ret = tldap_search_va(ld, base, scope, attrs, num_attrs, attrsonly, + mem_ctx, res, fmt, ap); + va_end(ap); + + if (ret != TLDAP_SERVER_DOWN) { + return ret; + } + + /* retry once */ + ld = pdb_ads_ld(state); + if (ld == NULL) { + return TLDAP_SERVER_DOWN; + } + + va_start(ap, fmt); + ret = tldap_search_va(ld, base, scope, attrs, num_attrs, attrsonly, + mem_ctx, res, fmt, ap); + va_end(ap); + return ret; +} + +static NTSTATUS pdb_ads_connect(struct pdb_ads_state *state, + const char *location) +{ + const char *domain_attrs[2] = { "objectSid", "objectGUID" }; + const char *ncname_attrs[1] = { "netbiosname" }; + struct tldap_context *ld; + struct tldap_message *rootdse, **domain, **ncname; + TALLOC_CTX *frame = talloc_stackframe(); + NTSTATUS status; + int num_domains; + int rc; + + ZERO_STRUCT(state->socket_address); + state->socket_address.sun_family = AF_UNIX; + strncpy(state->socket_address.sun_path, location, + sizeof(state->socket_address.sun_path) - 1); + + ld = pdb_ads_ld(state); + if (ld == NULL) { + status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO; goto done; } - rc = tldap_search_fmt( - state->ld, "", TLDAP_SCOPE_BASE, - rootdse_attrs, ARRAY_SIZE(rootdse_attrs), 0, - talloc_tos(), &rootdse, "(objectclass=*)"); + rc = tldap_fetch_rootdse(ld); if (rc != TLDAP_SUCCESS) { DEBUG(10, ("Could not retrieve rootdse: %s\n", - tldap_errstr(debug_ctx(), state->ld, rc))); + tldap_errstr(talloc_tos(), state->ld, rc))); status = NT_STATUS_LDAP(rc); goto done; } - if (talloc_array_length(rootdse) != 1) { - status = NT_STATUS_INTERNAL_DB_CORRUPTION; - goto done; - } + rootdse = tldap_rootdse(state->ld); state->domaindn = tldap_talloc_single_attribute( - rootdse[0], "defaultNamingContext", state); + rootdse, "defaultNamingContext", state); if (state->domaindn == NULL) { DEBUG(10, ("Could not get defaultNamingContext\n")); status = NT_STATUS_INTERNAL_DB_CORRUPTION; @@ -1611,7 +2229,7 @@ static NTSTATUS pdb_ads_connect(struct pdb_ads_state *state, DEBUG(10, ("defaultNamingContext = %s\n", state->domaindn)); state->configdn = tldap_talloc_single_attribute( - rootdse[0], "configurationNamingContext", state); + rootdse, "configurationNamingContext", state); if (state->domaindn == NULL) { DEBUG(10, ("Could not get configurationNamingContext\n")); status = NT_STATUS_INTERNAL_DB_CORRUPTION; @@ -1622,13 +2240,13 @@ static NTSTATUS pdb_ads_connect(struct pdb_ads_state *state, /* * Figure out our domain's SID */ - rc = tldap_search_fmt( - state->ld, state->domaindn, TLDAP_SCOPE_BASE, + rc = pdb_ads_search_fmt( + state, state->domaindn, TLDAP_SCOPE_BASE, domain_attrs, ARRAY_SIZE(domain_attrs), 0, talloc_tos(), &domain, "(objectclass=*)"); if (rc != TLDAP_SUCCESS) { DEBUG(10, ("Could not retrieve domain: %s\n", - tldap_errstr(debug_ctx(), state->ld, rc))); + tldap_errstr(talloc_tos(), state->ld, rc))); status = NT_STATUS_LDAP(rc); goto done; } @@ -1644,18 +2262,23 @@ static NTSTATUS pdb_ads_connect(struct pdb_ads_state *state, status = NT_STATUS_INTERNAL_DB_CORRUPTION; goto done; } + if (!tldap_pull_guid(domain[0], "objectGUID", &state->domainguid)) { + DEBUG(10, ("Could not retrieve domain GUID\n")); + status = NT_STATUS_INTERNAL_DB_CORRUPTION; + goto done; + } DEBUG(10, ("Domain SID: %s\n", sid_string_dbg(&state->domainsid))); /* * Figure out our domain's short name */ - rc = tldap_search_fmt( - state->ld, state->configdn, TLDAP_SCOPE_SUB, + rc = pdb_ads_search_fmt( + state, state->configdn, TLDAP_SCOPE_SUB, ncname_attrs, ARRAY_SIZE(ncname_attrs), 0, talloc_tos(), &ncname, "(ncname=%s)", state->domaindn); if (rc != TLDAP_SUCCESS) { DEBUG(10, ("Could not retrieve ncname: %s\n", - tldap_errstr(debug_ctx(), state->ld, rc))); + tldap_errstr(talloc_tos(), state->ld, rc))); status = NT_STATUS_LDAP(rc); goto done; } @@ -1700,7 +2323,7 @@ static NTSTATUS pdb_init_ads(struct pdb_methods **pdb_method, if (m == NULL) { return NT_STATUS_NO_MEMORY; } - state = talloc(m, struct pdb_ads_state); + state = talloc_zero(m, struct pdb_ads_state); if (state == NULL) { goto nomem; }