summaryrefslogtreecommitdiff
path: root/source3/winbindd
diff options
context:
space:
mode:
authorSimo Sorce <idra@samba.org>2008-02-01 14:24:31 -0500
committerSimo Sorce <idra@samba.org>2008-02-01 14:24:31 -0500
commit2fffc9a1b1fe2a1490e867bb38462e50c282d2b3 (patch)
tree428e09c9b35138db8b7ca7161c659a71aa129d29 /source3/winbindd
parent93a3c5b3f9927973b4ad1496f593ea147052d1e1 (diff)
parentb708005a7106db26d7df689b887b419c9f2ea41c (diff)
downloadsamba-2fffc9a1b1fe2a1490e867bb38462e50c282d2b3.tar.gz
samba-2fffc9a1b1fe2a1490e867bb38462e50c282d2b3.tar.bz2
samba-2fffc9a1b1fe2a1490e867bb38462e50c282d2b3.zip
Merge branch 'v3-2-test' of ssh://git.samba.org/data/git/samba into v3-2-test
(This used to be commit 7dbfc7bdc65314466a83e8121b35c9bcb24b2631)
Diffstat (limited to 'source3/winbindd')
-rw-r--r--source3/winbindd/idmap_nss.c10
-rw-r--r--source3/winbindd/idmap_tdb2.c1017
-rw-r--r--source3/winbindd/winbindd.c23
-rw-r--r--source3/winbindd/winbindd.h6
-rw-r--r--source3/winbindd/winbindd_ads.c110
-rw-r--r--source3/winbindd/winbindd_async.c20
-rw-r--r--source3/winbindd/winbindd_cache.c209
-rw-r--r--source3/winbindd/winbindd_cm.c205
-rw-r--r--source3/winbindd/winbindd_creds.c2
-rw-r--r--source3/winbindd/winbindd_dual.c92
-rw-r--r--source3/winbindd/winbindd_group.c31
-rw-r--r--source3/winbindd/winbindd_locator.c6
-rw-r--r--source3/winbindd/winbindd_misc.c6
-rw-r--r--source3/winbindd/winbindd_ndr.c153
-rw-r--r--source3/winbindd/winbindd_pam.c52
-rw-r--r--source3/winbindd/winbindd_rpc.c36
-rw-r--r--source3/winbindd/winbindd_util.c104
17 files changed, 1767 insertions, 315 deletions
diff --git a/source3/winbindd/idmap_nss.c b/source3/winbindd/idmap_nss.c
index fa9f2c9681..46c24d7fcb 100644
--- a/source3/winbindd/idmap_nss.c
+++ b/source3/winbindd/idmap_nss.c
@@ -145,7 +145,6 @@ static NTSTATUS idmap_nss_sids_to_unixids(struct idmap_domain *dom, struct id_ma
}
for (i = 0; ids[i]; i++) {
- struct passwd *pw;
struct group *gr;
enum lsa_SidType type;
const char *dom_name = NULL;
@@ -166,17 +165,20 @@ static NTSTATUS idmap_nss_sids_to_unixids(struct idmap_domain *dom, struct id_ma
}
switch (type) {
- case SID_NAME_USER:
+ case SID_NAME_USER: {
+ struct passwd *pw;
/* this will find also all lower case name and use username level */
-
- pw = Get_Pwnam(name);
+
+ pw = Get_Pwnam_alloc(talloc_tos(), name);
if (pw) {
ids[i]->xid.id = pw->pw_uid;
ids[i]->xid.type = ID_TYPE_UID;
ids[i]->status = ID_MAPPED;
}
+ TALLOC_FREE(pw);
break;
+ }
case SID_NAME_DOM_GRP:
case SID_NAME_ALIAS:
diff --git a/source3/winbindd/idmap_tdb2.c b/source3/winbindd/idmap_tdb2.c
new file mode 100644
index 0000000000..ab89e615f7
--- /dev/null
+++ b/source3/winbindd/idmap_tdb2.c
@@ -0,0 +1,1017 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ idmap TDB2 backend, used for clustered Samba setups.
+
+ This uses 2 tdb files. One is permanent, and is in shared storage
+ on the cluster (using "tdb:idmap2.tdb =" in smb.conf). The other is a
+ temporary cache tdb on local storage.
+
+ Copyright (C) Andrew Tridgell 2007
+
+ This is heavily based upon idmap_tdb.c, which is:
+
+ Copyright (C) Tim Potter 2000
+ Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003
+ Copyright (C) Jeremy Allison 2006
+ Copyright (C) Simo Sorce 2003-2006
+
+ 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 2 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, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+#include "winbindd.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_IDMAP
+
+/* High water mark keys */
+#define HWM_GROUP "GROUP HWM"
+#define HWM_USER "USER HWM"
+
+static struct idmap_tdb2_state {
+ /* User and group id pool */
+ uid_t low_uid, high_uid; /* Range of uids to allocate */
+ gid_t low_gid, high_gid; /* Range of gids to allocate */
+ const char *idmap_script;
+} idmap_tdb2_state;
+
+
+
+/* tdb context for the local cache tdb */
+static TDB_CONTEXT *idmap_tdb2_tmp;
+
+/* handle to the permanent tdb */
+static struct db_context *idmap_tdb2_perm;
+
+/*
+ open the cache tdb
+ */
+static NTSTATUS idmap_tdb2_open_cache_db(void)
+{
+ const char *db_path;
+
+ if (idmap_tdb2_tmp) {
+ /* its already open */
+ return NT_STATUS_OK;
+ }
+
+ db_path = lock_path("idmap2_cache.tdb");
+
+ /* Open idmap repository */
+ if (!(idmap_tdb2_tmp = tdb_open_log(db_path, 0, TDB_CLEAR_IF_FIRST, O_RDWR|O_CREAT, 0644))) {
+ DEBUG(0, ("Unable to open cache idmap database '%s'\n", db_path));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+static NTSTATUS idmap_tdb2_alloc_load(void);
+
+/*
+ open the permanent tdb
+ */
+static NTSTATUS idmap_tdb2_open_perm_db(void)
+{
+ char *db_path;
+
+ if (idmap_tdb2_perm) {
+ /* its already open */
+ return NT_STATUS_OK;
+ }
+
+ db_path = lp_parm_talloc_string(-1, "tdb", "idmap2.tdb", NULL);
+ if (db_path == NULL) {
+ /* fall back to the private directory, which, despite
+ its name, is usually on shared storage */
+ db_path = talloc_asprintf(NULL, "%s/idmap2.tdb", lp_private_dir());
+ }
+ NT_STATUS_HAVE_NO_MEMORY(db_path);
+
+ /* Open idmap repository */
+ idmap_tdb2_perm = db_open(NULL, db_path, 0, TDB_DEFAULT,
+ O_RDWR|O_CREAT, 0644);
+ TALLOC_FREE(db_path);
+
+ if (idmap_tdb2_perm == NULL) {
+ DEBUG(0, ("Unable to open permanent idmap database '%s'\n",
+ db_path));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ /* load the ranges and high/low water marks */
+ return idmap_tdb2_alloc_load();
+}
+
+
+/*
+ load the idmap allocation ranges and high/low water marks
+*/
+static NTSTATUS idmap_tdb2_alloc_load(void)
+{
+ const char *range;
+ uid_t low_uid = 0;
+ uid_t high_uid = 0;
+ gid_t low_gid = 0;
+ gid_t high_gid = 0;
+
+ /* load ranges */
+ idmap_tdb2_state.low_uid = 0;
+ idmap_tdb2_state.high_uid = 0;
+ idmap_tdb2_state.low_gid = 0;
+ idmap_tdb2_state.high_gid = 0;
+
+ /* see if a idmap script is configured */
+ idmap_tdb2_state.idmap_script = lp_parm_const_string(-1, "idmap", "script", NULL);
+
+ if (idmap_tdb2_state.idmap_script) {
+ DEBUG(1, ("using idmap script '%s'\n", idmap_tdb2_state.idmap_script));
+ }
+
+ range = lp_parm_const_string(-1, "idmap alloc config", "range", NULL);
+ if (range && range[0]) {
+ unsigned low_id, high_id;
+ if (sscanf(range, "%u - %u", &low_id, &high_id) == 2) {
+ if (low_id < high_id) {
+ idmap_tdb2_state.low_gid = idmap_tdb2_state.low_uid = low_id;
+ idmap_tdb2_state.high_gid = idmap_tdb2_state.high_uid = high_id;
+ } else {
+ DEBUG(1, ("ERROR: invalid idmap alloc range [%s]", range));
+ }
+ } else {
+ DEBUG(1, ("ERROR: invalid syntax for idmap alloc config:range [%s]", range));
+ }
+ }
+
+ /* Create high water marks for group and user id */
+ if (lp_idmap_uid(&low_uid, &high_uid)) {
+ idmap_tdb2_state.low_uid = low_uid;
+ idmap_tdb2_state.high_uid = high_uid;
+ }
+
+ if (lp_idmap_gid(&low_gid, &high_gid)) {
+ idmap_tdb2_state.low_gid = low_gid;
+ idmap_tdb2_state.high_gid = high_gid;
+ }
+
+ if (idmap_tdb2_state.high_uid <= idmap_tdb2_state.low_uid) {
+ DEBUG(1, ("idmap uid range missing or invalid\n"));
+ DEBUGADD(1, ("idmap will be unable to map foreign SIDs\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ } else {
+ uint32 low_id;
+
+ if (((low_id = dbwrap_fetch_int32(idmap_tdb2_perm,
+ HWM_USER)) == -1) ||
+ (low_id < idmap_tdb2_state.low_uid)) {
+ if (dbwrap_store_int32(
+ idmap_tdb2_perm, HWM_USER,
+ idmap_tdb2_state.low_uid) == -1) {
+ DEBUG(0, ("Unable to initialise user hwm in idmap database\n"));
+ return NT_STATUS_INTERNAL_DB_ERROR;
+ }
+ }
+ }
+
+ if (idmap_tdb2_state.high_gid <= idmap_tdb2_state.low_gid) {
+ DEBUG(1, ("idmap gid range missing or invalid\n"));
+ DEBUGADD(1, ("idmap will be unable to map foreign SIDs\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ } else {
+ uint32 low_id;
+
+ if (((low_id = dbwrap_fetch_int32(idmap_tdb2_perm,
+ HWM_GROUP)) == -1) ||
+ (low_id < idmap_tdb2_state.low_gid)) {
+ if (dbwrap_store_int32(
+ idmap_tdb2_perm, HWM_GROUP,
+ idmap_tdb2_state.low_gid) == -1) {
+ DEBUG(0, ("Unable to initialise group hwm in idmap database\n"));
+ return NT_STATUS_INTERNAL_DB_ERROR;
+ }
+ }
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+/*
+ Initialise idmap alloc database.
+*/
+static NTSTATUS idmap_tdb2_alloc_init(const char *params)
+{
+ /* nothing to do - we want to avoid opening the permanent
+ database if possible. Instead we load the params when we
+ first need it. */
+ return NT_STATUS_OK;
+}
+
+
+/*
+ Allocate a new id.
+*/
+static NTSTATUS idmap_tdb2_allocate_id(struct unixid *xid)
+{
+ bool ret;
+ const char *hwmkey;
+ const char *hwmtype;
+ uint32_t high_hwm;
+ uint32_t hwm;
+ NTSTATUS status;
+
+ status = idmap_tdb2_open_perm_db();
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ /* Get current high water mark */
+ switch (xid->type) {
+
+ case ID_TYPE_UID:
+ hwmkey = HWM_USER;
+ hwmtype = "UID";
+ high_hwm = idmap_tdb2_state.high_uid;
+ break;
+
+ case ID_TYPE_GID:
+ hwmkey = HWM_GROUP;
+ hwmtype = "GID";
+ high_hwm = idmap_tdb2_state.high_gid;
+ break;
+
+ default:
+ DEBUG(2, ("Invalid ID type (0x%x)\n", xid->type));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if ((hwm = dbwrap_fetch_int32(idmap_tdb2_perm, hwmkey)) == -1) {
+ return NT_STATUS_INTERNAL_DB_ERROR;
+ }
+
+ /* check it is in the range */
+ if (hwm > high_hwm) {
+ DEBUG(1, ("Fatal Error: %s range full!! (max: %lu)\n",
+ hwmtype, (unsigned long)high_hwm));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ /* fetch a new id and increment it */
+ ret = dbwrap_change_uint32_atomic(idmap_tdb2_perm, hwmkey, &hwm, 1);
+ if (ret == -1) {
+ DEBUG(1, ("Fatal error while fetching a new %s value\n!", hwmtype));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ /* recheck it is in the range */
+ if (hwm > high_hwm) {
+ DEBUG(1, ("Fatal Error: %s range full!! (max: %lu)\n",
+ hwmtype, (unsigned long)high_hwm));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ xid->id = hwm;
+ DEBUG(10,("New %s = %d\n", hwmtype, hwm));
+
+ return NT_STATUS_OK;
+}
+
+/*
+ Get current highest id.
+*/
+static NTSTATUS idmap_tdb2_get_hwm(struct unixid *xid)
+{
+ const char *hwmkey;
+ const char *hwmtype;
+ uint32_t hwm;
+ uint32_t high_hwm;
+
+ /* Get current high water mark */
+ switch (xid->type) {
+
+ case ID_TYPE_UID:
+ hwmkey = HWM_USER;
+ hwmtype = "UID";
+ high_hwm = idmap_tdb2_state.high_uid;
+ break;
+
+ case ID_TYPE_GID:
+ hwmkey = HWM_GROUP;
+ hwmtype = "GID";
+ high_hwm = idmap_tdb2_state.high_gid;
+ break;
+
+ default:
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if ((hwm = dbwrap_fetch_int32(idmap_tdb2_perm, hwmkey)) == -1) {
+ return NT_STATUS_INTERNAL_DB_ERROR;
+ }
+
+ xid->id = hwm;
+
+ /* Warn if it is out of range */
+ if (hwm >= high_hwm) {
+ DEBUG(0, ("Warning: %s range full!! (max: %lu)\n",
+ hwmtype, (unsigned long)high_hwm));
+ }
+
+ return NT_STATUS_OK;
+}
+
+/*
+ Set high id.
+*/
+static NTSTATUS idmap_tdb2_set_hwm(struct unixid *xid)
+{
+ /* not supported, or we would invalidate the cache tdb on
+ other nodes */
+ DEBUG(0,("idmap_tdb2_set_hwm not supported\n"));
+ return NT_STATUS_NOT_SUPPORTED;
+}
+
+/*
+ Close the alloc tdb
+*/
+static NTSTATUS idmap_tdb2_alloc_close(void)
+{
+ /* don't actually close it */
+ return NT_STATUS_OK;
+}
+
+/*
+ IDMAP MAPPING TDB BACKEND
+*/
+struct idmap_tdb2_context {
+ uint32_t filter_low_id;
+ uint32_t filter_high_id;
+};
+
+/*
+ try fetching from the cache tdb, and if that fails then
+ fetch from the permanent tdb
+ */
+static TDB_DATA tdb2_fetch_bystring(TALLOC_CTX *mem_ctx, const char *keystr)
+{
+ TDB_DATA ret;
+ NTSTATUS status;
+
+ ret = tdb_fetch_bystring(idmap_tdb2_tmp, keystr);
+ if (ret.dptr != NULL) {
+ /* got it from cache */
+ unsigned char *tmp;
+
+ tmp = (unsigned char *)talloc_memdup(mem_ctx, ret.dptr,
+ ret.dsize);
+ SAFE_FREE(ret.dptr);
+ ret.dptr = tmp;
+
+ if (ret.dptr == NULL) {
+ return make_tdb_data(NULL, 0);
+ }
+ return ret;
+ }
+
+ status = idmap_tdb2_open_perm_db();
+ if (!NT_STATUS_IS_OK(status)) {
+ return ret;
+ }
+
+ /* fetch from the permanent tdb */
+ return dbwrap_fetch_bystring(idmap_tdb2_perm, mem_ctx, keystr);
+}
+
+/*
+ store into both databases
+ */
+static NTSTATUS tdb2_store_bystring(const char *keystr, TDB_DATA data, int flags)
+{
+ NTSTATUS ret;
+ NTSTATUS status = idmap_tdb2_open_perm_db();
+ if (!NT_STATUS_IS_OK(status)) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ ret = dbwrap_store_bystring(idmap_tdb2_perm, keystr, data, flags);
+ if (!NT_STATUS_IS_OK(ret)) {
+ ret = tdb_store_bystring(idmap_tdb2_tmp, keystr, data, flags) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+ }
+ return ret;
+}
+
+/*
+ delete from both databases
+ */
+static NTSTATUS tdb2_delete_bystring(const char *keystr)
+{
+ NTSTATUS ret;
+ NTSTATUS status = idmap_tdb2_open_perm_db();
+ if (!NT_STATUS_IS_OK(status)) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ ret = dbwrap_delete_bystring(idmap_tdb2_perm, keystr);
+ if (!NT_STATUS_IS_OK(ret)) {
+ ret = tdb_delete_bystring(idmap_tdb2_tmp, keystr) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+ }
+ return ret;
+}
+
+/*
+ Initialise idmap database.
+*/
+static NTSTATUS idmap_tdb2_db_init(struct idmap_domain *dom)
+{
+ NTSTATUS ret;
+ struct idmap_tdb2_context *ctx;
+ char *config_option = NULL;
+ const char *range;
+ NTSTATUS status;
+
+ status = idmap_tdb2_open_cache_db();
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ ctx = talloc(dom, struct idmap_tdb2_context);
+ if ( ! ctx) {
+ DEBUG(0, ("Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ config_option = talloc_asprintf(ctx, "idmap config %s", dom->name);
+ if ( ! config_option) {
+ DEBUG(0, ("Out of memory!\n"));
+ ret = NT_STATUS_NO_MEMORY;
+ goto failed;
+ }
+
+ range = lp_parm_const_string(-1, config_option, "range", NULL);
+ if (( ! range) ||
+ (sscanf(range, "%u - %u", &ctx->filter_low_id, &ctx->filter_high_id) != 2) ||
+ (ctx->filter_low_id > ctx->filter_high_id)) {
+ ctx->filter_low_id = 0;
+ ctx->filter_high_id = 0;
+ }
+
+ dom->private_data = ctx;
+ dom->initialized = True;
+
+ talloc_free(config_option);
+ return NT_STATUS_OK;
+
+failed:
+ talloc_free(ctx);
+ return ret;
+}
+
+
+/*
+ run a script to perform a mapping
+
+ The script should the following command lines:
+
+ SIDTOID S-1-xxxx
+ IDTOSID UID xxxx
+ IDTOSID GID xxxx
+
+ and should return one of the following as a single line of text
+ UID:xxxx
+ GID:xxxx
+ SID:xxxx
+ ERR:xxxx
+ */
+static NTSTATUS idmap_tdb2_script(struct idmap_tdb2_context *ctx, struct id_map *map,
+ const char *fmt, ...)
+{
+ va_list ap;
+ char *cmd;
+ FILE *p;
+ char line[64];
+ unsigned long v;
+
+ cmd = talloc_asprintf(ctx, "%s ", idmap_tdb2_state.idmap_script);
+ NT_STATUS_HAVE_NO_MEMORY(cmd);
+
+ va_start(ap, fmt);
+ cmd = talloc_vasprintf_append(cmd, fmt, ap);
+ va_end(ap);
+ NT_STATUS_HAVE_NO_MEMORY(cmd);
+
+ p = popen(cmd, "r");
+ talloc_free(cmd);
+ if (p == NULL) {
+ return NT_STATUS_NONE_MAPPED;
+ }
+
+ if (fgets(line, sizeof(line)-1, p) == NULL) {
+ pclose(p);
+ return NT_STATUS_NONE_MAPPED;
+ }
+ pclose(p);
+
+ DEBUG(10,("idmap script gave: %s\n", line));
+
+ if (sscanf(line, "UID:%lu", &v) == 1) {
+ map->xid.id = v;
+ map->xid.type = ID_TYPE_UID;
+ } else if (sscanf(line, "GID:%lu", &v) == 1) {
+ map->xid.id = v;
+ map->xid.type = ID_TYPE_GID;
+ } else if (strncmp(line, "SID:S-", 6) == 0) {
+ if (!string_to_sid(map->sid, &line[4])) {
+ DEBUG(0,("Bad SID in '%s' from idmap script %s\n",
+ line, idmap_tdb2_state.idmap_script));
+ return NT_STATUS_NONE_MAPPED;
+ }
+ } else {
+ DEBUG(0,("Bad reply '%s' from idmap script %s\n",
+ line, idmap_tdb2_state.idmap_script));
+ return NT_STATUS_NONE_MAPPED;
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+
+/*
+ Single id to sid lookup function.
+*/
+static NTSTATUS idmap_tdb2_id_to_sid(struct idmap_tdb2_context *ctx, struct id_map *map)
+{
+ NTSTATUS ret;
+ TDB_DATA data;
+ char *keystr;
+
+ if (!ctx || !map) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ /* apply filters before checking */
+ if ((ctx->filter_low_id && (map->xid.id < ctx->filter_low_id)) ||
+ (ctx->filter_high_id && (map->xid.id > ctx->filter_high_id))) {
+ DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n",
+ map->xid.id, ctx->filter_low_id, ctx->filter_high_id));
+ return NT_STATUS_NONE_MAPPED;
+ }
+
+ switch (map->xid.type) {
+
+ case ID_TYPE_UID:
+ keystr = talloc_asprintf(ctx, "UID %lu", (unsigned long)map->xid.id);
+ break;
+
+ case ID_TYPE_GID:
+ keystr = talloc_asprintf(ctx, "GID %lu", (unsigned long)map->xid.id);
+ break;
+
+ default:
+ DEBUG(2, ("INVALID unix ID type: 0x02%x\n", map->xid.type));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ /* final SAFE_FREE safe */
+ data.dptr = NULL;
+
+ if (keystr == NULL) {
+ DEBUG(0, ("Out of memory!\n"));
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ DEBUG(10,("Fetching record %s\n", keystr));
+
+ /* Check if the mapping exists */
+ data = tdb2_fetch_bystring(keystr, keystr);
+
+ if (!data.dptr) {
+ fstring sidstr;
+
+ DEBUG(10,("Record %s not found\n", keystr));
+ if (idmap_tdb2_state.idmap_script == NULL) {
+ ret = NT_STATUS_NONE_MAPPED;
+ goto done;
+ }
+
+ ret = idmap_tdb2_script(ctx, map, "IDTOSID %s", keystr);
+
+ /* store it on shared storage */
+ if (!NT_STATUS_IS_OK(ret)) {
+ goto done;
+ }
+
+ if (sid_to_fstring(sidstr, map->sid)) {
+ /* both forward and reverse mappings */
+ tdb2_store_bystring(keystr,
+ string_term_tdb_data(sidstr),
+ TDB_REPLACE);
+ tdb2_store_bystring(sidstr,
+ string_term_tdb_data(keystr),
+ TDB_REPLACE);
+ }
+ goto done;
+ }
+
+ if (!string_to_sid(map->sid, (const char *)data.dptr)) {
+ DEBUG(10,("INVALID SID (%s) in record %s\n",
+ (const char *)data.dptr, keystr));
+ ret = NT_STATUS_INTERNAL_DB_ERROR;
+ goto done;
+ }
+
+ DEBUG(10,("Found record %s -> %s\n", keystr, (const char *)data.dptr));
+ ret = NT_STATUS_OK;
+
+done:
+ talloc_free(keystr);
+ return ret;
+}
+
+
+/*
+ Single sid to id lookup function.
+*/
+static NTSTATUS idmap_tdb2_sid_to_id(struct idmap_tdb2_context *ctx, struct id_map *map)
+{
+ NTSTATUS ret;
+ TDB_DATA data;
+ char *keystr;
+ unsigned long rec_id = 0;
+
+ if ((keystr = sid_string_talloc(ctx, map->sid)) == NULL) {
+ DEBUG(0, ("Out of memory!\n"));
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ DEBUG(10,("Fetching record %s\n", keystr));
+
+ /* Check if sid is present in database */
+ data = tdb2_fetch_bystring(keystr, keystr);
+ if (!data.dptr) {
+ fstring idstr;
+
+ DEBUG(10,(__location__ " Record %s not found\n", keystr));
+
+ if (idmap_tdb2_state.idmap_script == NULL) {
+ ret = NT_STATUS_NONE_MAPPED;
+ goto done;
+ }
+
+ ret = idmap_tdb2_script(ctx, map, "SIDTOID %s", keystr);
+ /* store it on shared storage */
+ if (!NT_STATUS_IS_OK(ret)) {
+ goto done;
+ }
+
+ snprintf(idstr, sizeof(idstr), "%cID %lu",
+ map->xid.type == ID_TYPE_UID?'U':'G',
+ (unsigned long)map->xid.id);
+ /* store both forward and reverse mappings */
+ tdb2_store_bystring(keystr, string_term_tdb_data(idstr),
+ TDB_REPLACE);
+ tdb2_store_bystring(idstr, string_term_tdb_data(keystr),
+ TDB_REPLACE);
+ goto done;
+ }
+
+ /* What type of record is this ? */
+ if (sscanf((const char *)data.dptr, "UID %lu", &rec_id) == 1) { /* Try a UID record. */
+ map->xid.id = rec_id;
+ map->xid.type = ID_TYPE_UID;
+ DEBUG(10,("Found uid record %s -> %s \n", keystr, (const char *)data.dptr ));
+ ret = NT_STATUS_OK;
+
+ } else if (sscanf((const char *)data.dptr, "GID %lu", &rec_id) == 1) { /* Try a GID record. */
+ map->xid.id = rec_id;
+ map->xid.type = ID_TYPE_GID;
+ DEBUG(10,("Found gid record %s -> %s \n", keystr, (const char *)data.dptr ));
+ ret = NT_STATUS_OK;
+
+ } else { /* Unknown record type ! */
+ DEBUG(2, ("Found INVALID record %s -> %s\n", keystr, (const char *)data.dptr));
+ ret = NT_STATUS_INTERNAL_DB_ERROR;
+ }
+
+ /* apply filters before returning result */
+ if ((ctx->filter_low_id && (map->xid.id < ctx->filter_low_id)) ||
+ (ctx->filter_high_id && (map->xid.id > ctx->filter_high_id))) {
+ DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n",
+ map->xid.id, ctx->filter_low_id, ctx->filter_high_id));
+ ret = NT_STATUS_NONE_MAPPED;
+ }
+
+done:
+ talloc_free(keystr);
+ return ret;
+}
+
+/*
+ lookup a set of unix ids.
+*/
+static NTSTATUS idmap_tdb2_unixids_to_sids(struct idmap_domain *dom, struct id_map **ids)
+{
+ struct idmap_tdb2_context *ctx;
+ NTSTATUS ret;
+ int i;
+
+ /* make sure we initialized */
+ if ( ! dom->initialized) {
+ ret = idmap_tdb2_db_init(dom);
+ if ( ! NT_STATUS_IS_OK(ret)) {
+ return ret;
+ }
+ }
+
+ ctx = talloc_get_type(dom->private_data, struct idmap_tdb2_context);
+
+ for (i = 0; ids[i]; i++) {
+ ret = idmap_tdb2_id_to_sid(ctx, ids[i]);
+ if ( ! NT_STATUS_IS_OK(ret)) {
+
+ /* if it is just a failed mapping continue */
+ if (NT_STATUS_EQUAL(ret, NT_STATUS_NONE_MAPPED)) {
+
+ /* make sure it is marked as unmapped */
+ ids[i]->status = ID_UNMAPPED;
+ continue;
+ }
+
+ /* some fatal error occurred, return immediately */
+ goto done;
+ }
+
+ /* all ok, id is mapped */
+ ids[i]->status = ID_MAPPED;
+ }
+
+ ret = NT_STATUS_OK;
+
+done:
+ return ret;
+}
+
+/*
+ lookup a set of sids.
+*/
+static NTSTATUS idmap_tdb2_sids_to_unixids(struct idmap_domain *dom, struct id_map **ids)
+{
+ struct idmap_tdb2_context *ctx;
+ NTSTATUS ret;
+ int i;
+
+ /* make sure we initialized */
+ if ( ! dom->initialized) {
+ ret = idmap_tdb2_db_init(dom);
+ if ( ! NT_STATUS_IS_OK(ret)) {
+ return ret;
+ }
+ }
+
+ ctx = talloc_get_type(dom->private_data, struct idmap_tdb2_context);
+
+ for (i = 0; ids[i]; i++) {
+ ret = idmap_tdb2_sid_to_id(ctx, ids[i]);
+ if ( ! NT_STATUS_IS_OK(ret)) {
+
+ /* if it is just a failed mapping continue */
+ if (NT_STATUS_EQUAL(ret, NT_STATUS_NONE_MAPPED)) {
+
+ /* make sure it is marked as unmapped */
+ ids[i]->status = ID_UNMAPPED;
+ continue;
+ }
+
+ /* some fatal error occurred, return immediately */
+ goto done;
+ }
+
+ /* all ok, id is mapped */
+ ids[i]->status = ID_MAPPED;
+ }
+
+ ret = NT_STATUS_OK;
+
+done:
+ return ret;
+}
+
+
+/*
+ set a mapping.
+*/
+static NTSTATUS idmap_tdb2_set_mapping(struct idmap_domain *dom, const struct id_map *map)
+{
+ struct idmap_tdb2_context *ctx;
+ NTSTATUS ret;
+ TDB_DATA data;
+ char *ksidstr, *kidstr;
+ struct db_record *update_lock = NULL;
+ struct db_record *rec = NULL;
+
+ /* make sure we initialized */
+ if ( ! dom->initialized) {
+ ret = idmap_tdb2_db_init(dom);
+ if ( ! NT_STATUS_IS_OK(ret)) {
+ return ret;
+ }
+ }
+
+ if (!map || !map->sid) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ ksidstr = kidstr = NULL;
+ data.dptr = NULL;
+
+ /* TODO: should we filter a set_mapping using low/high filters ? */
+
+ ctx = talloc_get_type(dom->private_data, struct idmap_tdb2_context);
+
+ switch (map->xid.type) {
+
+ case ID_TYPE_UID:
+ kidstr = talloc_asprintf(ctx, "UID %lu", (unsigned long)map->xid.id);
+ break;
+
+ case ID_TYPE_GID:
+ kidstr = talloc_asprintf(ctx, "GID %lu", (unsigned long)map->xid.id);
+ break;
+
+ default:
+ DEBUG(2, ("INVALID unix ID type: 0x02%x\n", map->xid.type));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (kidstr == NULL) {
+ DEBUG(0, ("ERROR: Out of memory!\n"));
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ if (!(ksidstr = sid_string_talloc(ctx, map->sid))) {
+ DEBUG(0, ("Out of memory!\n"));
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ DEBUG(10, ("Storing %s <-> %s map\n", ksidstr, kidstr));
+
+ /*
+ * Get us the update lock. This is necessary to get the lock orders
+ * right, we need to deal with two records under a lock.
+ */
+
+ if (!(update_lock = idmap_tdb2_perm->fetch_locked(
+ idmap_tdb2_perm, ctx,
+ string_term_tdb_data("UPDATELOCK")))) {
+ DEBUG(10,("Failed to lock record %s\n", ksidstr));
+ ret = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ /*
+ * *DELETE* previous mappings if any. *
+ */
+
+ /* First delete indexed on SID */
+
+ if (((rec = idmap_tdb2_perm->fetch_locked(
+ idmap_tdb2_perm, update_lock,
+ string_term_tdb_data(ksidstr))) != NULL)
+ && (rec->value.dsize != 0)) {
+ struct db_record *rec2;
+
+ if ((rec2 = idmap_tdb2_perm->fetch_locked(
+ idmap_tdb2_perm, update_lock, rec->value))
+ != NULL) {
+ rec2->delete_rec(rec2);
+ TALLOC_FREE(rec2);
+ }
+
+ rec->delete_rec(rec);
+
+ tdb_delete(idmap_tdb2_tmp, rec->key);
+ tdb_delete(idmap_tdb2_tmp, rec->value);
+ }
+ TALLOC_FREE(rec);
+
+ /* Now delete indexed on unix ID */
+
+ if (((rec = idmap_tdb2_perm->fetch_locked(
+ idmap_tdb2_perm, update_lock,
+ string_term_tdb_data(kidstr))) != NULL)
+ && (rec->value.dsize != 0)) {
+ struct db_record *rec2;
+
+ if ((rec2 = idmap_tdb2_perm->fetch_locked(
+ idmap_tdb2_perm, update_lock, rec->value))
+ != NULL) {
+ rec2->delete_rec(rec2);
+ TALLOC_FREE(rec2);
+ }
+
+ rec->delete_rec(rec);
+
+ tdb_delete(idmap_tdb2_tmp, rec->key);
+ tdb_delete(idmap_tdb2_tmp, rec->value);
+ }
+ TALLOC_FREE(rec);
+
+ if (!NT_STATUS_IS_OK(tdb2_store_bystring(ksidstr, string_term_tdb_data(kidstr),
+ TDB_INSERT))) {
+ DEBUG(0, ("Error storing SID -> ID\n"));
+ ret = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+ if (!NT_STATUS_IS_OK(tdb2_store_bystring(kidstr, string_term_tdb_data(ksidstr),
+ TDB_INSERT))) {
+ DEBUG(0, ("Error storing ID -> SID\n"));
+ /* try to remove the previous stored SID -> ID map */
+ tdb2_delete_bystring(ksidstr);
+ ret = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ DEBUG(10,("Stored %s <-> %s\n", ksidstr, kidstr));
+ ret = NT_STATUS_OK;
+
+done:
+ talloc_free(ksidstr);
+ talloc_free(kidstr);
+ SAFE_FREE(data.dptr);
+ TALLOC_FREE(update_lock);
+ return ret;
+}
+
+/*
+ remove a mapping.
+*/
+static NTSTATUS idmap_tdb2_remove_mapping(struct idmap_domain *dom, const struct id_map *map)
+{
+ /* not supported as it would invalidate the cache tdb on other
+ nodes */
+ DEBUG(0,("idmap_tdb2_remove_mapping not supported\n"));
+ return NT_STATUS_NOT_SUPPORTED;
+}
+
+/*
+ Close the idmap tdb instance
+*/
+static NTSTATUS idmap_tdb2_close(struct idmap_domain *dom)
+{
+ /* don't do anything */
+ return NT_STATUS_OK;
+}
+
+
+/*
+ Dump all mappings out
+*/
+static NTSTATUS idmap_tdb2_dump_data(struct idmap_domain *dom, struct id_map **maps, int *num_maps)
+{
+ DEBUG(0,("idmap_tdb2_dump_data not supported\n"));
+ return NT_STATUS_NOT_SUPPORTED;
+}
+
+static struct idmap_methods db_methods = {
+ .init = idmap_tdb2_db_init,
+ .unixids_to_sids = idmap_tdb2_unixids_to_sids,
+ .sids_to_unixids = idmap_tdb2_sids_to_unixids,
+ .set_mapping = idmap_tdb2_set_mapping,
+ .remove_mapping = idmap_tdb2_remove_mapping,
+ .dump_data = idmap_tdb2_dump_data,
+ .close_fn = idmap_tdb2_close
+};
+
+static struct idmap_alloc_methods db_alloc_methods = {
+ .init = idmap_tdb2_alloc_init,
+ .allocate_id = idmap_tdb2_allocate_id,
+ .get_id_hwm = idmap_tdb2_get_hwm,
+ .set_id_hwm = idmap_tdb2_set_hwm,
+ .close_fn = idmap_tdb2_alloc_close
+};
+
+NTSTATUS idmap_tdb2_init(void)
+{
+ NTSTATUS ret;
+
+ /* register both backends */
+ ret = smb_register_idmap_alloc(SMB_IDMAP_INTERFACE_VERSION, "tdb2", &db_alloc_methods);
+ if (! NT_STATUS_IS_OK(ret)) {
+ DEBUG(0, ("Unable to register idmap alloc tdb2 module: %s\n", get_friendly_nt_error_msg(ret)));
+ return ret;
+ }
+
+ return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "tdb2", &db_methods);
+}
diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c
index 07cf22618e..615f4a918e 100644
--- a/source3/winbindd/winbindd.c
+++ b/source3/winbindd/winbindd.c
@@ -121,7 +121,24 @@ static void flush_caches(void)
otherwise cached access denied errors due to restrict anonymous
hang around until the sequence number changes. */
- wcache_invalidate_cache();
+ if (!wcache_invalidate_cache()) {
+ DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
+ /* Close the cache to be able to valdite the cache */
+ close_winbindd_cache();
+ /*
+ * Ensure all cache and idmap caches are consistent
+ * before we initialize the cache again.
+ */
+ if (winbindd_validate_cache() < 0) {
+ DEBUG(0, ("winbindd cache tdb corrupt and no backup "
+ "could be restore.\n"));
+ }
+
+ /* Initialize cache again. */
+ if (!initialize_winbindd_cache()) {
+ exit(1);
+ }
+ }
}
/* Handle the signal by unlinking socket and exiting */
@@ -1210,6 +1227,10 @@ int main(int argc, char **argv, char **envp)
MSG_WINBIND_VALIDATE_CACHE,
winbind_msg_validate_cache);
+ messaging_register(winbind_messaging_context(), NULL,
+ MSG_WINBIND_DUMP_DOMAIN_LIST,
+ winbind_msg_dump_domain_list);
+
netsamlogon_cache_init(); /* Non-critical */
/* clear the cached list of trusted domains */
diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h
index 6bf6e6c68f..c4c1278d73 100644
--- a/source3/winbindd/winbindd.h
+++ b/source3/winbindd/winbindd.h
@@ -164,9 +164,9 @@ struct winbindd_domain {
fstring alt_name; /* alt Domain name, if any (FQDN for ADS) */
fstring forest_name; /* Name of the AD forest we're in */
DOM_SID sid; /* SID for this domain */
- uint32 domain_flags; /* Domain flags from rpc_ds.h */
- uint32 domain_type; /* Domain type from rpc_ds.h */
- uint32 domain_trust_attribs; /* Trust attribs from rpc_ds.h */
+ uint32 domain_flags; /* Domain flags from netlogon.h */
+ uint32 domain_type; /* Domain type from netlogon.h */
+ uint32 domain_trust_attribs; /* Trust attribs from netlogon.h */
bool initialized; /* Did we already ask for the domain mode? */
bool native_mode; /* is this a win2k domain in native mode ? */
bool active_directory; /* is this a win2k active directory ? */
diff --git a/source3/winbindd/winbindd_ads.c b/source3/winbindd/winbindd_ads.c
index c9b2a52388..db7ceca04d 100644
--- a/source3/winbindd/winbindd_ads.c
+++ b/source3/winbindd/winbindd_ads.c
@@ -596,8 +596,9 @@ static NTSTATUS lookup_usergroups_member(struct winbindd_domain *domain,
num_groups = 0;
/* always add the primary group to the sid array */
- if (!add_sid_to_array(mem_ctx, primary_group, user_sids, &num_groups)) {
- status = NT_STATUS_NO_MEMORY;
+ status = add_sid_to_array(mem_ctx, primary_group, user_sids,
+ &num_groups);
+ if (!NT_STATUS_IS_OK(status)) {
goto done;
}
@@ -615,10 +616,10 @@ static NTSTATUS lookup_usergroups_member(struct winbindd_domain *domain,
if (sid_check_is_in_builtin(&group_sid)) {
continue;
}
-
- if (!add_sid_to_array(mem_ctx, &group_sid, user_sids,
- &num_groups)) {
- status = NT_STATUS_NO_MEMORY;
+
+ status = add_sid_to_array(mem_ctx, &group_sid,
+ user_sids, &num_groups);
+ if (!NT_STATUS_IS_OK(status)) {
goto done;
}
}
@@ -684,8 +685,9 @@ static NTSTATUS lookup_usergroups_memberof(struct winbindd_domain *domain,
num_groups = 0;
/* always add the primary group to the sid array */
- if (!add_sid_to_array(mem_ctx, primary_group, user_sids, &num_groups)) {
- status = NT_STATUS_NO_MEMORY;
+ status = add_sid_to_array(mem_ctx, primary_group, user_sids,
+ &num_groups);
+ if (!NT_STATUS_IS_OK(status)) {
goto done;
}
@@ -720,10 +722,10 @@ static NTSTATUS lookup_usergroups_memberof(struct winbindd_domain *domain,
if (sid_check_is_in_builtin(&group_sids[i])) {
continue;
}
-
- if (!add_sid_to_array(mem_ctx, &group_sids[i], user_sids,
- &num_groups)) {
- status = NT_STATUS_NO_MEMORY;
+
+ status = add_sid_to_array(mem_ctx, &group_sids[i], user_sids,
+ &num_groups);
+ if (!NT_STATUS_IS_OK(status)) {
goto done;
}
@@ -861,8 +863,9 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
*user_sids = NULL;
num_groups = 0;
- if (!add_sid_to_array(mem_ctx, &primary_group, user_sids, &num_groups)) {
- status = NT_STATUS_NO_MEMORY;
+ status = add_sid_to_array(mem_ctx, &primary_group, user_sids,
+ &num_groups);
+ if (!NT_STATUS_IS_OK(status)) {
goto done;
}
@@ -872,10 +875,10 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
if (sid_check_is_in_builtin(&sids[i])) {
continue;
}
-
- if (!add_sid_to_array_unique(mem_ctx, &sids[i],
- user_sids, &num_groups)) {
- status = NT_STATUS_NO_MEMORY;
+
+ status = add_sid_to_array_unique(mem_ctx, &sids[i],
+ user_sids, &num_groups);
+ if (!NT_STATUS_IS_OK(status)) {
goto done;
}
}
@@ -1154,12 +1157,11 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
DOM_SID **dom_sids)
{
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
- struct ds_domain_trust *domains = NULL;
- int count = 0;
+ struct netr_DomainTrustList trusts;
int i;
uint32 flags;
struct rpc_pipe_client *cli;
- uint32 fr_flags = (DS_DOMAIN_IN_FOREST | DS_DOMAIN_TREE_ROOT);
+ uint32 fr_flags = (NETR_TRUST_FLAG_IN_FOREST | NETR_TRUST_FLAG_TREEROOT);
int ret_count;
DEBUG(3,("ads: trusted_domains\n"));
@@ -1176,11 +1178,11 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
if ( domain->primary ||
((domain->domain_flags&fr_flags) == fr_flags) )
{
- flags = DS_DOMAIN_DIRECT_OUTBOUND |
- DS_DOMAIN_DIRECT_INBOUND |
- DS_DOMAIN_IN_FOREST;
+ flags = NETR_TRUST_FLAG_OUTBOUND |
+ NETR_TRUST_FLAG_INBOUND |
+ NETR_TRUST_FLAG_IN_FOREST;
} else {
- flags = DS_DOMAIN_IN_FOREST;
+ flags = NETR_TRUST_FLAG_IN_FOREST;
}
result = cm_connect_netlogon(domain, &cli);
@@ -1191,29 +1193,27 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
domain->name, nt_errstr(result)));
return NT_STATUS_UNSUCCESSFUL;
}
-
- if ( NT_STATUS_IS_OK(result) ) {
- result = rpccli_ds_enum_domain_trusts(cli, mem_ctx,
- cli->cli->desthost,
- flags, &domains,
- (unsigned int *)&count);
- }
-
- if ( NT_STATUS_IS_OK(result) && count) {
+
+ result = rpccli_netr_DsrEnumerateDomainTrusts(cli, mem_ctx,
+ cli->cli->desthost,
+ flags,
+ &trusts,
+ NULL);
+ if ( NT_STATUS_IS_OK(result) && trusts.count) {
/* Allocate memory for trusted domain names and sids */
- if ( !(*names = TALLOC_ARRAY(mem_ctx, char *, count)) ) {
+ if ( !(*names = TALLOC_ARRAY(mem_ctx, char *, trusts.count)) ) {
DEBUG(0, ("trusted_domains: out of memory\n"));
return NT_STATUS_NO_MEMORY;
}
- if ( !(*alt_names = TALLOC_ARRAY(mem_ctx, char *, count)) ) {
+ if ( !(*alt_names = TALLOC_ARRAY(mem_ctx, char *, trusts.count)) ) {
DEBUG(0, ("trusted_domains: out of memory\n"));
return NT_STATUS_NO_MEMORY;
}
- if ( !(*dom_sids = TALLOC_ARRAY(mem_ctx, DOM_SID, count)) ) {
+ if ( !(*dom_sids = TALLOC_ARRAY(mem_ctx, DOM_SID, trusts.count)) ) {
DEBUG(0, ("trusted_domains: out of memory\n"));
return NT_STATUS_NO_MEMORY;
}
@@ -1222,7 +1222,7 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
ret_count = 0;
- for (i = 0; i < count; i++) {
+ for (i = 0; i < trusts.count; i++) {
struct winbindd_domain d;
/* drop external trusts if this is not our primary
@@ -1230,24 +1230,24 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
domains may be less that the ones actually trusted
by the DC. */
- if ( (domains[i].trust_attributes == DS_DOMAIN_TRUST_ATTRIB_QUARANTINED_DOMAIN) &&
+ if ( (trusts.array[i].trust_attributes == NETR_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN) &&
!domain->primary )
{
DEBUG(10,("trusted_domains: Skipping external trusted domain "
"%s because it is outside of our primary domain\n",
- domains[i].netbios_domain));
+ trusts.array[i].netbios_name));
continue;
}
- (*names)[ret_count] = domains[i].netbios_domain;
- (*alt_names)[ret_count] = domains[i].dns_domain;
- sid_copy(&(*dom_sids)[ret_count], &domains[i].sid);
+ (*names)[ret_count] = CONST_DISCARD(char *, trusts.array[i].netbios_name);
+ (*alt_names)[ret_count] = CONST_DISCARD(char *, trusts.array[i].dns_name);
+ sid_copy(&(*dom_sids)[ret_count], trusts.array[i].sid);
/* add to the trusted domain cache */
- fstrcpy( d.name, domains[i].netbios_domain );
- fstrcpy( d.alt_name, domains[i].dns_domain );
- sid_copy( &d.sid, &domains[i].sid );
+ fstrcpy( d.name, trusts.array[i].netbios_name);
+ fstrcpy( d.alt_name, trusts.array[i].dns_name);
+ sid_copy( &d.sid, trusts.array[i].sid);
/* This gets a little tricky. If we are
following a transitive forest trust, then
@@ -1266,16 +1266,28 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
we have the current trust flags and
attributes */
- d.domain_flags = domains[i].flags;
- d.domain_type = domains[i].trust_type;
- d.domain_trust_attribs = domains[i].trust_attributes;
+ d.domain_flags = trusts.array[i].trust_flags;
+ d.domain_type = trusts.array[i].trust_type;
+ d.domain_trust_attribs = trusts.array[i].trust_attributes;
} else {
+ /* Look up the record in the cache */
+ struct winbindd_tdc_domain *parent;
+
DEBUG(10,("trusted_domains(ads): Inheriting trust "
"flags for domain %s\n", d.alt_name));
+
+ parent = wcache_tdc_fetch_domain(NULL, domain->name);
+ if (parent) {
+ d.domain_flags = parent->trust_flags;
+ d.domain_type = parent->trust_type;
+ d.domain_trust_attribs = parent->trust_attribs;
+ } else {
d.domain_flags = domain->domain_flags;
d.domain_type = domain->domain_type;
d.domain_trust_attribs = domain->domain_trust_attribs;
}
+ TALLOC_FREE(parent);
+ }
wcache_tdc_add_domain( &d );
diff --git a/source3/winbindd/winbindd_async.c b/source3/winbindd/winbindd_async.c
index 76724582a1..ab32ee0c76 100644
--- a/source3/winbindd/winbindd_async.c
+++ b/source3/winbindd/winbindd_async.c
@@ -492,7 +492,9 @@ static bool parse_sidlist(TALLOC_CTX *mem_ctx, char *sidstr,
DEBUG(0, ("Could not parse sid %s\n", p));
return False;
}
- if (!add_sid_to_array(mem_ctx, &sid, sids, num_sids)) {
+ if (!NT_STATUS_IS_OK(add_sid_to_array(mem_ctx, &sid, sids,
+ num_sids)))
+ {
return False;
}
p = q;
@@ -714,7 +716,9 @@ enum winbindd_result winbindd_dual_getsidaliases(struct winbindd_domain *domain,
DEBUGADD(10, (" rid %d\n", alias_rids[i]));
sid_copy(&sid, &domain->sid);
sid_append_rid(&sid, alias_rids[i]);
- if (!add_sid_to_array(state->mem_ctx, &sid, &sids, &num_sids)) {
+ result = add_sid_to_array(state->mem_ctx, &sid, &sids,
+ &num_sids);
+ if (!NT_STATUS_IS_OK(result)) {
return WINBINDD_ERROR;
}
}
@@ -832,8 +836,9 @@ static void gettoken_recvdomgroups(TALLOC_CTX *mem_ctx, bool success,
state->sids = NULL;
state->num_sids = 0;
- if (!add_sid_to_array(mem_ctx, &state->user_sid, &state->sids,
- &state->num_sids)) {
+ if (!NT_STATUS_IS_OK(add_sid_to_array(mem_ctx, &state->user_sid,
+ &state->sids, &state->num_sids)))
+ {
DEBUG(0, ("Out of memory\n"));
state->cont(state->private_data, False, NULL, 0);
return;
@@ -874,8 +879,11 @@ static void gettoken_recvaliases(void *private_data, bool success,
}
for (i=0; i<num_aliases; i++) {
- if (!add_sid_to_array(state->mem_ctx, &aliases[i],
- &state->sids, &state->num_sids)) {
+ if (!NT_STATUS_IS_OK(add_sid_to_array(state->mem_ctx,
+ &aliases[i],
+ &state->sids,
+ &state->num_sids)))
+ {
DEBUG(0, ("Out of memory\n"));
state->cont(state->private_data, False, NULL, 0);
return;
diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c
index f63c7a5b2f..c293861492 100644
--- a/source3/winbindd/winbindd_cache.c
+++ b/source3/winbindd/winbindd_cache.c
@@ -62,7 +62,7 @@ static bool is_non_centry_key(TDB_DATA kbuf)
int i;
if (kbuf.dptr == NULL || kbuf.dsize == 0) {
- return False;
+ return false;
}
for (i = 0; non_centry_keys[i] != NULL; i++) {
size_t namelen = strlen(non_centry_keys[i]);
@@ -70,10 +70,10 @@ static bool is_non_centry_key(TDB_DATA kbuf)
continue;
}
if (strncmp(non_centry_keys[i], (const char *)kbuf.dptr, namelen) == 0) {
- return True;
+ return true;
}
}
- return False;
+ return false;
}
/* Global online/offline state - False when online. winbindd starts up online
@@ -210,9 +210,9 @@ static bool centry_check_bytes(struct cache_entry *centry, size_t nbytes)
DEBUG(0,("centry corruption? needed %u bytes, have %d\n",
(unsigned int)nbytes,
centry->len - centry->ofs));
- return False;
+ return false;
}
- return True;
+ return true;
}
/*
@@ -348,9 +348,9 @@ static bool centry_sid(struct cache_entry *centry, TALLOC_CTX *mem_ctx, DOM_SID
char *sid_string;
sid_string = centry_string(centry, mem_ctx);
if ((sid_string == NULL) || (!string_to_sid(sid, sid_string))) {
- return False;
+ return false;
}
- return True;
+ return true;
}
@@ -372,7 +372,7 @@ static bool wcache_server_down(struct winbindd_domain *domain)
bool ret;
if (!wcache->tdb)
- return False;
+ return false;
ret = (domain->sequence_number == DOM_SEQUENCE_NONE);
@@ -454,7 +454,7 @@ static NTSTATUS store_cache_seqnum( struct winbindd_domain *domain )
}
/*
- refresh the domain sequence number. If force is True
+ refresh the domain sequence number. If force is true
then always refresh it, no matter how recently we fetched it
*/
@@ -538,7 +538,7 @@ static bool centry_expired(struct winbindd_domain *domain, const char *keystr, s
if (lp_winbind_offline_logon() && global_winbindd_offline_state) {
DEBUG(10,("centry_expired: Key %s for domain %s valid as winbindd is globally offline.\n",
keystr, domain->name ));
- return False;
+ return false;
}
/* when the domain is offline return the cached entry.
@@ -547,7 +547,7 @@ static bool centry_expired(struct winbindd_domain *domain, const char *keystr, s
if (!domain->online) {
DEBUG(10,("centry_expired: Key %s for domain %s valid as domain is offline.\n",
keystr, domain->name ));
- return False;
+ return false;
}
/* if the server is OK and our cache entry came from when it was down then
@@ -556,7 +556,7 @@ static bool centry_expired(struct winbindd_domain *domain, const char *keystr, s
(centry->sequence_number == DOM_SEQUENCE_NONE)) {
DEBUG(10,("centry_expired: Key %s for domain %s invalid sequence.\n",
keystr, domain->name ));
- return True;
+ return true;
}
/* if the server is down or the cache entry is not older than the
@@ -565,14 +565,14 @@ static bool centry_expired(struct winbindd_domain *domain, const char *keystr, s
centry->sequence_number == domain->sequence_number) {
DEBUG(10,("centry_expired: Key %s for domain %s is good.\n",
keystr, domain->name ));
- return False;
+ return false;
}
DEBUG(10,("centry_expired: Key %s for domain %s expired\n",
keystr, domain->name ));
/* it's expired */
- return True;
+ return true;
}
static struct cache_entry *wcache_fetch_raw(char *kstr)
@@ -625,7 +625,7 @@ static struct cache_entry *wcache_fetch(struct winbind_cache *cache,
return NULL;
}
- refresh_sequence_number(domain, False);
+ refresh_sequence_number(domain, false);
va_start(ap, format);
smb_xvasprintf(&kstr, format, ap);
@@ -1189,7 +1189,7 @@ do_query:
(retry++ < 5));
/* and save it */
- refresh_sequence_number(domain, False);
+ refresh_sequence_number(domain, false);
centry = centry_start(domain, status);
if (!centry)
goto skip_save;
@@ -1280,7 +1280,7 @@ do_query:
status = domain->backend->enum_dom_groups(domain, mem_ctx, num_entries, info);
/* and save it */
- refresh_sequence_number(domain, False);
+ refresh_sequence_number(domain, false);
centry = centry_start(domain, status);
if (!centry)
goto skip_save;
@@ -1364,7 +1364,7 @@ do_query:
status = domain->backend->enum_local_groups(domain, mem_ctx, num_entries, info);
/* and save it */
- refresh_sequence_number(domain, False);
+ refresh_sequence_number(domain, false);
centry = centry_start(domain, status);
if (!centry)
goto skip_save;
@@ -1437,7 +1437,7 @@ do_query:
domain_name, name, sid, type);
/* and save it */
- refresh_sequence_number(domain, False);
+ refresh_sequence_number(domain, false);
if (domain->online &&
(NT_STATUS_IS_OK(status) || NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED))) {
@@ -1510,7 +1510,7 @@ do_query:
status = domain->backend->sid_to_name(domain, mem_ctx, sid, domain_name, name, type);
/* and save it */
- refresh_sequence_number(domain, False);
+ refresh_sequence_number(domain, false);
wcache_save_sid_to_name(domain, status, sid, *domain_name, *name, *type);
/* We can't save the name to sid mapping here, as with sid history a
@@ -1554,7 +1554,7 @@ static NTSTATUS rids_to_names(struct winbindd_domain *domain,
goto error;
}
- have_mapped = have_unmapped = False;
+ have_mapped = have_unmapped = false;
for (i=0; i<num_rids; i++) {
DOM_SID sid;
@@ -1577,7 +1577,7 @@ static NTSTATUS rids_to_names(struct winbindd_domain *domain,
if (NT_STATUS_IS_OK(centry->status)) {
char *dom;
- have_mapped = True;
+ have_mapped = true;
(*types)[i] = (enum lsa_SidType)centry_uint32(centry);
dom = centry_string(centry, mem_ctx);
@@ -1590,7 +1590,7 @@ static NTSTATUS rids_to_names(struct winbindd_domain *domain,
(*names)[i] = centry_string(centry, *names);
} else if (NT_STATUS_EQUAL(centry->status, NT_STATUS_NONE_MAPPED)) {
- have_unmapped = True;
+ have_unmapped = true;
} else {
/* something's definitely wrong */
@@ -1647,7 +1647,7 @@ static NTSTATUS rids_to_names(struct winbindd_domain *domain,
return result;
}
- refresh_sequence_number(domain, False);
+ refresh_sequence_number(domain, false);
for (i=0; i<num_rids; i++) {
DOM_SID sid;
@@ -1739,7 +1739,7 @@ do_query:
status = domain->backend->query_user(domain, mem_ctx, user_sid, info);
/* and save it */
- refresh_sequence_number(domain, False);
+ refresh_sequence_number(domain, false);
wcache_save_user(domain, status, info);
return status;
@@ -1819,7 +1819,7 @@ do_query:
goto skip_save;
/* and save it */
- refresh_sequence_number(domain, False);
+ refresh_sequence_number(domain, false);
centry = centry_start(domain, status);
if (!centry)
goto skip_save;
@@ -1912,7 +1912,7 @@ static NTSTATUS lookup_useraliases(struct winbindd_domain *domain,
num_aliases, alias_rids);
/* and save it */
- refresh_sequence_number(domain, False);
+ refresh_sequence_number(domain, false);
centry = centry_start(domain, status);
if (!centry)
goto skip_save;
@@ -1993,7 +1993,7 @@ do_query:
sid_mem, names, name_types);
/* and save it */
- refresh_sequence_number(domain, False);
+ refresh_sequence_number(domain, false);
centry = centry_start(domain, status);
if (!centry)
goto skip_save;
@@ -2013,7 +2013,7 @@ skip_save:
/* find the sequence number for a domain */
static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
{
- refresh_sequence_number(domain, False);
+ refresh_sequence_number(domain, false);
*seq = domain->sequence_number;
@@ -2104,7 +2104,7 @@ do_query:
the main parent and always to make the query. --jerry */
/* and save it */
- refresh_sequence_number(domain, False);
+ refresh_sequence_number(domain, false);
centry = centry_start(domain, status);
if (!centry)
@@ -2170,7 +2170,7 @@ do_query:
status = domain->backend->lockout_policy(domain, mem_ctx, policy);
/* and save it */
- refresh_sequence_number(domain, False);
+ refresh_sequence_number(domain, false);
wcache_save_lockout_policy(domain, status, policy);
return status;
@@ -2221,7 +2221,7 @@ do_query:
status = domain->backend->password_policy(domain, mem_ctx, policy);
/* and save it */
- refresh_sequence_number(domain, False);
+ refresh_sequence_number(domain, false);
wcache_save_password_policy(domain, status, policy);
return status;
@@ -2261,7 +2261,7 @@ void wcache_invalidate_samlogon(struct winbindd_domain *domain,
netsamlogon_clear_cached_user(cache->tdb, info3);
}
-void wcache_invalidate_cache(void)
+bool wcache_invalidate_cache(void)
{
struct winbindd_domain *domain;
@@ -2270,9 +2270,15 @@ void wcache_invalidate_cache(void)
DEBUG(10, ("wcache_invalidate_cache: invalidating cache "
"entries for %s\n", domain->name));
- if (cache)
- tdb_traverse(cache->tdb, traverse_fn, NULL);
+ if (cache) {
+ if (cache->tdb) {
+ tdb_traverse(cache->tdb, traverse_fn, NULL);
+ } else {
+ return false;
+ }
+ }
}
+ return true;
}
bool init_wcache(void)
@@ -2283,7 +2289,7 @@ bool init_wcache(void)
}
if (wcache->tdb != NULL)
- return True;
+ return true;
/* when working offline we must not clear the cache on restart */
wcache->tdb = tdb_open_log(lock_path("winbindd_cache.tdb"),
@@ -2293,10 +2299,10 @@ bool init_wcache(void)
if (wcache->tdb == NULL) {
DEBUG(0,("Failed to open winbindd_cache.tdb!\n"));
- return False;
+ return false;
}
- return True;
+ return true;
}
/************************************************************************
@@ -2307,18 +2313,18 @@ bool init_wcache(void)
bool initialize_winbindd_cache(void)
{
- bool cache_bad = True;
+ bool cache_bad = true;
uint32 vers;
if (!init_wcache()) {
DEBUG(0,("initialize_winbindd_cache: init_wcache failed.\n"));
- return False;
+ return false;
}
/* Check version number. */
if (tdb_fetch_uint32(wcache->tdb, WINBINDD_CACHE_VERSION_KEYSTR, &vers) &&
vers == WINBINDD_CACHE_VERSION) {
- cache_bad = False;
+ cache_bad = false;
}
if (cache_bad) {
@@ -2333,25 +2339,36 @@ bool initialize_winbindd_cache(void)
DEBUG(0,("initialize_winbindd_cache: unlink %s failed %s ",
lock_path("winbindd_cache.tdb"),
strerror(errno) ));
- return False;
+ return false;
}
if (!init_wcache()) {
DEBUG(0,("initialize_winbindd_cache: re-initialization "
"init_wcache failed.\n"));
- return False;
+ return false;
}
/* Write the version. */
if (!tdb_store_uint32(wcache->tdb, WINBINDD_CACHE_VERSION_KEYSTR, WINBINDD_CACHE_VERSION)) {
DEBUG(0,("initialize_winbindd_cache: version number store failed %s\n",
tdb_errorstr(wcache->tdb) ));
- return False;
+ return false;
}
}
tdb_close(wcache->tdb);
wcache->tdb = NULL;
- return True;
+ return true;
+}
+
+void close_winbindd_cache(void)
+{
+ if (!wcache) {
+ return;
+ }
+ if (wcache->tdb) {
+ tdb_close(wcache->tdb);
+ wcache->tdb = NULL;
+ }
}
void cache_store_response(pid_t pid, struct winbindd_response *response)
@@ -2400,7 +2417,7 @@ bool cache_retrieve_response(pid_t pid, struct winbindd_response * response)
fstring key_str;
if (!init_wcache())
- return False;
+ return false;
DEBUG(10, ("Retrieving response for pid %d\n", pid));
@@ -2408,17 +2425,17 @@ bool cache_retrieve_response(pid_t pid, struct winbindd_response * response)
data = tdb_fetch(wcache->tdb, string_tdb_data(key_str));
if (data.dptr == NULL)
- return False;
+ return false;
if (data.dsize != sizeof(*response))
- return False;
+ return false;
memcpy(response, data.dptr, data.dsize);
SAFE_FREE(data.dptr);
if (response->length == sizeof(*response)) {
response->extra_data.data = NULL;
- return True;
+ return true;
}
/* There's extra data */
@@ -2431,19 +2448,19 @@ bool cache_retrieve_response(pid_t pid, struct winbindd_response * response)
if (data.dptr == NULL) {
DEBUG(0, ("Did not find extra data\n"));
- return False;
+ return false;
}
if (data.dsize != (response->length - sizeof(*response))) {
DEBUG(0, ("Invalid extra data length: %d\n", (int)data.dsize));
SAFE_FREE(data.dptr);
- return False;
+ return false;
}
dump_data(11, (uint8 *)data.dptr, data.dsize);
response->extra_data.data = data.dptr;
- return True;
+ return true;
}
void cache_cleanup_response(pid_t pid)
@@ -2475,19 +2492,19 @@ bool lookup_cached_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
domain = find_lookup_domain_from_sid(sid);
if (domain == NULL) {
- return False;
+ return false;
}
cache = get_cache(domain);
if (cache->tdb == NULL) {
- return False;
+ return false;
}
centry = wcache_fetch(cache, domain, "SN/%s",
sid_to_fstring(tmp, sid));
if (centry == NULL) {
- return False;
+ return false;
}
if (NT_STATUS_IS_OK(centry->status)) {
@@ -2516,13 +2533,13 @@ bool lookup_cached_name(TALLOC_CTX *mem_ctx,
domain = find_lookup_domain_from_name(domain_name);
if (domain == NULL) {
- return False;
+ return false;
}
cache = get_cache(domain);
if (cache->tdb == NULL) {
- return False;
+ return false;
}
fstrcpy(uname, name);
@@ -2532,12 +2549,12 @@ bool lookup_cached_name(TALLOC_CTX *mem_ctx,
offline so the cache won't expire the entry */
original_online_state = domain->online;
- domain->online = False;
+ domain->online = false;
centry = wcache_fetch(cache, domain, "NS/%s/%s", domain_name, uname);
domain->online = original_online_state;
if (centry == NULL) {
- return False;
+ return false;
}
if (NT_STATUS_IS_OK(centry->status)) {
@@ -2555,7 +2572,7 @@ void cache_name2sid(struct winbindd_domain *domain,
const char *domain_name, const char *name,
enum lsa_SidType type, const DOM_SID *sid)
{
- refresh_sequence_number(domain, False);
+ refresh_sequence_number(domain, false);
wcache_save_name_to_sid(domain, NT_STATUS_OK, domain_name, name,
sid, type);
}
@@ -2769,17 +2786,17 @@ bool set_global_winbindd_state_offline(void)
if (wcache == NULL || wcache->tdb == NULL) {
DEBUG(10,("set_global_winbindd_state_offline: wcache not open yet.\n"));
- return False;
+ return false;
}
if (!lp_winbind_offline_logon()) {
DEBUG(10,("set_global_winbindd_state_offline: rejecting.\n"));
- return False;
+ return false;
}
if (global_winbindd_offline_state) {
/* Already offline. */
- return True;
+ return true;
}
data = tdb_fetch_bystring( wcache->tdb, "WINBINDD_OFFLINE" );
@@ -2787,12 +2804,12 @@ bool set_global_winbindd_state_offline(void)
if (!data.dptr || data.dsize != 4) {
DEBUG(10,("set_global_winbindd_state_offline: offline state not set.\n"));
SAFE_FREE(data.dptr);
- return False;
+ return false;
} else {
DEBUG(10,("set_global_winbindd_state_offline: offline state set.\n"));
- global_winbindd_offline_state = True;
+ global_winbindd_offline_state = true;
SAFE_FREE(data.dptr);
- return True;
+ return true;
}
}
@@ -2809,7 +2826,7 @@ void set_global_winbindd_state_online(void)
/* Already online. */
return;
}
- global_winbindd_offline_state = False;
+ global_winbindd_offline_state = false;
if (!wcache->tdb) {
return;
@@ -2846,8 +2863,8 @@ static struct cache_entry *create_centry_validate(const char *kstr, TDB_DATA dat
/* huh? corrupt cache? */
DEBUG(0,("create_centry_validate: Corrupt cache for key %s (len < 8) ?\n", kstr));
centry_free(centry);
- state->bad_entry = True;
- state->success = False;
+ state->bad_entry = true;
+ state->success = false;
return NULL;
}
@@ -2862,7 +2879,7 @@ static int validate_seqnum(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbu
if (dbuf.dsize != 8) {
DEBUG(0,("validate_seqnum: Corrupt cache for key %s (len %u != 8) ?\n",
keystr, (unsigned int)dbuf.dsize ));
- state->bad_entry = True;
+ state->bad_entry = true;
return 1;
}
return 0;
@@ -3157,8 +3174,8 @@ static int validate_dr(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf,
if (dbuf.dsize == 0) {
DEBUG(0,("validate_dr: Corrupt cache for key %s (len == 0) ?\n",
keystr));
- state->bad_entry = True;
- state->success = False;
+ state->bad_entry = true;
+ state->success = false;
return 1;
}
@@ -3173,8 +3190,8 @@ static int validate_de(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA dbuf,
if (dbuf.dsize == 0) {
DEBUG(0,("validate_de: Corrupt cache for key %s (len == 0) ?\n",
keystr));
- state->bad_entry = True;
- state->success = False;
+ state->bad_entry = true;
+ state->success = false;
return 1;
}
@@ -3217,8 +3234,8 @@ static int validate_trustdomcache(TALLOC_CTX *mem_ctx, const char *keystr,
if (dbuf.dsize == 0) {
DEBUG(0, ("validate_trustdomcache: Corrupt cache for "
"key %s (len ==0) ?\n", keystr));
- state->bad_entry = True;
- state->success = False;
+ state->bad_entry = true;
+ state->success = false;
return 1;
}
@@ -3233,8 +3250,8 @@ static int validate_offline(TALLOC_CTX *mem_ctx, const char *keystr, TDB_DATA db
if (dbuf.dsize != 4) {
DEBUG(0,("validate_offline: Corrupt cache for key %s (len %u != 4) ?\n",
keystr, (unsigned int)dbuf.dsize ));
- state->bad_entry = True;
- state->success = False;
+ state->bad_entry = true;
+ state->success = false;
return 1;
}
DEBUG(10,("validate_offline: %s ok\n", keystr));
@@ -3248,8 +3265,8 @@ static int validate_cache_version(TALLOC_CTX *mem_ctx, const char *keystr, TDB_D
DEBUG(0, ("validate_cache_version: Corrupt cache for "
"key %s (len %u != 4) ?\n",
keystr, (unsigned int)dbuf.dsize));
- state->bad_entry = True;
- state->success = False;
+ state->bad_entry = true;
+ state->success = false;
return 1;
}
@@ -3338,8 +3355,8 @@ static int cache_traverse_validate_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_D
dump_data(0, (uint8 *)kbuf.dptr, kbuf.dsize);
DEBUG(0,("data :\n"));
dump_data(0, (uint8 *)dbuf.dptr, dbuf.dsize);
- v_state->unknown_key = True;
- v_state->success = False;
+ v_state->unknown_key = true;
+ v_state->success = false;
return 1; /* terminate. */
}
@@ -3433,7 +3450,7 @@ static bool add_wbdomain_to_tdc_array( struct winbindd_domain *new_dom,
struct winbindd_tdc_domain *list = NULL;
size_t idx;
int i;
- bool set_only = False;
+ bool set_only = false;
/* don't allow duplicates */
@@ -3445,7 +3462,7 @@ static bool add_wbdomain_to_tdc_array( struct winbindd_domain *new_dom,
DEBUG(10,("add_wbdomain_to_tdc_array: Found existing record for %s\n",
new_dom->name));
idx = i;
- set_only = True;
+ set_only = true;
break;
}
@@ -3466,7 +3483,7 @@ static bool add_wbdomain_to_tdc_array( struct winbindd_domain *new_dom,
}
if ( !list )
- return False;
+ return false;
list[idx].domain_name = talloc_strdup( list, new_dom->name );
list[idx].dns_name = talloc_strdup( list, new_dom->alt_name );
@@ -3488,7 +3505,7 @@ static bool add_wbdomain_to_tdc_array( struct winbindd_domain *new_dom,
*num_domains = idx + 1;
}
- return True;
+ return true;
}
/*********************************************************************
@@ -3644,7 +3661,7 @@ static bool wcache_tdc_store_list( struct winbindd_tdc_domain *domains, size_t n
int ret;
if ( !key.dptr )
- return False;
+ return false;
/* See if we were asked to delete the cache entry */
@@ -3681,23 +3698,23 @@ bool wcache_tdc_fetch_list( struct winbindd_tdc_domain **domains, size_t *num_do
*num_domains = 0;
if ( !key.dptr )
- return False;
+ return false;
data = tdb_fetch( wcache->tdb, key );
SAFE_FREE( key.dptr );
if ( !data.dptr )
- return False;
+ return false;
*num_domains = unpack_tdc_domains( data.dptr, data.dsize, domains );
SAFE_FREE( data.dptr );
if ( !*domains )
- return False;
+ return false;
- return True;
+ return true;
}
/*********************************************************************
@@ -3707,7 +3724,7 @@ bool wcache_tdc_add_domain( struct winbindd_domain *domain )
{
struct winbindd_tdc_domain *dom_list = NULL;
size_t num_domains = 0;
- bool ret = False;
+ bool ret = false;
DEBUG(10,("wcache_tdc_add_domain: Adding domain %s (%s), SID %s, "
"flags = 0x%x, attributes = 0x%x, type = 0x%x\n",
@@ -3718,7 +3735,7 @@ bool wcache_tdc_add_domain( struct winbindd_domain *domain )
domain->domain_type));
if ( !init_wcache() ) {
- return False;
+ return false;
}
/* fetch the list */
@@ -3739,7 +3756,7 @@ bool wcache_tdc_add_domain( struct winbindd_domain *domain )
/* Success */
- ret = True;
+ ret = true;
done:
TALLOC_FREE( dom_list );
@@ -3759,7 +3776,7 @@ struct winbindd_tdc_domain * wcache_tdc_fetch_domain( TALLOC_CTX *ctx, const cha
DEBUG(10,("wcache_tdc_fetch_domain: Searching for domain %s\n", name));
if ( !init_wcache() ) {
- return False;
+ return false;
}
/* fetch the list */
@@ -3892,7 +3909,7 @@ do_query:
/* the cache backend methods are exposed via this structure */
struct winbindd_methods cache_methods = {
- True,
+ true,
query_user_list,
enum_dom_groups,
enum_local_groups,
diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c
index cb366a293c..d2a7663002 100644
--- a/source3/winbindd/winbindd_cm.c
+++ b/source3/winbindd/winbindd_cm.c
@@ -74,7 +74,7 @@ extern bool override_logfile;
static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain);
static void set_dc_type_and_flags( struct winbindd_domain *domain );
-static bool get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
+static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
struct dc_name_ip **dcs, int *num_dcs);
/****************************************************************
@@ -560,7 +560,7 @@ static void cm_get_ipc_userpass(char **username, char **domain, char **password)
}
}
-static bool get_dc_name_via_netlogon(const struct winbindd_domain *domain,
+static bool get_dc_name_via_netlogon(struct winbindd_domain *domain,
fstring dcname,
struct sockaddr_storage *dc_ss)
{
@@ -570,7 +570,7 @@ static bool get_dc_name_via_netlogon(const struct winbindd_domain *domain,
WERROR werr;
TALLOC_CTX *mem_ctx;
unsigned int orig_timeout;
- fstring tmp;
+ char *tmp = NULL;
char *p;
/* Hmmmm. We can only open one connection to the NETLOGON pipe at the
@@ -600,18 +600,51 @@ static bool get_dc_name_via_netlogon(const struct winbindd_domain *domain,
35 seconds should do it. */
orig_timeout = cli_set_timeout(netlogon_pipe->cli, 35000);
-
- werr = rpccli_netlogon_getanydcname(netlogon_pipe, mem_ctx, our_domain->dcname,
- domain->name, tmp);
+
+ if (our_domain->active_directory) {
+ struct DS_DOMAIN_CONTROLLER_INFO *domain_info = NULL;
+
+ werr = rpccli_netlogon_dsr_getdcname(netlogon_pipe,
+ mem_ctx,
+ our_domain->dcname,
+ domain->name,
+ NULL,
+ NULL,
+ DS_RETURN_DNS_NAME,
+ &domain_info);
+ if (W_ERROR_IS_OK(werr)) {
+ tmp = talloc_strdup(
+ mem_ctx, domain_info->domain_controller_name);
+ if (tmp == NULL) {
+ DEBUG(0, ("talloc_strdup failed\n"));
+ talloc_destroy(mem_ctx);
+ return false;
+ }
+ if (strlen(domain->alt_name) == 0) {
+ fstrcpy(domain->alt_name,
+ domain_info->domain_name);
+ }
+ if (strlen(domain->forest_name) == 0) {
+ fstrcpy(domain->forest_name,
+ domain_info->dns_forest_name);
+ }
+ }
+ } else {
+
+ werr = rpccli_netlogon_getanydcname(netlogon_pipe,
+ mem_ctx,
+ our_domain->dcname,
+ domain->name,
+ &tmp);
+ }
/* And restore our original timeout. */
cli_set_timeout(netlogon_pipe->cli, orig_timeout);
- talloc_destroy(mem_ctx);
-
if (!W_ERROR_IS_OK(werr)) {
DEBUG(10, ("rpccli_netlogon_getanydcname failed: %s\n",
dos_errstr(werr)));
+ talloc_destroy(mem_ctx);
return False;
}
@@ -626,6 +659,8 @@ static bool get_dc_name_via_netlogon(const struct winbindd_domain *domain,
fstrcpy(dcname, p);
+ talloc_destroy(mem_ctx);
+
DEBUG(10, ("rpccli_netlogon_getanydcname returned %s\n", dcname));
if (!resolve_name(dcname, dc_ss, 0x20)) {
@@ -644,8 +679,22 @@ static NTSTATUS get_trust_creds(const struct winbindd_domain *domain,
char **machine_krb5_principal)
{
const char *account_name;
+ const char *name = NULL;
+
+ /* If we are a DC and this is not our own domain */
- if (!get_trust_pw_clear(domain->name, machine_password,
+ if (IS_DC) {
+ name = domain->name;
+ } else {
+ struct winbindd_domain *our_domain = find_our_domain();
+
+ if (!our_domain)
+ return NT_STATUS_INVALID_SERVER_STATE;
+
+ name = our_domain->name;
+ }
+
+ if (!get_trust_pw_clear(name, machine_password,
&account_name, NULL))
{
return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
@@ -659,11 +708,15 @@ static NTSTATUS get_trust_creds(const struct winbindd_domain *domain,
/* this is at least correct when domain is our domain,
* which is the only case, when this is currently used: */
- if ((machine_krb5_principal != NULL) &&
- (asprintf(machine_krb5_principal, "%s$@%s", account_name,
- domain->alt_name) == -1))
+ if (machine_krb5_principal != NULL)
{
- return NT_STATUS_NO_MEMORY;
+ if (asprintf(machine_krb5_principal, "%s$@%s",
+ account_name, domain->alt_name) == -1)
+ {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ strupper_m(*machine_krb5_principal);
}
return NT_STATUS_OK;
@@ -978,6 +1031,7 @@ static bool send_getdc_request(struct sockaddr_storage *dc_ss,
char *p;
fstring my_acct_name;
fstring my_mailslot;
+ size_t sid_size;
if (dc_ss->ss_family != AF_INET) {
return false;
@@ -1019,7 +1073,9 @@ static bool send_getdc_request(struct sockaddr_storage *dc_ss,
SIVAL(p, 0, 0x80);
p+=4;
- SIVAL(p, 0, sid_size(sid));
+ sid_size = ndr_size_dom_sid(sid, 0);
+
+ SIVAL(p, 0, sid_size);
p+=4;
p = ALIGN4(p, outbuf);
@@ -1027,12 +1083,12 @@ static bool send_getdc_request(struct sockaddr_storage *dc_ss,
return false;
}
- sid_linearize(p, sid_size(sid), sid);
- if (sid_size(sid) + 8 > sizeof(outbuf) - PTR_DIFF(p, outbuf)) {
+ if (sid_size + 8 > sizeof(outbuf) - PTR_DIFF(p, outbuf)) {
return false;
}
+ sid_linearize(p, sizeof(outbuf) - PTR_DIFF(p, outbuf), sid);
- p += sid_size(sid);
+ p += sid_size;
SIVAL(p, 0, 1);
SSVAL(p, 4, 0xffff);
@@ -1216,7 +1272,7 @@ static bool dcip_to_name(const struct winbindd_domain *domain,
the dcs[] with results.
*******************************************************************/
-static bool get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
+static bool get_dcs(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
struct dc_name_ip **dcs, int *num_dcs)
{
fstring dcname;
@@ -1319,7 +1375,7 @@ static bool get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
}
static bool find_new_dc(TALLOC_CTX *mem_ctx,
- const struct winbindd_domain *domain,
+ struct winbindd_domain *domain,
fstring dcname, struct sockaddr_storage *pss, int *fd)
{
struct dc_name_ip *dcs = NULL;
@@ -1660,12 +1716,11 @@ static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
{
struct winbindd_domain *our_domain;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
- struct ds_domain_trust *domains = NULL;
- int count = 0;
+ struct netr_DomainTrustList trusts;
int i;
- uint32 flags = (DS_DOMAIN_IN_FOREST |
- DS_DOMAIN_DIRECT_OUTBOUND |
- DS_DOMAIN_DIRECT_INBOUND);
+ uint32 flags = (NETR_TRUST_FLAG_IN_FOREST |
+ NETR_TRUST_FLAG_OUTBOUND |
+ NETR_TRUST_FLAG_INBOUND);
struct rpc_pipe_client *cli;
TALLOC_CTX *mem_ctx = NULL;
@@ -1707,27 +1762,35 @@ static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
return False;
}
- result = rpccli_ds_enum_domain_trusts(cli, mem_ctx,
- cli->cli->desthost,
- flags, &domains,
- (unsigned int *)&count);
+ result = rpccli_netr_DsrEnumerateDomainTrusts(cli, mem_ctx,
+ cli->cli->desthost,
+ flags,
+ &trusts,
+ NULL);
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(0,("set_dc_type_and_flags_trustinfo: "
+ "failed to query trusted domain list: %s\n",
+ nt_errstr(result)));
+ talloc_destroy(mem_ctx);
+ return false;
+ }
/* Now find the domain name and get the flags */
- for ( i=0; i<count; i++ ) {
- if ( strequal( domain->name, domains[i].netbios_domain ) ) {
- domain->domain_flags = domains[i].flags;
- domain->domain_type = domains[i].trust_type;
- domain->domain_trust_attribs = domains[i].trust_attributes;
-
- if ( domain->domain_type == DS_DOMAIN_TRUST_TYPE_UPLEVEL )
+ for ( i=0; i<trusts.count; i++ ) {
+ if ( strequal( domain->name, trusts.array[i].netbios_name) ) {
+ domain->domain_flags = trusts.array[i].trust_flags;
+ domain->domain_type = trusts.array[i].trust_type;
+ domain->domain_trust_attribs = trusts.array[i].trust_attributes;
+
+ if ( domain->domain_type == NETR_TRUST_TYPE_UPLEVEL )
domain->active_directory = True;
/* This flag is only set if the domain is *our*
primary domain and the primary domain is in
native mode */
- domain->native_mode = (domain->domain_flags & DS_DOMAIN_NATIVE_MODE);
+ domain->native_mode = (domain->domain_flags & NETR_TRUST_FLAG_NATIVE);
DEBUG(5, ("set_dc_type_and_flags_trustinfo: domain %s is %sin "
"native mode.\n", domain->name,
@@ -1763,17 +1826,17 @@ static bool set_dc_type_and_flags_trustinfo( struct winbindd_domain *domain )
static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
{
NTSTATUS result;
- DS_DOMINFO_CTR ctr;
+ WERROR werr;
TALLOC_CTX *mem_ctx = NULL;
struct rpc_pipe_client *cli;
POLICY_HND pol;
+ union dssetup_DsRoleInfo info;
- char *domain_name = NULL;
- char *dns_name = NULL;
- char *forest_name = NULL;
+ const char *domain_name = NULL;
+ const char *dns_name = NULL;
+ const char *forest_name = NULL;
DOM_SID *dom_sid = NULL;
- ZERO_STRUCT( ctr );
if (!connection_ok(domain)) {
return;
@@ -1788,24 +1851,25 @@ static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
DEBUG(5, ("set_dc_type_and_flags_connect: domain %s\n", domain->name ));
- cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC_DS,
+ cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_DSSETUP,
&result);
if (cli == NULL) {
DEBUG(5, ("set_dc_type_and_flags_connect: Could not bind to "
- "PI_LSARPC_DS on domain %s: (%s)\n",
+ "PI_DSSETUP on domain %s: (%s)\n",
domain->name, nt_errstr(result)));
/* if this is just a non-AD domain we need to continue
* identifying so that we can in the end return with
* domain->initialized = True - gd */
- goto no_lsarpc_ds;
+ goto no_dssetup;
}
- result = rpccli_ds_getprimarydominfo(cli, mem_ctx,
- DsRolePrimaryDomainInfoBasic,
- &ctr);
+ result = rpccli_dssetup_DsRoleGetPrimaryDomainInformation(cli, mem_ctx,
+ DS_ROLE_BASIC_INFORMATION,
+ &info,
+ &werr);
cli_rpc_pipe_close(cli);
if (!NT_STATUS_IS_OK(result)) {
@@ -1814,26 +1878,26 @@ static void set_dc_type_and_flags_connect( struct winbindd_domain *domain )
domain->name, nt_errstr(result)));
/* older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for
- * every opcode on the LSARPC_DS pipe, continue with
- * no_lsarpc_ds mode here as well to get domain->initialized
+ * every opcode on the DSSETUP pipe, continue with
+ * no_dssetup mode here as well to get domain->initialized
* set - gd */
if (NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR) {
- goto no_lsarpc_ds;
+ goto no_dssetup;
}
TALLOC_FREE(mem_ctx);
return;
}
-
- if ((ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) &&
- !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE)) {
+
+ if ((info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING) &&
+ !(info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE)) {
domain->native_mode = True;
} else {
domain->native_mode = False;
}
-no_lsarpc_ds:
+no_dssetup:
cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC, &result);
if (cli == NULL) {
@@ -1866,9 +1930,17 @@ no_lsarpc_ds:
if (dns_name)
fstrcpy(domain->alt_name, dns_name);
- if ( forest_name )
+ /* See if we can set some domain trust flags about
+ ourself */
+
+ if ( forest_name ) {
fstrcpy(domain->forest_name, forest_name);
+ if (strequal(domain->forest_name, domain->alt_name)) {
+ domain->domain_flags = NETR_TRUST_FLAG_TREEROOT;
+ }
+ }
+
if (dom_sid)
sid_copy(&domain->sid, dom_sid);
} else {
@@ -2003,13 +2075,16 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
goto schannel;
}
domain_name = domain->name;
- goto schannel;
} else {
- machine_password = conn_pwd;
- machine_account = conn->cli->user_name;
+ machine_password = SMB_STRDUP(conn_pwd);
+ machine_account = SMB_STRDUP(conn->cli->user_name);
domain_name = conn->cli->domain;
}
+ if (!machine_password || !machine_account) {
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
/* We have an authenticated connection. Use a NTLMSSP SPNEGO
authenticated SAMR pipe with sign & seal. */
@@ -2101,12 +2176,12 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
}
open_domain:
- result = rpccli_samr_open_domain(conn->samr_pipe,
- mem_ctx,
- &conn->sam_connect_handle,
- SEC_RIGHTS_MAXIMUM_ALLOWED,
- &domain->sid,
- &conn->sam_domain_handle);
+ result = rpccli_samr_OpenDomain(conn->samr_pipe,
+ mem_ctx,
+ &conn->sam_connect_handle,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ &domain->sid,
+ &conn->sam_domain_handle);
done:
@@ -2249,7 +2324,7 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
struct winbindd_cm_conn *conn;
NTSTATUS result;
- uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
+ uint32 neg_flags = NETLOGON_NEG_SELECT_AUTH2_FLAGS;
uint8 mach_pwd[16];
uint32 sec_chan_type;
const char *account_name;
diff --git a/source3/winbindd/winbindd_creds.c b/source3/winbindd/winbindd_creds.c
index 62facb6769..4dbace5bcc 100644
--- a/source3/winbindd/winbindd_creds.c
+++ b/source3/winbindd/winbindd_creds.c
@@ -69,7 +69,7 @@ NTSTATUS winbindd_store_creds(struct winbindd_domain *domain,
sid_copy(&sid, &(info3->dom_sid.sid));
sid_append_rid(&sid, info3->user_rid);
sid_copy(&cred_sid, &sid);
- info3->user_flgs |= LOGON_CACHED_ACCOUNT;
+ info3->user_flgs |= NETLOGON_CACHED_ACCOUNT;
} else if (user_sid != NULL) {
diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c
index 2739ab542e..1f2972f9b2 100644
--- a/source3/winbindd/winbindd_dual.c
+++ b/source3/winbindd/winbindd_dual.c
@@ -481,7 +481,6 @@ void winbind_child_died(pid_t pid)
child->event.fd = 0;
child->event.flags = 0;
child->pid = 0;
- SAFE_FREE(child->logfilename);
schedule_async_request(child);
}
@@ -678,6 +677,88 @@ void winbind_msg_dump_event_list(struct messaging_context *msg_ctx,
}
+void winbind_msg_dump_domain_list(struct messaging_context *msg_ctx,
+ void *private_data,
+ uint32_t msg_type,
+ struct server_id server_id,
+ DATA_BLOB *data)
+{
+ TALLOC_CTX *mem_ctx;
+ const char *message = NULL;
+ struct server_id *sender = NULL;
+ const char *domain = NULL;
+ char *s = NULL;
+ NTSTATUS status;
+ struct winbindd_domain *dom = NULL;
+
+ DEBUG(5,("winbind_msg_dump_domain_list received.\n"));
+
+ if (!data || !data->data) {
+ return;
+ }
+
+ if (data->length < sizeof(struct server_id)) {
+ return;
+ }
+
+ mem_ctx = talloc_init("winbind_msg_dump_domain_list");
+ if (!mem_ctx) {
+ return;
+ }
+
+ sender = (struct server_id *)data->data;
+ if (data->length > sizeof(struct server_id)) {
+ domain = (const char *)data->data+sizeof(struct server_id);
+ }
+
+ if (domain) {
+
+ DEBUG(5,("winbind_msg_dump_domain_list for domain: %s\n",
+ domain));
+
+ message = NDR_PRINT_STRUCT_STRING(mem_ctx, winbindd_domain,
+ find_domain_from_name_noinit(domain));
+ if (!message) {
+ talloc_destroy(mem_ctx);
+ return;
+ }
+
+ messaging_send_buf(msg_ctx, *sender,
+ MSG_WINBIND_DUMP_DOMAIN_LIST,
+ (uint8_t *)message, strlen(message) + 1);
+
+ talloc_destroy(mem_ctx);
+
+ return;
+ }
+
+ DEBUG(5,("winbind_msg_dump_domain_list all domains\n"));
+
+ for (dom = domain_list(); dom; dom=dom->next) {
+ message = NDR_PRINT_STRUCT_STRING(mem_ctx, winbindd_domain, dom);
+ if (!message) {
+ talloc_destroy(mem_ctx);
+ return;
+ }
+
+ s = talloc_asprintf_append(s, "%s\n", message);
+ if (!s) {
+ talloc_destroy(mem_ctx);
+ return;
+ }
+ }
+
+ status = messaging_send_buf(msg_ctx, *sender,
+ MSG_WINBIND_DUMP_DOMAIN_LIST,
+ (uint8_t *)s, strlen(s) + 1);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0,("failed to send message: %s\n",
+ nt_errstr(status)));
+ }
+
+ talloc_destroy(mem_ctx);
+}
+
static void account_lockout_policy_handler(struct event_context *ctx,
struct timed_event *te,
const struct timeval *now,
@@ -879,6 +960,13 @@ static bool fork_domain_child(struct winbindd_child *child)
struct winbindd_cli_state state;
struct winbindd_domain *domain;
+ if (child->domain) {
+ DEBUG(10, ("fork_domain_child called for domain '%s'\n",
+ child->domain->name));
+ } else {
+ DEBUG(10, ("fork_domain_child called without domain.\n"));
+ }
+
if (socketpair(AF_UNIX, SOCK_STREAM, 0, fdpair) != 0) {
DEBUG(0, ("Could not open child pipe: %s\n",
strerror(errno)));
@@ -948,6 +1036,8 @@ static bool fork_domain_child(struct winbindd_child *child)
MSG_WINBIND_ONLINESTATUS, NULL);
messaging_deregister(winbind_messaging_context(),
MSG_DUMP_EVENT_LIST, NULL);
+ messaging_deregister(winbind_messaging_context(),
+ MSG_WINBIND_DUMP_DOMAIN_LIST, NULL);
/* Handle online/offline messages. */
messaging_register(winbind_messaging_context(), NULL,
diff --git a/source3/winbindd/winbindd_group.c b/source3/winbindd/winbindd_group.c
index 140943cc2c..6a704cf290 100644
--- a/source3/winbindd/winbindd_group.c
+++ b/source3/winbindd/winbindd_group.c
@@ -438,18 +438,15 @@ static NTSTATUS expand_groups( TALLOC_CTX *ctx,
if ( name_types[j] == SID_NAME_DOM_GRP ||
name_types[j] == SID_NAME_ALIAS )
{
- bool ret;
-
- ret = add_sid_to_array_unique( ctx,
- &sid_mem[j],
- &new_groups,
- &new_groups_size );
- if ( !ret ) {
- status = NT_STATUS_NO_MEMORY;
+ status = add_sid_to_array_unique(ctx,
+ &sid_mem[j],
+ &new_groups,
+ &new_groups_size);
+ if (NT_STATUS_IS_OK(status)) {
goto out;
}
- continue;
+ continue;
}
}
@@ -1045,7 +1042,10 @@ static bool get_sam_group_entries(struct getent_state *ent)
status = domain->methods->enum_local_groups(domain, mem_ctx, &num_entries, &sam_grp_entries);
if ( !NT_STATUS_IS_OK(status) ) {
- DEBUG(3,("get_sam_group_entries: Failed to enumerate domain local groups!\n"));
+ DEBUG(3,("get_sam_group_entries: "
+ "Failed to enumerate "
+ "domain local groups with error %s!\n",
+ nt_errstr(status)));
num_entries = 0;
}
else
@@ -1491,9 +1491,18 @@ void winbindd_getgroups(struct winbindd_cli_state *state)
s->username = talloc_strdup( state->mem_ctx, state->request.data.username );
}
- /* Get info for the domain */
+ /* Get info for the domain (either by short domain name or
+ DNS name in the case of a UPN) */
s->domain = find_domain_from_name_noinit(s->domname);
+ if (!s->domain) {
+ char *p = strchr(s->username, '@');
+
+ if (p) {
+ s->domain = find_domain_from_name_noinit(p+1);
+ }
+
+ }
if (s->domain == NULL) {
DEBUG(7, ("could not find domain entry for domain %s\n",
diff --git a/source3/winbindd/winbindd_locator.c b/source3/winbindd/winbindd_locator.c
index ee497ebf32..6b1cff99e0 100644
--- a/source3/winbindd/winbindd_locator.c
+++ b/source3/winbindd/winbindd_locator.c
@@ -48,7 +48,7 @@ void winbindd_dsgetdcname(struct winbindd_cli_state *state)
state->request.domain_name
[sizeof(state->request.domain_name)-1] = '\0';
- DEBUG(3, ("[%5lu]: DsGetDcName for %s\n", (unsigned long)state->pid,
+ DEBUG(3, ("[%5lu]: dsgetdcname for %s\n", (unsigned long)state->pid,
state->request.domain_name));
sendto_child(state, locator_child());
@@ -64,10 +64,10 @@ static enum winbindd_result dual_dsgetdcname(struct winbindd_domain *domain,
state->request.domain_name
[sizeof(state->request.domain_name)-1] = '\0';
- DEBUG(3, ("[%5lu]: DsGetDcName for %s\n", (unsigned long)state->pid,
+ DEBUG(3, ("[%5lu]: dsgetdcname for %s\n", (unsigned long)state->pid,
state->request.domain_name));
- result = DsGetDcName(state->mem_ctx, NULL, state->request.domain_name,
+ result = dsgetdcname(state->mem_ctx, state->request.domain_name,
NULL, NULL, state->request.flags, &info);
if (!NT_STATUS_IS_OK(result)) {
diff --git a/source3/winbindd/winbindd_misc.c b/source3/winbindd/winbindd_misc.c
index 8c3ef5bb6f..76f2554122 100644
--- a/source3/winbindd/winbindd_misc.c
+++ b/source3/winbindd/winbindd_misc.c
@@ -231,7 +231,7 @@ void winbindd_getdcname(struct winbindd_cli_state *state)
enum winbindd_result winbindd_dual_getdcname(struct winbindd_domain *domain,
struct winbindd_cli_state *state)
{
- fstring dcname_slash;
+ char *dcname_slash = NULL;
char *p;
struct rpc_pipe_client *netlogon_pipe;
NTSTATUS result;
@@ -262,12 +262,12 @@ enum winbindd_result winbindd_dual_getdcname(struct winbindd_domain *domain,
werr = rpccli_netlogon_getdcname(netlogon_pipe, state->mem_ctx,
domain->dcname,
state->request.domain_name,
- dcname_slash);
+ &dcname_slash);
} else {
werr = rpccli_netlogon_getanydcname(netlogon_pipe, state->mem_ctx,
domain->dcname,
state->request.domain_name,
- dcname_slash);
+ &dcname_slash);
}
/* And restore our original timeout. */
cli_set_timeout(netlogon_pipe->cli, orig_timeout);
diff --git a/source3/winbindd/winbindd_ndr.c b/source3/winbindd/winbindd_ndr.c
new file mode 100644
index 0000000000..842c915c5f
--- /dev/null
+++ b/source3/winbindd/winbindd_ndr.c
@@ -0,0 +1,153 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * winbindd debug helper
+ * Copyright (C) Guenther Deschner 2008
+ *
+ * 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/>.
+ */
+
+#include "includes.h"
+#include "winbindd.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_WINBIND
+
+/****************************************************************
+****************************************************************/
+
+void ndr_print_winbindd_child(struct ndr_print *ndr,
+ const char *name,
+ const struct winbindd_child *r)
+{
+ ndr_print_struct(ndr, name, "winbindd_child");
+ ndr->depth++;
+ ndr_print_ptr(ndr, "next", r->next);
+ ndr_print_ptr(ndr, "prev", r->prev);
+ ndr_print_uint32(ndr, "pid", (uint32_t)r->pid);
+#if 0
+ ndr_print_winbindd_domain(ndr, "domain", r->domain);
+#else
+ ndr_print_ptr(ndr, "domain", r->domain);
+#endif
+ ndr_print_string(ndr, "logfilename", r->logfilename);
+ /* struct fd_event event; */
+ ndr_print_ptr(ndr, "lockout_policy_event", r->lockout_policy_event);
+ ndr_print_ptr(ndr, "requests", r->requests);
+ ndr_print_ptr(ndr, "table", r->table);
+ ndr->depth--;
+}
+
+/****************************************************************
+****************************************************************/
+
+void ndr_print_winbindd_cm_conn(struct ndr_print *ndr,
+ const char *name,
+ const struct winbindd_cm_conn *r)
+{
+ ndr_print_struct(ndr, name, "winbindd_cm_conn");
+ ndr->depth++;
+ ndr_print_ptr(ndr, "cli", r->cli);
+ ndr_print_ptr(ndr, "samr_pipe", r->samr_pipe);
+ ndr_print_policy_handle(ndr, "sam_connect_handle", &r->sam_connect_handle);
+ ndr_print_policy_handle(ndr, "sam_domain_handle", &r->sam_domain_handle);
+ ndr_print_ptr(ndr, "lsa_pipe", r->lsa_pipe);
+ ndr_print_policy_handle(ndr, "lsa_policy", &r->lsa_policy);
+ ndr_print_ptr(ndr, "netlogon_pipe", r->netlogon_pipe);
+ ndr->depth--;
+}
+
+/****************************************************************
+****************************************************************/
+
+void ndr_print_winbindd_methods(struct ndr_print *ndr,
+ const char *name,
+ const struct winbindd_methods *r)
+{
+#ifdef HAVE_ADS
+ extern struct winbindd_methods ads_methods;
+#endif
+ extern struct winbindd_methods msrpc_methods;
+ extern struct winbindd_methods passdb_methods;
+ extern struct winbindd_methods reconnect_methods;
+ extern struct winbindd_methods cache_methods;
+
+ ndr_print_struct(ndr, name, "winbindd_methods");
+ ndr->depth++;
+
+ if (r == NULL) {
+ ndr_print_string(ndr, name, "(NULL)");
+ ndr->depth--;
+ return;
+ }
+
+ if (r == &msrpc_methods) {
+ ndr_print_string(ndr, name, "msrpc_methods");
+#ifdef HAVE_ADS
+ } else if (r == &ads_methods) {
+ ndr_print_string(ndr, name, "ads_methods");
+#endif
+ } else if (r == &passdb_methods) {
+ ndr_print_string(ndr, name, "passdb_methods");
+ } else if (r == &reconnect_methods) {
+ ndr_print_string(ndr, name, "reconnect_methods");
+ } else if (r == &cache_methods) {
+ ndr_print_string(ndr, name, "cache_methods");
+ } else {
+ ndr_print_string(ndr, name, "UNKNOWN");
+ }
+ ndr->depth--;
+}
+
+/****************************************************************
+****************************************************************/
+
+void ndr_print_winbindd_domain(struct ndr_print *ndr,
+ const char *name,
+ const struct winbindd_domain *r)
+{
+ if (!r) {
+ return;
+ }
+
+ ndr_print_struct(ndr, name, "winbindd_domain");
+ ndr->depth++;
+ ndr_print_string(ndr, "name", r->name);
+ ndr_print_string(ndr, "alt_name", r->alt_name);
+ ndr_print_string(ndr, "forest_name", r->forest_name);
+ ndr_print_dom_sid(ndr, "sid", &r->sid);
+ ndr_print_netr_TrustFlags(ndr, "domain_flags", r->domain_flags);
+ ndr_print_netr_TrustType(ndr, "domain_type", r->domain_type);
+ ndr_print_netr_TrustAttributes(ndr, "domain_trust_attribs", r->domain_trust_attribs);
+ ndr_print_bool(ndr, "initialized", r->initialized);
+ ndr_print_bool(ndr, "native_mode", r->native_mode);
+ ndr_print_bool(ndr, "active_directory", r->active_directory);
+ ndr_print_bool(ndr, "primary", r->primary);
+ ndr_print_bool(ndr, "internal", r->internal);
+ ndr_print_bool(ndr, "online", r->online);
+ ndr_print_time_t(ndr, "startup_time", r->startup_time);
+ ndr_print_bool(ndr, "startup", r->startup);
+ ndr_print_winbindd_methods(ndr, "methods", r->methods);
+ ndr_print_winbindd_methods(ndr, "backend", r->backend);
+ ndr_print_ptr(ndr, "private_data", r->private_data);
+ ndr_print_string(ndr, "dcname", r->dcname);
+ ndr_print_sockaddr_storage(ndr, "dcaddr", &r->dcaddr);
+ ndr_print_time_t(ndr, "last_seq_check", r->last_seq_check);
+ ndr_print_uint32(ndr, "sequence_number", r->sequence_number);
+ ndr_print_NTSTATUS(ndr, "last_status", r->last_status);
+ ndr_print_winbindd_cm_conn(ndr, "conn", &r->conn);
+ ndr_print_winbindd_child(ndr, "child", &r->child);
+ ndr_print_uint32(ndr, "check_online_timeout", r->check_online_timeout);
+ ndr_print_ptr(ndr, "check_online_event", r->check_online_event);
+ ndr->depth--;
+}
diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c
index 5133239258..14b1621fc9 100644
--- a/source3/winbindd/winbindd_pam.c
+++ b/source3/winbindd/winbindd_pam.c
@@ -31,8 +31,6 @@ static NTSTATUS append_info3_as_txt(TALLOC_CTX *mem_ctx,
struct winbindd_cli_state *state,
NET_USER_INFO_3 *info3)
{
- fstring str_sid;
-
state->response.data.auth.info3.logon_time =
nt_time_to_unix(info3->logon_time);
state->response.data.auth.info3.logoff_time =
@@ -51,8 +49,7 @@ static NTSTATUS append_info3_as_txt(TALLOC_CTX *mem_ctx,
state->response.data.auth.info3.user_rid = info3->user_rid;
state->response.data.auth.info3.group_rid = info3->group_rid;
- sid_to_fstring(str_sid, &(info3->dom_sid.sid));
- fstrcpy(state->response.data.auth.info3.dom_sid, str_sid);
+ sid_to_fstring(state->response.data.auth.info3.dom_sid, &(info3->dom_sid.sid));
state->response.data.auth.info3.num_groups = info3->num_groups;
state->response.data.auth.info3.user_flgs = info3->user_flgs;
@@ -273,12 +270,13 @@ static NTSTATUS check_info3_in_group(TALLOC_CTX *mem_ctx,
return NT_STATUS_INVALID_PARAMETER;
}
- if (!add_sid_to_array(mem_ctx, &sid,
- &require_membership_of_sid,
- &num_require_membership_of_sid)) {
+ status = add_sid_to_array(mem_ctx, &sid,
+ &require_membership_of_sid,
+ &num_require_membership_of_sid);
+ if (!NT_STATUS_IS_OK(status)) {
DEBUG(0, ("add_sid_to_array failed\n"));
TALLOC_FREE(frame);
- return NT_STATUS_NO_MEMORY;
+ return status;
}
}
@@ -922,7 +920,7 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain,
/* User *DOES* know the password, update logon_time and reset
* bad_pw_count */
- my_info3->user_flgs |= LOGON_CACHED_ACCOUNT;
+ my_info3->user_flgs |= NETLOGON_CACHED_ACCOUNT;
if (my_info3->acct_flags & ACB_AUTOLOCK) {
return NT_STATUS_ACCOUNT_LOCKED_OUT;
@@ -958,7 +956,7 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain,
must_change_time = nt_time_to_unix(my_info3->pass_must_change_time);
if (must_change_time != 0 && must_change_time < time(NULL)) {
/* we allow grace logons when the password has expired */
- my_info3->user_flgs |= LOGON_GRACE_LOGON;
+ my_info3->user_flgs |= NETLOGON_GRACE_LOGON;
/* return NT_STATUS_PASSWORD_EXPIRED; */
goto success;
}
@@ -966,7 +964,7 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain,
#ifdef HAVE_KRB5
if ((state->request.flags & WBFLAG_PAM_KRB5) &&
((tdc_domain = wcache_tdc_fetch_domain(state->mem_ctx, name_domain)) != NULL) &&
- (tdc_domain->trust_type & DS_DOMAIN_TRUST_TYPE_UPLEVEL)) {
+ (tdc_domain->trust_type & NETR_TRUST_TYPE_UPLEVEL)) {
uid_t uid = -1;
const char *cc = NULL;
@@ -1074,7 +1072,7 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain,
}
if ((my_info3->user_rid != DOMAIN_USER_RID_ADMIN) ||
- (password_properties & DOMAIN_LOCKOUT_ADMINS)) {
+ (password_properties & DOMAIN_PASSWORD_LOCKOUT_ADMINS)) {
my_info3->acct_flags |= ACB_AUTOLOCK;
}
}
@@ -1341,10 +1339,11 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain,
goto done;
}
- status_tmp = rpccli_samr_open_user(samr_pipe, state->mem_ctx,
- &samr_domain_handle,
- MAXIMUM_ALLOWED_ACCESS,
- my_info3->user_rid, &user_pol);
+ status_tmp = rpccli_samr_OpenUser(samr_pipe, state->mem_ctx,
+ &samr_domain_handle,
+ MAXIMUM_ALLOWED_ACCESS,
+ my_info3->user_rid,
+ &user_pol);
if (!NT_STATUS_IS_OK(status_tmp)) {
DEBUG(3, ("could not open user handle on SAMR pipe: %s\n",
@@ -1358,14 +1357,14 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain,
if (!NT_STATUS_IS_OK(status_tmp)) {
DEBUG(3, ("could not query user info on SAMR pipe: %s\n",
nt_errstr(status_tmp)));
- rpccli_samr_close(samr_pipe, state->mem_ctx, &user_pol);
+ rpccli_samr_Close(samr_pipe, state->mem_ctx, &user_pol);
goto done;
}
acct_flags = user_ctr->info.id16->acb_info;
if (acct_flags == 0) {
- rpccli_samr_close(samr_pipe, state->mem_ctx, &user_pol);
+ rpccli_samr_Close(samr_pipe, state->mem_ctx, &user_pol);
goto done;
}
@@ -1373,7 +1372,7 @@ NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain,
DEBUG(10,("successfully retrieved acct_flags 0x%x\n", acct_flags));
- rpccli_samr_close(samr_pipe, state->mem_ctx, &user_pol);
+ rpccli_samr_Close(samr_pipe, state->mem_ctx, &user_pol);
}
*info3 = my_info3;
@@ -1593,13 +1592,16 @@ process_result:
}
}
- result = fillup_password_policy(domain, state);
- if (!NT_STATUS_IS_OK(result)
- && !NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED) )
- {
- DEBUG(10,("Failed to get password policies: %s\n", nt_errstr(result)));
- goto done;
+ if (state->request.flags & WBFLAG_PAM_GET_PWD_POLICY) {
+ result = fillup_password_policy(domain, state);
+
+ if (!NT_STATUS_IS_OK(result)
+ && !NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED) )
+ {
+ DEBUG(10,("Failed to get password policies: %s\n", nt_errstr(result)));
+ goto done;
+ }
}
result = NT_STATUS_OK;
diff --git a/source3/winbindd/winbindd_rpc.c b/source3/winbindd/winbindd_rpc.c
index ffb47692cb..0d937ef30e 100644
--- a/source3/winbindd/winbindd_rpc.c
+++ b/source3/winbindd/winbindd_rpc.c
@@ -308,7 +308,7 @@ NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain,
{
char **domains;
char **names;
- enum lsa_SidType *types;
+ enum lsa_SidType *types = NULL;
NTSTATUS result;
struct rpc_pipe_client *cli;
POLICY_HND lsa_policy;
@@ -456,6 +456,12 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
return NT_STATUS_OK;
}
+ if ( !winbindd_can_contact_domain( domain ) ) {
+ DEBUG(10,("query_user: No incoming trust for domain %s\n",
+ domain->name));
+ return NT_STATUS_OK;
+ }
+
/* no cache; hit the wire */
result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
@@ -463,9 +469,11 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
return result;
/* Get user handle */
- result = rpccli_samr_open_user(cli, mem_ctx, &dom_pol,
- SEC_RIGHTS_MAXIMUM_ALLOWED, user_rid,
- &user_pol);
+ result = rpccli_samr_OpenUser(cli, mem_ctx,
+ &dom_pol,
+ SEC_RIGHTS_MAXIMUM_ALLOWED,
+ user_rid,
+ &user_pol);
if (!NT_STATUS_IS_OK(result))
return result;
@@ -474,7 +482,7 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
result = rpccli_samr_query_userinfo(cli, mem_ctx, &user_pol,
0x15, &ctr);
- rpccli_samr_close(cli, mem_ctx, &user_pol);
+ rpccli_samr_Close(cli, mem_ctx, &user_pol);
if (!NT_STATUS_IS_OK(result))
return result;
@@ -539,8 +547,11 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
return result;
/* Get user handle */
- result = rpccli_samr_open_user(cli, mem_ctx, &dom_pol,
- des_access, user_rid, &user_pol);
+ result = rpccli_samr_OpenUser(cli, mem_ctx,
+ &dom_pol,
+ des_access,
+ user_rid,
+ &user_pol);
if (!NT_STATUS_IS_OK(result))
return result;
@@ -549,7 +560,7 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
result = rpccli_samr_query_usergroups(cli, mem_ctx, &user_pol,
num_groups, &user_groups);
- rpccli_samr_close(cli, mem_ctx, &user_pol);
+ rpccli_samr_Close(cli, mem_ctx, &user_pol);
if (!NT_STATUS_IS_OK(result) || (*num_groups) == 0)
return result;
@@ -694,8 +705,11 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
if (!NT_STATUS_IS_OK(result))
return result;
- result = rpccli_samr_open_group(cli, mem_ctx, &dom_pol,
- des_access, group_rid, &group_pol);
+ result = rpccli_samr_OpenGroup(cli, mem_ctx,
+ &dom_pol,
+ des_access,
+ group_rid,
+ &group_pol);
if (!NT_STATUS_IS_OK(result))
return result;
@@ -715,7 +729,7 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
/* And restore our original timeout. */
cli_set_timeout(cli->cli, orig_timeout);
- rpccli_samr_close(cli, mem_ctx, &group_pol);
+ rpccli_samr_Close(cli, mem_ctx, &group_pol);
if (!NT_STATUS_IS_OK(result))
return result;
diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c
index 795209619c..7933ecf63e 100644
--- a/source3/winbindd/winbindd_util.c
+++ b/source3/winbindd/winbindd_util.c
@@ -41,7 +41,7 @@ extern struct winbindd_methods passdb_methods;
individual winbindd_domain structures cannot be made. Keep a copy of
the domain name instead. */
-static struct winbindd_domain *_domain_list;
+static struct winbindd_domain *_domain_list = NULL;
/**
When was the last scan of trusted domains done?
@@ -212,7 +212,7 @@ static void add_trusted_domains( struct winbindd_domain *domain )
TALLOC_CTX *mem_ctx;
struct winbindd_request *request;
struct winbindd_response *response;
- uint32 fr_flags = (DS_DOMAIN_TREE_ROOT|DS_DOMAIN_IN_FOREST);
+ uint32 fr_flags = (NETR_TRUST_FLAG_TREEROOT|NETR_TRUST_FLAG_IN_FOREST);
struct trustdom_state *state;
@@ -385,8 +385,8 @@ static void rescan_forest_root_trusts( void )
the domain_list() as our primary domain may not
have been initialized. */
- if ( !(dom_list[i].trust_flags & DS_DOMAIN_TREE_ROOT) ) {
- continue;
+ if ( !(dom_list[i].trust_flags & NETR_TRUST_FLAG_TREEROOT) ) {
+ continue;
}
/* Here's the forest root */
@@ -450,10 +450,10 @@ static void rescan_forest_trusts( void )
if ( d && (d->internal || d->primary ) )
continue;
-
- if ( (flags & DS_DOMAIN_DIRECT_INBOUND) &&
- (type == DS_DOMAIN_TRUST_TYPE_UPLEVEL) &&
- (attribs == DS_DOMAIN_TRUST_ATTRIB_FOREST_TRANSITIVE) )
+
+ if ( (flags & NETR_TRUST_FLAG_INBOUND) &&
+ (type == NETR_TRUST_TYPE_UPLEVEL) &&
+ (attribs == NETR_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) )
{
/* add the trusted domain if we don't know
about it */
@@ -494,9 +494,13 @@ void rescan_trusted_domains( void )
((now-last_trustdom_scan) < WINBINDD_RESCAN_FREQ) )
return;
- /* clear the TRUSTDOM cache first */
-
- wcache_tdc_clear();
+ /* I use to clear the cache here and start over but that
+ caused problems in child processes that needed the
+ trust dom list early on. Removing it means we
+ could have some trusted domains listed that have been
+ removed from our primary domain's DC until a full
+ restart. This should be ok since I think this is what
+ Windows does as well. */
/* this will only add new domains we didn't already know about
in the domain_list()*/
@@ -561,7 +565,7 @@ enum winbindd_result init_child_connection(struct winbindd_domain *domain,
/* The primary domain has to find the DC name itself */
request->cmd = WINBINDD_INIT_CONNECTION;
fstrcpy(request->domain_name, domain->name);
- request->data.init_conn.is_primary = domain->internal ? False : True;
+ request->data.init_conn.is_primary = domain->primary ? true : false;
fstrcpy(request->data.init_conn.dcname, "");
async_request(mem_ctx, &domain->child, request, response,
init_child_recv, state);
@@ -760,8 +764,8 @@ void check_domain_trusted( const char *name, const DOM_SID *user_sid )
forest trust */
domain->active_directory = True;
- domain->domain_flags = DS_DOMAIN_DIRECT_OUTBOUND;
- domain->domain_type = DS_DOMAIN_TRUST_TYPE_UPLEVEL;
+ domain->domain_flags = NETR_TRUST_FLAG_OUTBOUND;
+ domain->domain_type = NETR_TRUST_TYPE_UPLEVEL;
domain->internal = False;
domain->online = True;
@@ -1294,19 +1298,22 @@ NTSTATUS lookup_usergroups_cached(struct winbindd_domain *domain,
/* always add the primary group to the sid array */
sid_compose(&primary_group, &info3->dom_sid.sid, info3->user_rid);
- if (!add_sid_to_array(mem_ctx, &primary_group, user_sids, &num_groups)) {
+ status = add_sid_to_array(mem_ctx, &primary_group, user_sids,
+ &num_groups);
+ if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(info3);
- return NT_STATUS_NO_MEMORY;
+ return status;
}
for (i=0; i<info3->num_groups; i++) {
sid_copy(&group_sid, &info3->dom_sid.sid);
sid_append_rid(&group_sid, info3->gids[i].g_rid);
- if (!add_sid_to_array(mem_ctx, &group_sid, user_sids,
- &num_groups)) {
+ status = add_sid_to_array(mem_ctx, &group_sid, user_sids,
+ &num_groups);
+ if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(info3);
- return NT_STATUS_NO_MEMORY;
+ return status;
}
}
@@ -1318,11 +1325,11 @@ NTSTATUS lookup_usergroups_cached(struct winbindd_domain *domain,
if (info3->other_sids_attrib[i] & SE_GROUP_RESOURCE)
continue;
- if (!add_sid_to_array(mem_ctx, &info3->other_sids[i].sid,
- user_sids, &num_groups))
- {
+ status = add_sid_to_array(mem_ctx, &info3->other_sids[i].sid,
+ user_sids, &num_groups);
+ if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(info3);
- return NT_STATUS_NO_MEMORY;
+ return status;
}
}
@@ -1373,31 +1380,56 @@ void ws_name_return( char *name, char replace )
/*********************************************************************
********************************************************************/
-bool winbindd_can_contact_domain( struct winbindd_domain *domain )
+bool winbindd_can_contact_domain(struct winbindd_domain *domain)
{
+ struct winbindd_tdc_domain *tdc = NULL;
+ TALLOC_CTX *frame = talloc_stackframe();
+ bool ret = false;
+
/* We can contact the domain if it is our primary domain */
- if ( domain->primary )
- return True;
+ if (domain->primary) {
+ return true;
+ }
- /* Can always contact a domain that is in out forest */
+ /* Trust the TDC cache and not the winbindd_domain flags */
- if ( domain->domain_flags & DS_DOMAIN_IN_FOREST )
- return True;
+ if ((tdc = wcache_tdc_fetch_domain(frame, domain->name)) == NULL) {
+ DEBUG(10,("winbindd_can_contact_domain: %s not found in cache\n",
+ domain->name));
+ return false;
+ }
- /* We cannot contact the domain if it is running AD and
- we have no inbound trust */
+ /* Can always contact a domain that is in out forest */
- if ( domain->active_directory &&
- ((domain->domain_flags&DS_DOMAIN_DIRECT_INBOUND) != DS_DOMAIN_DIRECT_INBOUND) )
- {
- return False;
+ if (tdc->trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
+ ret = true;
+ goto done;
}
+ /*
+ * On a _member_ server, we cannot contact the domain if it
+ * is running AD and we have no inbound trust.
+ */
+
+ if (!IS_DC &&
+ domain->active_directory &&
+ ((tdc->trust_flags & NETR_TRUST_FLAG_INBOUND) != NETR_TRUST_FLAG_INBOUND))
+ {
+ DEBUG(10, ("winbindd_can_contact_domain: %s is an AD domain "
+ "and we have no inbound trust.\n", domain->name));
+ goto done;
+ }
+
/* Assume everything else is ok (probably not true but what
can you do?) */
+
+ ret = true;
+
+done:
+ talloc_destroy(frame);
- return True;
+ return ret;
}
/*********************************************************************