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
+ 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,
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.
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "includes.h"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_WINBIND
+extern struct winbindd_methods cache_methods;
+extern struct winbindd_methods passdb_methods;
+
/**
* @file winbindd_util.c
*
* Winbind daemon for NT domain authentication nss module.
**/
-
-/**
- * Used to clobber name fields that have an undefined value.
- *
- * Correct code should never look at a field that has this value.
- **/
-
-static const fstring name_deadbeef = "<deadbeef>";
-
/* The list of trusted domains. Note that the list can be deleted and
recreated using the init_domain_list() function so pointers to
individual winbindd_domain structures cannot be made. Keep a copy of
/* Initialise list */
if ((!_domain_list) && (!init_domain_list())) {
- smb_panic("Init_domain_list failed\n");
+ smb_panic("Init_domain_list failed");
}
return _domain_list;
if (sid == NULL)
return False;
+ if ( IS_DC )
+ return sid_check_is_builtin(sid);
+
return (sid_check_is_domain(sid) || sid_check_is_builtin(sid));
}
if (sid == NULL)
return False;
+ if ( IS_DC )
+ return sid_check_is_in_builtin(sid);
+
return (sid_check_is_in_our_domain(sid) || sid_check_is_in_builtin(sid));
}
init_domain_list() and we'll get stuck in a loop. */
for (domain = _domain_list; domain; domain = domain->next) {
if (strequal(domain_name, domain->name) ||
- strequal(domain_name, domain->alt_name)) {
- return domain;
+ strequal(domain_name, domain->alt_name))
+ {
+ break;
}
- if (alternative_name && *alternative_name) {
+
+ if (alternative_name && *alternative_name)
+ {
if (strequal(alternative_name, domain->name) ||
- strequal(alternative_name, domain->alt_name)) {
- return domain;
+ strequal(alternative_name, domain->alt_name))
+ {
+ break;
}
}
- if (sid) {
+
+ if (sid)
+ {
if (is_null_sid(sid)) {
+ continue;
+ }
- } else if (sid_equal(sid, &domain->sid)) {
- return domain;
+ if (sid_equal(sid, &domain->sid)) {
+ break;
}
}
}
+ /* See if we found a match. Check if we need to update the
+ SID. */
+
+ if ( domain ) {
+ if ( sid_equal( &domain->sid, &global_sid_NULL ) )
+ sid_copy( &domain->sid, sid );
+
+ return domain;
+ }
+
/* Create new domain entry */
if ((domain = SMB_MALLOC_P(struct winbindd_domain)) == NULL)
domain->last_seq_check = 0;
domain->initialized = False;
domain->online = is_internal_domain(sid);
+ domain->check_online_timeout = 0;
if (sid) {
sid_copy(&domain->sid, sid);
}
/* Link to domain list */
DLIST_ADD(_domain_list, domain);
+ wcache_tdc_add_domain( domain );
+
DEBUG(2,("Added domain %s %s %s\n",
domain->name, domain->alt_name,
&domain->sid?sid_string_static(&domain->sid):""));
struct trustdom_state {
TALLOC_CTX *mem_ctx;
+ BOOL primary;
+ BOOL forest_root;
struct winbindd_response *response;
};
static void trustdom_recv(void *private_data, BOOL success);
+static void rescan_forest_root_trusts( void );
+static void rescan_forest_trusts( void );
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);
struct trustdom_state *state;
state->mem_ctx = mem_ctx;
state->response = response;
+ /* Flags used to know how to continue the forest trust search */
+
+ state->primary = domain->primary;
+ state->forest_root = ((domain->domain_flags & fr_flags) == fr_flags );
+
request->length = sizeof(*request);
request->cmd = WINBINDD_LIST_TRUSTDOM;
static void trustdom_recv(void *private_data, BOOL success)
{
- extern struct winbindd_methods cache_methods;
struct trustdom_state *state =
talloc_get_type_abort(private_data, struct trustdom_state);
struct winbindd_response *response = state->response;
while ((p != NULL) && (*p != '\0')) {
char *q, *sidstr, *alt_name;
DOM_SID sid;
+ struct winbindd_domain *domain;
+ char *alternate_name = NULL;
alt_name = strchr(p, '\\');
if (alt_name == NULL) {
*q = '\0';
if (!string_to_sid(&sid, sidstr)) {
- DEBUG(0, ("Got invalid trustdom response\n"));
- break;
+ /* Allow NULL sid for sibling domains */
+ if ( strcmp(sidstr,"S-0-0") == 0) {
+ sid_copy( &sid, &global_sid_NULL);
+ } else {
+ DEBUG(0, ("Got invalid trustdom response\n"));
+ break;
+ }
}
- if (find_domain_from_name_noinit(p) == NULL) {
- struct winbindd_domain *domain;
- char *alternate_name = NULL;
-
/* use the real alt_name if we have one, else pass in NULL */
if ( !strequal( alt_name, "(null)" ) )
alternate_name = alt_name;
+ /* If we have an existing domain structure, calling
+ add_trusted_domain() will update the SID if
+ necessary. This is important because we need the
+ SID for sibling domains */
+
+ if ( find_domain_from_name_noinit(p) != NULL ) {
+ domain = add_trusted_domain(p, alternate_name,
+ &cache_methods,
+ &sid);
+ } else {
domain = add_trusted_domain(p, alternate_name,
&cache_methods,
&sid);
}
SAFE_FREE(response->extra_data.data);
+
+ /*
+ Cases to consider when scanning trusts:
+ (a) we are calling from a child domain (primary && !forest_root)
+ (b) we are calling from the root of the forest (primary && forest_root)
+ (c) we are calling from a trusted forest domain (!primary
+ && !forest_root)
+ */
+
+ if ( state->primary ) {
+ /* If this is our primary domain and we are not the in the
+ forest root, we have to scan the root trusts first */
+
+ if ( !state->forest_root )
+ rescan_forest_root_trusts();
+ else
+ rescan_forest_trusts();
+
+ } else if ( state->forest_root ) {
+ /* Once we have done root forest trust search, we can
+ go on to search thing trusted forests */
+
+ rescan_forest_trusts();
+ }
+
talloc_destroy(state->mem_ctx);
+
+ return;
}
/********************************************************************
- Periodically we need to refresh the trusted domain cache for smbd
+ Scan the trusts of our forest root
********************************************************************/
+static void rescan_forest_root_trusts( void )
+{
+ struct winbindd_tdc_domain *dom_list = NULL;
+ size_t num_trusts = 0;
+ int i;
+
+ /* The only transitive trusts supported by Windows 2003 AD are
+ (a) Parent-Child, (b) Tree-Root, and (c) Forest. The
+ first two are handled in forest and listed by
+ DsEnumerateDomainTrusts(). Forest trusts are not so we
+ have to do that ourselves. */
+
+ if ( !wcache_tdc_fetch_list( &dom_list, &num_trusts ) )
+ return;
+
+ for ( i=0; i<num_trusts; i++ ) {
+ struct winbindd_domain *d = NULL;
+
+ /* Find the forest root. Don't necessarily trust
+ the domain_list() as our primary domain may not
+ have been initialized. */
+
+ if ( !(dom_list[i].trust_flags & DS_DOMAIN_TREE_ROOT) ) {
+ continue;
+ }
+
+ /* Here's the forest root */
+
+ d = find_domain_from_name_noinit( dom_list[i].domain_name );
+
+ if ( !d ) {
+ d = add_trusted_domain( dom_list[i].domain_name,
+ dom_list[i].dns_name,
+ &cache_methods,
+ &dom_list[i].sid );
+ }
+
+ DEBUG(10,("rescan_forest_root_trusts: Following trust path "
+ "for domain tree root %s (%s)\n",
+ d->name, d->alt_name ));
+
+ d->domain_flags = dom_list[i].trust_flags;
+ d->domain_type = dom_list[i].trust_type;
+ d->domain_trust_attribs = dom_list[i].trust_attribs;
+
+ add_trusted_domains( d );
+
+ break;
+ }
+
+ TALLOC_FREE( dom_list );
+
+ return;
+}
+
+/********************************************************************
+ scan the transitive forest trists (not our own)
+********************************************************************/
+
+
+static void rescan_forest_trusts( void )
+{
+ struct winbindd_domain *d = NULL;
+ struct winbindd_tdc_domain *dom_list = NULL;
+ size_t num_trusts = 0;
+ int i;
+
+ /* The only transitive trusts supported by Windows 2003 AD are
+ (a) Parent-Child, (b) Tree-Root, and (c) Forest. The
+ first two are handled in forest and listed by
+ DsEnumerateDomainTrusts(). Forest trusts are not so we
+ have to do that ourselves. */
+
+ if ( !wcache_tdc_fetch_list( &dom_list, &num_trusts ) )
+ return;
+
+ for ( i=0; i<num_trusts; i++ ) {
+ uint32 flags = dom_list[i].trust_flags;
+ uint32 type = dom_list[i].trust_type;
+ uint32 attribs = dom_list[i].trust_attribs;
+
+ d = find_domain_from_name_noinit( dom_list[i].domain_name );
+
+ /* ignore our primary and internal domains */
+
+ 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) )
+ {
+ /* add the trusted domain if we don't know
+ about it */
+
+ if ( !d ) {
+ d = add_trusted_domain( dom_list[i].domain_name,
+ dom_list[i].dns_name,
+ &cache_methods,
+ &dom_list[i].sid );
+ }
+
+ DEBUG(10,("Following trust path for domain %s (%s)\n",
+ d->name, d->alt_name ));
+ add_trusted_domains( d );
+ }
+ }
+
+ TALLOC_FREE( dom_list );
+
+ return;
+}
+
+/*********************************************************************
+ The process of updating the trusted domain list is a three step
+ async process:
+ (a) ask our domain
+ (b) ask the root domain in our forest
+ (c) ask the a DC in any Win2003 trusted forests
+*********************************************************************/
+
void rescan_trusted_domains( void )
{
time_t now = time(NULL);
((now-last_trustdom_scan) < WINBINDD_RESCAN_FREQ) )
return;
- /* this will only add new domains we didn't already know about */
+ /* clear the TRUSTDOM cache first */
+
+ wcache_tdc_clear();
+
+ /* this will only add new domains we didn't already know about
+ in the domain_list()*/
add_trusted_domains( find_our_domain() );
state->continuation = continuation;
state->private_data = private_data;
- if (IS_DC || domain->primary) {
+ if (IS_DC || domain->primary || domain->internal ) {
/* 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 = True;
+ request->data.init_conn.is_primary = domain->internal ? False : True;
fstrcpy(request->data.init_conn.dcname, "");
async_request(mem_ctx, &domain->child, request, response,
init_child_recv, state);
request->cmd = WINBINDD_GETDCNAME;
fstrcpy(request->domain_name, domain->name);
- /* save online flag */
request_domain = find_our_domain();
- request_domain->online = domain->online;
-
async_domain_request(mem_ctx, request_domain, request, response,
init_child_getdc_recv, state);
return WINBINDD_PENDING;
state->domain->sequence_number =
state->response->data.domain_info.sequence_number;
- state->domain->initialized = 1;
+ init_dc_connection(state->domain);
if (state->continuation != NULL)
state->continuation(state->private_data, True);
init_dc_connection(domain);
-#if 1
if (!domain->initialized) {
/* If we return error here we can't do any cached authentication,
but we may be in disconnected mode and can't initialize correctly.
DEBUG(5, ("winbindd_dual_init_connection: %s returning without initialization "
"online = %d\n", domain->name, (int)domain->online ));
}
-#else
- if (!domain->initialized) {
- DEBUG(1, ("Could not initialize domain %s\n",
- state->request.domain_name));
- return WINBINDD_ERROR;
- }
-#endif
fstrcpy(state->response.data.domain_info.name, domain->name);
fstrcpy(state->response.data.domain_info.alt_name, domain->alt_name);
/* Look up global info for the winbind daemon */
BOOL init_domain_list(void)
{
- extern struct winbindd_methods cache_methods;
- extern struct winbindd_methods passdb_methods;
struct winbindd_domain *domain;
int role = lp_server_role();
&cache_methods, &our_sid);
domain->primary = True;
setup_domain_child(domain, &domain->child, NULL);
+
+ /* Even in the parent winbindd we'll need to
+ talk to the DC, so try and see if we can
+ contact it. Theoretically this isn't neccessary
+ as the init_dc_connection() in init_child_recv()
+ will do this, but we can start detecting the DC
+ early here. */
+ set_domain_online_request(domain);
}
/* Local SAM */
return True;
}
+void check_domain_trusted( const char *name, const DOM_SID *user_sid )
+{
+ struct winbindd_domain *domain;
+ DOM_SID dom_sid;
+ uint32 rid;
+
+ domain = find_domain_from_name_noinit( name );
+ if ( domain )
+ return;
+
+ sid_copy( &dom_sid, user_sid );
+ if ( !sid_split_rid( &dom_sid, &rid ) )
+ return;
+
+ /* add the newly discovered trusted domain */
+
+ domain = add_trusted_domain( name, NULL, &cache_methods,
+ &dom_sid);
+
+ if ( !domain )
+ return;
+
+ /* assume this is a trust from a one-way transitive
+ forest trust */
+
+ domain->active_directory = True;
+ domain->domain_flags = DS_DOMAIN_DIRECT_OUTBOUND;
+ domain->domain_type = DS_DOMAIN_TRUST_TYPE_UPLEVEL;
+ domain->internal = False;
+ domain->online = True;
+
+ setup_domain_child(domain, &domain->child, NULL);
+
+ wcache_tdc_add_domain( domain );
+
+ return;
+}
+
/**
* Given a domain name, return the struct winbindd domain info for it
*
return domain;
}
- smb_panic("Could not find our domain\n");
+ smb_panic("Could not find our domain");
return NULL;
}
+struct winbindd_domain *find_root_domain(void)
+{
+ struct winbindd_domain *ours = find_our_domain();
+
+ if ( !ours )
+ return NULL;
+
+ if ( strlen(ours->forest_name) == 0 )
+ return NULL;
+
+ return find_domain_from_name( ours->forest_name );
+}
+
struct winbindd_domain *find_builtin_domain(void)
{
DOM_SID sid;
string_to_sid(&sid, "S-1-5-32");
domain = find_domain_from_sid(&sid);
- if (domain == NULL)
- smb_panic("Could not find BUILTIN domain\n");
+ if (domain == NULL) {
+ smb_panic("Could not find BUILTIN domain");
+ }
return domain;
}
struct winbindd_domain *find_lookup_domain_from_sid(const DOM_SID *sid)
{
+ /* SIDs in the S-1-22-{1,2} domain should be handled by our passdb */
+
+ if ( sid_check_is_in_unix_groups(sid) ||
+ sid_check_is_unix_groups(sid) ||
+ sid_check_is_in_unix_users(sid) ||
+ sid_check_is_unix_users(sid) )
+ {
+ return find_domain_from_sid(get_global_sam_sid());
+ }
+
/* A DC can't ask the local smbd for remote SIDs, here winbindd is the
* one to contact the external DC's. On member servers the internal
* domains are different: These are part of the local SAM. */
if (IS_DC || is_internal_domain(sid) || is_in_internal_domain(sid)) {
DEBUG(10, ("calling find_domain_from_sid\n"));
return find_domain_from_sid(sid);
- }
+ }
/* On a member server a query for SID or name can always go to our
* primary DC. */
struct winbindd_domain *find_lookup_domain_from_name(const char *domain_name)
{
+ if ( strequal(domain_name, unix_users_domain_name() ) ||
+ strequal(domain_name, unix_groups_domain_name() ) )
+ {
+ return find_domain_from_name_noinit( get_global_sam_name() );
+ }
+
if (IS_DC || strequal(domain_name, "BUILTIN") ||
strequal(domain_name, get_global_sam_name()))
return find_domain_from_name_noinit(domain_name);
+ /* The "Unix User" and "Unix Group" domain our handled by passdb */
+
return find_our_domain();
}
/* Lookup a sid in a domain from a name */
BOOL winbindd_lookup_sid_by_name(TALLOC_CTX *mem_ctx,
+ enum winbindd_cmd orig_cmd,
struct winbindd_domain *domain,
const char *domain_name,
const char *name, DOM_SID *sid,
NTSTATUS result;
/* Lookup name */
- result = domain->methods->name_to_sid(domain, mem_ctx, domain_name, name, sid, type);
+ result = domain->methods->name_to_sid(domain, mem_ctx, orig_cmd,
+ domain_name, name, sid, type);
- /* Return rid and type if lookup successful */
+ /* Return sid and type if lookup successful */
if (!NT_STATUS_IS_OK(result)) {
*type = SID_NAME_UNKNOWN;
}
* are set, otherwise False.
**/
BOOL winbindd_lookup_name_by_sid(TALLOC_CTX *mem_ctx,
+ struct winbindd_domain *domain,
DOM_SID *sid,
- fstring dom_name,
- fstring name,
+ char **dom_name,
+ char **name,
enum lsa_SidType *type)
{
- char *names;
- char *dom_names;
NTSTATUS result;
- BOOL rv = False;
- struct winbindd_domain *domain;
- domain = find_lookup_domain_from_sid(sid);
-
- if (!domain) {
- DEBUG(1,("Can't find domain from sid\n"));
- return False;
- }
+ *dom_name = NULL;
+ *name = NULL;
/* Lookup name */
- result = domain->methods->sid_to_name(domain, mem_ctx, sid, &dom_names, &names, type);
+ result = domain->methods->sid_to_name(domain, mem_ctx, sid, dom_name, name, type);
/* Return name and type if successful */
- if ((rv = NT_STATUS_IS_OK(result))) {
- fstrcpy(dom_name, dom_names);
- fstrcpy(name, names);
- } else {
- *type = SID_NAME_UNKNOWN;
- fstrcpy(name, name_deadbeef);
+ if (NT_STATUS_IS_OK(result)) {
+ return True;
}
+
+ *type = SID_NAME_UNKNOWN;
- return rv;
+ return False;
}
/* Free state information held for {set,get,end}{pw,gr}ent() functions */
}
}
-/* Parse winbindd related parameters */
-
-BOOL winbindd_param_init(void)
-{
- /* Parse winbind uid and winbind_gid parameters */
-
- if (!lp_idmap_uid(&server_state.uid_low, &server_state.uid_high)) {
- DEBUG(0, ("winbindd: idmap uid range missing or invalid\n"));
- DEBUG(0, ("winbindd: cannot continue, exiting.\n"));
- return False;
- }
-
- if (!lp_idmap_gid(&server_state.gid_low, &server_state.gid_high)) {
- DEBUG(0, ("winbindd: idmap gid range missing or invalid\n"));
- DEBUG(0, ("winbindd: cannot continue, exiting.\n"));
- return False;
- }
-
- return True;
-}
-
-BOOL is_in_uid_range(uid_t uid)
-{
- return ((uid >= server_state.uid_low) &&
- (uid <= server_state.uid_high));
-}
-
-BOOL is_in_gid_range(gid_t gid)
-{
- return ((gid >= server_state.gid_low) &&
- (gid <= server_state.gid_high));
-}
-
/* Is this a domain which we may assume no DOMAIN\ prefix? */
static BOOL assume_domain(const char *domain)
return lock_path(WINBINDD_PRIV_SOCKET_SUBDIR);
}
-/* Open the winbindd socket */
-
-static int _winbindd_socket = -1;
-static int _winbindd_priv_socket = -1;
-
-int open_winbindd_socket(void)
-{
- if (_winbindd_socket == -1) {
- _winbindd_socket = create_pipe_sock(
- WINBINDD_SOCKET_DIR, WINBINDD_SOCKET_NAME, 0755);
- DEBUG(10, ("open_winbindd_socket: opened socket fd %d\n",
- _winbindd_socket));
- }
-
- return _winbindd_socket;
-}
-
-int open_winbindd_priv_socket(void)
-{
- if (_winbindd_priv_socket == -1) {
- _winbindd_priv_socket = create_pipe_sock(
- get_winbind_priv_pipe_dir(), WINBINDD_SOCKET_NAME, 0750);
- DEBUG(10, ("open_winbindd_priv_socket: opened socket fd %d\n",
- _winbindd_priv_socket));
- }
-
- return _winbindd_priv_socket;
-}
-
-/* Close the winbindd socket */
-
-void close_winbindd_socket(void)
-{
- if (_winbindd_socket != -1) {
- DEBUG(10, ("close_winbindd_socket: closing socket fd %d\n",
- _winbindd_socket));
- close(_winbindd_socket);
- _winbindd_socket = -1;
- }
- if (_winbindd_priv_socket != -1) {
- DEBUG(10, ("close_winbindd_socket: closing socket fd %d\n",
- _winbindd_priv_socket));
- close(_winbindd_priv_socket);
- _winbindd_priv_socket = -1;
- }
-}
-
/*
* Client list accessor functions
*/
return _num_clients;
}
-/*****************************************************************************
- For idmap conversion: convert one record to new format
- Ancient versions (eg 2.2.3a) of winbindd_idmap.tdb mapped DOMAINNAME/rid
- instead of the SID.
-*****************************************************************************/
-static int convert_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA data, void *state)
-{
- struct winbindd_domain *domain;
- char *p;
- DOM_SID sid;
- uint32 rid;
- fstring keystr;
- fstring dom_name;
- TDB_DATA key2;
- BOOL *failed = (BOOL *)state;
-
- DEBUG(10,("Converting %s\n", key.dptr));
-
- p = strchr(key.dptr, '/');
- if (!p)
- return 0;
-
- *p = 0;
- fstrcpy(dom_name, key.dptr);
- *p++ = '/';
-
- domain = find_domain_from_name(dom_name);
- if (domain == NULL) {
- /* We must delete the old record. */
- DEBUG(0,("Unable to find domain %s\n", dom_name ));
- DEBUG(0,("deleting record %s\n", key.dptr ));
-
- if (tdb_delete(tdb, key) != 0) {
- DEBUG(0, ("Unable to delete record %s\n", key.dptr));
- *failed = True;
- return -1;
- }
-
- return 0;
- }
-
- rid = atoi(p);
-
- sid_copy(&sid, &domain->sid);
- sid_append_rid(&sid, rid);
-
- sid_to_string(keystr, &sid);
- key2.dptr = keystr;
- key2.dsize = strlen(keystr) + 1;
-
- if (tdb_store(tdb, key2, data, TDB_INSERT) != 0) {
- DEBUG(0,("Unable to add record %s\n", key2.dptr ));
- *failed = True;
- return -1;
- }
-
- if (tdb_store(tdb, data, key2, TDB_REPLACE) != 0) {
- DEBUG(0,("Unable to update record %s\n", data.dptr ));
- *failed = True;
- return -1;
- }
-
- if (tdb_delete(tdb, key) != 0) {
- DEBUG(0,("Unable to delete record %s\n", key.dptr ));
- *failed = True;
- return -1;
- }
-
- return 0;
-}
-
-/* These definitions are from sam/idmap_tdb.c. Replicated here just
- out of laziness.... :-( */
-
-/* High water mark keys */
-#define HWM_GROUP "GROUP HWM"
-#define HWM_USER "USER HWM"
-
-/*****************************************************************************
- Convert the idmap database from an older version.
-*****************************************************************************/
-
-static BOOL idmap_convert(const char *idmap_name)
-{
- int32 vers;
- BOOL bigendianheader;
- BOOL failed = False;
- TDB_CONTEXT *idmap_tdb;
-
- if (!(idmap_tdb = tdb_open_log(idmap_name, 0,
- TDB_DEFAULT, O_RDWR,
- 0600))) {
- DEBUG(0, ("idmap_convert: Unable to open idmap database\n"));
- return False;
- }
-
- bigendianheader = (tdb_get_flags(idmap_tdb) & TDB_BIGENDIAN) ? True : False;
-
- vers = tdb_fetch_int32(idmap_tdb, "IDMAP_VERSION");
-
- if (((vers == -1) && bigendianheader) || (IREV(vers) == IDMAP_VERSION)) {
- /* Arrggghh ! Bytereversed or old big-endian - make order independent ! */
- /*
- * high and low records were created on a
- * big endian machine and will need byte-reversing.
- */
-
- int32 wm;
-
- wm = tdb_fetch_int32(idmap_tdb, HWM_USER);
-
- if (wm != -1) {
- wm = IREV(wm);
- } else {
- wm = server_state.uid_low;
- }
-
- if (tdb_store_int32(idmap_tdb, HWM_USER, wm) == -1) {
- DEBUG(0, ("idmap_convert: Unable to byteswap user hwm in idmap database\n"));
- tdb_close(idmap_tdb);
- return False;
- }
-
- wm = tdb_fetch_int32(idmap_tdb, HWM_GROUP);
- if (wm != -1) {
- wm = IREV(wm);
- } else {
- wm = server_state.gid_low;
- }
-
- if (tdb_store_int32(idmap_tdb, HWM_GROUP, wm) == -1) {
- DEBUG(0, ("idmap_convert: Unable to byteswap group hwm in idmap database\n"));
- tdb_close(idmap_tdb);
- return False;
- }
- }
-
- /* the old format stored as DOMAIN/rid - now we store the SID direct */
- tdb_traverse(idmap_tdb, convert_fn, &failed);
-
- if (failed) {
- DEBUG(0, ("Problem during conversion\n"));
- tdb_close(idmap_tdb);
- return False;
- }
-
- if (tdb_store_int32(idmap_tdb, "IDMAP_VERSION", IDMAP_VERSION) == -1) {
- DEBUG(0, ("idmap_convert: Unable to dtore idmap version in databse\n"));
- tdb_close(idmap_tdb);
- return False;
- }
-
- tdb_close(idmap_tdb);
- return True;
-}
-
-/*****************************************************************************
- Convert the idmap database from an older version if necessary
-*****************************************************************************/
-
-BOOL winbindd_upgrade_idmap(void)
-{
- pstring idmap_name;
- pstring backup_name;
- SMB_STRUCT_STAT stbuf;
- TDB_CONTEXT *idmap_tdb;
-
- pstrcpy(idmap_name, lock_path("winbindd_idmap.tdb"));
-
- if (!file_exist(idmap_name, &stbuf)) {
- /* nothing to convert return */
- return True;
- }
-
- if (!(idmap_tdb = tdb_open_log(idmap_name, 0,
- TDB_DEFAULT, O_RDWR,
- 0600))) {
- DEBUG(0, ("idmap_convert: Unable to open idmap database\n"));
- return False;
- }
-
- if (tdb_fetch_int32(idmap_tdb, "IDMAP_VERSION") == IDMAP_VERSION) {
- /* nothing to convert return */
- tdb_close(idmap_tdb);
- return True;
- }
-
- /* backup_tdb expects the tdb not to be open */
- tdb_close(idmap_tdb);
-
- DEBUG(0, ("Upgrading winbindd_idmap.tdb from an old version\n"));
-
- pstrcpy(backup_name, idmap_name);
- pstrcat(backup_name, ".bak");
-
- if (backup_tdb(idmap_name, backup_name) != 0) {
- DEBUG(0, ("Could not backup idmap database\n"));
- return False;
- }
-
- return idmap_convert(idmap_name);
-}
-
NTSTATUS lookup_usergroups_cached(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
const DOM_SID *user_sid,
}
if (info3->num_groups == 0) {
- SAFE_FREE(info3);
+ TALLOC_FREE(info3);
return NT_STATUS_UNSUCCESSFUL;
}
/* always add the primary group to the sid array */
sid_compose(&primary_group, &info3->dom_sid.sid, info3->user_rid);
- add_sid_to_array(mem_ctx, &primary_group, user_sids, &num_groups);
+ if (!add_sid_to_array(mem_ctx, &primary_group, user_sids, &num_groups)) {
+ TALLOC_FREE(info3);
+ return NT_STATUS_NO_MEMORY;
+ }
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);
- add_sid_to_array(mem_ctx, &group_sid, user_sids,
- &num_groups);
+ if (!add_sid_to_array(mem_ctx, &group_sid, user_sids,
+ &num_groups)) {
+ TALLOC_FREE(info3);
+ return NT_STATUS_NO_MEMORY;
+ }
}
- SAFE_FREE(info3);
+ TALLOC_FREE(info3);
*p_num_groups = num_groups;
status = (user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
return status;
}
+
+/*********************************************************************
+ We use this to remove spaces from user and group names
+********************************************************************/
+
+void ws_name_replace( char *name, char replace )
+{
+ char replace_char[2] = { 0x0, 0x0 };
+
+ if ( !lp_winbind_normalize_names() || (replace == '\0') )
+ return;
+
+ replace_char[0] = replace;
+ all_string_sub( name, " ", replace_char, 0 );
+
+ return;
+}
+
+/*********************************************************************
+ We use this to do the inverse of ws_name_replace()
+********************************************************************/
+
+void ws_name_return( char *name, char replace )
+{
+ char replace_char[2] = { 0x0, 0x0 };
+
+ if ( !lp_winbind_normalize_names() || (replace == '\0') )
+ return;
+
+ replace_char[0] = replace;
+ all_string_sub( name, replace_char, " ", 0 );
+
+ return;
+}
+
+/*********************************************************************
+ ********************************************************************/
+
+BOOL winbindd_can_contact_domain( struct winbindd_domain *domain )
+{
+ /* We can contact the domain if it is our primary domain */
+
+ if ( domain->primary )
+ return True;
+
+ /* Can always contact a domain that is in out forest */
+
+ if ( domain->domain_flags & DS_DOMAIN_IN_FOREST )
+ return True;
+
+ /* We cannot contact the domain if it is running AD and
+ we have no inbound trust */
+
+ if ( domain->active_directory &&
+ ((domain->domain_flags&DS_DOMAIN_DIRECT_INBOUND) != DS_DOMAIN_DIRECT_INBOUND) )
+ {
+ return False;
+ }
+
+ /* Assume everything else is ok (probably not true but what
+ can you do?) */
+
+ return True;
+}