*/
#include "includes.h"
-
-static NTSTATUS pdb_ads_getsampwsid(struct pdb_methods *m,
- struct samu *sam_acct,
- const DOM_SID *sid);
+#include "tldap.h"
+#include "tldap_util.h"
+#include "../libds/common/flags.h"
+#include "secrets.h"
+#include "../librpc/gen_ndr/samr.h"
+#include "../libcli/ldap/ldap_ndr.h"
+#include "../libcli/security/security.h"
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 bool pdb_ads_gid_to_sid(struct pdb_methods *m, gid_t gid,
+ struct 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)
{
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 = '.';
+ }
-static struct samu *pdb_ads_init_guest(TALLOC_CTX *mem_ctx,
- struct pdb_methods *m)
+ return result;
+}
+
+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);
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 = ldap_encode_ndr_dom_sid(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;
+ uint32_t i;
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);
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",
pdb_set_profile_path(sam, str, PDB_SET);
}
+ str = tldap_talloc_single_attribute(entry, "comment",
+ talloc_tos());
+ if (str != NULL) {
+ pdb_set_comment(sam, str, PDB_SET);
+ }
+
+ str = tldap_talloc_single_attribute(entry, "description",
+ talloc_tos());
+ if (str != NULL) {
+ pdb_set_acct_desc(sam, str, PDB_SET);
+ }
+
+ str = tldap_talloc_single_attribute(entry, "userWorkstations",
+ talloc_tos());
+ if (str != NULL) {
+ pdb_set_workstations(sam, str, PDB_SET);
+ }
+
+ str = tldap_talloc_single_attribute(entry, "userParameters",
+ talloc_tos());
+ if (str != NULL) {
+ pdb_set_munged_dial(sam, str, PDB_SET);
+ }
+
if (!tldap_pull_binsid(entry, "objectSid", &sid)) {
DEBUG(10, ("Could not pull SID\n"));
goto fail;
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) {
}
- priv->ldapmsg = talloc_move(priv, &entry);
- pdb_set_backend_private_data(sam, priv, NULL, m, PDB_SET);
+ if (tldap_pull_uint32(entry, "countryCode", &i)) {
+ pdb_set_country_code(sam, i, PDB_SET);
+ }
status = NT_STATUS_OK;
fail:
static bool pdb_ads_init_ads_from_sam(struct pdb_ads_state *state,
struct tldap_message *existing,
TALLOC_CTX *mem_ctx,
- int *pnum_mods, struct tldap_mod **pmods,
+ struct tldap_mod **pmods, int *pnum_mods,
struct samu *sam)
{
bool ret = true;
+ DATA_BLOB blob;
+ const char *pw;
/* TODO: All fields :-) */
ret &= tldap_make_mod_fmt(
- existing, mem_ctx, pnum_mods, pmods, "displayName",
- pdb_get_fullname(sam));
+ existing, mem_ctx, pmods, pnum_mods, "displayName",
+ "%s", pdb_get_fullname(sam));
+
+ pw = pdb_get_plaintext_passwd(sam);
+
+ /*
+ * If we have the plain text pw, this is probably about to be
+ * set. Is this true always?
+ */
+ if (pw != NULL) {
+ char *pw_quote;
+ uint8_t *pw_utf16;
+ size_t pw_utf16_len;
+
+ pw_quote = talloc_asprintf(talloc_tos(), "\"%s\"", pw);
+ if (pw_quote == NULL) {
+ ret = false;
+ goto fail;
+ }
+
+ ret &= convert_string_talloc(talloc_tos(),
+ CH_UNIX, CH_UTF16LE,
+ pw_quote, strlen(pw_quote),
+ &pw_utf16, &pw_utf16_len, false);
+ if (!ret) {
+ goto fail;
+ }
+ blob = data_blob_const(pw_utf16, pw_utf16_len);
+
+ ret &= tldap_add_mod_blobs(mem_ctx, pmods, pnum_mods,
+ TLDAP_MOD_REPLACE,
+ "unicodePwd", &blob, 1);
+ TALLOC_FREE(pw_utf16);
+ TALLOC_FREE(pw_quote);
+ }
+
+ ret &= tldap_make_mod_fmt(
+ existing, mem_ctx, pmods, pnum_mods, "userAccountControl",
+ "%d", ds_acb2uf(pdb_get_acct_ctrl(sam)));
+
+ ret &= tldap_make_mod_fmt(
+ existing, mem_ctx, pmods, pnum_mods, "homeDirectory",
+ "%s", pdb_get_homedir(sam));
+
+ ret &= tldap_make_mod_fmt(
+ existing, mem_ctx, pmods, pnum_mods, "homeDrive",
+ "%s", pdb_get_dir_drive(sam));
+
+ ret &= tldap_make_mod_fmt(
+ existing, mem_ctx, pmods, pnum_mods, "scriptPath",
+ "%s", pdb_get_logon_script(sam));
+
+ ret &= tldap_make_mod_fmt(
+ existing, mem_ctx, pmods, pnum_mods, "profilePath",
+ "%s", pdb_get_profile_path(sam));
+
+ ret &= tldap_make_mod_fmt(
+ existing, mem_ctx, pmods, pnum_mods, "comment",
+ "%s", pdb_get_comment(sam));
- ret &= tldap_make_mod_blob(
- existing, mem_ctx, pnum_mods, pmods, "unicodePwd",
- data_blob_const(pdb_get_nt_passwd(sam), NT_HASH_LEN));
+ ret &= tldap_make_mod_fmt(
+ existing, mem_ctx, pmods, pnum_mods, "description",
+ "%s", pdb_get_acct_desc(sam));
+
+ ret &= tldap_make_mod_fmt(
+ existing, mem_ctx, pmods, pnum_mods, "userWorkstations",
+ "%s", pdb_get_workstations(sam));
+
+ ret &= tldap_make_mod_fmt(
+ existing, mem_ctx, pmods, pnum_mods, "userParameters",
+ "%s", pdb_get_munged_dial(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, pmods, pnum_mods, "countryCode",
+ "%i", (int)pdb_get_country_code(sam));
+fail:
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",
"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, 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,
static NTSTATUS pdb_ads_getsampwsid(struct pdb_methods *m,
struct samu *sam_acct,
- const DOM_SID *sid)
+ const struct dom_sid *sid)
{
struct pdb_ads_state *state = talloc_get_type_abort(
m->private_data, struct pdb_ads_state);
char *sidstr, *filter;
- sidstr = sid_binstring(talloc_tos(), sid);
+ sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), sid);
NT_STATUS_HAVE_NO_MEMORY(sidstr);
filter = talloc_asprintf(
{
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;
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;
ok &= tldap_make_mod_fmt(
- NULL, talloc_tos(), &num_mods, &mods, "objectClass", "user");
+ NULL, talloc_tos(), &mods, &num_mods, "objectClass", "user");
ok &= tldap_make_mod_fmt(
- NULL, talloc_tos(), &num_mods, &mods, "samAccountName", "%s",
+ NULL, talloc_tos(), &mods, &num_mods, "samAccountName", "%s",
name);
if (!ok) {
return NT_STATUS_NO_MEMORY;
}
- rc = tldap_add(state->ld, dn, num_mods, mods, NULL, NULL);
+
+ rc = tldap_add(ld, dn, mods, num_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);
}
{
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;
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)) {
+ &mods, &num_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, mods, num_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;
}
return NT_STATUS_NOT_IMPLEMENTED;
}
+static NTSTATUS pdb_ads_getgrfilter(struct pdb_methods *m, GROUP_MAP *map,
+ const char *filter)
+{
+ struct pdb_ads_state *state = talloc_get_type_abort(
+ m->private_data, struct pdb_ads_state);
+ const char *attrs[4] = { "objectSid", "description", "samAccountName",
+ "groupType" };
+ char *str;
+ struct tldap_message **group;
+ uint32_t grouptype;
+ int rc;
+
+ 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(talloc_tos(), state->ld, rc)));
+ return NT_STATUS_LDAP(rc);
+ }
+ if (talloc_array_length(group) != 1) {
+ DEBUG(10, ("Expected 1 user, got %d\n",
+ (int)talloc_array_length(group)));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ if (!tldap_pull_binsid(group[0], "objectSid", &map->sid)) {
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+ map->gid = pdb_ads_sid2gid(&map->sid);
+
+ if (!tldap_pull_uint32(group[0], "groupType", &grouptype)) {
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+ switch (grouptype) {
+ case GTYPE_SECURITY_BUILTIN_LOCAL_GROUP:
+ case GTYPE_SECURITY_DOMAIN_LOCAL_GROUP:
+ map->sid_name_use = SID_NAME_ALIAS;
+ break;
+ case GTYPE_SECURITY_GLOBAL_GROUP:
+ map->sid_name_use = SID_NAME_DOM_GRP;
+ break;
+ default:
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ str = tldap_talloc_single_attribute(group[0], "samAccountName",
+ talloc_tos());
+ if (str == NULL) {
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+ fstrcpy(map->nt_name, str);
+ TALLOC_FREE(str);
+
+ str = tldap_talloc_single_attribute(group[0], "description",
+ talloc_tos());
+ if (str != NULL) {
+ fstrcpy(map->comment, str);
+ TALLOC_FREE(str);
+ } else {
+ map->comment[0] = '\0';
+ }
+
+ TALLOC_FREE(group);
+ return NT_STATUS_OK;
+}
+
static NTSTATUS pdb_ads_getgrsid(struct pdb_methods *m, GROUP_MAP *map,
- DOM_SID sid)
+ struct dom_sid sid)
{
- return NT_STATUS_NOT_IMPLEMENTED;
+ char *filter;
+ NTSTATUS status;
+
+ filter = talloc_asprintf(talloc_tos(),
+ "(&(objectsid=%s)(objectclass=group))",
+ sid_string_talloc(talloc_tos(), &sid));
+ if (filter == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ status = pdb_ads_getgrfilter(m, map, filter);
+ TALLOC_FREE(filter);
+ return status;
}
static NTSTATUS pdb_ads_getgrgid(struct pdb_methods *m, GROUP_MAP *map,
gid_t gid)
{
- return NT_STATUS_NOT_IMPLEMENTED;
+ struct dom_sid sid;
+ pdb_ads_gid_to_sid(m, gid, &sid);
+ return pdb_ads_getgrsid(m, map, sid);
}
static NTSTATUS pdb_ads_getgrnam(struct pdb_methods *m, GROUP_MAP *map,
const char *name)
{
- return NT_STATUS_NOT_IMPLEMENTED;
+ char *filter;
+ NTSTATUS status;
+
+ filter = talloc_asprintf(talloc_tos(),
+ "(&(samaccountname=%s)(objectclass=group))",
+ name);
+ if (filter == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ status = pdb_ads_getgrfilter(m, map, filter);
+ TALLOC_FREE(filter);
+ return status;
}
static NTSTATUS pdb_ads_create_dom_group(struct pdb_methods *m,
TALLOC_CTX *mem_ctx, const char *name,
uint32 *rid)
{
- return NT_STATUS_NOT_IMPLEMENTED;
-}
+ 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;
+ struct tldap_message **alias;
+ struct dom_sid sid;
+ char *dn;
+ int rc;
+ bool ok = true;
-static NTSTATUS pdb_ads_delete_dom_group(struct pdb_methods *m,
- TALLOC_CTX *mem_ctx, uint32 rid)
-{
- return NT_STATUS_NOT_IMPLEMENTED;
-}
+ ld = pdb_ads_ld(state);
+ if (ld == NULL) {
+ return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
+ }
-static NTSTATUS pdb_ads_add_group_mapping_entry(struct pdb_methods *m,
- GROUP_MAP *map)
-{
- return NT_STATUS_NOT_IMPLEMENTED;
-}
+ dn = talloc_asprintf(talloc_tos(), "cn=%s,cn=users,%s", name,
+ state->domaindn);
+ if (dn == NULL) {
+ TALLOC_FREE(frame);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ ok &= tldap_make_mod_fmt(
+ NULL, talloc_tos(), &mods, &num_mods, "samAccountName", "%s",
+ name);
+ ok &= tldap_make_mod_fmt(
+ NULL, talloc_tos(), &mods, &num_mods, "objectClass", "group");
+ ok &= tldap_make_mod_fmt(
+ NULL, talloc_tos(), &mods, &num_mods, "groupType",
+ "%d", (int)GTYPE_SECURITY_GLOBAL_GROUP);
+
+ if (!ok) {
+ TALLOC_FREE(frame);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ rc = tldap_add(ld, dn, mods, num_mods, NULL, 0, NULL, 0);
+ if (rc != TLDAP_SUCCESS) {
+ DEBUG(10, ("ldap_add failed %s\n",
+ tldap_errstr(talloc_tos(), state->ld, rc)));
+ TALLOC_FREE(frame);
+ return NT_STATUS_LDAP(rc);
+ }
+
+ 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(talloc_tos(), state->ld, rc)));
+ TALLOC_FREE(frame);
+ return NT_STATUS_LDAP(rc);
+ }
+
+ if (talloc_array_length(alias) != 1) {
+ DEBUG(10, ("Got %d alias, expected one\n",
+ (int)talloc_array_length(alias)));
+ TALLOC_FREE(frame);
+ return NT_STATUS_LDAP(rc);
+ }
+
+ if (!tldap_pull_binsid(alias[0], "objectSid", &sid)) {
+ DEBUG(10, ("Could not fetch objectSid from alias %s\n",
+ name));
+ TALLOC_FREE(frame);
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ sid_peek_rid(&sid, rid);
+ TALLOC_FREE(frame);
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS pdb_ads_delete_dom_group(struct pdb_methods *m,
+ TALLOC_CTX *mem_ctx, uint32 rid)
+{
+ 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 = ldap_encode_ndr_dom_sid(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,
+ GROUP_MAP *map)
+{
+ return NT_STATUS_NOT_IMPLEMENTED;
+}
static NTSTATUS pdb_ads_update_group_mapping_entry(struct pdb_methods *m,
GROUP_MAP *map)
}
static NTSTATUS pdb_ads_delete_group_mapping_entry(struct pdb_methods *m,
- DOM_SID sid)
+ struct dom_sid sid)
{
return NT_STATUS_NOT_IMPLEMENTED;
}
static NTSTATUS pdb_ads_enum_group_mapping(struct pdb_methods *m,
- const DOM_SID *sid,
+ const struct dom_sid *sid,
enum lsa_SidType sid_name_use,
GROUP_MAP **pp_rmap,
size_t *p_num_entries,
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)
+ const struct dom_sid *group,
+ 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 = ldap_encode_ndr_dom_sid(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", &blobs, &num_members)) {
+ 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; i<num_members; i++) {
+ struct dom_sid sid;
+ if (!pdb_ads_dnblob2sid(state, &blobs[i], &sid)
+ || !sid_peek_rid(&sid, &members[i])) {
+ TALLOC_FREE(members);
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+ }
+
+ *pmembers = members;
+ *pnum_members = num_members;
+ return NT_STATUS_OK;
}
static NTSTATUS pdb_ads_enum_group_memberships(struct pdb_methods *m,
TALLOC_CTX *mem_ctx,
struct samu *user,
- DOM_SID **pp_sids,
+ struct dom_sid **pp_sids,
gid_t **pp_gids,
size_t *p_num_groups)
{
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, user);
+ struct pdb_ads_samu_private *priv;
const char *attrs[1] = { "objectSid" };
struct tldap_message **groups;
int i, rc, count;
struct dom_sid *group_sids;
gid_t *gids;
- rc = tldap_search_fmt(
- state->ld, 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)));
- return NT_STATUS_LDAP(rc);
+ priv = pdb_ads_get_samu_private(m, user);
+ if (priv != NULL) {
+ 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(talloc_tos(), state->ld, rc)));
+ return NT_STATUS_LDAP(rc);
+ }
+ count = talloc_array_length(groups);
+ } else {
+ /*
+ * This happens for artificial samu users
+ */
+ DEBUG(10, ("Could not get pdb_ads_samu_private\n"));
+ count = 0;
}
- count = talloc_array_length(groups);
-
- group_sids = talloc_array(mem_ctx, struct dom_sid, count);
+ group_sids = talloc_array(mem_ctx, struct dom_sid, count+1);
if (group_sids == NULL) {
return NT_STATUS_NO_MEMORY;
}
- gids = talloc_array(mem_ctx, gid_t, count);
+ gids = talloc_array(mem_ctx, gid_t, count+1);
if (gids == NULL) {
TALLOC_FREE(group_sids);
return NT_STATUS_NO_MEMORY;
}
- num_groups = 0;
+
+ sid_copy(&group_sids[0], pdb_get_group_sid(user));
+ if (!sid_to_gid(&group_sids[0], &gids[0])) {
+ TALLOC_FREE(gids);
+ TALLOC_FREE(group_sids);
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+ num_groups = 1;
for (i=0; i<count; i++) {
if (!tldap_pull_binsid(groups[i], "objectSid",
}
gids[num_groups] = pdb_ads_sid2gid(&group_sids[num_groups]);
- num_groups += 1;
- if (num_groups == count) {
- break;
+ num_groups += 1;
+ if (num_groups == count) {
+ break;
+ }
+ }
+
+ *pp_sids = group_sids;
+ *pp_gids = gids;
+ *p_num_groups = num_groups;
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS pdb_ads_set_unix_primary_group(struct pdb_methods *m,
+ TALLOC_CTX *mem_ctx,
+ struct samu *user)
+{
+ 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 num_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;
+ num_mods = 0;
+
+ if (!tldap_add_mod_str(talloc_tos(), &mods, &num_mods, mod_op,
+ "member", memberdn)) {
+ TALLOC_FREE(frame);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ rc = tldap_modify(ld, groupdn, mods, num_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 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 pdb_ads_mod_groupmem(m, mem_ctx, group_rid, member_rid,
+ TLDAP_MOD_DELETE);
+}
+
+static NTSTATUS pdb_ads_create_alias(struct pdb_methods *m,
+ const char *name, uint32 *rid)
+{
+ 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;
+ struct tldap_message **alias;
+ struct dom_sid sid;
+ char *dn;
+ 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) {
+ TALLOC_FREE(frame);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ ok &= tldap_make_mod_fmt(
+ NULL, talloc_tos(), &mods, &num_mods, "samAccountName", "%s",
+ name);
+ ok &= tldap_make_mod_fmt(
+ NULL, talloc_tos(), &mods, &num_mods, "objectClass", "group");
+ ok &= tldap_make_mod_fmt(
+ NULL, talloc_tos(), &mods, &num_mods, "groupType",
+ "%d", (int)GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
+
+ if (!ok) {
+ TALLOC_FREE(frame);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ rc = tldap_add(ld, dn, mods, num_mods, NULL, 0, NULL, 0);
+ if (rc != TLDAP_SUCCESS) {
+ DEBUG(10, ("ldap_add failed %s\n",
+ tldap_errstr(talloc_tos(), state->ld, rc)));
+ TALLOC_FREE(frame);
+ return NT_STATUS_LDAP(rc);
+ }
+
+ 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(talloc_tos(), state->ld, rc)));
+ TALLOC_FREE(frame);
+ return NT_STATUS_LDAP(rc);
+ }
+
+ if (talloc_array_length(alias) != 1) {
+ DEBUG(10, ("Got %d alias, expected one\n",
+ (int)talloc_array_length(alias)));
+ TALLOC_FREE(frame);
+ return NT_STATUS_LDAP(rc);
+ }
+
+ if (!tldap_pull_binsid(alias[0], "objectSid", &sid)) {
+ DEBUG(10, ("Could not fetch objectSid from alias %s\n",
+ name));
+ TALLOC_FREE(frame);
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ sid_peek_rid(&sid, rid);
+ TALLOC_FREE(frame);
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS pdb_ads_delete_alias(struct pdb_methods *m,
+ const struct dom_sid *sid)
+{
+ 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 = NULL;
+ int rc;
+
+ ld = pdb_ads_ld(state);
+ if (ld == NULL) {
+ return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
+ }
+
+ sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), sid);
+ if (sidstr == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ 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(talloc_tos(), state->ld, rc)));
+ return NT_STATUS_LDAP(rc);
+ }
+ if (talloc_array_length(alias) != 1) {
+ DEBUG(10, ("Expected 1 alias, got %d\n",
+ (int)talloc_array_length(alias)));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+ if (!tldap_entry_dn(alias[0], &dn)) {
+ DEBUG(10, ("Could not get DN for alias %s\n",
+ sid_string_dbg(sid)));
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+
+ rc = tldap_delete(ld, dn, NULL, 0, NULL, 0);
+ 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_set_aliasinfo(struct pdb_methods *m,
+ const struct dom_sid *sid,
+ struct acct_info *info)
+{
+ 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 = ldap_encode_ndr_dom_sid(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, &mods, &num_mods, "description",
+ "%s", info->acct_desc);
+ ok &= tldap_make_mod_fmt(
+ msg[0], msg, &mods, &num_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, mods, num_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,
+ const struct dom_sid *sid,
+ TALLOC_CTX *mem_ctx, char **pdn)
+{
+ struct tldap_message **msg;
+ char *sidstr, *dn;
+ int rc;
+
+ sidstr = ldap_encode_ndr_dom_sid(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)", 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_NOT_FOUND;
+ case 1:
+ break;
+ default:
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ if (!tldap_entry_dn(msg[0], &dn)) {
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ dn = talloc_strdup(mem_ctx, dn);
+ if (dn == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ TALLOC_FREE(msg);
+
+ *pdn = dn;
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS pdb_ads_mod_aliasmem(struct pdb_methods *m,
+ const struct dom_sid *alias,
+ const struct dom_sid *member,
+ int mod_op)
+{
+ 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 num_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",
+ sid_string_dbg(alias), nt_errstr(status)));
+ TALLOC_FREE(frame);
+ return NT_STATUS_NO_SUCH_ALIAS;
+ }
+ status = pdb_ads_sid2dn(state, member, talloc_tos(), &memberdn);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10, ("pdb_ads_sid2dn (%s) failed: %s\n",
+ sid_string_dbg(member), nt_errstr(status)));
+ TALLOC_FREE(frame);
+ return status;
+ }
+
+ mods = NULL;
+ num_mods = 0;
+
+ if (!tldap_add_mod_str(talloc_tos(), &mods, &num_mods, mod_op,
+ "member", memberdn)) {
+ TALLOC_FREE(frame);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ rc = tldap_modify(ld, aliasdn, mods, num_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_ALIAS;
+ }
+ if (rc == TLDAP_NO_SUCH_ATTRIBUTE) {
+ return NT_STATUS_MEMBER_NOT_IN_ALIAS;
+ }
+ return NT_STATUS_LDAP(rc);
+ }
+
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS pdb_ads_add_aliasmem(struct pdb_methods *m,
+ const struct dom_sid *alias,
+ const struct dom_sid *member)
+{
+ return pdb_ads_mod_aliasmem(m, alias, member, TLDAP_MOD_ADD);
+}
+
+static NTSTATUS pdb_ads_del_aliasmem(struct pdb_methods *m,
+ const struct dom_sid *alias,
+ const struct dom_sid *member)
+{
+ return pdb_ads_mod_aliasmem(m, alias, member, TLDAP_MOD_DELETE);
+}
+
+static bool pdb_ads_dnblob2sid(struct pdb_ads_state *state, DATA_BLOB *dnblob,
+ struct dom_sid *psid)
+{
+ const char *attrs[1] = { "objectSid" };
+ struct tldap_message **msg;
+ char *dn;
+ size_t len;
+ int rc;
+ bool ret;
+
+ if (!convert_string_talloc(talloc_tos(), CH_UTF8, CH_UNIX,
+ dnblob->data, dnblob->length, &dn, &len,
+ false)) {
+ return false;
+ }
+ 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",
+ (int)talloc_array_length(msg)));
+ TALLOC_FREE(msg);
+ return false;
+ }
+
+ ret = tldap_pull_binsid(msg[0], "objectSid", psid);
+ TALLOC_FREE(msg);
+ return ret;
+}
+
+static NTSTATUS pdb_ads_enum_aliasmem(struct pdb_methods *m,
+ const struct dom_sid *alias,
+ TALLOC_CTX *mem_ctx,
+ struct dom_sid **pmembers,
+ size_t *pnum_members)
+{
+ 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;
+ struct dom_sid *members;
+
+ sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), alias);
+ 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", &blobs, &num_members)) {
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ members = talloc_array(mem_ctx, struct dom_sid, num_members);
+ if (members == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ for (i=0; i<num_members; i++) {
+ if (!pdb_ads_dnblob2sid(state, &blobs[i], &members[i])) {
+ TALLOC_FREE(members);
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
}
- *pp_sids = group_sids;
- *pp_gids = gids;
- *p_num_groups = num_groups;
+ *pmembers = members;
+ *pnum_members = num_members;
return NT_STATUS_OK;
}
-static NTSTATUS pdb_ads_set_unix_primary_group(struct pdb_methods *m,
+static NTSTATUS pdb_ads_enum_alias_memberships(struct pdb_methods *m,
TALLOC_CTX *mem_ctx,
- struct samu *user)
-{
- return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-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;
-}
-
-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;
-}
-
-static NTSTATUS pdb_ads_create_alias(struct pdb_methods *m,
- const char *name, uint32 *rid)
+ const struct dom_sid *domain_sid,
+ const struct dom_sid *members,
+ size_t num_members,
+ uint32_t **palias_rids,
+ size_t *pnum_alias_rids)
{
- TALLOC_CTX *frame = talloc_stackframe();
struct pdb_ads_state *state = talloc_get_type_abort(
m->private_data, struct pdb_ads_state);
const char *attrs[1] = { "objectSid" };
- int num_mods = 0;
- struct tldap_mod *mods = NULL;
- struct tldap_message **alias;
- struct dom_sid sid;
- char *dn;
- int rc;
- bool ok = true;
+ struct tldap_message **msg = NULL;
+ uint32_t *alias_rids = NULL;
+ size_t num_alias_rids = 0;
+ int i, rc, count;
+ bool got_members = false;
+ char *filter;
+ NTSTATUS status;
- dn = talloc_asprintf(talloc_tos(), "cn=%s,cn=users,%s", name,
- state->domaindn);
- if (dn == NULL) {
- TALLOC_FREE(frame);
+ /*
+ * 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;
}
- ok &= tldap_make_mod_fmt(
- NULL, talloc_tos(), &num_mods, &mods, "samAccountName", "%s",
- name);
- ok &= tldap_make_mod_fmt(
- NULL, talloc_tos(), &num_mods, &mods, "objectClass", "group");
- ok &= tldap_make_mod_fmt(
- NULL, talloc_tos(), &num_mods, &mods, "groupType",
- "%d", (int)GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
+ for (i=0; i<num_members; i++) {
+ char *dn;
- if (!ok) {
- TALLOC_FREE(frame);
- return NT_STATUS_NO_MEMORY;
+ status = pdb_ads_sid2dn(state, &members[i], talloc_tos(), &dn);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10, ("pdb_ads_sid2dn failed for %s: %s\n",
+ sid_string_dbg(&members[i]),
+ nt_errstr(status)));
+ continue;
+ }
+ filter = talloc_asprintf_append_buffer(
+ filter, "(member=%s)", dn);
+ TALLOC_FREE(dn);
+ if (filter == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ got_members = true;
}
- rc = tldap_add(state->ld, dn, num_mods, mods, NULL, NULL);
- if (rc != TLDAP_SUCCESS) {
- DEBUG(10, ("ldap_add failed %s\n",
- tldap_errstr(debug_ctx(), state->ld, rc)));
- TALLOC_FREE(frame);
- return NT_STATUS_LDAP(rc);
+ if (!got_members) {
+ goto done;
}
- rc = tldap_search_fmt(
- state->ld, state->domaindn, TLDAP_SCOPE_SUB,
- attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &alias,
- "(&(objectclass=group)(samaccountname=%s))", name);
+ rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
+ attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
+ &msg, "%s))", filter);
+ TALLOC_FREE(filter);
if (rc != TLDAP_SUCCESS) {
- DEBUG(10, ("Could not find just created alias %s: %s\n",
- name, tldap_errstr(debug_ctx(), state->ld, rc)));
- TALLOC_FREE(frame);
+ DEBUG(10, ("tldap_search failed %s\n",
+ tldap_errstr(talloc_tos(), state->ld, rc)));
return NT_STATUS_LDAP(rc);
}
- if (talloc_array_length(alias) != 1) {
- DEBUG(10, ("Got %d alias, expected one\n",
- (int)talloc_array_length(alias)));
- TALLOC_FREE(frame);
- return NT_STATUS_LDAP(rc);
+ count = talloc_array_length(msg);
+ if (count == 0) {
+ goto done;
}
- if (!tldap_pull_binsid(alias[0], "objectSid", &sid)) {
- DEBUG(10, ("Could not fetch objectSid from alias %s\n",
- name));
- TALLOC_FREE(frame);
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ alias_rids = talloc_array(mem_ctx, uint32_t, count);
+ if (alias_rids == NULL) {
+ TALLOC_FREE(msg);
+ return NT_STATUS_NO_MEMORY;
}
- sid_peek_rid(&sid, rid);
- TALLOC_FREE(frame);
+ for (i=0; i<count; i++) {
+ struct dom_sid sid;
+
+ if (!tldap_pull_binsid(msg[i], "objectSid", &sid)) {
+ DEBUG(10, ("Could not pull SID for member %d\n", i));
+ continue;
+ }
+ if (sid_peek_check_rid(domain_sid, &sid,
+ &alias_rids[num_alias_rids])) {
+ num_alias_rids += 1;
+ }
+ }
+done:
+ TALLOC_FREE(msg);
+ *palias_rids = alias_rids;
+ *pnum_alias_rids = 0;
return NT_STATUS_OK;
}
-static NTSTATUS pdb_ads_delete_alias(struct pdb_methods *m,
- const DOM_SID *sid)
+static NTSTATUS pdb_ads_lookup_rids(struct pdb_methods *m,
+ const struct dom_sid *domain_sid,
+ int num_rids,
+ uint32 *rids,
+ const char **names,
+ enum lsa_SidType *lsa_attrs)
{
- return NT_STATUS_NOT_IMPLEMENTED;
-}
+ struct pdb_ads_state *state = talloc_get_type_abort(
+ m->private_data, struct pdb_ads_state);
+ const char *attrs[2] = { "sAMAccountType", "sAMAccountName" };
+ int i, num_mapped;
-static NTSTATUS pdb_ads_get_aliasinfo(struct pdb_methods *m,
- const DOM_SID *sid,
- struct acct_info *info)
-{
- return NT_STATUS_NOT_IMPLEMENTED;
-}
+ if (num_rids == 0) {
+ return NT_STATUS_NONE_MAPPED;
+ }
-static NTSTATUS pdb_ads_set_aliasinfo(struct pdb_methods *m,
- const DOM_SID *sid,
- struct acct_info *info)
-{
- return NT_STATUS_NOT_IMPLEMENTED;
-}
+ num_mapped = 0;
-static NTSTATUS pdb_ads_add_aliasmem(struct pdb_methods *m,
- const DOM_SID *alias,
- const DOM_SID *member)
-{
- return NT_STATUS_NOT_IMPLEMENTED;
-}
+ for (i=0; i<num_rids; i++) {
+ struct dom_sid sid;
+ struct tldap_message **msg;
+ char *sidstr;
+ uint32_t attr;
+ int rc;
-static NTSTATUS pdb_ads_del_aliasmem(struct pdb_methods *m,
- const DOM_SID *alias,
- const DOM_SID *member)
-{
- return NT_STATUS_NOT_IMPLEMENTED;
-}
+ lsa_attrs[i] = SID_NAME_UNKNOWN;
-static NTSTATUS pdb_ads_enum_aliasmem(struct pdb_methods *m,
- const DOM_SID *alias, DOM_SID **members,
- size_t *p_num_members)
-{
- return NT_STATUS_NOT_IMPLEMENTED;
-}
+ sid_compose(&sid, domain_sid, rids[i]);
-static NTSTATUS pdb_ads_enum_alias_memberships(struct pdb_methods *m,
- TALLOC_CTX *mem_ctx,
- const DOM_SID *domain_sid,
- const DOM_SID *members,
- size_t num_members,
- uint32 **pp_alias_rids,
- size_t *p_num_alias_rids)
-{
- return NT_STATUS_NOT_IMPLEMENTED;
-}
+ sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), &sid);
+ NT_STATUS_HAVE_NO_MEMORY(sidstr);
-static NTSTATUS pdb_ads_lookup_rids(struct pdb_methods *m,
- const DOM_SID *domain_sid,
- int num_rids,
- uint32 *rids,
- const char **pp_names,
- enum lsa_SidType *attrs)
-{
- return NT_STATUS_NOT_IMPLEMENTED;
+ 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)));
+ 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,
- const DOM_SID *domain_sid,
+ const struct dom_sid *domain_sid,
int num_names,
const char **pp_names,
uint32 *rids,
}
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;
}
TALLOC_FREE(state);
}
-static bool pdb_ads_search_users(struct pdb_methods *m,
- struct pdb_search *search,
- uint32 acct_flags)
+static bool pdb_ads_search_filter(struct pdb_methods *m,
+ struct pdb_search *search,
+ const char *filter,
+ struct pdb_ads_search_state **pstate)
{
struct pdb_ads_state *state = talloc_get_type_abort(
m->private_data, struct pdb_ads_state);
if (sstate == NULL) {
return false;
}
- sstate->acct_flags = acct_flags;
- 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,
- "(objectclass=user)");
+ "%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;
}
search->private_data = sstate;
search->next_entry = pdb_ads_next_entry;
search->search_end = pdb_ads_search_end;
+ *pstate = sstate;
+ return true;
+}
+
+static bool pdb_ads_search_users(struct pdb_methods *m,
+ struct pdb_search *search,
+ uint32 acct_flags)
+{
+ struct pdb_ads_search_state *sstate;
+ char *filter;
+ bool ret;
+
+ if (acct_flags & ACB_NORMAL) {
+ filter = talloc_asprintf(
+ talloc_tos(),
+ "(&(objectclass=user)(sAMAccountType=%d))",
+ ATYPE_NORMAL_ACCOUNT);
+ } else if (acct_flags & ACB_WSTRUST) {
+ filter = talloc_asprintf(
+ talloc_tos(),
+ "(&(objectclass=user)(sAMAccountType=%d))",
+ ATYPE_WORKSTATION_TRUST);
+ } else {
+ filter = talloc_strdup(talloc_tos(), "(objectclass=user)");
+ }
+ if (filter == NULL) {
+ return false;
+ }
+
+ ret = pdb_ads_search_filter(m, search, filter, &sstate);
+ TALLOC_FREE(filter);
+ if (!ret) {
+ return false;
+ }
+ sstate->acct_flags = acct_flags;
return true;
}
static bool pdb_ads_search_groups(struct pdb_methods *m,
struct pdb_search *search)
{
- return false;
+ struct pdb_ads_search_state *sstate;
+ char *filter;
+ bool ret;
+
+ filter = talloc_asprintf(talloc_tos(),
+ "(&(grouptype=%d)(objectclass=group))",
+ GTYPE_SECURITY_GLOBAL_GROUP);
+ if (filter == NULL) {
+ return false;
+ }
+ ret = pdb_ads_search_filter(m, search, filter, &sstate);
+ TALLOC_FREE(filter);
+ if (!ret) {
+ return false;
+ }
+ sstate->acct_flags = 0;
+ return true;
}
static bool pdb_ads_search_aliases(struct pdb_methods *m,
struct pdb_search *search,
- const DOM_SID *sid)
+ const struct dom_sid *sid)
{
- return false;
-}
+ struct pdb_ads_search_state *sstate;
+ char *filter;
+ bool ret;
-static bool pdb_ads_uid_to_rid(struct pdb_methods *m, uid_t uid,
- uint32 *rid)
-{
- return false;
+ filter = talloc_asprintf(
+ talloc_tos(), "(&(grouptype=%d)(objectclass=group))",
+ sid_check_is_builtin(sid)
+ ? GTYPE_SECURITY_BUILTIN_LOCAL_GROUP
+ : GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
+
+ if (filter == NULL) {
+ return false;
+ }
+ ret = pdb_ads_search_filter(m, search, filter, &sstate);
+ TALLOC_FREE(filter);
+ if (!ret) {
+ return false;
+ }
+ sstate->acct_flags = 0;
+ return true;
}
static bool pdb_ads_uid_to_sid(struct pdb_methods *m, uid_t uid,
- DOM_SID *sid)
+ struct dom_sid *sid)
{
- return false;
+ struct pdb_ads_state *state = talloc_get_type_abort(
+ m->private_data, struct pdb_ads_state);
+ sid_compose(sid, &state->domainsid, uid);
+ return true;
}
static bool pdb_ads_gid_to_sid(struct pdb_methods *m, gid_t gid,
- DOM_SID *sid)
+ struct dom_sid *sid)
{
- return false;
+ struct pdb_ads_state *state = talloc_get_type_abort(
+ m->private_data, struct pdb_ads_state);
+ sid_compose(sid, &state->domainsid, gid);
+ return true;
}
-static bool pdb_ads_sid_to_id(struct pdb_methods *m, const DOM_SID *sid,
+static bool pdb_ads_sid_to_id(struct pdb_methods *m, const struct dom_sid *sid,
union unid_t *id, enum lsa_SidType *type)
{
struct pdb_ads_state *state = talloc_get_type_abort(
sid_peek_rid(sid, &rid);
- sidstr = sid_binstring(talloc_tos(), sid);
+ sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), sid);
if (sidstr == NULL) {
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)) {
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)) {
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)
static bool pdb_ads_get_trusteddom_pw(struct pdb_methods *m,
const char *domain, char** pwd,
- DOM_SID *sid,
+ struct dom_sid *sid,
time_t *pass_last_set_time)
{
return false;
static bool pdb_ads_set_trusteddom_pw(struct pdb_methods *m,
const char* domain, const char* pwd,
- const DOM_SID *sid)
+ const struct dom_sid *sid)
{
return false;
}
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;
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;
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;
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;
+ strlcpy(state->socket_address.sun_path, location,
+ sizeof(state->socket_address.sun_path));
+
+ 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;
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;
/*
* 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;
}
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;
}
char *tmp = NULL;
NTSTATUS status;
- m = talloc(talloc_autofree_context(), struct pdb_methods);
+ m = talloc(NULL, struct pdb_methods);
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;
}