summaryrefslogtreecommitdiffstats
path: root/source3/passdb
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2011-06-24 16:26:23 +1000
committerAndrew Bartlett <abartlet@samba.org>2011-06-24 16:26:23 +1000
commit6da26870e0ae5acd6ff49a30ec2f6886b44d095e (patch)
tree850c71039563c16a5d563c47e7ba2ab645baf198 /source3/passdb
parent6925a799d04c6fa59dd2ddef1f5510f9bb7d17d1 (diff)
parent2610c05b5b95cc7036b3d6dfb894c6cfbdb68483 (diff)
downloadsamba-f3218697433d586bd8209de513d8f6160e13405d.tar.gz
samba-f3218697433d586bd8209de513d8f6160e13405d.tar.xz
samba-f3218697433d586bd8209de513d8f6160e13405d.zip
Merge 2610c05b5b95cc7036b3d6dfb894c6cfbdb68483 as Samba-4.0alpha16samba-4.0.0alpha16
Diffstat (limited to 'source3/passdb')
-rw-r--r--source3/passdb/login_cache.c5
-rw-r--r--source3/passdb/lookup_sid.c14
-rw-r--r--source3/passdb/machine_account_secrets.c59
-rw-r--r--source3/passdb/machine_sid.c8
-rw-r--r--source3/passdb/machine_sid.h21
-rw-r--r--source3/passdb/passdb.c17
-rw-r--r--source3/passdb/pdb_get_set.c5
-rw-r--r--source3/passdb/pdb_interface.c108
-rw-r--r--source3/passdb/pdb_ipa.c6
-rw-r--r--source3/passdb/pdb_ldap.c28
-rw-r--r--source3/passdb/pdb_samba4.c2100
-rw-r--r--source3/passdb/pdb_smbpasswd.c8
-rw-r--r--source3/passdb/pdb_tdb.c1
-rw-r--r--source3/passdb/pdb_wbc_sam.c2
-rw-r--r--source3/passdb/proto.h40
-rw-r--r--source3/passdb/secrets.c5
-rw-r--r--source3/passdb/wscript_build13
17 files changed, 2388 insertions, 52 deletions
diff --git a/source3/passdb/login_cache.c b/source3/passdb/login_cache.c
index 1785a4dacac..a53fe5b24f7 100644
--- a/source3/passdb/login_cache.c
+++ b/source3/passdb/login_cache.c
@@ -20,6 +20,7 @@
#include "includes.h"
#include "system/filesys.h"
#include "passdb.h"
+#include "util_tdb.h"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_PASSDB
@@ -58,10 +59,10 @@ bool login_cache_init(void)
bool login_cache_shutdown(void)
{
- /* tdb_close routine returns -1 on error */
+ /* tdb_close routine returns non-zero on error */
if (!cache) return False;
DEBUG(5, ("Closing cache file\n"));
- return tdb_close(cache) != -1;
+ return tdb_close(cache) == 0;
}
/* if we can't read the cache, oh well, no need to return anything */
diff --git a/source3/passdb/lookup_sid.c b/source3/passdb/lookup_sid.c
index 5cf391f11c7..8b5330c0974 100644
--- a/source3/passdb/lookup_sid.c
+++ b/source3/passdb/lookup_sid.c
@@ -482,8 +482,8 @@ static bool lookup_rids(TALLOC_CTX *mem_ctx, const struct dom_sid *domain_sid,
sid_string_dbg(domain_sid)));
if (num_rids) {
- *names = TALLOC_ZERO_ARRAY(mem_ctx, const char *, num_rids);
- *types = TALLOC_ARRAY(mem_ctx, enum lsa_SidType, num_rids);
+ *names = talloc_zero_array(mem_ctx, const char *, num_rids);
+ *types = talloc_array(mem_ctx, enum lsa_SidType, num_rids);
if ((*names == NULL) || (*types == NULL)) {
return false;
@@ -750,7 +750,7 @@ NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
}
if (num_sids) {
- name_infos = TALLOC_ARRAY(mem_ctx, struct lsa_name_info, num_sids);
+ name_infos = talloc_array(mem_ctx, struct lsa_name_info, num_sids);
if (name_infos == NULL) {
result = NT_STATUS_NO_MEMORY;
goto fail;
@@ -759,7 +759,7 @@ NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
name_infos = NULL;
}
- dom_infos = TALLOC_ZERO_ARRAY(mem_ctx, struct lsa_dom_info,
+ dom_infos = talloc_zero_array(mem_ctx, struct lsa_dom_info,
LSA_REF_DOMAIN_LIST_MULTIPLIER);
if (dom_infos == NULL) {
result = NT_STATUS_NO_MEMORY;
@@ -896,7 +896,7 @@ NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
}
if (dom->num_idxs) {
- if (!(rids = TALLOC_ARRAY(tmp_ctx, uint32, dom->num_idxs))) {
+ if (!(rids = talloc_array(tmp_ctx, uint32, dom->num_idxs))) {
result = NT_STATUS_NO_MEMORY;
goto fail;
}
@@ -1404,7 +1404,7 @@ bool sids_to_unix_ids(const struct dom_sid *sids, uint32_t num_sids,
wbcErr err;
bool ret = false;
- wbc_sids = TALLOC_ARRAY(talloc_tos(), struct wbcDomainSid, num_sids);
+ wbc_sids = talloc_array(talloc_tos(), struct wbcDomainSid, num_sids);
if (wbc_sids == NULL) {
return false;
}
@@ -1455,7 +1455,7 @@ bool sids_to_unix_ids(const struct dom_sid *sids, uint32_t num_sids,
if (num_not_cached == 0) {
goto done;
}
- wbc_ids = TALLOC_ARRAY(talloc_tos(), struct wbcUnixId, num_not_cached);
+ wbc_ids = talloc_array(talloc_tos(), struct wbcUnixId, num_not_cached);
if (wbc_ids == NULL) {
goto fail;
}
diff --git a/source3/passdb/machine_account_secrets.c b/source3/passdb/machine_account_secrets.c
index a51a99c9a2f..665e2f89a45 100644
--- a/source3/passdb/machine_account_secrets.c
+++ b/source3/passdb/machine_account_secrets.c
@@ -28,6 +28,7 @@
#include "secrets.h"
#include "dbwrap.h"
#include "../librpc/ndr/libndr.h"
+#include "util_tdb.h"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_PASSDB
@@ -56,6 +57,17 @@ bool secrets_store_domain_sid(const char *domain, const struct dom_sid *sid)
{
bool ret;
+#ifdef _SAMBA_WAF_BUILD_
+ if (strequal(domain, get_global_sam_name()) &&
+ (pdb_capabilities() & PDB_CAP_ADS)) {
+ /* If we have a ADS-capable passdb backend, we
+ * must never make up our own SID, it will
+ * already be in the directory */
+ DEBUG(0, ("Refusing to store a Domain SID, this should be read from the directory not stored here\n"));
+ return false;
+ }
+#endif
+
ret = secrets_store(domain_sid_keystr(domain), sid, sizeof(struct dom_sid ));
/* Force a re-query, in case we modified our domain */
@@ -69,6 +81,24 @@ bool secrets_fetch_domain_sid(const char *domain, struct dom_sid *sid)
struct dom_sid *dyn_sid;
size_t size = 0;
+#ifdef _SAMBA_WAF_BUILD_
+ if (strequal(domain, get_global_sam_name()) &&
+ (pdb_capabilities() & PDB_CAP_ADS)) {
+ struct pdb_domain_info *domain_info;
+ domain_info = pdb_get_domain_info(talloc_tos());
+ if (!domain_info) {
+ /* If we have a ADS-capable passdb backend, we
+ * must never make up our own SID, it will
+ * already be in the directory */
+ DEBUG(0, ("Unable to fetch a Domain SID from the directory!\n"));
+ return false;
+ }
+
+ *sid = domain_info->sid;
+ return true;
+ }
+#endif
+
dyn_sid = (struct dom_sid *)secrets_fetch(domain_sid_keystr(domain), &size);
if (dyn_sid == NULL)
@@ -88,6 +118,17 @@ bool secrets_store_domain_guid(const char *domain, struct GUID *guid)
{
fstring key;
+#ifdef _SAMBA_WAF_BUILD_
+ if (strequal(domain, get_global_sam_name()) &&
+ (pdb_capabilities() & PDB_CAP_ADS)) {
+ /* If we have a ADS-capable passdb backend, we
+ * must never make up our own GUID, it will
+ * already be in the directory */
+ DEBUG(0, ("Refusing to store a Domain GUID, this should be read from the directory not stored here\n"));
+ return false;
+ }
+#endif
+
slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain);
strupper_m(key);
return secrets_store(key, guid, sizeof(struct GUID));
@@ -100,6 +141,24 @@ bool secrets_fetch_domain_guid(const char *domain, struct GUID *guid)
size_t size = 0;
struct GUID new_guid;
+#ifdef _SAMBA_WAF_BUILD_
+ if (strequal(domain, get_global_sam_name()) &&
+ (pdb_capabilities() & PDB_CAP_ADS)) {
+ struct pdb_domain_info *domain_info;
+ domain_info = pdb_get_domain_info(talloc_tos());
+ if (!domain_info) {
+ /* If we have a ADS-capable passdb backend, we
+ * must never make up our own SID, it will
+ * already be in the directory */
+ DEBUG(0, ("Unable to fetch a Domain GUID from the directory!\n"));
+ return false;
+ }
+
+ *guid = domain_info->guid;
+ return true;
+ }
+#endif
+
slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain);
strupper_m(key);
dyn_guid = (struct GUID *)secrets_fetch(key, &size);
diff --git a/source3/passdb/machine_sid.c b/source3/passdb/machine_sid.c
index 8fd51031648..6d4cf237c77 100644
--- a/source3/passdb/machine_sid.c
+++ b/source3/passdb/machine_sid.c
@@ -97,7 +97,7 @@ static struct dom_sid *pdb_generate_sam_sid(void)
}
}
- if (secrets_fetch_domain_sid(global_myname(), sam_sid)) {
+ if (secrets_fetch_domain_sid(lp_netbios_name(), sam_sid)) {
/* We got our sid. If not a pdc/bdc, we're done. */
if ( !IS_DC )
@@ -120,7 +120,7 @@ static struct dom_sid *pdb_generate_sam_sid(void)
/* Domain name sid doesn't match global sam sid. Re-store domain sid as 'local' sid. */
DEBUG(0,("pdb_generate_sam_sid: Mismatched SIDs as a pdc/bdc.\n"));
- if (!secrets_store_domain_sid(global_myname(), &domain_sid)) {
+ if (!secrets_store_domain_sid(lp_netbios_name(), &domain_sid)) {
DEBUG(0,("pdb_generate_sam_sid: Can't re-store domain SID for local sid as PDC/BDC.\n"));
SAFE_FREE(sam_sid);
return NULL;
@@ -139,7 +139,7 @@ static struct dom_sid *pdb_generate_sam_sid(void)
if (read_sid_from_file(fname, sam_sid)) {
/* remember it for future reference and unlink the old MACHINE.SID */
- if (!secrets_store_domain_sid(global_myname(), sam_sid)) {
+ if (!secrets_store_domain_sid(lp_netbios_name(), sam_sid)) {
DEBUG(0,("pdb_generate_sam_sid: Failed to store SID from file.\n"));
SAFE_FREE(fname);
SAFE_FREE(sam_sid);
@@ -166,7 +166,7 @@ static struct dom_sid *pdb_generate_sam_sid(void)
generate one and save it */
generate_random_sid(sam_sid);
- if (!secrets_store_domain_sid(global_myname(), sam_sid)) {
+ if (!secrets_store_domain_sid(lp_netbios_name(), sam_sid)) {
DEBUG(0,("pdb_generate_sam_sid: Failed to store generated machine SID.\n"));
SAFE_FREE(sam_sid);
return NULL;
diff --git a/source3/passdb/machine_sid.h b/source3/passdb/machine_sid.h
index 2da281ac34c..12fde2f3ac6 100644
--- a/source3/passdb/machine_sid.h
+++ b/source3/passdb/machine_sid.h
@@ -1,3 +1,24 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * Password and authentication handling
+ * Copyright (C) Jeremy Allison 1996-2002
+ * Copyright (C) Andrew Tridgell 2002
+ * Copyright (C) Gerald (Jerry) Carter 2000
+ * Copyright (C) Stefan (metze) Metzmacher 2002
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
/* The following definitions come from passdb/machine_sid.c */
diff --git a/source3/passdb/passdb.c b/source3/passdb/passdb.c
index 62af5be7eb4..5116396cd1b 100644
--- a/source3/passdb/passdb.c
+++ b/source3/passdb/passdb.c
@@ -29,6 +29,7 @@
#include "secrets.h"
#include "../libcli/security/security.h"
#include "../lib/util/util_pw.h"
+#include "util_tdb.h"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_PASSDB
@@ -45,7 +46,7 @@ const char *my_sam_name(void)
{
/* Standalone servers can only use the local netbios name */
if ( lp_server_role() == ROLE_STANDALONE )
- return global_myname();
+ return lp_netbios_name();
/* Default to the DOMAIN name when not specified */
return lp_workgroup();
@@ -73,7 +74,7 @@ struct samu *samu_new( TALLOC_CTX *ctx )
{
struct samu *user;
- if ( !(user = TALLOC_ZERO_P( ctx, struct samu )) ) {
+ if ( !(user = talloc_zero( ctx, struct samu )) ) {
DEBUG(0,("samuser_new: Talloc failed!\n"));
return NULL;
}
@@ -148,7 +149,7 @@ static int count_commas(const char *str)
static NTSTATUS samu_set_unix_internal(struct samu *user, const struct passwd *pwd, bool create)
{
const char *guest_account = lp_guestaccount();
- const char *domain = global_myname();
+ const char *domain = lp_netbios_name();
char *fullname;
uint32_t urid;
@@ -384,9 +385,9 @@ void pdb_sethexpwd(char p[33], const unsigned char *pwd, uint32_t acct_ctrl)
slprintf(&p[i*2], 3, "%02X", pwd[i]);
} else {
if (acct_ctrl & ACB_PWNOTREQ)
- safe_strcpy(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 32);
+ strlcpy(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 33);
else
- safe_strcpy(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 32);
+ strlcpy(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 33);
}
}
@@ -435,7 +436,7 @@ void pdb_sethexhours(char *p, const unsigned char *hours)
slprintf(&p[i*2], 3, "%02X", hours[i]);
}
} else {
- safe_strcpy(p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 43);
+ strlcpy(p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 44);
}
}
@@ -2354,7 +2355,7 @@ bool get_trust_pw_clear(const char *domain, char **ret_pwd,
if (pwd != NULL) {
*ret_pwd = pwd;
if (account_name != NULL) {
- *account_name = global_myname();
+ *account_name = lp_netbios_name();
}
return true;
@@ -2392,7 +2393,7 @@ bool get_trust_pw_hash(const char *domain, uint8_t ret_pwd[16],
channel))
{
if (account_name != NULL) {
- *account_name = global_myname();
+ *account_name = lp_netbios_name();
}
return true;
diff --git a/source3/passdb/pdb_get_set.c b/source3/passdb/pdb_get_set.c
index 6c1a2ab23d7..eec82f9c984 100644
--- a/source3/passdb/pdb_get_set.c
+++ b/source3/passdb/pdb_get_set.c
@@ -123,8 +123,7 @@ time_t pdb_get_pass_must_change_time(const struct samu *sampass)
bool pdb_get_pass_can_change(const struct samu *sampass)
{
- if (sampass->pass_can_change_time == get_time_t_max() &&
- sampass->pass_last_set_time != 0)
+ if (sampass->pass_can_change_time == get_time_t_max())
return False;
return True;
}
@@ -512,7 +511,7 @@ bool pdb_set_group_sid(struct samu *sampass, const struct dom_sid *g_sid, enum p
if (!g_sid)
return False;
- if ( !(sampass->group_sid = TALLOC_P( sampass, struct dom_sid )) ) {
+ if ( !(sampass->group_sid = talloc( sampass, struct dom_sid )) ) {
return False;
}
diff --git a/source3/passdb/pdb_interface.c b/source3/passdb/pdb_interface.c
index 36d5aaa01a7..94ed355e2c5 100644
--- a/source3/passdb/pdb_interface.c
+++ b/source3/passdb/pdb_interface.c
@@ -25,6 +25,8 @@
#include "passdb.h"
#include "secrets.h"
#include "../librpc/gen_ndr/samr.h"
+#include "../librpc/gen_ndr/drsblobs.h"
+#include "../librpc/gen_ndr/ndr_drsblobs.h"
#include "memcache.h"
#include "nsswitch/winbind_client.h"
#include "../libcli/security/security.h"
@@ -1518,7 +1520,7 @@ static NTSTATUS pdb_default_enum_group_members(struct pdb_methods *methods,
if (num_uids == 0)
return NT_STATUS_OK;
- *pp_member_rids = TALLOC_ZERO_ARRAY(mem_ctx, uint32_t, num_uids);
+ *pp_member_rids = talloc_zero_array(mem_ctx, uint32_t, num_uids);
for (i=0; i<num_uids; i++) {
struct dom_sid sid;
@@ -1570,7 +1572,7 @@ static NTSTATUS pdb_default_enum_group_memberships(struct pdb_methods *methods,
smb_panic("primary group missing");
}
- *pp_sids = TALLOC_ARRAY(mem_ctx, struct dom_sid, *p_num_groups);
+ *pp_sids = talloc_array(mem_ctx, struct dom_sid, *p_num_groups);
if (*pp_sids == NULL) {
TALLOC_FREE(*pp_gids);
@@ -2144,7 +2146,62 @@ static NTSTATUS pdb_default_get_trusted_domain(struct pdb_methods *methods,
const char *domain,
struct pdb_trusted_domain **td)
{
- return NT_STATUS_NOT_IMPLEMENTED;
+ struct trustAuthInOutBlob taiob;
+ struct AuthenticationInformation aia;
+ struct pdb_trusted_domain *tdom;
+ enum ndr_err_code ndr_err;
+ time_t last_set_time;
+ char *pwd;
+ bool ok;
+
+ tdom = talloc(mem_ctx, struct pdb_trusted_domain);
+ if (!tdom) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ tdom->domain_name = talloc_strdup(tdom, domain);
+ tdom->netbios_name = talloc_strdup(tdom, domain);
+ if (!tdom->domain_name || !tdom->netbios_name) {
+ talloc_free(tdom);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ tdom->trust_auth_incoming = data_blob_null;
+
+ ok = pdb_get_trusteddom_pw(domain, &pwd, &tdom->security_identifier,
+ &last_set_time);
+ if (!ok) {
+ talloc_free(tdom);
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ ZERO_STRUCT(taiob);
+ ZERO_STRUCT(aia);
+ taiob.count = 1;
+ taiob.current.count = 1;
+ taiob.current.array = &aia;
+ unix_to_nt_time(&aia.LastUpdateTime, last_set_time);
+ aia.AuthType = TRUST_AUTH_TYPE_CLEAR;
+ aia.AuthInfo.clear.password = (uint8_t *) pwd;
+ aia.AuthInfo.clear.size = strlen(pwd);
+ taiob.previous.count = 0;
+ taiob.previous.array = NULL;
+
+ ndr_err = ndr_push_struct_blob(&tdom->trust_auth_outgoing,
+ tdom, &taiob,
+ (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ talloc_free(tdom);
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ tdom->trust_direction = LSA_TRUST_DIRECTION_OUTBOUND;
+ tdom->trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
+ tdom->trust_attributes = 0;
+ tdom->trust_forest_trust_info = data_blob_null;
+
+ *td = tdom;
+ return NT_STATUS_OK;
}
static NTSTATUS pdb_default_get_trusted_domain_by_sid(struct pdb_methods *methods,
@@ -2155,11 +2212,54 @@ static NTSTATUS pdb_default_get_trusted_domain_by_sid(struct pdb_methods *method
return NT_STATUS_NOT_IMPLEMENTED;
}
+#define IS_NULL_DATA_BLOB(d) ((d).data == NULL && (d).length == 0)
+
static NTSTATUS pdb_default_set_trusted_domain(struct pdb_methods *methods,
const char* domain,
const struct pdb_trusted_domain *td)
{
- return NT_STATUS_NOT_IMPLEMENTED;
+ struct trustAuthInOutBlob taiob;
+ struct AuthenticationInformation *aia;
+ enum ndr_err_code ndr_err;
+ char *pwd;
+ bool ok;
+
+ if (td->trust_attributes != 0 ||
+ td->trust_type != LSA_TRUST_TYPE_DOWNLEVEL ||
+ td->trust_direction != LSA_TRUST_DIRECTION_OUTBOUND ||
+ !IS_NULL_DATA_BLOB(td->trust_auth_incoming) ||
+ !IS_NULL_DATA_BLOB(td->trust_forest_trust_info)) {
+ return NT_STATUS_NOT_IMPLEMENTED;
+ }
+
+ ZERO_STRUCT(taiob);
+ ndr_err = ndr_pull_struct_blob(&td->trust_auth_outgoing, talloc_tos(),
+ &taiob,
+ (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ aia = (struct AuthenticationInformation *) taiob.current.array;
+
+ if (taiob.count != 1 || taiob.current.count != 1 ||
+ taiob.previous.count != 0 ||
+ aia->AuthType != TRUST_AUTH_TYPE_CLEAR) {
+ return NT_STATUS_NOT_IMPLEMENTED;
+ }
+
+ pwd = talloc_strndup(talloc_tos(), (char *) aia->AuthInfo.clear.password,
+ aia->AuthInfo.clear.size);
+ if (!pwd) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ ok = pdb_set_trusteddom_pw(domain, pwd, &td->security_identifier);
+ if (!ok) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ return NT_STATUS_OK;
}
static NTSTATUS pdb_default_del_trusted_domain(struct pdb_methods *methods,
diff --git a/source3/passdb/pdb_ipa.c b/source3/passdb/pdb_ipa.c
index 5f89be7a29f..02f7bb68888 100644
--- a/source3/passdb/pdb_ipa.c
+++ b/source3/passdb/pdb_ipa.c
@@ -636,7 +636,7 @@ static NTSTATUS ipasam_enum_trusted_domains(struct pdb_methods *methods,
}
*num_domains = 0;
- if (!(*domains = TALLOC_ARRAY(mem_ctx, struct pdb_trusted_domain *, 1))) {
+ if (!(*domains = talloc_array(mem_ctx, struct pdb_trusted_domain *, 1))) {
DEBUG(1, ("talloc failed\n"));
return NT_STATUS_NO_MEMORY;
}
@@ -684,7 +684,7 @@ static NTSTATUS ipasam_enum_trusteddoms(struct pdb_methods *methods,
return NT_STATUS_OK;
}
- if (!(*domains = TALLOC_ARRAY(mem_ctx, struct trustdom_info *,
+ if (!(*domains = talloc_array(mem_ctx, struct trustdom_info *,
*num_domains))) {
DEBUG(1, ("talloc failed\n"));
return NT_STATUS_NO_MEMORY;
@@ -693,7 +693,7 @@ static NTSTATUS ipasam_enum_trusteddoms(struct pdb_methods *methods,
for (i = 0; i < *num_domains; i++) {
struct trustdom_info *dom_info;
- dom_info = TALLOC_P(*domains, struct trustdom_info);
+ dom_info = talloc(*domains, struct trustdom_info);
if (dom_info == NULL) {
DEBUG(1, ("talloc failed\n"));
return NT_STATUS_NO_MEMORY;
diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c
index 7ce5edcefa9..f8da0ff2553 100644
--- a/source3/passdb/pdb_ldap.c
+++ b/source3/passdb/pdb_ldap.c
@@ -208,7 +208,7 @@ static NTSTATUS ldapsam_get_seq_num(struct pdb_methods *my_methods, time_t *seq_
if (mem_ctx == NULL)
return NT_STATUS_NO_MEMORY;
- if ((attrs = TALLOC_ARRAY(mem_ctx, const char *, 2)) == NULL) {
+ if ((attrs = talloc_array(mem_ctx, const char *, 2)) == NULL) {
ntstatus = NT_STATUS_NO_MEMORY;
goto done;
}
@@ -887,7 +887,7 @@ static bool init_sam_from_ldap(struct ldapsam_privates *ldap_state,
if (pwHistLen > 0){
uint8 *pwhist = NULL;
int i;
- char *history_string = TALLOC_ARRAY(ctx, char,
+ char *history_string = talloc_array(ctx, char,
MAX_PW_HISTORY_LEN*64);
if (!history_string) {
@@ -896,7 +896,7 @@ static bool init_sam_from_ldap(struct ldapsam_privates *ldap_state,
pwHistLen = MIN(pwHistLen, MAX_PW_HISTORY_LEN);
- pwhist = TALLOC_ARRAY(ctx, uint8,
+ pwhist = talloc_array(ctx, uint8,
pwHistLen * PW_HISTORY_ENTRY_LEN);
if (pwhist == NULL) {
DEBUG(0, ("init_sam_from_ldap: talloc failed!\n"));
@@ -1532,7 +1532,7 @@ static void append_attr(TALLOC_CTX *mem_ctx, const char ***attr_list,
;
}
- (*attr_list) = TALLOC_REALLOC_ARRAY(mem_ctx, (*attr_list),
+ (*attr_list) = talloc_realloc(mem_ctx, (*attr_list),
const char *, i+2);
SMB_ASSERT((*attr_list) != NULL);
(*attr_list)[i] = talloc_strdup((*attr_list), new_attr);
@@ -4340,7 +4340,7 @@ static const char **talloc_attrs(TALLOC_CTX *mem_ctx, ...)
num += 1;
va_end(ap);
- if ((result = TALLOC_ARRAY(mem_ctx, const char *, num+1)) == NULL) {
+ if ((result = talloc_array(mem_ctx, const char *, num+1)) == NULL) {
return NULL;
}
@@ -4564,7 +4564,7 @@ static bool ldapuser2displayentry(struct ldap_search_state *state,
return False;
}
if (!pull_utf8_talloc(mem_ctx,
- CONST_DISCARD(char **, &result->account_name),
+ discard_const_p(char *, &result->account_name),
vals[0], &converted_size))
{
DEBUG(0,("ldapuser2displayentry: pull_utf8_talloc failed: %s",
@@ -4577,7 +4577,7 @@ static bool ldapuser2displayentry(struct ldap_search_state *state,
if ((vals == NULL) || (vals[0] == NULL))
DEBUG(8, ("\"displayName\" not found\n"));
else if (!pull_utf8_talloc(mem_ctx,
- CONST_DISCARD(char **, &result->fullname),
+ discard_const_p(char *, &result->fullname),
vals[0], &converted_size))
{
DEBUG(0,("ldapuser2displayentry: pull_utf8_talloc failed: %s",
@@ -4590,7 +4590,7 @@ static bool ldapuser2displayentry(struct ldap_search_state *state,
if ((vals == NULL) || (vals[0] == NULL))
DEBUG(8, ("\"description\" not found\n"));
else if (!pull_utf8_talloc(mem_ctx,
- CONST_DISCARD(char **, &result->description),
+ discard_const_p(char *, &result->description),
vals[0], &converted_size))
{
DEBUG(0,("ldapuser2displayentry: pull_utf8_talloc failed: %s",
@@ -4724,7 +4724,7 @@ static bool ldapgroup2displayentry(struct ldap_search_state *state,
return False;
}
if (!pull_utf8_talloc(mem_ctx,
- CONST_DISCARD(char **,
+ discard_const_p(char *,
&result->account_name),
vals[0], &converted_size))
{
@@ -4733,7 +4733,7 @@ static bool ldapgroup2displayentry(struct ldap_search_state *state,
}
}
else if (!pull_utf8_talloc(mem_ctx,
- CONST_DISCARD(char **,
+ discard_const_p(char *,
&result->account_name),
vals[0], &converted_size))
{
@@ -4747,7 +4747,7 @@ static bool ldapgroup2displayentry(struct ldap_search_state *state,
if ((vals == NULL) || (vals[0] == NULL))
DEBUG(8, ("\"description\" not found\n"));
else if (!pull_utf8_talloc(mem_ctx,
- CONST_DISCARD(char **, &result->description),
+ discard_const_p(char *, &result->description),
vals[0], &converted_size))
{
DEBUG(0,("ldapgroup2displayentry: pull_utf8_talloc failed: %s",
@@ -6356,7 +6356,7 @@ static NTSTATUS ldapsam_enum_trusteddoms(struct pdb_methods *methods,
}
*num_domains = 0;
- if (!(*domains = TALLOC_ARRAY(mem_ctx, struct trustdom_info *, 1))) {
+ if (!(*domains = talloc_array(mem_ctx, struct trustdom_info *, 1))) {
DEBUG(1, ("talloc failed\n"));
return NT_STATUS_NO_MEMORY;
}
@@ -6368,7 +6368,7 @@ static NTSTATUS ldapsam_enum_trusteddoms(struct pdb_methods *methods,
char *dom_name, *dom_sid_str;
struct trustdom_info *dom_info;
- dom_info = TALLOC_P(*domains, struct trustdom_info);
+ dom_info = talloc(*domains, struct trustdom_info);
if (dom_info == NULL) {
DEBUG(1, ("talloc failed\n"));
return NT_STATUS_NO_MEMORY;
@@ -6480,7 +6480,7 @@ static NTSTATUS pdb_init_ldapsam_common(struct pdb_methods **pdb_method, const c
/* TODO: Setup private data and free */
- if ( !(ldap_state = TALLOC_ZERO_P(*pdb_method, struct ldapsam_privates)) ) {
+ if ( !(ldap_state = talloc_zero(*pdb_method, struct ldapsam_privates)) ) {
DEBUG(0, ("pdb_init_ldapsam_common: talloc() failed for ldapsam private_data!\n"));
return NT_STATUS_NO_MEMORY;
}
diff --git a/source3/passdb/pdb_samba4.c b/source3/passdb/pdb_samba4.c
new file mode 100644
index 00000000000..5848c23de8e
--- /dev/null
+++ b/source3/passdb/pdb_samba4.c
@@ -0,0 +1,2100 @@
+/*
+ Unix SMB/CIFS implementation.
+ pdb glue module for samba4
+ Copyright (C) Volker Lendecke 2009-2011
+ Copyright (C) Andrew Bartlett 2010
+ Copyright (C) Matthias Dieter Wallnöfer 2009
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/* This module, is a port of Volker's pdb_ads to ldb and DSDB APIs */
+
+#include "includes.h"
+#include "source3/include/passdb.h"
+#include "source4/dsdb/samdb/samdb.h"
+#include "ldb_errors.h"
+#include "libcli/security/dom_sid.h"
+#include "source4/winbind/idmap.h"
+#include "librpc/gen_ndr/ndr_security.h"
+#include "libds/common/flag_mapping.h"
+#include "source4/lib/events/events.h"
+#include "source4/auth/session.h"
+#include "source4/auth/system_session_proto.h"
+#include "source4/param/param.h"
+
+struct pdb_samba4_state {
+ struct tevent_context *ev;
+ struct ldb_context *ldb;
+ struct idmap_context *idmap_ctx;
+ struct loadparm_context *lp_ctx;
+};
+
+static NTSTATUS pdb_samba4_getsampwsid(struct pdb_methods *m,
+ struct samu *sam_acct,
+ const struct dom_sid *sid);
+static NTSTATUS pdb_samba4_getsamupriv(struct pdb_samba4_state *state,
+ const char *filter,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_message **pmsg);
+static bool pdb_samba4_sid_to_id(struct pdb_methods *m, const struct dom_sid *sid,
+ union unid_t *id, enum lsa_SidType *type);
+
+static bool pdb_samba4_pull_time(struct ldb_message *msg, const char *attr,
+ time_t *ptime)
+{
+ uint64_t tmp;
+ if (! ldb_msg_find_element(msg, attr)) {
+ return false;
+ }
+ tmp = ldb_msg_find_attr_as_uint64(msg, attr, 0);
+ *ptime = uint64s_nt_time_to_unix_abs(&tmp);
+ return true;
+}
+
+static struct pdb_domain_info *pdb_samba4_get_domain_info(
+ struct pdb_methods *m, TALLOC_CTX *mem_ctx)
+{
+ struct pdb_samba4_state *state = talloc_get_type_abort(
+ m->private_data, struct pdb_samba4_state);
+ struct pdb_domain_info *info;
+ struct dom_sid *domain_sid;
+ struct ldb_dn *forest_dn, *domain_dn;
+ struct ldb_result *dom_res = NULL;
+ const char *dom_attrs[] = {
+ "objectSid",
+ "objectGUID",
+ "nTMixedDomain",
+ "fSMORoleOwner",
+ NULL
+ };
+ char *p;
+ int ret;
+
+ info = talloc(mem_ctx, struct pdb_domain_info);
+ if (info == NULL) {
+ return NULL;
+ }
+
+ domain_dn = ldb_get_default_basedn(state->ldb);
+
+ ret = ldb_search(state->ldb, info, &dom_res,
+ domain_dn, LDB_SCOPE_BASE, dom_attrs, NULL);
+ if (ret != LDB_SUCCESS) {
+ goto fail;
+ }
+ if (dom_res->count != 1) {
+ goto fail;
+ }
+
+ info->guid = samdb_result_guid(dom_res->msgs[0], "objectGUID");
+
+ domain_sid = samdb_result_dom_sid(state, dom_res->msgs[0], "objectSid");
+ if (!domain_sid) {
+ goto fail;
+ }
+ info->sid = *domain_sid;
+
+ TALLOC_FREE(dom_res);
+
+ info->name = talloc_strdup(info, lpcfg_sam_name(state->lp_ctx));
+ info->dns_domain = ldb_dn_canonical_string(info, domain_dn);
+
+ if (!info->dns_domain) {
+ goto fail;
+ }
+ p = strchr(info->dns_domain, '/');
+ if (p) {
+ *p = '\0';
+ }
+
+ forest_dn = ldb_get_root_basedn(state->ldb);
+ if (!forest_dn) {
+ goto fail;
+ }
+
+ info->dns_forest = ldb_dn_canonical_string(info, forest_dn);
+ if (!info->dns_forest) {
+ goto fail;
+ }
+ p = strchr(info->dns_forest, '/');
+ if (p) {
+ *p = '\0';
+ }
+
+ return info;
+
+fail:
+ TALLOC_FREE(dom_res);
+ TALLOC_FREE(info);
+ return NULL;
+}
+
+static struct ldb_message *pdb_samba4_get_samu_private(
+ struct pdb_methods *m, struct samu *sam)
+{
+ struct pdb_samba4_state *state = talloc_get_type_abort(
+ m->private_data, struct pdb_samba4_state);
+ struct ldb_message *msg;
+ char *sidstr, *filter;
+ NTSTATUS status;
+
+ msg = (struct ldb_message *)
+ pdb_get_backend_private_data(sam, m);
+
+ if (msg != NULL) {
+ return talloc_get_type_abort(msg, struct ldb_message);
+ }
+
+ sidstr = dom_sid_string(talloc_tos(), pdb_get_user_sid(sam));
+ if (sidstr == NULL) {
+ return NULL;
+ }
+
+ filter = talloc_asprintf(
+ talloc_tos(), "(&(objectsid=%s)(objectclass=user))", sidstr);
+ TALLOC_FREE(sidstr);
+ if (filter == NULL) {
+ return NULL;
+ }
+
+ status = pdb_samba4_getsamupriv(state, filter, sam, &msg);
+ TALLOC_FREE(filter);
+ if (!NT_STATUS_IS_OK(status)) {
+ return NULL;
+ }
+
+ return msg;
+}
+
+static NTSTATUS pdb_samba4_init_sam_from_priv(struct pdb_methods *m,
+ struct samu *sam,
+ struct ldb_message *msg)
+{
+ struct pdb_samba4_state *state = talloc_get_type_abort(
+ m->private_data, struct pdb_samba4_state);
+ TALLOC_CTX *frame = talloc_stackframe();
+ NTSTATUS status = NT_STATUS_INTERNAL_DB_CORRUPTION;
+ const char *str;
+ time_t tmp_time;
+ struct dom_sid *sid, group_sid;
+ uint64_t n;
+ const DATA_BLOB *blob;
+
+ str = ldb_msg_find_attr_as_string(msg, "samAccountName", NULL);
+ if (str == NULL) {
+ DEBUG(10, ("no samAccountName\n"));
+ goto fail;
+ }
+ pdb_set_username(sam, str, PDB_SET);
+
+ if (pdb_samba4_pull_time(msg, "lastLogon", &tmp_time)) {
+ pdb_set_logon_time(sam, tmp_time, PDB_SET);
+ }
+ if (pdb_samba4_pull_time(msg, "lastLogoff", &tmp_time)) {
+ pdb_set_logoff_time(sam, tmp_time, PDB_SET);
+ }
+ if (pdb_samba4_pull_time(msg, "pwdLastSet", &tmp_time)) {
+ pdb_set_pass_last_set_time(sam, tmp_time, PDB_SET);
+ }
+ if (pdb_samba4_pull_time(msg, "accountExpires", &tmp_time)) {
+ pdb_set_kickoff_time(sam, tmp_time, PDB_SET);
+ }
+
+ str = ldb_msg_find_attr_as_string(msg, "displayName",
+ NULL);
+ if (str != NULL) {
+ pdb_set_fullname(sam, str, PDB_SET);
+ }
+
+ str = ldb_msg_find_attr_as_string(msg, "homeDirectory",
+ NULL);
+ if (str != NULL) {
+ pdb_set_homedir(sam, str, PDB_SET);
+ }
+
+ str = ldb_msg_find_attr_as_string(msg, "homeDrive", NULL);
+ if (str != NULL) {
+ pdb_set_dir_drive(sam, str, PDB_SET);
+ }
+
+ str = ldb_msg_find_attr_as_string(msg, "scriptPath", NULL);
+ if (str != NULL) {
+ pdb_set_logon_script(sam, str, PDB_SET);
+ }
+
+ str = ldb_msg_find_attr_as_string(msg, "profilePath",
+ NULL);
+ if (str != NULL) {
+ pdb_set_profile_path(sam, str, PDB_SET);
+ }
+
+ str = ldb_msg_find_attr_as_string(msg, "profilePath",
+ NULL);
+ if (str != NULL) {
+ pdb_set_profile_path(sam, str, PDB_SET);
+ }
+
+ str = ldb_msg_find_attr_as_string(msg, "comment",
+ NULL);
+ if (str != NULL) {
+ pdb_set_comment(sam, str, PDB_SET);
+ }
+
+ str = ldb_msg_find_attr_as_string(msg, "description",
+ NULL);
+ if (str != NULL) {
+ pdb_set_acct_desc(sam, str, PDB_SET);
+ }
+
+ str = ldb_msg_find_attr_as_string(msg, "userWorkstations",
+ NULL);
+ if (str != NULL) {
+ pdb_set_workstations(sam, str, PDB_SET);
+ }
+
+ str = ldb_msg_find_attr_as_string(msg, "userParameters",
+ NULL);
+ if (str != NULL) {
+ pdb_set_munged_dial(sam, str, PDB_SET);
+ }
+
+ sid = samdb_result_dom_sid(talloc_tos(), msg, "objectSid");
+ if (!sid) {
+ DEBUG(10, ("Could not pull SID\n"));
+ goto fail;
+ }
+ pdb_set_user_sid(sam, sid, PDB_SET);
+
+ n = ldb_msg_find_attr_as_uint(msg, "userAccountControl", 0);
+ if (n == 0) {
+ DEBUG(10, ("Could not pull userAccountControl\n"));
+ goto fail;
+ }
+ pdb_set_acct_ctrl(sam, ds_uf2acb(n), PDB_SET);
+
+ blob = ldb_msg_find_ldb_val(msg, "unicodePwd");
+ if (blob) {
+ if (blob->length != NT_HASH_LEN) {
+ DEBUG(0, ("Got NT hash of length %d, expected %d\n",
+ (int)blob->length, NT_HASH_LEN));
+ goto fail;
+ }
+ pdb_set_nt_passwd(sam, blob->data, PDB_SET);
+ }
+
+ blob = ldb_msg_find_ldb_val(msg, "dBCSPwd");
+ if (blob) {
+ if (blob->length != LM_HASH_LEN) {
+ DEBUG(0, ("Got LM hash of length %d, expected %d\n",
+ (int)blob->length, LM_HASH_LEN));
+ goto fail;
+ }
+ pdb_set_lanman_passwd(sam, blob->data, PDB_SET);
+ }
+
+ n = ldb_msg_find_attr_as_uint(msg, "primaryGroupID", 0);
+ if (n == 0) {
+ DEBUG(10, ("Could not pull primaryGroupID\n"));
+ goto fail;
+ }
+ sid_compose(&group_sid, samdb_domain_sid(state->ldb), n);
+ pdb_set_group_sid(sam, &group_sid, PDB_SET);
+
+ status = NT_STATUS_OK;
+fail:
+ TALLOC_FREE(frame);
+ return status;
+}
+
+static bool pdb_samba4_add_time(struct ldb_message *msg,
+ const char *attrib, time_t t)
+{
+ uint64_t nt_time;
+
+ unix_to_nt_time(&nt_time, t);
+
+ return ldb_msg_add_fmt(msg, attrib, "%llu", (unsigned long long) nt_time);
+}
+
+/* Like in pdb_ldap(), this will need to be a function pointer when we
+ * start to support 'adds' for migrations from samba3 passdb backends
+ * to samba4 */
+static bool update_required(struct samu *sam, enum pdb_elements element)
+{
+ return (IS_SAM_CHANGED(sam, element));
+}
+
+static bool pdb_samba4_init_samba4_from_sam(struct pdb_samba4_state *state,
+ struct ldb_message *existing,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_message **pmods,
+ struct samu *sam)
+{
+ int ret = LDB_SUCCESS;
+ const char *pw;
+ struct ldb_message *msg;
+
+ /* TODO: All fields :-) */
+
+ msg = ldb_msg_new(mem_ctx);
+ if (!msg) {
+ return false;
+ }
+
+ msg->dn = existing->dn;
+
+ pw = pdb_get_plaintext_passwd(sam);
+ if (update_required(sam, PDB_PLAINTEXT_PW)) {
+ if (pw == NULL) {
+ ret = LDB_ERR_OPERATIONS_ERROR;
+ goto fail;
+ }
+
+ ret |= ldb_msg_add_string(msg, "clearTextPassword", pw);
+ }
+
+ if (update_required(sam, PDB_FULLNAME)) {
+ ret |= ldb_msg_add_string(msg, "displayName", pdb_get_fullname(sam));
+ }
+
+ if (update_required(sam, PDB_SMBHOME)) {
+ ret |= ldb_msg_add_string(msg, "homeDirectory",
+ pdb_get_homedir(sam));
+ }
+
+ if (update_required(sam, PDB_PROFILE)) {
+ ret |= ldb_msg_add_string(msg, "profilePath",
+ pdb_get_profile_path(sam));
+ }
+
+ if (update_required(sam, PDB_DRIVE)) {
+ ret |= ldb_msg_add_string(msg, "homeDrive",
+ pdb_get_dir_drive(sam));
+ }
+
+ if (update_required(sam, PDB_LOGONSCRIPT)) {
+ ret |= ldb_msg_add_string(msg, "scriptPath",
+ pdb_get_logon_script(sam));
+ }
+
+ if (update_required(sam, PDB_KICKOFFTIME)) {
+ ret |= pdb_samba4_add_time(msg, "accountExpires",
+ pdb_get_kickoff_time(sam));
+ }
+
+ if (update_required(sam, PDB_USERNAME)) {
+ ret |= ldb_msg_add_string(msg, "samAccountName",
+ pdb_get_username(sam));
+ }
+
+ if (update_required(sam, PDB_HOURSLEN) || update_required(sam, PDB_HOURS)) {
+ struct ldb_val hours = data_blob_const(pdb_get_hours(sam), pdb_get_hours_len(sam));
+ ret |= ldb_msg_add_value(msg, "logonHours",
+ &hours, NULL);
+ }
+
+ if (update_required(sam, PDB_ACCTCTRL)) {
+ ret |= ldb_msg_add_fmt(msg, "userAccountControl",
+ "%d", ds_acb2uf(pdb_get_acct_ctrl(sam)));
+ }
+
+ if (update_required(sam, PDB_COMMENT)) {
+ ret |= ldb_msg_add_string(msg, "comment",
+ pdb_get_comment(sam));
+ }
+
+ if (update_required(sam, PDB_ACCTDESC)) {
+ ret |= ldb_msg_add_string(msg, "description",
+ pdb_get_acct_desc(sam));
+ }
+
+ if (update_required(sam, PDB_WORKSTATIONS)) {
+ ret |= ldb_msg_add_string(msg, "userWorkstations",
+ pdb_get_workstations(sam));
+ }
+
+ /* This will need work, it is actually a UTF8 'string' with internal NULLs, to handle TS parameters */
+ if (update_required(sam, PDB_MUNGEDDIAL)) {
+ ret |= ldb_msg_add_string(msg, "userParameters",
+ pdb_get_munged_dial(sam));
+ }
+
+ if (update_required(sam, PDB_COUNTRY_CODE)) {
+ ret |= ldb_msg_add_fmt(msg, "countryCode",
+ "%i", (int)pdb_get_country_code(sam));
+ }
+
+ if (update_required(sam, PDB_CODE_PAGE)) {
+ ret |= ldb_msg_add_fmt(msg, "codePage",
+ "%i", (int)pdb_get_code_page(sam));
+ }
+
+ /* Not yet handled here or not meaningful for modifies on a Samba4 backend:
+ PDB_LOGONTIME,
+ PDB_LOGOFFTIME,
+ PDB_BAD_PASSWORD_TIME,
+ PDB_CANCHANGETIME,
+ PDB_MUSTCHANGETIME,
+ PDB_DOMAIN,
+ PDB_NTUSERNAME,
+ PDB_LOGONDIVS,
+ PDB_USERSID,
+ PDB_GROUPSID,
+ PDB_PASSLASTSET,
+ PDB_FIELDS_PRESENT,
+ PDB_BAD_PASSWORD_COUNT,
+ PDB_LOGON_COUNT,
+ PDB_UNKNOWN6,
+ PDB_LMPASSWD,
+ PDB_NTPASSWD,
+ PDB_PWHISTORY,
+ PDB_BACKEND_PRIVATE_DATA,
+
+ */
+
+ *pmods = msg;
+fail:
+ return ret == LDB_SUCCESS;
+}
+
+static NTSTATUS pdb_samba4_getsamupriv(struct pdb_samba4_state *state,
+ const char *filter,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_message **msg)
+{
+ const char * attrs[] = {
+ "lastLogon", "lastLogoff", "pwdLastSet", "accountExpires",
+ "sAMAccountName", "displayName", "homeDirectory",
+ "homeDrive", "scriptPath", "profilePath", "description",
+ "userWorkstations", "comment", "userParameters", "objectSid",
+ "primaryGroupID", "userAccountControl", "logonHours",
+ "badPwdCount", "logonCount", "countryCode", "codePage",
+ "unicodePwd", "dBCSPwd", NULL };
+
+ int rc = dsdb_search_one(state->ldb, mem_ctx, msg, NULL, LDB_SCOPE_SUBTREE, attrs, 0, "%s", filter);
+ if (rc != LDB_SUCCESS) {
+ DEBUG(10, ("ldap_search failed %s\n",
+ ldb_errstring(state->ldb)));
+ return NT_STATUS_LDAP(rc);
+ }
+
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS pdb_samba4_getsampwfilter(struct pdb_methods *m,
+ struct pdb_samba4_state *state,
+ struct samu *sam_acct,
+ const char *exp_fmt, ...) _PRINTF_ATTRIBUTE(4, 5)
+{
+ struct ldb_message *priv;
+ NTSTATUS status;
+ va_list ap;
+ char *expression = NULL;
+ TALLOC_CTX *tmp_ctx = talloc_new(state);
+ NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
+
+ va_start(ap, exp_fmt);
+ expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap);
+ va_end(ap);
+
+ if (!expression) {
+ talloc_free(tmp_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ status = pdb_samba4_getsamupriv(state, expression, sam_acct, &priv);
+ talloc_free(tmp_ctx);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10, ("pdb_samba4_getsamupriv failed: %s\n",
+ nt_errstr(status)));
+ return status;
+ }
+
+ status = pdb_samba4_init_sam_from_priv(m, sam_acct, priv);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10, ("pdb_samba4_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_samba4_getsampwnam(struct pdb_methods *m,
+ struct samu *sam_acct,
+ const char *username)
+{
+ struct pdb_samba4_state *state = talloc_get_type_abort(
+ m->private_data, struct pdb_samba4_state);
+
+ return pdb_samba4_getsampwfilter(m, state, sam_acct,
+ "(&(samaccountname=%s)(objectclass=user))",
+ username);
+}
+
+static NTSTATUS pdb_samba4_getsampwsid(struct pdb_methods *m,
+ struct samu *sam_acct,
+ const struct dom_sid *sid)
+{
+ NTSTATUS status;
+ struct pdb_samba4_state *state = talloc_get_type_abort(
+ m->private_data, struct pdb_samba4_state);
+ char *sidstr;
+
+ sidstr = dom_sid_string(talloc_tos(), sid);
+ NT_STATUS_HAVE_NO_MEMORY(sidstr);
+
+ status = pdb_samba4_getsampwfilter(m, state, sam_acct,
+ "(&(objectsid=%s)(objectclass=user))",
+ sidstr);
+ talloc_free(sidstr);
+ return status;
+}
+
+static NTSTATUS pdb_samba4_create_user(struct pdb_methods *m,
+ TALLOC_CTX *mem_ctx,
+ const char *name, uint32 acct_flags,
+ uint32 *rid)
+{
+ struct pdb_samba4_state *state = talloc_get_type_abort(
+ m->private_data, struct pdb_samba4_state);
+ struct dom_sid *sid;
+ struct ldb_dn *dn;
+ NTSTATUS status;
+ TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
+ NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
+
+ /* Internally this uses transactions to ensure all the steps
+ * happen or fail as one */
+ status = dsdb_add_user(state->ldb, tmp_ctx, name, acct_flags, &sid, &dn);
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(tmp_ctx);
+ return status;
+ }
+ sid_peek_rid(sid, rid);
+ talloc_free(tmp_ctx);
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS pdb_samba4_delete_user(struct pdb_methods *m,
+ TALLOC_CTX *mem_ctx,
+ struct samu *sam)
+{
+ struct pdb_samba4_state *state = talloc_get_type_abort(
+ m->private_data, struct pdb_samba4_state);
+ struct ldb_dn *dn;
+ int rc;
+ TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
+ NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
+
+ dn = ldb_dn_new_fmt(tmp_ctx, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, pdb_get_user_sid(sam)));
+ if (!dn || !ldb_dn_validate(dn)) {
+ talloc_free(tmp_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+ rc = ldb_delete(state->ldb, dn);
+
+ if (rc != LDB_SUCCESS) {
+ DEBUG(10, ("ldb_delete for %s failed: %s\n", ldb_dn_get_linearized(dn),
+ ldb_errstring(state->ldb)));
+ talloc_free(tmp_ctx);
+ return NT_STATUS_LDAP(rc);
+ }
+ talloc_free(tmp_ctx);
+ return NT_STATUS_OK;
+}
+
+/* This interface takes a fully populated struct samu and places it in
+ * the database. This is not implemented at this time as we need to
+ * be careful around the creation of arbitary SIDs (ie, we must ensrue
+ * they are not left in a RID pool */
+static NTSTATUS pdb_samba4_add_sam_account(struct pdb_methods *m,
+ struct samu *sampass)
+{
+ return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+/*
+ * Update the Samba4 LDB with the changes from a struct samu.
+ *
+ * This takes care not to update elements that have not been changed
+ * by the caller
+ */
+static NTSTATUS pdb_samba4_update_sam_account(struct pdb_methods *m,
+ struct samu *sam)
+{
+ struct pdb_samba4_state *state = talloc_get_type_abort(
+ m->private_data, struct pdb_samba4_state);
+ struct ldb_message *msg = pdb_samba4_get_samu_private(
+ m, sam);
+ struct ldb_message *replace_msg;
+ int rc;
+
+ if (!pdb_samba4_init_samba4_from_sam(state, msg, talloc_tos(),
+ &replace_msg, sam)) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (replace_msg->num_elements == 0) {
+ /* Nothing to do, just return success */
+ return NT_STATUS_OK;
+ }
+
+ rc = dsdb_replace(state->ldb, replace_msg, 0);
+ TALLOC_FREE(replace_msg);
+ if (rc != LDB_SUCCESS) {
+ DEBUG(10, ("dsdb_replace for %s failed: %s\n", ldb_dn_get_linearized(replace_msg->dn),
+ ldb_errstring(state->ldb)));
+ return NT_STATUS_LDAP(rc);
+ }
+
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS pdb_samba4_delete_sam_account(struct pdb_methods *m,
+ struct samu *username)
+{
+ NTSTATUS status;
+ TALLOC_CTX *tmp_ctx = talloc_new(NULL);
+ NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
+ status = pdb_samba4_delete_user(m, tmp_ctx, username);
+ talloc_free(tmp_ctx);
+ return status;
+}
+
+static NTSTATUS pdb_samba4_rename_sam_account(struct pdb_methods *m,
+ struct samu *oldname,
+ const char *newname)
+{
+ return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+/* This is not implemented, as this module is exptected to be used
+ * with auth_samba4, and this is responible for login counters etc
+ *
+ */
+static NTSTATUS pdb_samba4_update_login_attempts(struct pdb_methods *m,
+ struct samu *sam_acct,
+ bool success)
+{
+ return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS pdb_samba4_getgrfilter(struct pdb_methods *m, GROUP_MAP *map,
+ const char *exp_fmt, ...) _PRINTF_ATTRIBUTE(4, 5)
+{
+ struct pdb_samba4_state *state = talloc_get_type_abort(
+ m->private_data, struct pdb_samba4_state);
+ const char *attrs[] = { "objectSid", "description", "samAccountName",
+ NULL };
+ struct ldb_message *msg;
+ va_list ap;
+ char *expression = NULL;
+ struct dom_sid *sid;
+ const char *str;
+ int rc;
+ union unid_t id;
+ TALLOC_CTX *tmp_ctx = talloc_stackframe();
+ NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
+
+ va_start(ap, exp_fmt);
+ expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap);
+ va_end(ap);
+
+ if (!expression) {
+ talloc_free(tmp_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ rc = dsdb_search_one(state->ldb, tmp_ctx, &msg, NULL, LDB_SCOPE_SUBTREE, attrs, 0, "%s", expression);
+ if (rc == LDB_ERR_NO_SUCH_OBJECT) {
+ talloc_free(tmp_ctx);
+ return NT_STATUS_NO_SUCH_GROUP;
+ } else if (rc != LDB_SUCCESS) {
+ talloc_free(tmp_ctx);
+ DEBUG(10, ("dsdb_search_one failed %s\n",
+ ldb_errstring(state->ldb)));
+ return NT_STATUS_LDAP(rc);
+ }
+
+ sid = samdb_result_dom_sid(tmp_ctx, msg, "objectSid");
+ if (!sid) {
+ talloc_free(tmp_ctx);
+ DEBUG(10, ("Could not pull SID\n"));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ map->sid = *sid;
+
+ if (!pdb_samba4_sid_to_id(m, sid, &id, &map->sid_name_use)) {
+ talloc_free(tmp_ctx);
+ return NT_STATUS_NO_SUCH_GROUP;
+ }
+ if (map->sid_name_use == SID_NAME_USER) {
+ DEBUG(1, (__location__ "Got SID_NAME_USER when searching for a group with %s", expression));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+ map->gid = id.gid;
+
+ str = ldb_msg_find_attr_as_string(msg, "samAccountName",
+ NULL);
+ if (str == NULL) {
+ talloc_free(tmp_ctx);
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+ fstrcpy(map->nt_name, str);
+
+ str = ldb_msg_find_attr_as_string(msg, "description",
+ NULL);
+ if (str != NULL) {
+ fstrcpy(map->comment, str);
+ } else {
+ map->comment[0] = '\0';
+ }
+
+ talloc_free(tmp_ctx);
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS pdb_samba4_getgrsid(struct pdb_methods *m, GROUP_MAP *map,
+ struct dom_sid sid)
+{
+ 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_samba4_getgrfilter(m, map, filter);
+ TALLOC_FREE(filter);
+ return status;
+}
+
+static NTSTATUS pdb_samba4_getgrgid(struct pdb_methods *m, GROUP_MAP *map,
+ gid_t gid)
+{
+ struct pdb_samba4_state *state = talloc_get_type_abort(
+ m->private_data, struct pdb_samba4_state);
+ NTSTATUS status;
+ struct id_map id_map;
+ struct id_map *id_maps[2];
+ TALLOC_CTX *tmp_ctx = talloc_stackframe();
+ NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
+
+ id_map.xid.id = gid;
+ id_map.xid.type = ID_TYPE_GID;
+ id_maps[0] = &id_map;
+ id_maps[1] = NULL;
+
+ status = idmap_xids_to_sids(state->idmap_ctx, tmp_ctx, id_maps);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ status = pdb_samba4_getgrsid(m, map, *id_map.sid);
+ talloc_free(tmp_ctx);
+ return status;
+}
+
+static NTSTATUS pdb_samba4_getgrnam(struct pdb_methods *m, GROUP_MAP *map,
+ const char *name)
+{
+ char *filter;
+ NTSTATUS status;
+
+ filter = talloc_asprintf(talloc_tos(),
+ "(&(samaccountname=%s)(objectclass=group))",
+ name);
+ if (filter == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ status = pdb_samba4_getgrfilter(m, map, filter);
+ TALLOC_FREE(filter);
+ return status;
+}
+
+static NTSTATUS pdb_samba4_create_dom_group(struct pdb_methods *m,
+ TALLOC_CTX *mem_ctx, const char *name,
+ uint32 *rid)
+{
+ struct pdb_samba4_state *state = talloc_get_type_abort(
+ m->private_data, struct pdb_samba4_state);
+ NTSTATUS status;
+ struct dom_sid *sid;
+ struct ldb_dn *dn;
+ TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
+ NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
+
+ status = dsdb_add_domain_group(state->ldb, tmp_ctx, name, &sid, &dn);
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(tmp_ctx);
+ return status;
+ }
+
+ sid_peek_rid(sid, rid);
+ talloc_free(tmp_ctx);
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS pdb_samba4_delete_dom_group(struct pdb_methods *m,
+ TALLOC_CTX *mem_ctx, uint32 rid)
+{
+ const char *attrs[] = { NULL };
+ struct pdb_samba4_state *state = talloc_get_type_abort(
+ m->private_data, struct pdb_samba4_state);
+ struct dom_sid sid;
+ struct ldb_message *msg;
+ struct ldb_dn *dn;
+ int rc;
+ TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
+ NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
+
+ sid_compose(&sid, samdb_domain_sid(state->ldb), rid);
+
+ if (ldb_transaction_start(state->ldb) != LDB_SUCCESS) {
+ DEBUG(0, ("Unable to start transaction in pdb_samba4_delete_dom_group()\n"));
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+
+ dn = ldb_dn_new_fmt(tmp_ctx, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, &sid));
+ if (!dn || !ldb_dn_validate(dn)) {
+ talloc_free(tmp_ctx);
+ ldb_transaction_cancel(state->ldb);
+ return NT_STATUS_NO_MEMORY;
+ }
+ rc = dsdb_search_one(state->ldb, tmp_ctx, &msg, dn, LDB_SCOPE_BASE, attrs, 0, "objectclass=group");
+ if (rc == LDB_ERR_NO_SUCH_OBJECT) {
+ talloc_free(tmp_ctx);
+ ldb_transaction_cancel(state->ldb);
+ return NT_STATUS_NO_SUCH_GROUP;
+ }
+ rc = ldb_delete(state->ldb, dn);
+ if (rc == LDB_ERR_NO_SUCH_OBJECT) {
+ talloc_free(tmp_ctx);
+ ldb_transaction_cancel(state->ldb);
+ return NT_STATUS_NO_SUCH_GROUP;
+ } else if (rc != LDB_SUCCESS) {
+ DEBUG(10, ("ldb_delete failed %s\n",
+ ldb_errstring(state->ldb)));
+ ldb_transaction_cancel(state->ldb);
+ return NT_STATUS_LDAP(rc);
+ }
+
+ if (ldb_transaction_commit(state->ldb) != LDB_SUCCESS) {
+ DEBUG(0, ("Unable to commit transaction in pdb_samba4_delete_dom_group()\n"));
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS pdb_samba4_add_group_mapping_entry(struct pdb_methods *m,
+ GROUP_MAP *map)
+{
+ return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS pdb_samba4_update_group_mapping_entry(struct pdb_methods *m,
+ GROUP_MAP *map)
+{
+ return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS pdb_samba4_delete_group_mapping_entry(struct pdb_methods *m,
+ struct dom_sid sid)
+{
+ return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS pdb_samba4_enum_group_mapping(struct pdb_methods *m,
+ const struct dom_sid *sid,
+ enum lsa_SidType sid_name_use,
+ GROUP_MAP **pp_rmap,
+ size_t *p_num_entries,
+ bool unix_only)
+{
+ return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS pdb_samba4_enum_group_members(struct pdb_methods *m,
+ TALLOC_CTX *mem_ctx,
+ const struct dom_sid *group,
+ uint32_t **pmembers,
+ size_t *pnum_members)
+{
+ unsigned int i, num_sids, num_members;
+ struct pdb_samba4_state *state = talloc_get_type_abort(
+ m->private_data, struct pdb_samba4_state);
+ struct dom_sid *members_as_sids;
+ struct dom_sid *dom_sid;
+ uint32_t *members;
+ struct ldb_dn *dn;
+ NTSTATUS status;
+
+ TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
+ NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
+
+ dn = ldb_dn_new_fmt(tmp_ctx, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, group));
+ if (!dn || !ldb_dn_validate(dn)) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ status = dsdb_enum_group_mem(state->ldb, tmp_ctx, dn, &members_as_sids, &num_sids);
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(tmp_ctx);
+ return status;
+ }
+ status = dom_sid_split_rid(tmp_ctx, group, &dom_sid, NULL);
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(tmp_ctx);
+ return status;
+ }
+
+ *pmembers = members = talloc_array(mem_ctx, uint32_t, num_sids);
+ NT_STATUS_HAVE_NO_MEMORY_AND_FREE(*pmembers, tmp_ctx);
+ num_members = 0;
+
+ for (i = 0; i < num_sids; i++) {
+ if (!dom_sid_in_domain(dom_sid, &members_as_sids[i])) {
+ continue;
+ }
+ status = dom_sid_split_rid(NULL, &members_as_sids[i],
+ NULL, &members[num_members]);
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(tmp_ctx);
+ return status;
+ }
+ num_members++;
+ }
+ *pnum_members = num_members;
+ return NT_STATUS_OK;
+}
+
+/* Just convert the primary group SID into a group */
+static NTSTATUS fake_enum_group_memberships(struct pdb_samba4_state *state,
+ TALLOC_CTX *mem_ctx,
+ struct samu *user,
+ struct dom_sid **pp_sids,
+ gid_t **pp_gids,
+ uint32_t *p_num_groups)
+{
+ NTSTATUS status;
+ size_t num_groups = 0;
+ struct dom_sid *group_sids;
+ gid_t *gids;
+ TALLOC_CTX *tmp_ctx;
+
+ tmp_ctx = talloc_new(mem_ctx);
+ NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
+
+ if (user->group_sid) {
+ struct id_map *id_maps[2];
+ struct id_map id_map;
+
+ num_groups = 1;
+
+ group_sids = talloc_array(tmp_ctx, struct dom_sid, num_groups);
+ if (group_sids == NULL) {
+ talloc_free(tmp_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+ gids = talloc_array(tmp_ctx, gid_t, num_groups);
+ if (gids == NULL) {
+ talloc_free(tmp_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ group_sids[0] = *user->group_sid;
+
+ ZERO_STRUCT(id_map);
+ id_map.sid = &group_sids[0];
+ id_maps[0] = &id_map;
+ id_maps[1] = NULL;
+
+ status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(tmp_ctx);
+ return status;
+ }
+ if (id_map.xid.type == ID_TYPE_GID || id_map.xid.type == ID_TYPE_BOTH) {
+ gids[0] = id_map.xid.id;
+ } else {
+ DEBUG(1, (__location__
+ "Group %s, of which %s is a member, could not be converted to a GID\n",
+ dom_sid_string(tmp_ctx, &group_sids[0]),
+ dom_sid_string(tmp_ctx, &user->user_sid)));
+ talloc_free(tmp_ctx);
+ /* We must error out, otherwise a user might
+ * avoid a DENY acl based on a group they
+ * missed out on */
+ return NT_STATUS_NO_SUCH_GROUP;
+ }
+ }
+
+ *pp_sids = talloc_steal(mem_ctx, group_sids);
+ *pp_gids = talloc_steal(mem_ctx, gids);
+ *p_num_groups = num_groups;
+ talloc_free(tmp_ctx);
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS pdb_samba4_enum_group_memberships(struct pdb_methods *m,
+ TALLOC_CTX *mem_ctx,
+ struct samu *user,
+ struct dom_sid **pp_sids,
+ gid_t **pp_gids,
+ uint32_t *p_num_groups)
+{
+ struct pdb_samba4_state *state = talloc_get_type_abort(
+ m->private_data, struct pdb_samba4_state);
+ struct ldb_message *msg = pdb_samba4_get_samu_private(
+ m, user);
+ const char *attrs[] = { "tokenGroups", NULL};
+ struct ldb_message *tokengroups_msg;
+ struct ldb_message_element *tokengroups;
+ int i, rc;
+ NTSTATUS status;
+ unsigned int count = 0;
+ size_t num_groups;
+ struct dom_sid *group_sids;
+ gid_t *gids;
+ TALLOC_CTX *tmp_ctx;
+
+ if (msg == NULL) {
+ /* Fake up some things here */
+ return fake_enum_group_memberships(state,
+ mem_ctx,
+ user, pp_sids,
+ pp_gids, p_num_groups);
+ }
+
+ tmp_ctx = talloc_new(mem_ctx);
+ NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
+
+ rc = dsdb_search_one(state->ldb, tmp_ctx, &tokengroups_msg, msg->dn, LDB_SCOPE_BASE, attrs, 0, NULL);
+
+ if (rc == LDB_ERR_NO_SUCH_OBJECT) {
+ talloc_free(tmp_ctx);
+ return NT_STATUS_NO_SUCH_USER;
+ } else if (rc != LDB_SUCCESS) {
+ DEBUG(10, ("dsdb_search_one failed %s\n",
+ ldb_errstring(state->ldb)));
+ talloc_free(tmp_ctx);
+ return NT_STATUS_LDAP(rc);
+ }
+
+ tokengroups = ldb_msg_find_element(tokengroups_msg, "tokenGroups");
+
+ if (tokengroups) {
+ count = tokengroups->num_values;
+ }
+
+ group_sids = talloc_array(tmp_ctx, struct dom_sid, count);
+ if (group_sids == NULL) {
+ talloc_free(tmp_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+ gids = talloc_array(tmp_ctx, gid_t, count);
+ if (gids == NULL) {
+ talloc_free(tmp_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+ num_groups = 0;
+
+ for (i=0; i<count; i++) {
+ struct id_map *id_maps[2];
+ struct id_map id_map;
+ struct ldb_val *v = &tokengroups->values[i];
+ enum ndr_err_code ndr_err
+ = ndr_pull_struct_blob(v, group_sids, &group_sids[num_groups],
+ (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ talloc_free(tmp_ctx);
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ ZERO_STRUCT(id_map);
+ id_map.sid = &group_sids[num_groups];
+ id_maps[0] = &id_map;
+ id_maps[1] = NULL;
+
+ status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(tmp_ctx);
+ return status;
+ }
+ if (id_map.xid.type == ID_TYPE_GID || id_map.xid.type == ID_TYPE_BOTH) {
+ gids[num_groups] = id_map.xid.id;
+ } else {
+ DEBUG(1, (__location__
+ "Group %s, of which %s is a member, could not be converted to a GID\n",
+ dom_sid_string(tmp_ctx, &group_sids[num_groups]),
+ ldb_dn_get_linearized(msg->dn)));
+ talloc_free(tmp_ctx);
+ /* We must error out, otherwise a user might
+ * avoid a DENY acl based on a group they
+ * missed out on */
+ return NT_STATUS_NO_SUCH_GROUP;
+ }
+
+ num_groups += 1;
+ if (num_groups == count) {
+ break;
+ }
+ }
+
+ *pp_sids = talloc_steal(mem_ctx, group_sids);
+ *pp_gids = talloc_steal(mem_ctx, gids);
+ *p_num_groups = num_groups;
+ talloc_free(tmp_ctx);
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS pdb_samba4_set_unix_primary_group(struct pdb_methods *m,
+ TALLOC_CTX *mem_ctx,
+ struct samu *user)
+{
+ return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS pdb_samba4_mod_groupmem_by_sid(struct pdb_methods *m,
+ TALLOC_CTX *mem_ctx,
+ const struct dom_sid *groupsid,
+ const struct dom_sid *membersid,
+ int mod_op)
+{
+ struct pdb_samba4_state *state = talloc_get_type_abort(
+ m->private_data, struct pdb_samba4_state);
+ struct ldb_message *msg;
+ int ret;
+ struct ldb_message_element *el;
+ TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
+ NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
+ msg = ldb_msg_new(tmp_ctx);
+ NT_STATUS_HAVE_NO_MEMORY_AND_FREE(msg, tmp_ctx);
+
+ msg->dn = ldb_dn_new_fmt(msg, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, groupsid));
+ if (!msg->dn || !ldb_dn_validate(msg->dn)) {
+ talloc_free(tmp_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+ ret = ldb_msg_add_fmt(msg, "member", "<SID=%s>", dom_sid_string(tmp_ctx, membersid));
+ if (ret != LDB_SUCCESS) {
+ talloc_free(tmp_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+ el = ldb_msg_find_element(msg, "member");
+ el->flags = mod_op;
+
+ /* No need for transactions here, the ldb auto-transaction
+ * code will handle things for the single operation */
+ ret = ldb_modify(state->ldb, msg);
+ talloc_free(tmp_ctx);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(10, ("ldb_modify failed: %s\n",
+ ldb_errstring(state->ldb)));
+ if (ret == LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS) {
+ return NT_STATUS_MEMBER_IN_GROUP;
+ }
+ if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
+ return NT_STATUS_MEMBER_NOT_IN_GROUP;
+ }
+ return NT_STATUS_LDAP(ret);
+ }
+
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS pdb_samba4_mod_groupmem(struct pdb_methods *m,
+ TALLOC_CTX *mem_ctx,
+ uint32 grouprid, uint32 memberrid,
+ int mod_op)
+{
+ struct pdb_samba4_state *state = talloc_get_type_abort(
+ m->private_data, struct pdb_samba4_state);
+ const struct dom_sid *dom_sid, *groupsid, *membersid;
+ NTSTATUS status;
+ TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
+ NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
+
+ dom_sid = samdb_domain_sid(state->ldb);
+
+ groupsid = dom_sid_add_rid(tmp_ctx, dom_sid, grouprid);
+ NT_STATUS_HAVE_NO_MEMORY_AND_FREE(groupsid, tmp_ctx);
+ membersid = dom_sid_add_rid(tmp_ctx, dom_sid, memberrid);
+ NT_STATUS_HAVE_NO_MEMORY_AND_FREE(membersid, tmp_ctx);
+ status = pdb_samba4_mod_groupmem_by_sid(m, tmp_ctx, groupsid, membersid, mod_op);
+ talloc_free(tmp_ctx);
+ return status;
+}
+
+static NTSTATUS pdb_samba4_add_groupmem(struct pdb_methods *m,
+ TALLOC_CTX *mem_ctx,
+ uint32 group_rid, uint32 member_rid)
+{
+ return pdb_samba4_mod_groupmem(m, mem_ctx, group_rid, member_rid,
+ LDB_FLAG_MOD_ADD);
+}
+
+static NTSTATUS pdb_samba4_del_groupmem(struct pdb_methods *m,
+ TALLOC_CTX *mem_ctx,
+ uint32 group_rid, uint32 member_rid)
+{
+ return pdb_samba4_mod_groupmem(m, mem_ctx, group_rid, member_rid,
+ LDB_FLAG_MOD_DELETE);
+}
+
+static NTSTATUS pdb_samba4_create_alias(struct pdb_methods *m,
+ const char *name, uint32 *rid)
+{
+ TALLOC_CTX *frame = talloc_stackframe();
+ struct pdb_samba4_state *state = talloc_get_type_abort(
+ m->private_data, struct pdb_samba4_state);
+ struct dom_sid *sid;
+
+ struct ldb_dn *dn;
+ NTSTATUS status;
+
+ /* Internally this uses transactions to ensure all the steps
+ * happen or fail as one */
+ status = dsdb_add_domain_alias(state->ldb, frame, name, &sid, &dn);
+ if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(frame);
+ }
+
+ sid_peek_rid(sid, rid);
+ TALLOC_FREE(frame);
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS pdb_samba4_delete_alias(struct pdb_methods *m,
+ const struct dom_sid *sid)
+{
+ const char *attrs[] = { NULL };
+ struct pdb_samba4_state *state = talloc_get_type_abort(
+ m->private_data, struct pdb_samba4_state);
+ struct ldb_message *msg;
+ struct ldb_dn *dn;
+ int rc;
+ TALLOC_CTX *tmp_ctx = talloc_stackframe();
+ NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
+
+ dn = ldb_dn_new_fmt(tmp_ctx, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, sid));
+ if (!dn || !ldb_dn_validate(dn)) {
+ talloc_free(tmp_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (ldb_transaction_start(state->ldb) != LDB_SUCCESS) {
+ DEBUG(0, ("Failed to start transaction in dsdb_add_domain_alias(): %s\n", ldb_errstring(state->ldb)));
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+
+ rc = dsdb_search_one(state->ldb, tmp_ctx, &msg, dn, LDB_SCOPE_BASE, attrs, 0, "(objectclass=group)"
+ "(|(grouptype=%d)(grouptype=%d)))",
+ GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
+ GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
+ if (rc == LDB_ERR_NO_SUCH_OBJECT) {
+ talloc_free(tmp_ctx);
+ ldb_transaction_cancel(state->ldb);
+ return NT_STATUS_NO_SUCH_ALIAS;
+ }
+ rc = ldb_delete(state->ldb, dn);
+ if (rc == LDB_ERR_NO_SUCH_OBJECT) {
+ talloc_free(tmp_ctx);
+ ldb_transaction_cancel(state->ldb);
+ return NT_STATUS_NO_SUCH_ALIAS;
+ } else if (rc != LDB_SUCCESS) {
+ DEBUG(10, ("ldb_delete failed %s\n",
+ ldb_errstring(state->ldb)));
+ ldb_transaction_cancel(state->ldb);
+ return NT_STATUS_LDAP(rc);
+ }
+
+ if (ldb_transaction_commit(state->ldb) != LDB_SUCCESS) {
+ DEBUG(0, ("Failed to commit transaction in pdb_samba4_delete_alias(): %s\n",
+ ldb_errstring(state->ldb)));
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+
+ return NT_STATUS_OK;
+}
+
+#if 0
+static NTSTATUS pdb_samba4_set_aliasinfo(struct pdb_methods *m,
+ const struct dom_sid *sid,
+ struct acct_info *info)
+{
+ struct pdb_samba4_state *state = talloc_get_type_abort(
+ m->private_data, struct pdb_samba4_state);
+ struct tldap_context *ld;
+ const char *attrs[3] = { "objectSid", "description",
+ "samAccountName" };
+ struct ldb_message **msg;
+ char *sidstr, *dn;
+ int rc;
+ struct tldap_mod *mods;
+ int num_mods;
+ bool ok;
+
+ ld = pdb_samba4_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_samba4_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 != LDB_SUCCESS) {
+ DEBUG(10, ("ldap_search failed %s\n",
+ ldb_errstring(state->ldb)));
+ 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 != LDB_SUCCESS) {
+ DEBUG(10, ("ldap_modify failed: %s\n",
+ ldb_errstring(state->ldb)));
+ return NT_STATUS_LDAP(rc);
+ }
+ return NT_STATUS_OK;
+}
+#endif
+static NTSTATUS pdb_samba4_add_aliasmem(struct pdb_methods *m,
+ const struct dom_sid *alias,
+ const struct dom_sid *member)
+{
+ NTSTATUS status;
+ TALLOC_CTX *frame = talloc_stackframe();
+ status = pdb_samba4_mod_groupmem_by_sid(m, frame, alias, member, LDB_FLAG_MOD_ADD);
+ talloc_free(frame);
+ return status;
+}
+
+static NTSTATUS pdb_samba4_del_aliasmem(struct pdb_methods *m,
+ const struct dom_sid *alias,
+ const struct dom_sid *member)
+{
+ NTSTATUS status;
+ TALLOC_CTX *frame = talloc_stackframe();
+ status = pdb_samba4_mod_groupmem_by_sid(m, frame, alias, member, LDB_FLAG_MOD_DELETE);
+ talloc_free(frame);
+ return status;
+}
+
+static NTSTATUS pdb_samba4_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_samba4_state *state = talloc_get_type_abort(
+ m->private_data, struct pdb_samba4_state);
+ struct ldb_dn *dn;
+ unsigned int num_members;
+ NTSTATUS status;
+ TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
+ NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
+
+ dn = ldb_dn_new_fmt(tmp_ctx, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, alias));
+ if (!dn || !ldb_dn_validate(dn)) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ status = dsdb_enum_group_mem(state->ldb, mem_ctx, dn, pmembers, &num_members);
+ *pnum_members = num_members;
+ if (NT_STATUS_IS_OK(status)) {
+ talloc_steal(mem_ctx, pmembers);
+ }
+ talloc_free(tmp_ctx);
+ return status;
+}
+
+static NTSTATUS pdb_samba4_enum_alias_memberships(struct pdb_methods *m,
+ TALLOC_CTX *mem_ctx,
+ const struct dom_sid *domain_sid,
+ const struct dom_sid *members,
+ size_t num_members,
+ uint32_t **palias_rids,
+ size_t *pnum_alias_rids)
+{
+ struct pdb_samba4_state *state = talloc_get_type_abort(
+ m->private_data, struct pdb_samba4_state);
+ uint32_t *alias_rids = NULL;
+ size_t num_alias_rids = 0;
+ int i;
+ struct dom_sid *groupSIDs = NULL;
+ unsigned int num_groupSIDs = 0;
+ char *filter;
+ NTSTATUS status;
+ const char *sid_string;
+ const char *sid_dn;
+ DATA_BLOB sid_blob;
+
+ TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
+ NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
+ /*
+ * TODO: Get the filter right so that we only get the aliases from
+ * either the SAM or BUILTIN
+ */
+
+ filter = talloc_asprintf(tmp_ctx, "(&(objectClass=group)(groupType:1.2.840.113556.1.4.803:=%u))",
+ GROUP_TYPE_BUILTIN_LOCAL_GROUP);
+ if (filter == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ for (i = 0; i < num_members; i++) {
+ sid_string = dom_sid_string(tmp_ctx, &members[i]);
+ NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sid_string, tmp_ctx);
+
+ sid_dn = talloc_asprintf(tmp_ctx, "<SID=%s>", sid_string);
+ NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sid_dn, tmp_ctx);
+
+ sid_blob = data_blob_string_const(sid_dn);
+
+ status = dsdb_expand_nested_groups(state->ldb, &sid_blob, true, filter,
+ tmp_ctx, &groupSIDs, &num_groupSIDs);
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(tmp_ctx);
+ return status;
+ }
+ }
+
+ alias_rids = talloc_array(mem_ctx, uint32_t, num_groupSIDs);
+ if (alias_rids == NULL) {
+ talloc_free(tmp_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ for (i=0; i<num_groupSIDs; i++) {
+ if (sid_peek_check_rid(domain_sid, &groupSIDs[i],
+ &alias_rids[num_alias_rids])) {
+ num_alias_rids++;;
+ }
+ }
+
+ *palias_rids = alias_rids;
+ *pnum_alias_rids = num_alias_rids;
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS pdb_samba4_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)
+{
+ struct pdb_samba4_state *state = talloc_get_type_abort(
+ m->private_data, struct pdb_samba4_state);
+ NTSTATUS status;
+
+ TALLOC_CTX *tmp_ctx;
+
+ if (num_rids == 0) {
+ return NT_STATUS_NONE_MAPPED;
+ }
+
+ tmp_ctx = talloc_stackframe();
+ NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
+
+ status = dsdb_lookup_rids(state->ldb, tmp_ctx, domain_sid, num_rids, rids, names, lsa_attrs);
+ talloc_free(tmp_ctx);
+ return status;
+}
+
+static NTSTATUS pdb_samba4_lookup_names(struct pdb_methods *m,
+ const struct dom_sid *domain_sid,
+ int num_names,
+ const char **pp_names,
+ uint32 *rids,
+ enum lsa_SidType *attrs)
+{
+ return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS pdb_samba4_get_account_policy(struct pdb_methods *m,
+ enum pdb_policy_type type,
+ uint32_t *value)
+{
+ return account_policy_get(type, value)
+ ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+}
+
+static NTSTATUS pdb_samba4_set_account_policy(struct pdb_methods *m,
+ enum pdb_policy_type type,
+ uint32_t value)
+{
+ return account_policy_set(type, value)
+ ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+}
+
+static NTSTATUS pdb_samba4_get_seq_num(struct pdb_methods *m,
+ time_t *seq_num_out)
+{
+ struct pdb_samba4_state *state = talloc_get_type_abort(
+ m->private_data, struct pdb_samba4_state);
+ uint64_t seq_num;
+ int ret = ldb_sequence_number(state->ldb, LDB_SEQ_HIGHEST_SEQ, &seq_num);
+ if (ret == LDB_SUCCESS) {
+ *seq_num_out = seq_num;
+ return NT_STATUS_OK;
+ } else {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+}
+
+struct pdb_samba4_search_state {
+ uint32_t acct_flags;
+ struct samr_displayentry *entries;
+ uint32_t num_entries;
+ ssize_t array_size;
+ uint32_t current;
+};
+
+static bool pdb_samba4_next_entry(struct pdb_search *search,
+ struct samr_displayentry *entry)
+{
+ struct pdb_samba4_search_state *state = talloc_get_type_abort(
+ search->private_data, struct pdb_samba4_search_state);
+
+ if (state->current == state->num_entries) {
+ return false;
+ }
+
+ entry->idx = state->entries[state->current].idx;
+ entry->rid = state->entries[state->current].rid;
+ entry->acct_flags = state->entries[state->current].acct_flags;
+
+ entry->account_name = talloc_strdup(
+ search, state->entries[state->current].account_name);
+ entry->fullname = talloc_strdup(
+ search, state->entries[state->current].fullname);
+ entry->description = talloc_strdup(
+ search, state->entries[state->current].description);
+
+ state->current += 1;
+ return true;
+}
+
+static void pdb_samba4_search_end(struct pdb_search *search)
+{
+ struct pdb_samba4_search_state *state = talloc_get_type_abort(
+ search->private_data, struct pdb_samba4_search_state);
+ talloc_free(state);
+}
+
+static bool pdb_samba4_search_filter(struct pdb_methods *m,
+ struct pdb_search *search,
+ struct pdb_samba4_search_state **pstate,
+ const char *exp_fmt, ...) _PRINTF_ATTRIBUTE(4, 5)
+{
+ struct pdb_samba4_state *state = talloc_get_type_abort(
+ m->private_data, struct pdb_samba4_state);
+ struct pdb_samba4_search_state *sstate;
+ const char * attrs[] = { "objectSid", "sAMAccountName", "displayName",
+ "userAccountControl", "description", NULL };
+ struct ldb_result *res;
+ int i, rc, num_users;
+
+ va_list ap;
+ char *expression = NULL;
+
+ TALLOC_CTX *tmp_ctx = talloc_stackframe();
+ if (!tmp_ctx) {
+ return false;
+ }
+
+ va_start(ap, exp_fmt);
+ expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap);
+ va_end(ap);
+
+ if (!expression) {
+ talloc_free(tmp_ctx);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ sstate = talloc_zero(tmp_ctx, struct pdb_samba4_search_state);
+ if (sstate == NULL) {
+ talloc_free(tmp_ctx);
+ return false;
+ }
+
+ rc = dsdb_search(state->ldb, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE, attrs, 0, "%s", expression);
+ if (rc != LDB_SUCCESS) {
+ talloc_free(tmp_ctx);
+ DEBUG(10, ("dsdb_search failed: %s\n",
+ ldb_errstring(state->ldb)));
+ return false;
+ }
+
+ num_users = res->count;
+
+ sstate->entries = talloc_array(sstate, struct samr_displayentry,
+ num_users);
+ if (sstate->entries == NULL) {
+ talloc_free(tmp_ctx);
+ DEBUG(10, ("talloc failed\n"));
+ return false;
+ }
+
+ sstate->num_entries = 0;
+
+ for (i=0; i<num_users; i++) {
+ struct samr_displayentry *e;
+ struct dom_sid *sid;
+
+ e = &sstate->entries[sstate->num_entries];
+
+ e->idx = sstate->num_entries;
+ sid = samdb_result_dom_sid(tmp_ctx, res->msgs[i], "objectSid");
+ if (!sid) {
+ talloc_free(tmp_ctx);
+ DEBUG(10, ("Could not pull SID\n"));
+ return false;
+ }
+ sid_peek_rid(sid, &e->rid);
+
+ e->acct_flags = samdb_result_acct_flags(state->ldb, tmp_ctx,
+ res->msgs[i],
+ ldb_get_default_basedn(state->ldb));
+ e->account_name = ldb_msg_find_attr_as_string(
+ res->msgs[i], "samAccountName", NULL);
+ if (e->account_name == NULL) {
+ talloc_free(tmp_ctx);
+ return false;
+ }
+ e->fullname = ldb_msg_find_attr_as_string(
+ res->msgs[i], "displayName", "");
+ e->description = ldb_msg_find_attr_as_string(
+ res->msgs[i], "description", "");
+
+ sstate->num_entries += 1;
+ if (sstate->num_entries >= num_users) {
+ break;
+ }
+ }
+ talloc_steal(sstate->entries, res->msgs);
+ search->private_data = talloc_steal(search, sstate);
+ search->next_entry = pdb_samba4_next_entry;
+ search->search_end = pdb_samba4_search_end;
+ *pstate = sstate;
+ talloc_free(tmp_ctx);
+ return true;
+}
+
+static bool pdb_samba4_search_users(struct pdb_methods *m,
+ struct pdb_search *search,
+ uint32 acct_flags)
+{
+ struct pdb_samba4_search_state *sstate;
+ bool ret;
+
+ ret = pdb_samba4_search_filter(m, search, &sstate, "(objectclass=user)");
+ if (!ret) {
+ return false;
+ }
+ sstate->acct_flags = acct_flags;
+ return true;
+}
+
+static bool pdb_samba4_search_groups(struct pdb_methods *m,
+ struct pdb_search *search)
+{
+ struct pdb_samba4_search_state *sstate;
+ bool ret;
+
+ ret = pdb_samba4_search_filter(m, search, &sstate,
+ "(&(grouptype=%d)(objectclass=group))",
+ GTYPE_SECURITY_GLOBAL_GROUP);
+ if (!ret) {
+ return false;
+ }
+ sstate->acct_flags = 0;
+ return true;
+}
+
+static bool pdb_samba4_search_aliases(struct pdb_methods *m,
+ struct pdb_search *search,
+ const struct dom_sid *sid)
+{
+ struct pdb_samba4_search_state *sstate;
+ bool ret;
+
+ ret = pdb_samba4_search_filter(m, search, &sstate,
+ "(&(grouptype=%d)(objectclass=group))",
+ sid_check_is_builtin(sid)
+ ? GTYPE_SECURITY_BUILTIN_LOCAL_GROUP
+ : GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
+ if (!ret) {
+ return false;
+ }
+ sstate->acct_flags = 0;
+ return true;
+}
+
+static bool pdb_samba4_uid_to_sid(struct pdb_methods *m, uid_t uid,
+ struct dom_sid *sid)
+{
+ struct pdb_samba4_state *state = talloc_get_type_abort(
+ m->private_data, struct pdb_samba4_state);
+ NTSTATUS status;
+ struct id_map id_map;
+ struct id_map *id_maps[2];
+ TALLOC_CTX *tmp_ctx = talloc_stackframe();
+ if (!tmp_ctx) {
+ return false;
+ }
+
+ id_map.xid.id = uid;
+ id_map.xid.type = ID_TYPE_UID;
+ id_maps[0] = &id_map;
+ id_maps[1] = NULL;
+
+ status = idmap_xids_to_sids(state->idmap_ctx, tmp_ctx, id_maps);
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(tmp_ctx);
+ return false;
+ }
+ *sid = *id_map.sid;
+ talloc_free(tmp_ctx);
+ return true;
+}
+
+static bool pdb_samba4_gid_to_sid(struct pdb_methods *m, gid_t gid,
+ struct dom_sid *sid)
+{
+ struct pdb_samba4_state *state = talloc_get_type_abort(
+ m->private_data, struct pdb_samba4_state);
+ NTSTATUS status;
+ struct id_map id_map;
+ struct id_map *id_maps[2];
+ TALLOC_CTX *tmp_ctx = talloc_stackframe();
+ if (!tmp_ctx) {
+ return false;
+ }
+
+ id_map.xid.id = gid;
+ id_map.xid.type = ID_TYPE_GID;
+ id_maps[0] = &id_map;
+ id_maps[1] = NULL;
+
+ status = idmap_xids_to_sids(state->idmap_ctx, tmp_ctx, id_maps);
+ if (!NT_STATUS_IS_OK(status)) {
+ return false;
+ }
+ *sid = *id_map.sid;
+ talloc_free(tmp_ctx);
+ return true;
+}
+
+static bool pdb_samba4_sid_to_id(struct pdb_methods *m, const struct dom_sid *sid,
+ union unid_t *id, enum lsa_SidType *type)
+{
+ struct pdb_samba4_state *state = talloc_get_type_abort(
+ m->private_data, struct pdb_samba4_state);
+ struct id_map id_map;
+ struct id_map *id_maps[2];
+ const char *attrs[] = { "objectClass", "groupType", NULL };
+ struct ldb_message *msg;
+ struct ldb_dn *dn;
+ NTSTATUS status;
+ int rc;
+ TALLOC_CTX *tmp_ctx = talloc_stackframe();
+ if (!tmp_ctx) {
+ return false;
+ }
+
+ ZERO_STRUCT(id_map);
+
+ dn = ldb_dn_new_fmt(tmp_ctx, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, sid));
+ if (!dn || !ldb_dn_validate(dn)) {
+ talloc_free(tmp_ctx);
+ return false;
+ }
+ rc = dsdb_search_one(state->ldb, tmp_ctx, &msg, dn, LDB_SCOPE_BASE, attrs, 0, NULL);
+ if (rc == LDB_ERR_NO_SUCH_OBJECT) {
+ DEBUG(5, (__location__ "SID to Unix ID lookup failed because SID %s could not be found in the samdb\n", dom_sid_string(tmp_ctx, sid)));
+ talloc_free(tmp_ctx);
+ return false;
+ }
+ if (samdb_find_attribute(state->ldb, msg, "objectClass", "group")) {
+ uint32_t grouptype = ldb_msg_find_attr_as_uint(msg, "groupType", 0);
+ switch (grouptype) {
+ case GTYPE_SECURITY_BUILTIN_LOCAL_GROUP:
+ case GTYPE_SECURITY_DOMAIN_LOCAL_GROUP:
+ *type = SID_NAME_ALIAS;
+ break;
+ case GTYPE_SECURITY_GLOBAL_GROUP:
+ *type = SID_NAME_DOM_GRP;
+ break;
+ default:
+ talloc_free(tmp_ctx);
+ DEBUG(10, ("Could not pull groupType\n"));
+ return false;
+ }
+
+ *type = SID_NAME_DOM_GRP;
+
+ ZERO_STRUCT(id_map);
+ id_map.sid = sid;
+ id_maps[0] = &id_map;
+ id_maps[1] = NULL;
+
+ status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
+ talloc_free(tmp_ctx);
+ if (!NT_STATUS_IS_OK(status)) {
+ return false;
+ }
+ if (id_map.xid.type == ID_TYPE_GID || id_map.xid.type == ID_TYPE_BOTH) {
+ id->gid = id_map.xid.id;
+ return true;
+ }
+ return false;
+ } else if (samdb_find_attribute(state->ldb, msg, "objectClass", "user")) {
+ *type = SID_NAME_USER;
+ ZERO_STRUCT(id_map);
+ id_map.sid = sid;
+ id_maps[0] = &id_map;
+ id_maps[1] = NULL;
+
+ status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
+ talloc_free(tmp_ctx);
+ if (!NT_STATUS_IS_OK(status)) {
+ return false;
+ }
+ if (id_map.xid.type == ID_TYPE_UID || id_map.xid.type == ID_TYPE_BOTH) {
+ id->uid = id_map.xid.id;
+ return true;
+ }
+ return false;
+ }
+ DEBUG(5, (__location__ "SID to Unix ID lookup failed because SID %s was found, but was not a user or group\n", dom_sid_string(tmp_ctx, sid)));
+ talloc_free(tmp_ctx);
+ return false;
+}
+
+static uint32_t pdb_samba4_capabilities(struct pdb_methods *m)
+{
+ return PDB_CAP_STORE_RIDS | PDB_CAP_ADS;
+}
+
+static bool pdb_samba4_new_rid(struct pdb_methods *m, uint32 *rid)
+{
+ return false;
+}
+
+static bool pdb_samba4_get_trusteddom_pw(struct pdb_methods *m,
+ const char *domain, char** pwd,
+ struct dom_sid *sid,
+ time_t *pass_last_set_time)
+{
+ return false;
+}
+
+static bool pdb_samba4_set_trusteddom_pw(struct pdb_methods *m,
+ const char* domain, const char* pwd,
+ const struct dom_sid *sid)
+{
+ return false;
+}
+
+static bool pdb_samba4_del_trusteddom_pw(struct pdb_methods *m,
+ const char *domain)
+{
+ return false;
+}
+
+static NTSTATUS pdb_samba4_enum_trusteddoms(struct pdb_methods *m,
+ TALLOC_CTX *mem_ctx,
+ uint32 *num_domains,
+ struct trustdom_info ***domains)
+{
+ *num_domains = 0;
+ *domains = NULL;
+ return NT_STATUS_OK;
+}
+
+static void pdb_samba4_init_methods(struct pdb_methods *m)
+{
+ m->name = "samba4";
+ m->get_domain_info = pdb_samba4_get_domain_info;
+ m->getsampwnam = pdb_samba4_getsampwnam;
+ m->getsampwsid = pdb_samba4_getsampwsid;
+ m->create_user = pdb_samba4_create_user;
+ m->delete_user = pdb_samba4_delete_user;
+ m->add_sam_account = pdb_samba4_add_sam_account;
+ m->update_sam_account = pdb_samba4_update_sam_account;
+ m->delete_sam_account = pdb_samba4_delete_sam_account;
+ m->rename_sam_account = pdb_samba4_rename_sam_account;
+ m->update_login_attempts = pdb_samba4_update_login_attempts;
+ m->getgrsid = pdb_samba4_getgrsid;
+ m->getgrgid = pdb_samba4_getgrgid;
+ m->getgrnam = pdb_samba4_getgrnam;
+ m->create_dom_group = pdb_samba4_create_dom_group;
+ m->delete_dom_group = pdb_samba4_delete_dom_group;
+ m->add_group_mapping_entry = pdb_samba4_add_group_mapping_entry;
+ m->update_group_mapping_entry = pdb_samba4_update_group_mapping_entry;
+ m->delete_group_mapping_entry = pdb_samba4_delete_group_mapping_entry;
+ m->enum_group_mapping = pdb_samba4_enum_group_mapping;
+ m->enum_group_members = pdb_samba4_enum_group_members;
+ m->enum_group_memberships = pdb_samba4_enum_group_memberships;
+ m->set_unix_primary_group = pdb_samba4_set_unix_primary_group;
+ m->add_groupmem = pdb_samba4_add_groupmem;
+ m->del_groupmem = pdb_samba4_del_groupmem;
+ m->create_alias = pdb_samba4_create_alias;
+ m->delete_alias = pdb_samba4_delete_alias;
+ m->get_aliasinfo = pdb_default_get_aliasinfo;
+ m->add_aliasmem = pdb_samba4_add_aliasmem;
+ m->del_aliasmem = pdb_samba4_del_aliasmem;
+ m->enum_aliasmem = pdb_samba4_enum_aliasmem;
+ m->enum_alias_memberships = pdb_samba4_enum_alias_memberships;
+ m->lookup_rids = pdb_samba4_lookup_rids;
+ m->lookup_names = pdb_samba4_lookup_names;
+ m->get_account_policy = pdb_samba4_get_account_policy;
+ m->set_account_policy = pdb_samba4_set_account_policy;
+ m->get_seq_num = pdb_samba4_get_seq_num;
+ m->search_users = pdb_samba4_search_users;
+ m->search_groups = pdb_samba4_search_groups;
+ m->search_aliases = pdb_samba4_search_aliases;
+ m->uid_to_sid = pdb_samba4_uid_to_sid;
+ m->gid_to_sid = pdb_samba4_gid_to_sid;
+ m->sid_to_id = pdb_samba4_sid_to_id;
+ m->capabilities = pdb_samba4_capabilities;
+ m->new_rid = pdb_samba4_new_rid;
+ m->get_trusteddom_pw = pdb_samba4_get_trusteddom_pw;
+ m->set_trusteddom_pw = pdb_samba4_set_trusteddom_pw;
+ m->del_trusteddom_pw = pdb_samba4_del_trusteddom_pw;
+ m->enum_trusteddoms = pdb_samba4_enum_trusteddoms;
+}
+
+static void free_private_data(void **vp)
+{
+ struct pdb_samba4_state *state = talloc_get_type_abort(
+ *vp, struct pdb_samba4_state);
+ talloc_unlink(state, state->ldb);
+ return;
+}
+
+static NTSTATUS pdb_init_samba4(struct pdb_methods **pdb_method,
+ const char *location)
+{
+ struct pdb_methods *m;
+ struct pdb_samba4_state *state;
+ NTSTATUS status;
+
+ if ( !NT_STATUS_IS_OK(status = make_pdb_method( &m )) ) {
+ return status;
+ }
+
+ state = talloc_zero(m, struct pdb_samba4_state);
+ if (state == NULL) {
+ goto nomem;
+ }
+ m->private_data = state;
+ m->free_private_data = free_private_data;
+ pdb_samba4_init_methods(m);
+
+ state->ev = s4_event_context_init(state);
+ if (!state->ev) {
+ DEBUG(10, ("s4_event_context_init failed\n"));
+ goto fail;
+ }
+
+ state->lp_ctx = loadparm_init_s3(state, loadparm_s3_context());
+ if (state->lp_ctx == NULL) {
+ DEBUG(10, ("loadparm_init_s3 failed\n"));
+ goto fail;
+ }
+
+ state->ldb = samdb_connect(state,
+ state->ev,
+ state->lp_ctx,
+ system_session(state->lp_ctx), 0);
+
+ if (!state->ldb) {
+ DEBUG(10, ("samdb_connect failed\n"));
+ goto fail;
+ }
+
+ state->idmap_ctx = idmap_init(state, state->ev,
+ state->lp_ctx);
+ if (!state->idmap_ctx) {
+ DEBUG(10, ("samdb_connect failed\n"));
+ goto fail;
+ }
+
+ *pdb_method = m;
+ return NT_STATUS_OK;
+nomem:
+ status = NT_STATUS_NO_MEMORY;
+fail:
+ TALLOC_FREE(m);
+ return status;
+}
+
+NTSTATUS pdb_samba4_init(void);
+NTSTATUS pdb_samba4_init(void)
+{
+ return smb_register_passdb(PASSDB_INTERFACE_VERSION, "samba4",
+ pdb_init_samba4);
+}
diff --git a/source3/passdb/pdb_smbpasswd.c b/source3/passdb/pdb_smbpasswd.c
index 43d6eaf6645..2cfacd3a136 100644
--- a/source3/passdb/pdb_smbpasswd.c
+++ b/source3/passdb/pdb_smbpasswd.c
@@ -549,7 +549,7 @@ static struct smb_passwd *getsmbfilepwent(struct smbpasswd_privates *smbpasswd_s
}
if(*p == ':') {
p++;
- if(*p && (StrnCaseCmp((char *)p, "LCT-", 4)==0)) {
+ if(*p && (strncasecmp_m((char *)p, "LCT-", 4)==0)) {
int i;
p += 4;
for(i = 0; i < 8; i++) {
@@ -975,7 +975,7 @@ This is no longer supported.!\n", pwd->smb_name));
p++;
/* We should be pointing at the LCT entry. */
- if((linebuf_len > (PTR_DIFF(p, linebuf) + 13)) && (StrnCaseCmp((char *)p, "LCT-", 4) == 0)) {
+ if((linebuf_len > (PTR_DIFF(p, linebuf) + 13)) && (strncasecmp_m((char *)p, "LCT-", 4) == 0)) {
p += 4;
for(i = 0; i < 8; i++) {
if(p[i] == '\0' || !isxdigit(p[i])) {
@@ -990,7 +990,7 @@ This is no longer supported.!\n", pwd->smb_name));
*/
got_pass_last_set_time = True;
} /* i == 8 */
- } /* *p && StrnCaseCmp() */
+ } /* *p && strncasecmp_m() */
} /* p == ':' */
} /* p == '[' */
@@ -1694,7 +1694,7 @@ static NTSTATUS pdb_init_smbpasswd( struct pdb_methods **pdb_method, const char
/* Setup private data and free function */
- if ( !(privates = TALLOC_ZERO_P( *pdb_method, struct smbpasswd_privates )) ) {
+ if ( !(privates = talloc_zero( *pdb_method, struct smbpasswd_privates )) ) {
DEBUG(0, ("talloc() failed for smbpasswd private_data!\n"));
return NT_STATUS_NO_MEMORY;
}
diff --git a/source3/passdb/pdb_tdb.c b/source3/passdb/pdb_tdb.c
index 79c0ed196af..28461d0ac3d 100644
--- a/source3/passdb/pdb_tdb.c
+++ b/source3/passdb/pdb_tdb.c
@@ -27,6 +27,7 @@
#include "passdb.h"
#include "dbwrap.h"
#include "../libcli/security/security.h"
+#include "util_tdb.h"
#if 0 /* when made a module use this */
diff --git a/source3/passdb/pdb_wbc_sam.c b/source3/passdb/pdb_wbc_sam.c
index 64529c78961..91adc8108b3 100644
--- a/source3/passdb/pdb_wbc_sam.c
+++ b/source3/passdb/pdb_wbc_sam.c
@@ -112,7 +112,7 @@ static NTSTATUS pdb_wbc_sam_enum_group_memberships(struct pdb_methods *methods,
smb_panic("primary group missing");
}
- *pp_sids = TALLOC_ARRAY(mem_ctx, struct dom_sid, *p_num_groups);
+ *pp_sids = talloc_array(mem_ctx, struct dom_sid, *p_num_groups);
if (*pp_sids == NULL) {
TALLOC_FREE(*pp_gids);
diff --git a/source3/passdb/proto.h b/source3/passdb/proto.h
index a64985c7091..8b95b729597 100644
--- a/source3/passdb/proto.h
+++ b/source3/passdb/proto.h
@@ -1,3 +1,41 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * passdb - password and authentication handling
+ *
+ * Copyright (C) Andrew Tridgell 1992-1998
+ * Copyright (C) Jeremy Allison 1995-2009
+ * Copyright (C) Luke Kenneth Casson Leighton 1996-1998
+ * Copyright (C) Jean François Micouleau 1998-2001
+ * Copyright (C) Gerald (Jerry) Carter 2000-2006
+ * Copyright (C) Simo Sorce 2000-2003,2006
+ * Copyright (C) Andrew Bartlett 2001-2002
+ * Copyright (C) Shahms King 2001
+ * Copyright (C) Jelmer Vernooij 2002
+ * Copyright (C) Rafal Szczesniak 2002
+ * Copyright (C) Stefan (metze) Metzmacher 2002-2003
+ * Copyright (C) Guenther Deschner 2004-2005
+ * Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2004-2005
+ * Copyright (C) Vince Brimhall 2004-2005
+ * Copyright (C) Volker Lendecke 2006
+ * Copyright (C) Michael Adam 2007
+ * Copyright (C) Dan Sledz 2009
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _PASSDB_PROTO_H_
+#define _PASSDB_PROTO_H_
/* The following definitions come from passdb/account_pol.c */
@@ -300,3 +338,5 @@ NTSTATUS pdb_tdbsam_init(void);
NTSTATUS create_builtin_users(const struct dom_sid *sid);
NTSTATUS create_builtin_administrators(const struct dom_sid *sid);
+
+#endif /* _PASSDB_PROTO_H_ */
diff --git a/source3/passdb/secrets.c b/source3/passdb/secrets.c
index c16d15807bd..c9101ca0506 100644
--- a/source3/passdb/secrets.c
+++ b/source3/passdb/secrets.c
@@ -30,6 +30,7 @@
#include "secrets.h"
#include "dbwrap.h"
#include "../libcli/security/security.h"
+#include "util_tdb.h"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_PASSDB
@@ -419,7 +420,7 @@ static int list_trusted_domain(struct db_record *rec, void *private_data)
return 0;
}
- if (!(dom_info = TALLOC_P(state->domains, struct trustdom_info))) {
+ if (!(dom_info = talloc(state->domains, struct trustdom_info))) {
DEBUG(0, ("talloc failed\n"));
return 0;
}
@@ -458,7 +459,7 @@ NTSTATUS secrets_trusted_domains(TALLOC_CTX *mem_ctx, uint32 *num_domains,
* exists
*/
- if (!(state.domains = TALLOC_ARRAY(
+ if (!(state.domains = talloc_array(
mem_ctx, struct trustdom_info *, 1))) {
return NT_STATUS_NO_MEMORY;
}
diff --git a/source3/passdb/wscript_build b/source3/passdb/wscript_build
index 79b143507f1..90ce2c4c4d2 100644
--- a/source3/passdb/wscript_build
+++ b/source3/passdb/wscript_build
@@ -14,6 +14,7 @@ bld.SAMBA3_SUBSYSTEM('pdb',
bld.SAMBA3_MODULE('pdb_tdbsam',
subsystem='pdb',
source=PDB_TDBSAM_SRC,
+ deps='samba-util',
init_function='',
internal_module=bld.SAMBA3_IS_STATIC_MODULE('pdb_tdbsam'),
enabled=bld.SAMBA3_IS_ENABLED_MODULE('pdb_tdbsam'))
@@ -36,6 +37,7 @@ bld.SAMBA3_MODULE('pdb_ads',
bld.SAMBA3_MODULE('pdb_smbpasswd',
subsystem='pdb',
source=PDB_SMBPASSWD_SRC,
+ deps='samba-util',
init_function='',
internal_module=bld.SAMBA3_IS_STATIC_MODULE('pdb_smbpasswd'),
enabled=bld.SAMBA3_IS_ENABLED_MODULE('pdb_smbpasswd'))
@@ -43,6 +45,17 @@ bld.SAMBA3_MODULE('pdb_smbpasswd',
bld.SAMBA3_MODULE('pdb_wbc_sam',
subsystem='pdb',
source=PDB_WBC_SAM_SRC,
+ deps='samba-util',
init_function='',
internal_module=bld.SAMBA3_IS_STATIC_MODULE('pdb_wbc_sam'),
enabled=bld.SAMBA3_IS_ENABLED_MODULE('pdb_wbc_sam'))
+
+bld.SAMBA3_MODULE('pdb_samba4',
+ subsystem='pdb',
+ source='pdb_samba4.c',
+ init_function='',
+ deps='IDMAP samdb',
+ allow_undefined_symbols=False,
+ internal_module=bld.SAMBA3_IS_STATIC_MODULE('pdb_samba4'),
+ enabled=bld.SAMBA3_IS_ENABLED_MODULE('pdb_samba4'))
+