Remove sam/api.c.
authorAndrew Bartlett <abartlet@samba.org>
Sun, 29 Sep 2002 06:07:58 +0000 (06:07 +0000)
committerAndrew Bartlett <abartlet@samba.org>
Sun, 29 Sep 2002 06:07:58 +0000 (06:07 +0000)
In order to reduce complexity, this patch removes the upper layer of the SAM
API.  Also, we remove the function pointers on the sam context - there really
is no point making these replaceable - that's for the modules.

Move a number of functions in include/interface.c around to allow for use of
'static' and to keep the external API in one chunk, at the bottem.  All these
functions were renamed to remove the context_sam -> sam

Consequential changes in the samtest module, and back out metze's change for
ACB filtering, becouse I think it belongs in the SAM backeds.  (But I will take
debate on this one).

Changes to the lib/util_sid.c code to create a 'system' token, and make it a
SAM_ASSERT() enforced requirement to have a token on those calls that specify
it.  samtest now uses this.

We should have a samtest call to set your own token.

We also need to extend our se_access code to cover the things that Win2k is
returning in it's access tokens.  Currently our system token doesn't pass, due
to unexpected flags.  (When running sam_ads against Win2k)

Andrew Bartlett

source/Makefile.in
source/include/sam.h
source/lib/util_sid.c
source/sam/api.c [deleted file]
source/sam/interface.c
source/torture/cmd_sam.c
source/torture/samtest.c

index 598062ec0517d0501a735b4053939add81ac8f80..0c553a95e8f257d6e89c54196eb75472673a8b78 100644 (file)
@@ -224,7 +224,7 @@ PASSDB_OBJ = $(PASSDB_GET_SET_OBJ) passdb/passdb.o passdb/pdb_interface.o \
 SAM_STATIC_MODULES = sam/sam_plugin.o sam/sam_skel.o sam/sam_ads.o
 
 SAM_OBJ = sam/account.o sam/get_set_account.o sam/get_set_group.o \
-               sam/get_set_domain.o sam/interface.o sam/api.o $(SAM_STATIC_MODULES)
+               sam/get_set_domain.o sam/interface.o $(SAM_STATIC_MODULES)
 
 SAMTEST_OBJ = torture/samtest.o torture/cmd_sam.o $(SAM_OBJ) $(LIB_OBJ) $(PARAM_OBJ) $(LIBSMB_OBJ) $(UBIQX_OBJ) $(READLINE_OBJ) lib/util_seaccess.o $(LIBADS_OBJ) $(PASSDB_OBJ) $(SECRETS_OBJ) $(GROUPDB_OBJ)
 
index 4cf46bfa757e75fc150b56cc62c5a8b879d3d9a8..d6fc1d7a1c7e3faf95321f9dda33bc245b0dac48 100644 (file)
@@ -162,51 +162,6 @@ typedef struct sam_context
        struct sam_methods *methods;
        TALLOC_CTX *mem_ctx;
        
-       /* General API */
-       
-       NTSTATUS (*sam_get_sec_desc) (const struct sam_context *, const NT_USER_TOKEN *access_token, const DOM_SID *sid, SEC_DESC **sd);
-       NTSTATUS (*sam_set_sec_desc) (const struct sam_context *, const NT_USER_TOKEN *access_token, const DOM_SID *sid, const SEC_DESC *sd);
-       
-       NTSTATUS (*sam_lookup_sid) (const struct sam_context *, const NT_USER_TOKEN *access_token, TALLOC_CTX *ctx, const DOM_SID *sid, char **name, uint32 *type);
-       NTSTATUS (*sam_lookup_name) (const struct sam_context *, const NT_USER_TOKEN *access_token, const char *domain, const char *name, DOM_SID *sid, uint32 *type);
-
-
-       /* Domain API */
-
-       NTSTATUS (*sam_update_domain) (const struct sam_context *, const SAM_DOMAIN_HANDLE *domain);
-
-       NTSTATUS (*sam_enum_domains) (const struct sam_context *, const NT_USER_TOKEN *access_token, int32 *domain_count, DOM_SID **domains, char **domain_names);
-       NTSTATUS (*sam_lookup_domain) (const struct sam_context *, const NT_USER_TOKEN * access_token, const char *domain, DOM_SID **domainsid);
-
-       NTSTATUS (*sam_get_domain_by_sid) (const struct sam_context *, const NT_USER_TOKEN *access_token, uint32 access_desired, const DOM_SID *domainsid, SAM_DOMAIN_HANDLE **domain);
-
-
-       /* Account API */
-
-       NTSTATUS (*sam_create_account) (const struct sam_context *context, const NT_USER_TOKEN *access_token, uint32 access_desired, const DOM_SID *domainsid, const char *account_name, uint16 acct_ctrl, SAM_ACCOUNT_HANDLE **account);
-       NTSTATUS (*sam_add_account) (const struct sam_context *, const DOM_SID *domainsid, const SAM_ACCOUNT_HANDLE *account);
-       NTSTATUS (*sam_update_account) (const struct sam_context *, const SAM_ACCOUNT_HANDLE *account);
-       NTSTATUS (*sam_delete_account) (const struct sam_context *, const SAM_ACCOUNT_HANDLE *account);
-       NTSTATUS (*sam_enum_accounts) (const struct sam_context *, const NT_USER_TOKEN *access_token, const DOM_SID *domain, uint16 acct_ctrl, uint32 *account_count, SAM_ACCOUNT_ENUM **accounts);
-
-       NTSTATUS (*sam_get_account_by_sid) (const struct sam_context *, const NT_USER_TOKEN *access_token, uint32 access_desired, const DOM_SID *accountsid, SAM_ACCOUNT_HANDLE **account);
-       NTSTATUS (*sam_get_account_by_name) (const struct sam_context *, const NT_USER_TOKEN *access_token, uint32 access_desired, const char *domain, const char *name, SAM_ACCOUNT_HANDLE **account);
-
-       /* Group API */
-
-       NTSTATUS (*sam_create_group) (const struct sam_context *, const NT_USER_TOKEN *access_token, uint32 access_desired, const DOM_SID *domainsid, const char *group_name, uint16 group_ctrl, SAM_GROUP_HANDLE **group);
-       NTSTATUS (*sam_add_group) (const struct sam_context *, const DOM_SID *domainsid, const SAM_GROUP_HANDLE *group);
-       NTSTATUS (*sam_update_group) (const struct sam_context *, const SAM_GROUP_HANDLE *group);
-       NTSTATUS (*sam_delete_group) (const struct sam_context *, const SAM_GROUP_HANDLE *group);
-       NTSTATUS (*sam_enum_groups) (const struct sam_context *, const NT_USER_TOKEN *access_token, const DOM_SID *domainsid, const uint16 group_ctrl, uint32 *groups_count, SAM_GROUP_ENUM **groups);
-       NTSTATUS (*sam_get_group_by_sid) (const struct sam_context *, const NT_USER_TOKEN *access_token, uint32 access_desired, const DOM_SID *groupsid, SAM_GROUP_HANDLE **group);
-       NTSTATUS (*sam_get_group_by_name) (const struct sam_context *, const NT_USER_TOKEN *access_token, uint32 access_desired, const char *domain, const char *name, SAM_GROUP_HANDLE **group);
-
-       NTSTATUS (*sam_add_member_to_group) (const struct sam_context *, const SAM_GROUP_HANDLE *group, const SAM_GROUP_MEMBER *member);
-       NTSTATUS (*sam_delete_member_from_group) (const struct sam_context *, const SAM_GROUP_HANDLE *group, const SAM_GROUP_MEMBER *member);
-       NTSTATUS (*sam_enum_groupmembers) (const struct sam_context *, const SAM_GROUP_HANDLE *group, uint32 *members_count, SAM_GROUP_MEMBER **members);
-
-       NTSTATUS (*sam_get_groups_of_sid) (const struct sam_context *, const NT_USER_TOKEN *access_token, const DOM_SID **sids, uint16 group_ctrl, uint32 *group_count, SAM_GROUP_ENUM **groups);
        void (*free_fn)(struct sam_context **);
 } SAM_CONTEXT;
 
index 18260be8700984e10d76335dfc98ac1c1442a858..9e533eb9fd1577e99c8831111ce7ac0e011c3591 100644 (file)
@@ -34,6 +34,7 @@ DOM_SID global_sid_World_Domain;              /* Everyone domain */
 DOM_SID global_sid_World;                              /* Everyone */
 DOM_SID global_sid_Creator_Owner_Domain;    /* Creator Owner domain */
 DOM_SID global_sid_NT_Authority;               /* NT Authority */
+DOM_SID global_sid_System;             /* System */
 DOM_SID global_sid_NULL;                       /* NULL sid */
 DOM_SID global_sid_Authenticated_Users;                /* All authenticated rids */
 DOM_SID global_sid_Network;                                    /* Network rids */
@@ -58,6 +59,12 @@ NT_USER_TOKEN anonymous_token = {
     anon_sid_array
 };
 
+static DOM_SID system_sid_array[4];
+NT_USER_TOKEN system_token = {
+    4,
+    system_sid_array
+};
+
 /****************************************************************************
  Lookup string names for SID types.
 ****************************************************************************/
@@ -101,6 +108,10 @@ const char *sid_type_lookup(uint32 sid_type)
 
 void generate_wellknown_sids(void)
 {
+       static BOOL initialised = False;
+       if (initialised) 
+               return;
+
        string_to_sid(&global_sid_Builtin, "S-1-5-32");
        string_to_sid(&global_sid_Builtin_Administrators, "S-1-5-32-544");
        string_to_sid(&global_sid_Builtin_Users, "S-1-5-32-545");
@@ -111,6 +122,7 @@ void generate_wellknown_sids(void)
        string_to_sid(&global_sid_Creator_Owner, "S-1-3-0");
        string_to_sid(&global_sid_Creator_Group, "S-1-3-1");
        string_to_sid(&global_sid_NT_Authority, "S-1-5");
+       string_to_sid(&global_sid_System, "S-1-5-18");
        string_to_sid(&global_sid_NULL, "S-1-0-0");
        string_to_sid(&global_sid_Authenticated_Users, "S-1-5-11");
        string_to_sid(&global_sid_Network, "S-1-5-2");
@@ -120,6 +132,20 @@ void generate_wellknown_sids(void)
        sid_copy( &anonymous_token.user_sids[0], &global_sid_World);
        sid_copy( &anonymous_token.user_sids[1], &global_sid_Network);
        sid_copy( &anonymous_token.user_sids[2], &global_sid_Anonymous);
+
+       /* Create the system token. */
+       sid_copy( &system_token.user_sids[0], &global_sid_World);
+       sid_copy( &system_token.user_sids[1], &global_sid_Authenticated_Users);
+       sid_copy( &system_token.user_sids[2], &global_sid_Builtin_Administrators);
+       sid_copy( &system_token.user_sids[3], &global_sid_System);
+       
+       initialised = True;
+}
+
+NT_USER_TOKEN *get_system_token(void) 
+{
+       generate_wellknown_sids(); /* The token is initialised here */
+       return &system_token;
 }
 
 /**************************************************************************
diff --git a/source/sam/api.c b/source/sam/api.c
deleted file mode 100644 (file)
index fd34559..0000000
+++ /dev/null
@@ -1,322 +0,0 @@
-/* 
-   Unix SMB/CIFS implementation.
-   SAM interface API.
-
-   Copyright (C) Stefan (metze) Metzmacher             2002
-      
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 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"
-
-#undef DBGC_CLASS
-#define DBGC_CLASS DBGC_SAM
-
-/* these functions should be used by the rest of SAMBA --metze */
-
-/* General API */
-
-NTSTATUS sam_get_sec_desc(const NT_USER_TOKEN *access_token, const DOM_SID *sid, SEC_DESC **sd)
-{
-       SAM_CONTEXT *sam_context = sam_get_static_context(False);
-
-       if (!sam_context) {
-               return NT_STATUS_UNSUCCESSFUL;
-       }
-
-       return sam_context->sam_get_sec_desc(sam_context, access_token, sid, sd);
-}
-
-NTSTATUS sam_set_sec_desc(const NT_USER_TOKEN *access_token, const DOM_SID *sid, const SEC_DESC *sd)
-{
-       SAM_CONTEXT *sam_context = sam_get_static_context(False);
-
-       if (!sam_context) {
-               return NT_STATUS_UNSUCCESSFUL;
-       }
-
-       return sam_context->sam_set_sec_desc(sam_context, access_token, sid, sd);
-}
-
-NTSTATUS sam_lookup_sid(const NT_USER_TOKEN *access_token, TALLOC_CTX *mem_ctx, const DOM_SID *sid, char **name, uint32 *type)
-{
-       SAM_CONTEXT *sam_context = sam_get_static_context(False);
-
-       if (!sam_context) {
-               return NT_STATUS_UNSUCCESSFUL;
-       }
-
-       return sam_context->sam_lookup_sid(sam_context, access_token, mem_ctx, sid, name, type);
-}
-
-NTSTATUS sam_lookup_name(const NT_USER_TOKEN *access_token, const char *domain, const char *name, DOM_SID *sid,  uint32 *type)
-{
-       SAM_CONTEXT *sam_context = sam_get_static_context(False);
-
-       if (!sam_context) {
-               return NT_STATUS_UNSUCCESSFUL;
-       }
-
-       return sam_context->sam_lookup_name(sam_context, access_token,domain, name, sid, type);
-}
-
-/* Domain API */
-
-NTSTATUS sam_update_domain(const SAM_DOMAIN_HANDLE *domain)
-{
-       SAM_CONTEXT *sam_context = sam_get_static_context(False);
-
-       if (!sam_context) {
-               return NT_STATUS_UNSUCCESSFUL;
-       }
-
-       return sam_context->sam_update_domain(sam_context, domain);
-}
-
-NTSTATUS sam_enum_domains(const NT_USER_TOKEN *access_token, int32 *domain_count, DOM_SID **domains, char **domain_names)
-{
-       SAM_CONTEXT *sam_context = sam_get_static_context(False);
-
-       if (!sam_context) {
-               return NT_STATUS_UNSUCCESSFUL;
-       }
-
-       return sam_context->sam_enum_domains(sam_context, access_token, domain_count, domains, domain_names);
-}
-
-NTSTATUS sam_lookup_domain(const NT_USER_TOKEN * access_token, const char *domain, DOM_SID **domainsid)
-{
-       SAM_CONTEXT *sam_context = sam_get_static_context(False);
-
-       if (!sam_context) {
-               return NT_STATUS_UNSUCCESSFUL;
-       }
-
-       return sam_context->sam_lookup_domain(sam_context, access_token, domain, domainsid);
-}
-
-NTSTATUS sam_get_domain_by_sid(const NT_USER_TOKEN *access_token, const uint32 access_desired, const DOM_SID *domainsid, SAM_DOMAIN_HANDLE **domain)
-{
-       SAM_CONTEXT *sam_context = sam_get_static_context(False);
-
-       if (!sam_context) {
-               return NT_STATUS_UNSUCCESSFUL;
-       }
-
-       return sam_context->sam_get_domain_by_sid(sam_context, access_token, access_desired, domainsid, domain);
-}
-
-/* Account API */
-
-NTSTATUS sam_create_account(const NT_USER_TOKEN *access_token, const uint32 access_desired, const DOM_SID *domainsid, const char *account_name, uint16 acct_ctrl, SAM_ACCOUNT_HANDLE **account)
-{
-       SAM_CONTEXT *sam_context = sam_get_static_context(False);
-
-       if (!sam_context) {
-               return NT_STATUS_UNSUCCESSFUL;
-       }
-
-       return sam_context->sam_create_account(sam_context, access_token, access_desired, domainsid, account_name, acct_ctrl, account);
-}
-
-NTSTATUS sam_add_account(const DOM_SID *domainsid, const SAM_ACCOUNT_HANDLE *account)
-{
-       SAM_CONTEXT *sam_context = sam_get_static_context(False);
-
-       if (!sam_context) {
-               return NT_STATUS_UNSUCCESSFUL;
-       }
-
-       return sam_context->sam_add_account(sam_context, domainsid, account);
-}
-
-NTSTATUS sam_update_account(const SAM_ACCOUNT_HANDLE *account)
-{
-       SAM_CONTEXT *sam_context = sam_get_static_context(False);
-
-       if (!sam_context) {
-               return NT_STATUS_UNSUCCESSFUL;
-       }
-
-       return sam_context->sam_update_account(sam_context, account);
-}
-
-NTSTATUS sam_delete_account(const SAM_ACCOUNT_HANDLE *account)
-{
-       SAM_CONTEXT *sam_context = sam_get_static_context(False);
-
-       if (!sam_context) {
-               return NT_STATUS_UNSUCCESSFUL;
-       }
-
-       return sam_context->sam_delete_account(sam_context, account);
-}
-
-NTSTATUS sam_enum_accounts(const NT_USER_TOKEN *access_token, const DOM_SID *domain, uint16 acct_ctrl, uint32 *account_count, SAM_ACCOUNT_ENUM **accounts)
-{
-       SAM_CONTEXT *sam_context = sam_get_static_context(False);
-
-       if (!sam_context) {
-               return NT_STATUS_UNSUCCESSFUL;
-       }
-
-       return sam_context->sam_enum_accounts(sam_context, access_token, domain, acct_ctrl, account_count, accounts);
-}
-
-NTSTATUS sam_get_account_by_sid(const NT_USER_TOKEN *access_token, const uint32 access_desired, const DOM_SID *accountsid, SAM_ACCOUNT_HANDLE **account)
-{
-       SAM_CONTEXT *sam_context = sam_get_static_context(False);
-
-       if (!sam_context) {
-               return NT_STATUS_UNSUCCESSFUL;
-       }
-
-       return sam_context->sam_get_account_by_sid(sam_context, access_token, access_desired, accountsid, account);
-}
-
-NTSTATUS sam_get_account_by_name(const NT_USER_TOKEN *access_token, const uint32 access_desired, const char *domain, const char *name, SAM_ACCOUNT_HANDLE **account)
-{
-       SAM_CONTEXT *sam_context = sam_get_static_context(False);
-
-       if (!sam_context) {
-               return NT_STATUS_UNSUCCESSFUL;
-       }
-
-       return sam_context->sam_get_account_by_name(sam_context, access_token, access_desired, domain, name, account);
-}
-
-/* Group API */
-
-NTSTATUS sam_create_group(const NT_USER_TOKEN *access_token, const uint32 access_desired, const DOM_SID *domainsid, const char *group_name, uint16 group_ctrl, SAM_GROUP_HANDLE **group)
-{
-       SAM_CONTEXT *sam_context = sam_get_static_context(False);
-
-       if (!sam_context) {
-               return NT_STATUS_UNSUCCESSFUL;
-       }
-
-       return sam_context->sam_create_group(sam_context, access_token, access_desired, domainsid, group_name, group_ctrl, group);
-}
-
-NTSTATUS sam_add_group(const DOM_SID *domainsid, const SAM_GROUP_HANDLE *group)
-{
-       SAM_CONTEXT *sam_context = sam_get_static_context(False);
-
-       if (!sam_context) {
-               return NT_STATUS_UNSUCCESSFUL;
-       }
-
-       return sam_context->sam_add_group(sam_context, domainsid, group);
-}
-
-NTSTATUS sam_update_group(const SAM_GROUP_HANDLE *group)
-{
-       SAM_CONTEXT *sam_context = sam_get_static_context(False);
-
-       if (!sam_context) {
-               return NT_STATUS_UNSUCCESSFUL;
-       }
-
-       return sam_context->sam_update_group(sam_context, group);
-}
-
-NTSTATUS sam_delete_group(const SAM_GROUP_HANDLE *group)
-{
-       SAM_CONTEXT *sam_context = sam_get_static_context(False);
-
-       if (!sam_context) {
-               return NT_STATUS_UNSUCCESSFUL;
-       }
-
-       return sam_context->sam_delete_group(sam_context, group);
-}
-
-NTSTATUS sam_enum_groups(const NT_USER_TOKEN *access_token, const DOM_SID *domainsid, uint16 group_ctrl, uint32 *groups_count, SAM_GROUP_ENUM **groups)
-{
-       SAM_CONTEXT *sam_context = sam_get_static_context(False);
-
-       if (!sam_context) {
-               return NT_STATUS_UNSUCCESSFUL;
-       }
-
-       return sam_context->sam_enum_groups(sam_context, access_token, domainsid, group_ctrl, groups_count, groups);
-}
-
-NTSTATUS sam_get_group_by_sid(const NT_USER_TOKEN *access_token, const uint32 access_desired, const DOM_SID *groupsid, SAM_GROUP_HANDLE **group)
-{
-       SAM_CONTEXT *sam_context = sam_get_static_context(False);
-
-       if (!sam_context) {
-               return NT_STATUS_UNSUCCESSFUL;
-       }
-
-       return sam_context->sam_get_group_by_sid(sam_context, access_token, access_desired, groupsid, group);
-}
-
-NTSTATUS sam_get_group_by_name(const NT_USER_TOKEN *access_token, const uint32 access_desired, const char *domain, const char *name, SAM_GROUP_HANDLE **group)
-{
-       SAM_CONTEXT *sam_context = sam_get_static_context(False);
-
-       if (!sam_context) {
-               return NT_STATUS_UNSUCCESSFUL;
-       }
-
-       return sam_context->sam_get_group_by_name(sam_context, access_token, access_desired, domain, name, group);
-}
-
-NTSTATUS sam_add_member_to_group(const SAM_GROUP_HANDLE *group, const SAM_GROUP_MEMBER *member)
-{
-       SAM_CONTEXT *sam_context = sam_get_static_context(False);
-
-       if (!sam_context) {
-               return NT_STATUS_UNSUCCESSFUL;
-       }
-
-       return sam_context->sam_add_member_to_group(sam_context, group, member);
-}
-
-NTSTATUS sam_delete_member_from_group(const SAM_GROUP_HANDLE *group, const SAM_GROUP_MEMBER *member)
-{
-       SAM_CONTEXT *sam_context = sam_get_static_context(False);
-
-       if (!sam_context) {
-               return NT_STATUS_UNSUCCESSFUL;
-       }
-
-       return sam_context->sam_delete_member_from_group(sam_context, group, member);
-}
-
-NTSTATUS sam_enum_groupmembers(const SAM_GROUP_HANDLE *group, uint32 *members_count, SAM_GROUP_MEMBER **members)
-{
-       SAM_CONTEXT *sam_context = sam_get_static_context(False);
-
-       if (!sam_context) {
-               return NT_STATUS_UNSUCCESSFUL;
-       }
-
-       return sam_context->sam_enum_groupmembers(sam_context, group, members_count, members);
-}
-
-NTSTATUS sam_get_groups_of_sid(const NT_USER_TOKEN *access_token, const DOM_SID **sids, uint16 group_ctrl, uint32 *group_count, SAM_GROUP_ENUM **groups)
-{
-       SAM_CONTEXT *sam_context = sam_get_static_context(False);
-
-       if (!sam_context) {
-               return NT_STATUS_UNSUCCESSFUL;
-       }
-
-       return sam_context->sam_get_groups_of_sid(sam_context, access_token, sids, group_ctrl, group_count, groups);
-}
-
index 9a21eb844fd2fc9c30b04bada19515700e64e3ae..8e4e0d114bc0b402d21c88e2037a519d4d23afdc 100644 (file)
@@ -39,14 +39,8 @@ const struct sam_init_function_entry builtin_sam_init_functions[] = {
        { NULL, NULL}
 };
 
-/******************************************************************
-  context_sam_* functions are used to link the external SAM interface
-  with the internal backends. These functions lookup the appropriate
-  backends for the domain and pass on to the function in sam_methods
-  in the selected backend
- *******************************************************************/
 
-NTSTATUS sam_get_methods_by_sid(const SAM_CONTEXT *context, SAM_METHODS **sam_method, const DOM_SID *domainsid)
+static NTSTATUS sam_get_methods_by_sid(const SAM_CONTEXT *context, SAM_METHODS **sam_method, const DOM_SID *domainsid)
 {
        SAM_METHODS     *tmp_methods;
 
@@ -71,7 +65,7 @@ NTSTATUS sam_get_methods_by_sid(const SAM_CONTEXT *context, SAM_METHODS **sam_me
        return NT_STATUS_NO_SUCH_DOMAIN;
 }
 
-NTSTATUS sam_get_methods_by_name(const SAM_CONTEXT *context, SAM_METHODS **sam_method, const char *domainname)
+static NTSTATUS sam_get_methods_by_name(const SAM_CONTEXT *context, SAM_METHODS **sam_method, const char *domainname)
 {
        SAM_METHODS     *tmp_methods;
 
@@ -96,379 +90,526 @@ NTSTATUS sam_get_methods_by_name(const SAM_CONTEXT *context, SAM_METHODS **sam_m
        return NT_STATUS_NO_SUCH_DOMAIN;
 }
 
-NTSTATUS context_sam_get_sec_desc(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, const DOM_SID *sid, SEC_DESC **sd)
+static NTSTATUS make_sam_methods(TALLOC_CTX *mem_ctx, SAM_METHODS **methods)
 {
-       SAM_METHODS     *tmp_methods;
-       NTSTATUS        nt_status;
-
-       DEBUG(5,("context_sam_get_sec_desc: %d\n", __LINE__));
-
-       if (!NT_STATUS_IS_OK(nt_status = sam_get_methods_by_sid(context, &tmp_methods, sid))) {
-               DEBUG(4,("sam_get_methods_by_sid failed\n"));
-               return nt_status;
-       }
+       *methods = talloc(mem_ctx, sizeof(SAM_METHODS));
 
-       if (!tmp_methods->sam_get_sec_desc) {
-               DEBUG(3, ("context_sam_get_sec_desc: sam_methods of the domain did not specify sam_get_sec_desc\n"));
-               return NT_STATUS_NOT_IMPLEMENTED;
+       if (!*methods) {
+               return NT_STATUS_NO_MEMORY;
        }
 
-       if (!NT_STATUS_IS_OK(nt_status = tmp_methods->sam_get_sec_desc(tmp_methods, access_token, sid, sd))) {
-               DEBUG(4,("sam_get_sec_desc for %s in backend %s failed\n", sid_string_static(sid), tmp_methods->backendname));
-               return nt_status;
-       }
+       ZERO_STRUCTP(*methods);
 
        return NT_STATUS_OK;
 }
 
-NTSTATUS context_sam_set_sec_desc(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, const DOM_SID *sid, const SEC_DESC *sd)
+/******************************************************************
+  Free and cleanup a sam context, any associated data and anything
+  that the attached modules might have associated.
+ *******************************************************************/
+
+void free_sam_context(SAM_CONTEXT **context)
 {
-       SAM_METHODS     *tmp_methods;
-       NTSTATUS        nt_status;
+       SAM_METHODS *sam_selected = (*context)->methods;
 
-       DEBUG(5,("context_sam_set_sec_desc: %d\n", __LINE__));
-       
-       if (!NT_STATUS_IS_OK(nt_status = sam_get_methods_by_sid(context, &tmp_methods, sid))) {
-               DEBUG(4,("sam_get_methods_by_sid failed\n"));
-               return nt_status;
+       while (sam_selected) {
+               if (sam_selected->free_private_data) {
+                       sam_selected->free_private_data(&(sam_selected->private_data));
+               }
+               sam_selected = sam_selected->next;
        }
 
-       if (!tmp_methods->sam_set_sec_desc) {
-               DEBUG(3, ("context_sam_set_sec_desc: sam_methods of the domain did not specify sam_set_sec_desc\n"));
-               return NT_STATUS_NOT_IMPLEMENTED;
-       }
+       talloc_destroy((*context)->mem_ctx);
+       *context = NULL;
+}
 
-       if (!NT_STATUS_IS_OK(nt_status = tmp_methods->sam_set_sec_desc(tmp_methods, access_token, sid, sd))) {
-               DEBUG(4,("sam_set_sec_desc for %s in backend %s failed\n", sid_string_static(sid), tmp_methods->backendname));
-               return nt_status;
+/******************************************************************
+  Make a backend_entry from scratch
+ *******************************************************************/
+static NTSTATUS make_backend_entry(SAM_BACKEND_ENTRY *backend_entry, char *sam_backend_string)
+{
+       char *tmp = NULL;
+       char *tmp_string = sam_backend_string;
+       
+       DEBUG(5,("make_backend_entry: %d\n", __LINE__));
+       
+       SAM_ASSERT(sam_backend_string && backend_entry);
+       
+       backend_entry->module_name = sam_backend_string;
+       
+       DEBUG(5,("makeing backend_entry for %s\n", backend_entry->module_name));
+       
+       if ((tmp = strchr(tmp_string, '|')) != NULL) {
+               DEBUGADD(20,("a domain name has been specified\n"));
+               *tmp = 0;
+               backend_entry->domain_name = smb_xstrdup(tmp + 1);
+               tmp_string = tmp + 1;
        }
-
+       
+       if ((tmp = strchr(tmp_string, ':')) != NULL) {
+               DEBUG(20,("options for the backend have been specified\n"));
+               *tmp = 0;
+               backend_entry->module_params = smb_xstrdup(tmp + 1);
+               tmp_string = tmp + 1;
+       }
+               
+       if (backend_entry->domain_name == NULL) {
+               DEBUG(10,("make_backend_entry: no domain was specified for sam module %s. Using default domain %s\n",
+                       backend_entry->module_name, lp_workgroup()));
+               backend_entry->domain_name = smb_xstrdup(lp_workgroup());
+       }
+       
+       if ((backend_entry->domain_sid = (DOM_SID *)malloc(sizeof(DOM_SID))) == NULL) {
+               DEBUG(0,("make_backend_entry: failed to malloc domain_sid\n"));
+               return NT_STATUS_NO_MEMORY;
+       }
+       
+       DEBUG(10,("looking up sid for domain %s\n", backend_entry->domain_name));
+       
+       if (!secrets_fetch_domain_sid(backend_entry->domain_name, backend_entry->domain_sid)) {
+               DEBUG(2,("make_backend_entry: There is no SID stored for domain %s. Creating a new one.\n",
+                       backend_entry->domain_name));           
+               DEBUG(0, ("FIXME in %s:%d\n", __FILE__, __LINE__));
+               ZERO_STRUCTP(backend_entry->domain_sid);
+       }
+       
+       DEBUG(5,("make_backend_entry: module name: %s, module parameters: %s, domain name: %s, domain sid: %s\n",
+               backend_entry->module_name, backend_entry->module_params, backend_entry->domain_name, sid_string_static(backend_entry->domain_sid)));
+       
        return NT_STATUS_OK;
 }
 
+/******************************************************************
+ create sam_methods struct based on sam_backend_entry
+ *****************************************************************/
 
-NTSTATUS context_sam_lookup_name(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, const char *domain, const char *name, DOM_SID *sid, uint32 *type)
+static NTSTATUS make_sam_methods_backend_entry(SAM_CONTEXT *context, SAM_METHODS **methods_ptr, SAM_BACKEND_ENTRY *backend_entry)
 {
-       SAM_METHODS     *tmp_methods;
-       NTSTATUS        nt_status;
+       NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+       SAM_METHODS *methods;
+       int i;
 
-       DEBUG(5,("context_sam_lookup_name: %d\n", __LINE__));
+       DEBUG(5,("make_sam_methods_backend_entry: %d\n", __LINE__));
 
-       if (!NT_STATUS_IS_OK(nt_status = sam_get_methods_by_name(context, &tmp_methods, domain))) {
-               DEBUG(4,("sam_get_methods_by_name failed\n"));
+       if (!NT_STATUS_IS_OK(nt_status = make_sam_methods(context->mem_ctx, methods_ptr))) {
                return nt_status;
        }
 
-       if (!tmp_methods->sam_lookup_name) {
-               DEBUG(3, ("context_sam_lookup_name: sam_methods of the domain did not specify sam_lookup_name\n"));
-               return NT_STATUS_NOT_IMPLEMENTED;
-       }
+       methods = *methods_ptr;
+       methods->backendname = talloc_strdup(context->mem_ctx, backend_entry->module_name);
+       methods->domain_name = talloc_strdup(context->mem_ctx, backend_entry->domain_name);
+       sid_copy(&methods->domain_sid, backend_entry->domain_sid);
+       methods->parent = context;
 
-       if (!NT_STATUS_IS_OK(nt_status = tmp_methods->sam_lookup_name(tmp_methods, access_token, name, sid, type))) {
-               DEBUG(4,("sam_lookup_name for %s\\%s in backend %s failed\n",
-                                tmp_methods->domain_name, name, tmp_methods->backendname));
-               return nt_status;
+       DEBUG(5,("Attempting to find sam backend %s\n", backend_entry->module_name));
+       for (i = 0; builtin_sam_init_functions[i].module_name; i++)
+       {
+               if (strequal(builtin_sam_init_functions[i].module_name, backend_entry->module_name))
+               {
+                       DEBUG(5,("Found sam backend %s (at pos %d)\n", backend_entry->module_name, i));
+                       DEBUGADD(5,("initialising it with options=%s for domain %s\n", backend_entry->module_params, sid_string_static(backend_entry->domain_sid)));
+                       nt_status = builtin_sam_init_functions[i].init(methods, backend_entry->module_params);
+                       if (NT_STATUS_IS_OK(nt_status)) {
+                               DEBUG(5,("sam backend %s has a valid init\n", backend_entry->module_name));
+                       } else {
+                               DEBUG(2,("sam backend %s did not correctly init (error was %s)\n",
+                                       backend_entry->module_name, nt_errstr(nt_status)));
+                       }
+                       return nt_status;
+               }
        }
+       
+       DEBUG(2,("could not find backend %s\n", backend_entry->module_name));
 
-       return NT_STATUS_OK;
+       return NT_STATUS_INVALID_PARAMETER;
 }
 
-NTSTATUS context_sam_lookup_sid(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, TALLOC_CTX *mem_ctx, const DOM_SID *sid, char **name, uint32 *type)
+static NTSTATUS sam_context_check_default_backends(SAM_CONTEXT *context)
 {
-       SAM_METHODS     *tmp_methods;
-       uint32          rid;
-       NTSTATUS        nt_status;
-       DOM_SID         domainsid;
+       SAM_BACKEND_ENTRY entry;
+       DOM_SID *global_sam_sid  = get_global_sam_sid(); /* lp_workgroup doesn't play nicely with multiple domains */
+       SAM_METHODS *methods, *tmpmethods;
+       NTSTATUS ntstatus;
+       
+       DEBUG(5,("sam_context_check_default_backends: %d\n", __LINE__));
 
-       DEBUG(5,("context_sam_lookup_sid: %d\n", __LINE__));
+       /* Make sure domain lp_workgroup() is available */
+       
+       ntstatus = sam_get_methods_by_sid(context, &methods, &global_sid_Builtin);
 
-       sid_copy(&domainsid, sid);
-       if (!sid_split_rid(&domainsid, &rid)) {
-               DEBUG(3,("context_sam_lookup_sid: failed to split the sid\n"));
-               return NT_STATUS_INVALID_SID;
-       }
+       if (NT_STATUS_EQUAL(ntstatus, NT_STATUS_NO_SUCH_DOMAIN)) {
+               DEBUG(4,("There was no backend specified for domain %s(%s); using %s\n",
+                       lp_workgroup(), sid_string_static(global_sam_sid), SAM_DEFAULT_BACKEND));
 
-       if (!NT_STATUS_IS_OK(nt_status = sam_get_methods_by_sid(context, &tmp_methods, &domainsid))) {
-               DEBUG(4,("sam_get_methods_by_sid failed\n"));
-               return nt_status;
-       }
+               SAM_ASSERT(global_sam_sid);
 
-       if (!tmp_methods->sam_lookup_sid) {
-               DEBUG(3, ("context_sam_lookup_sid: sam_methods of the domain did not specify sam_lookup_sid\n"));
-               return NT_STATUS_NOT_IMPLEMENTED;
+               entry.module_name = SAM_DEFAULT_BACKEND;
+               entry.module_params = NULL;
+               entry.domain_name = lp_workgroup();
+               entry.domain_sid = (DOM_SID *)malloc(sizeof(DOM_SID));
+               sid_copy(entry.domain_sid, global_sam_sid);
+
+               if (!NT_STATUS_IS_OK(ntstatus = make_sam_methods_backend_entry(context, &methods, &entry))) {
+                       DEBUG(4,("make_sam_methods_backend_entry failed\n"));
+                       return ntstatus;
+               }
+
+               DLIST_ADD_END(context->methods, methods, tmpmethods);
+
+       } else if (!NT_STATUS_IS_OK(ntstatus)) {
+               DEBUG(2, ("sam_get_methods_by_sid failed for %s\n", lp_workgroup()));
+               return ntstatus;
        }
 
-       if (!NT_STATUS_IS_OK(nt_status = tmp_methods->sam_lookup_sid(tmp_methods, access_token, mem_ctx, sid, name, type))) {
-               DEBUG(4,("sam_lookup_name for %s in backend %s failed\n",
-                                sid_string_static(sid), tmp_methods->backendname));
-               return nt_status;
+       /* Make sure the BUILTIN domain is available */
+
+       ntstatus = sam_get_methods_by_sid(context, &methods, global_sam_sid);
+       
+       if (NT_STATUS_EQUAL(ntstatus, NT_STATUS_NO_SUCH_DOMAIN)) {
+               DEBUG(4,("There was no backend specified for domain BUILTIN; using %s\n", 
+                                SAM_DEFAULT_BACKEND));
+               entry.module_name = SAM_DEFAULT_BACKEND;
+               entry.module_params = NULL;
+               entry.domain_name = "BUILTIN";
+               entry.domain_sid    = (DOM_SID *)malloc(sizeof(DOM_SID)); 
+               sid_copy(entry.domain_sid, &global_sid_Builtin);
+
+               if (!NT_STATUS_IS_OK(ntstatus = make_sam_methods_backend_entry(context, &methods,  &entry))) {
+                       DEBUG(4,("make_sam_methods_backend_entry failed\n"));
+                       return ntstatus;
+               }
+
+               DLIST_ADD_END(context->methods, methods, tmpmethods);
+       } else if (!NT_STATUS_IS_OK(ntstatus)) {
+               DEBUG(2, ("sam_get_methods_by_sid failed for BUILTIN\n"));
+               return ntstatus;
        }
 
        return NT_STATUS_OK;
 }
 
-
-NTSTATUS context_sam_update_domain(const SAM_CONTEXT *context, const SAM_DOMAIN_HANDLE *domain)
+static NTSTATUS check_duplicate_backend_entries(SAM_BACKEND_ENTRY **backend_entries, int *nBackends)
 {
-       const SAM_METHODS *tmp_methods;
-       NTSTATUS     nt_status;
-
-       DEBUG(5,("context_sam_update_domain: %d\n", __LINE__));
-       
-       /* invalid domain specified */
-       SAM_ASSERT(domain && domain->current_sam_methods);
+       int i, j;
        
-       tmp_methods = domain->current_sam_methods;
+       DEBUG(5,("check_duplicate_backend_entries: %d\n", __LINE__));
        
-       if (!tmp_methods->sam_update_domain) {
-               DEBUG(3, ("context_sam_update_domain: sam_methods of the domain did not specify sam_update_domain\n"));
-               return NT_STATUS_NOT_IMPLEMENTED;
-       }
-
-       if (!NT_STATUS_IS_OK(nt_status = tmp_methods->sam_update_domain(tmp_methods, domain))){
-               DEBUG(4,("sam_update_domain in backend %s failed\n",
-                                tmp_methods->backendname));
-               return nt_status;
+       for (i = 0; i < *nBackends; i++) {
+               for (j = i + 1; j < *nBackends; j++) {
+                       if (sid_equal((*backend_entries)[i].domain_sid, (*backend_entries)[j].domain_sid)) {
+                               DEBUG(0,("two backend modules claim the same domain %s\n",
+                                       sid_string_static((*backend_entries)[j].domain_sid)));
+                               return NT_STATUS_INVALID_PARAMETER;                     
+                       }
+               }               
        }
 
        return NT_STATUS_OK;
 }
 
-NTSTATUS context_sam_enum_domains(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, int32 *domain_count, DOM_SID **domains, char ***domain_names)
+NTSTATUS make_sam_context_list(SAM_CONTEXT **context, char **sam_backends_param)
 {
-       SAM_METHODS     *tmp_methods;
-       NTSTATUS         nt_status;
+       int i = 0, j = 0;
+       SAM_METHODS *curmethods, *tmpmethods;
+       int nBackends               = 0;
+       SAM_BACKEND_ENTRY *backends = NULL;
+       NTSTATUS nt_status          = NT_STATUS_UNSUCCESSFUL;
 
-       SEC_DESC        *sd;
-       size_t          sd_size;
-       uint32          acc_granted;
-       int             i = 0;
-
-       DEBUG(5,("context_sam_enum_domains: %d\n", __LINE__));
+       DEBUG(5,("make_sam_context_from_conf: %d\n", __LINE__));
 
-       /* invalid sam_context specified */
-       SAM_ASSERT(context && context->methods);
+       if (!sam_backends_param) {
+               DEBUG(1, ("no SAM backeds specified!\n"));
+               return NT_STATUS_INVALID_PARAMETER;
+       }
 
-       if (!NT_STATUS_IS_OK(nt_status = samr_make_sam_obj_sd(context->mem_ctx, &sd, &sd_size))) {
-               DEBUG(4,("samr_make_sam_obj_sd failed\n"));
+       if (!NT_STATUS_IS_OK(nt_status = make_sam_context(context))) {
+               DEBUG(4,("make_sam_context failed\n"));
                return nt_status;
        }
 
-       if (!se_access_check(sd, access_token, SAMR_ACCESS_ENUM_DOMAINS, &acc_granted, &nt_status)) {
-               DEBUG(3,("context_sam_enum_domains: ACCESS DENIED\n"));
-                       return nt_status;
-       }
+       while (sam_backends_param[nBackends])
+               nBackends++;
 
-       tmp_methods= context->methods;
-       *domain_count = 0;
+       DEBUG(6,("There are %d domains listed with their backends\n", nBackends));
 
-       while (tmp_methods) {
-               (*domain_count)++;
-               tmp_methods= tmp_methods->next;
+       if ((backends = (SAM_BACKEND_ENTRY *)malloc(sizeof(*backends)*nBackends)) == NULL) {
+               DEBUG(0,("make_sam_context_list: failed to allocate backends\n"));
+               return NT_STATUS_NO_MEMORY;
        }
 
-       DEBUG(6,("context_sam_enum_domains: enumerating %d domains\n", (*domain_count)));
-
-       tmp_methods = context->methods;
+       memset(backends, '\0', sizeof(*backends)*nBackends);
 
-       if (((*domains) = malloc( sizeof(DOM_SID) * (*domain_count))) == NULL) {
-               DEBUG(0,("context_sam_enum_domains: Out of memory allocating domain SID list\n"));
-               return NT_STATUS_NO_MEMORY;
+       for (i = 0; i < nBackends; i++) {
+               DEBUG(8,("processing %s\n",sam_backends_param[i]));
+               if (!NT_STATUS_IS_OK(nt_status = make_backend_entry(&backends[i], sam_backends_param[i]))) {
+                       DEBUG(4,("make_backend_entry failed\n"));
+                       for (j = 0; j < nBackends; j++) SAFE_FREE(backends[j].domain_sid);
+                       SAFE_FREE(backends);
+                       free_sam_context(context);
+                       return nt_status;
+               }
        }
 
-       if (((*domain_names) = malloc( sizeof(char*) * (*domain_count))) == NULL) {
-               DEBUG(0,("context_sam_enum_domains: Out of memory allocating domain name list\n"));
-               SAFE_FREE((*domains));
-               return NT_STATUS_NO_MEMORY;
+       if (!NT_STATUS_IS_OK(nt_status = check_duplicate_backend_entries(&backends, &nBackends))) {
+               DEBUG(4,("check_duplicate_backend_entries failed\n"));
+               for (j = 0; j < nBackends; j++) SAFE_FREE(backends[j].domain_sid);
+               SAFE_FREE(backends);
+               free_sam_context(context);
+               return nt_status;
        }
 
-       while (tmp_methods) {
-               DEBUGADD(7,("    [%d] %s: %s\n", i, tmp_methods->domain_name, sid_string_static(&tmp_methods->domain_sid)));
-               sid_copy(domains[i],&tmp_methods->domain_sid);
-               *domain_names[i] = smb_xstrdup(tmp_methods->domain_name);
-               i++;
-               tmp_methods= tmp_methods->next;
+       for (i = 0; i < nBackends; i++) {
+               if (!NT_STATUS_IS_OK(nt_status = make_sam_methods_backend_entry(*context, &curmethods,  &backends[i]))) {
+                       DEBUG(4,("make_sam_methods_backend_entry failed\n"));
+                       for (j = 0; j < nBackends; j++) SAFE_FREE(backends[j].domain_sid);
+                       SAFE_FREE(backends);
+                       free_sam_context(context);
+                       return nt_status;
+               }
+               DLIST_ADD_END((*context)->methods, curmethods, tmpmethods);
        }
+       
+       for (i = 0; i < nBackends; i++) SAFE_FREE(backends[i].domain_sid);
 
+       SAFE_FREE(backends);
        return NT_STATUS_OK;
 }
 
-NTSTATUS context_sam_lookup_domain(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, const char *domain, DOM_SID **domainsid)
-{
-       SAM_METHODS     *tmp_methods;
-       NTSTATUS        nt_status;
+/******************************************************************
+  Make a sam_context from scratch.
+ *******************************************************************/
 
-       SEC_DESC        *sd;
-       size_t          sd_size;
-       uint32          acc_granted;
+NTSTATUS make_sam_context(SAM_CONTEXT **context) 
+{
+       TALLOC_CTX *mem_ctx;
 
-       DEBUG(5,("context_sam_lookup_domain: %d\n", __LINE__));
+       mem_ctx = talloc_init_named("sam_context internal allocation context");
 
-       /* invalid sam_context specified */
-       SAM_ASSERT(context && context->methods);
+       if (!mem_ctx) {
+               DEBUG(0, ("make_sam_context: talloc init failed!\n"));
+               return NT_STATUS_NO_MEMORY;
+       }               
 
-       if (!NT_STATUS_IS_OK(nt_status = samr_make_sam_obj_sd(context->mem_ctx, &sd, &sd_size))) {
-               DEBUG(4,("samr_make_sam_obj_sd failed\n"));
-               return nt_status;
+       *context = talloc(mem_ctx, sizeof(**context));
+       if (!*context) {
+               DEBUG(0, ("make_sam_context: talloc failed!\n"));
+               return NT_STATUS_NO_MEMORY;
        }
 
-       if (!se_access_check(sd, access_token, SAMR_ACCESS_OPEN_DOMAIN, &acc_granted, &nt_status)) {
-               DEBUG(3,("context_sam_lookup_domain: ACCESS DENIED\n"));
-                       return nt_status;
+       ZERO_STRUCTP(*context);
+
+       (*context)->mem_ctx = mem_ctx;
+
+       (*context)->free_fn = free_sam_context;
+
+       return NT_STATUS_OK;
+}
+
+/******************************************************************
+  Return an already initialised sam_context, to facilitate backward 
+  compatibility (see functions below).
+ *******************************************************************/
+
+static struct sam_context *sam_get_static_context(BOOL reload) 
+{
+       static SAM_CONTEXT *sam_context = NULL;
+
+       if ((sam_context) && (reload)) {
+               sam_context->free_fn(&sam_context);
+               sam_context = NULL;
        }
 
-       tmp_methods= context->methods;
+       if (!sam_context) {
+               if (!NT_STATUS_IS_OK(make_sam_context_list(&sam_context, lp_sam_backend()))) {
+                       DEBUG(4,("make_sam_context_list failed\n"));
+                       return NULL;
+               }
 
-       while (tmp_methods) {
-               if (strcmp(domain, tmp_methods->domain_name) == 0) {
-                       (*domainsid) = (DOM_SID *)malloc(sizeof(DOM_SID));
-                       sid_copy((*domainsid), &tmp_methods->domain_sid);
-                       return NT_STATUS_OK;
+               /* Make sure the required domains (default domain, builtin) are available */
+               if (!NT_STATUS_IS_OK(sam_context_check_default_backends(sam_context))) {
+                       DEBUG(4,("sam_context_check_default_backends failed\n"));
+                       return NULL;
                }
-               tmp_methods= tmp_methods->next;
        }
 
-       return NT_STATUS_NO_SUCH_DOMAIN;
+       return sam_context;
+}
+
+/***************************************************************
+  Initialize the static context (at smbd startup etc). 
+
+  If uninitialised, context will auto-init on first use.
+ ***************************************************************/
+
+BOOL initialize_sam(BOOL reload)
+{      
+       return (sam_get_static_context(reload) != NULL);
 }
 
 
-NTSTATUS context_sam_get_domain_by_sid(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, uint32 access_desired, const DOM_SID *domainsid, SAM_DOMAIN_HANDLE **domain)
+/**************************************************************
+ External API.  This is what the rest of the world calls...
+***************************************************************/
+
+/******************************************************************
+  sam_* functions are used to link the external SAM interface
+  with the internal backends. These functions lookup the appropriate
+  backends for the domain and pass on to the function in sam_methods
+  in the selected backend
+
+  When the context parmater is NULL, the default is used.
+ *******************************************************************/
+
+#define SAM_SETUP_CONTEXT if (!context) \
+               context = sam_get_static_context(False);\
+       if (!context) {\
+               return NT_STATUS_UNSUCCESSFUL; \
+       }\
+       
+
+
+NTSTATUS sam_get_sec_desc(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, const DOM_SID *sid, SEC_DESC **sd)
 {
        SAM_METHODS     *tmp_methods;
-       NTSTATUS        nt_status;
+       NTSTATUS        nt_status;
 
-       DEBUG(5,("context_sam_get_domain_by_sid: %d\n", __LINE__));
+       DEBUG(5,("sam_get_sec_desc: %d\n", __LINE__));
 
-       if (!NT_STATUS_IS_OK(nt_status = sam_get_methods_by_sid(context, &tmp_methods, domainsid))) {
+       SAM_SETUP_CONTEXT;
+
+       if (!NT_STATUS_IS_OK(nt_status = sam_get_methods_by_sid(context, &tmp_methods, sid))) {
                DEBUG(4,("sam_get_methods_by_sid failed\n"));
                return nt_status;
        }
 
-       if (!tmp_methods->sam_get_domain_handle) {
-               DEBUG(3, ("context_sam_get_domain_by_sid: sam_methods of the domain did not specify sam_get_domain_handle\n"));
+       if (!tmp_methods->sam_get_sec_desc) {
+               DEBUG(3, ("sam_get_sec_desc: sam_methods of the domain did not specify sam_get_sec_desc\n"));
                return NT_STATUS_NOT_IMPLEMENTED;
        }
 
-       if (!NT_STATUS_IS_OK(nt_status = tmp_methods->sam_get_domain_handle(tmp_methods, access_token, access_desired, domain))) {
-               DEBUG(4,("sam_get_domain_handle for %s in backend %s failed\n",
-                                sid_string_static(domainsid), tmp_methods->backendname));
+       if (!NT_STATUS_IS_OK(nt_status = tmp_methods->sam_get_sec_desc(tmp_methods, access_token, sid, sd))) {
+               DEBUG(4,("sam_get_sec_desc for %s in backend %s failed\n", sid_string_static(sid), tmp_methods->backendname));
                return nt_status;
        }
 
        return NT_STATUS_OK;
 }
 
-NTSTATUS context_sam_create_account(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, uint32 access_desired, const DOM_SID *domainsid, const char *account_name, uint16 acct_ctrl, SAM_ACCOUNT_HANDLE **account)
+NTSTATUS sam_set_sec_desc(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, const DOM_SID *sid, const SEC_DESC *sd)
 {
        SAM_METHODS     *tmp_methods;
        NTSTATUS        nt_status;
 
-       DEBUG(5,("context_sam_create_account: %d\n", __LINE__));
+       DEBUG(5,("sam_set_sec_desc: %d\n", __LINE__));
+       
+       SAM_SETUP_CONTEXT;
 
-       if (!NT_STATUS_IS_OK(nt_status = sam_get_methods_by_sid(context, &tmp_methods, domainsid))) {
+       if (!NT_STATUS_IS_OK(nt_status = sam_get_methods_by_sid(context, &tmp_methods, sid))) {
                DEBUG(4,("sam_get_methods_by_sid failed\n"));
                return nt_status;
        }
 
-       if (!tmp_methods->sam_create_account) {
-               DEBUG(3, ("context_sam_create_account: sam_methods of the domain did not specify sam_create_account\n"));
+       if (!tmp_methods->sam_set_sec_desc) {
+               DEBUG(3, ("sam_set_sec_desc: sam_methods of the domain did not specify sam_set_sec_desc\n"));
                return NT_STATUS_NOT_IMPLEMENTED;
        }
 
-       if (!NT_STATUS_IS_OK(nt_status = tmp_methods->sam_create_account(tmp_methods, access_token, access_desired, account_name, acct_ctrl, account))) {
-               DEBUG(4,("sam_create_account in backend %s failed\n",
-                                tmp_methods->backendname));
+       if (!NT_STATUS_IS_OK(nt_status = tmp_methods->sam_set_sec_desc(tmp_methods, access_token, sid, sd))) {
+               DEBUG(4,("sam_set_sec_desc for %s in backend %s failed\n", sid_string_static(sid), tmp_methods->backendname));
                return nt_status;
        }
 
        return NT_STATUS_OK;
 }
 
-NTSTATUS context_sam_add_account(const SAM_CONTEXT *context, const SAM_ACCOUNT_HANDLE *account)
+
+NTSTATUS sam_lookup_name(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, const char *domain, const char *name, DOM_SID *sid, uint32 *type)
 {
-       DOM_SID         domainsid;
-       const DOM_SID           *accountsid;
        SAM_METHODS     *tmp_methods;
-       uint32          rid;
        NTSTATUS        nt_status;
-       
-       DEBUG(5,("context_sam_add_account: %d\n", __LINE__));
 
-       if (!NT_STATUS_IS_OK(nt_status = sam_get_account_sid(account, &accountsid))) {
-               DEBUG(0,("Can't get account SID\n"));
-               return nt_status;
-       }
+       DEBUG(5,("sam_lookup_name: %d\n", __LINE__));
 
-       sid_copy(&domainsid, accountsid);
-       if (!sid_split_rid(&domainsid, &rid)) {
-               DEBUG(3,("context_sam_get_account_by_sid: failed to split the sid\n"));
-               return NT_STATUS_INVALID_SID;
-       }
+       SAM_SETUP_CONTEXT;
 
-       if (!NT_STATUS_IS_OK(nt_status = sam_get_methods_by_sid(context, &tmp_methods, &domainsid))) {
-               DEBUG(4,("sam_get_methods_by_sid failed\n"));
+       if (!NT_STATUS_IS_OK(nt_status = sam_get_methods_by_name(context, &tmp_methods, domain))) {
+               DEBUG(4,("sam_get_methods_by_name failed\n"));
                return nt_status;
        }
 
-       if (!tmp_methods->sam_add_account) {
-               DEBUG(3, ("context_sam_add_account: sam_methods of the domain did not specify sam_add_account\n"));
+       if (!tmp_methods->sam_lookup_name) {
+               DEBUG(3, ("sam_lookup_name: sam_methods of the domain did not specify sam_lookup_name\n"));
                return NT_STATUS_NOT_IMPLEMENTED;
        }
 
-       if (!NT_STATUS_IS_OK(nt_status = tmp_methods->sam_add_account(tmp_methods, account))){
-               DEBUG(4,("sam_add_account in backend %s failed\n",
-                                tmp_methods->backendname));
+       if (!NT_STATUS_IS_OK(nt_status = tmp_methods->sam_lookup_name(tmp_methods, access_token, name, sid, type))) {
+               DEBUG(4,("sam_lookup_name for %s\\%s in backend %s failed\n",
+                                tmp_methods->domain_name, name, tmp_methods->backendname));
                return nt_status;
        }
 
        return NT_STATUS_OK;
 }
 
-NTSTATUS context_sam_update_account(const SAM_CONTEXT *context, const SAM_ACCOUNT_HANDLE *account)
+NTSTATUS sam_lookup_sid(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, TALLOC_CTX *mem_ctx, const DOM_SID *sid, char **name, uint32 *type)
 {
-       const SAM_METHODS *tmp_methods;
-       NTSTATUS     nt_status;
-       
-       DEBUG(5,("context_sam_update_account: %d\n", __LINE__));
-       
-       /* invalid account specified */
-       SAM_ASSERT(account && account->current_sam_methods);
-       
-       tmp_methods = account->current_sam_methods;
-               
-       if (!tmp_methods->sam_update_account) {
-               DEBUG(3, ("context_sam_update_account: sam_methods of the domain did not specify sam_update_account\n"));
+       SAM_METHODS     *tmp_methods;
+       uint32          rid;
+       NTSTATUS        nt_status;
+       DOM_SID         domainsid;
+
+       DEBUG(5,("sam_lookup_sid: %d\n", __LINE__));
+
+       SAM_SETUP_CONTEXT;
+
+       sid_copy(&domainsid, sid);
+       if (!sid_split_rid(&domainsid, &rid)) {
+               DEBUG(3,("sam_lookup_sid: failed to split the sid\n"));
+               return NT_STATUS_INVALID_SID;
+       }
+
+       if (!NT_STATUS_IS_OK(nt_status = sam_get_methods_by_sid(context, &tmp_methods, &domainsid))) {
+               DEBUG(4,("sam_get_methods_by_sid failed\n"));
+               return nt_status;
+       }
+
+       if (!tmp_methods->sam_lookup_sid) {
+               DEBUG(3, ("sam_lookup_sid: sam_methods of the domain did not specify sam_lookup_sid\n"));
                return NT_STATUS_NOT_IMPLEMENTED;
        }
 
-       if (!NT_STATUS_IS_OK(nt_status = tmp_methods->sam_update_account(tmp_methods, account))){
-               DEBUG(4,("sam_update_account in backend %s failed\n",
-                                tmp_methods->backendname));
+       if (!NT_STATUS_IS_OK(nt_status = tmp_methods->sam_lookup_sid(tmp_methods, access_token, mem_ctx, sid, name, type))) {
+               DEBUG(4,("sam_lookup_name for %s in backend %s failed\n",
+                                sid_string_static(sid), tmp_methods->backendname));
                return nt_status;
        }
 
        return NT_STATUS_OK;
 }
 
-NTSTATUS context_sam_delete_account(const SAM_CONTEXT *context, const SAM_ACCOUNT_HANDLE *account)
+
+NTSTATUS sam_update_domain(const SAM_CONTEXT *context, const SAM_DOMAIN_HANDLE *domain)
 {
        const SAM_METHODS *tmp_methods;
        NTSTATUS     nt_status;
+
+       DEBUG(5,("sam_update_domain: %d\n", __LINE__));
        
-       DEBUG(5,("context_sam_delete_account: %d\n", __LINE__));
+       SAM_SETUP_CONTEXT;
+
+       /* invalid domain specified */
+       SAM_ASSERT(domain && domain->current_sam_methods);
        
-       /* invalid account specified */
-       SAM_ASSERT(account && account->current_sam_methods);
+       tmp_methods = domain->current_sam_methods;
        
-       tmp_methods = account->current_sam_methods;
-
-       if (!tmp_methods->sam_delete_account) {
-               DEBUG(3, ("context_sam_delete_account: sam_methods of the domain did not specify sam_delete_account\n"));
+       if (!tmp_methods->sam_update_domain) {
+               DEBUG(3, ("sam_update_domain: sam_methods of the domain did not specify sam_update_domain\n"));
                return NT_STATUS_NOT_IMPLEMENTED;
        }
 
-       if (!NT_STATUS_IS_OK(nt_status = tmp_methods->sam_delete_account(tmp_methods, account))){
-               DEBUG(4,("sam_delete_account in backend %s failed\n",
+       if (!NT_STATUS_IS_OK(nt_status = tmp_methods->sam_update_domain(tmp_methods, domain))){
+               DEBUG(4,("sam_update_domain in backend %s failed\n",
                                 tmp_methods->backendname));
                return nt_status;
        }
@@ -476,20 +617,288 @@ NTSTATUS context_sam_delete_account(const SAM_CONTEXT *context, const SAM_ACCOUN
        return NT_STATUS_OK;
 }
 
-NTSTATUS context_sam_enum_accounts(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, const DOM_SID *domainsid, uint16 acct_ctrl, int32 *account_count, SAM_ACCOUNT_ENUM **accounts)
+NTSTATUS sam_enum_domains(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, int32 *domain_count, DOM_SID **domains, char ***domain_names)
 {
        SAM_METHODS     *tmp_methods;
-       NTSTATUS        nt_status;
-
-       DEBUG(5,("context_sam_enum_accounts: %d\n", __LINE__));
+       NTSTATUS         nt_status;
 
-       if (!NT_STATUS_IS_OK(nt_status = sam_get_methods_by_sid(context, &tmp_methods, domainsid))) {
-               DEBUG(4,("sam_get_methods_by_sid failed\n"));
+       SEC_DESC        *sd;
+       size_t          sd_size;
+       uint32          acc_granted;
+       int             i = 0;
+
+       DEBUG(5,("sam_enum_domains: %d\n", __LINE__));
+
+       SAM_SETUP_CONTEXT;
+
+       /* invalid parmaters specified */
+       SAM_ASSERT(domain_count && domains && domain_names);
+
+       if (!NT_STATUS_IS_OK(nt_status = samr_make_sam_obj_sd(context->mem_ctx, &sd, &sd_size))) {
+               DEBUG(4,("samr_make_sam_obj_sd failed\n"));
+               return nt_status;
+       }
+
+       if (!se_access_check(sd, access_token, SAMR_ACCESS_ENUM_DOMAINS, &acc_granted, &nt_status)) {
+               DEBUG(3,("sam_enum_domains: ACCESS DENIED\n"));
+                       return nt_status;
+       }
+
+       tmp_methods= context->methods;
+       *domain_count = 0;
+
+       while (tmp_methods) {
+               (*domain_count)++;
+               tmp_methods= tmp_methods->next;
+       }
+
+       DEBUG(6,("sam_enum_domains: enumerating %d domains\n", (*domain_count)));
+
+       tmp_methods = context->methods;
+
+       if (((*domains) = malloc( sizeof(DOM_SID) * (*domain_count))) == NULL) {
+               DEBUG(0,("sam_enum_domains: Out of memory allocating domain SID list\n"));
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       if (((*domain_names) = malloc( sizeof(char*) * (*domain_count))) == NULL) {
+               DEBUG(0,("sam_enum_domains: Out of memory allocating domain name list\n"));
+               SAFE_FREE((*domains));
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       while (tmp_methods) {
+               DEBUGADD(7,("    [%d] %s: %s\n", i, tmp_methods->domain_name, sid_string_static(&tmp_methods->domain_sid)));
+               sid_copy(domains[i],&tmp_methods->domain_sid);
+               *domain_names[i] = smb_xstrdup(tmp_methods->domain_name);
+               i++;
+               tmp_methods= tmp_methods->next;
+       }
+
+       return NT_STATUS_OK;
+}
+
+NTSTATUS sam_lookup_domain(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, const char *domain, DOM_SID **domainsid)
+{
+       SAM_METHODS     *tmp_methods;
+       NTSTATUS        nt_status;
+
+       SEC_DESC        *sd;
+       size_t          sd_size;
+       uint32          acc_granted;
+
+       DEBUG(5,("sam_lookup_domain: %d\n", __LINE__));
+
+       SAM_SETUP_CONTEXT;
+
+       /* invalid paramters */
+       SAM_ASSERT(access_token && domain && domainsid);
+
+       if (!NT_STATUS_IS_OK(nt_status = samr_make_sam_obj_sd(context->mem_ctx, &sd, &sd_size))) {
+               DEBUG(4,("samr_make_sam_obj_sd failed\n"));
+               return nt_status;
+       }
+
+       if (!se_access_check(sd, access_token, SAMR_ACCESS_OPEN_DOMAIN, &acc_granted, &nt_status)) {
+               DEBUG(3,("sam_lookup_domain: ACCESS DENIED\n"));
+                       return nt_status;
+       }
+
+       tmp_methods= context->methods;
+
+       while (tmp_methods) {
+               if (strcmp(domain, tmp_methods->domain_name) == 0) {
+                       (*domainsid) = (DOM_SID *)malloc(sizeof(DOM_SID));
+                       sid_copy((*domainsid), &tmp_methods->domain_sid);
+                       return NT_STATUS_OK;
+               }
+               tmp_methods= tmp_methods->next;
+       }
+
+       return NT_STATUS_NO_SUCH_DOMAIN;
+}
+
+
+NTSTATUS sam_get_domain_by_sid(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, uint32 access_desired, const DOM_SID *domainsid, SAM_DOMAIN_HANDLE **domain)
+{
+       SAM_METHODS     *tmp_methods;
+       NTSTATUS        nt_status;
+
+       DEBUG(5,("sam_get_domain_by_sid: %d\n", __LINE__));
+
+       SAM_SETUP_CONTEXT;
+
+       SAM_ASSERT(access_token && domainsid && domain);
+
+       if (!NT_STATUS_IS_OK(nt_status = sam_get_methods_by_sid(context, &tmp_methods, domainsid))) {
+               DEBUG(4,("sam_get_methods_by_sid failed\n"));
+               return nt_status;
+       }
+
+       if (!tmp_methods->sam_get_domain_handle) {
+               DEBUG(3, ("sam_get_domain_by_sid: sam_methods of the domain did not specify sam_get_domain_handle\n"));
+               return NT_STATUS_NOT_IMPLEMENTED;
+       }
+
+       if (!NT_STATUS_IS_OK(nt_status = tmp_methods->sam_get_domain_handle(tmp_methods, access_token, access_desired, domain))) {
+               DEBUG(4,("sam_get_domain_handle for %s in backend %s failed\n",
+                                sid_string_static(domainsid), tmp_methods->backendname));
+               return nt_status;
+       }
+
+       return NT_STATUS_OK;
+}
+
+NTSTATUS sam_create_account(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, uint32 access_desired, const DOM_SID *domainsid, const char *account_name, uint16 acct_ctrl, SAM_ACCOUNT_HANDLE **account)
+{
+       SAM_METHODS     *tmp_methods;
+       NTSTATUS        nt_status;
+
+       DEBUG(5,("sam_create_account: %d\n", __LINE__));
+
+       SAM_SETUP_CONTEXT;
+
+       /* invalid parmaters */
+       SAM_ASSERT(access_token && domainsid && account_name && account);
+
+       if (!NT_STATUS_IS_OK(nt_status = sam_get_methods_by_sid(context, &tmp_methods, domainsid))) {
+               DEBUG(4,("sam_get_methods_by_sid failed\n"));
+               return nt_status;
+       }
+
+       if (!tmp_methods->sam_create_account) {
+               DEBUG(3, ("sam_create_account: sam_methods of the domain did not specify sam_create_account\n"));
+               return NT_STATUS_NOT_IMPLEMENTED;
+       }
+
+       if (!NT_STATUS_IS_OK(nt_status = tmp_methods->sam_create_account(tmp_methods, access_token, access_desired, account_name, acct_ctrl, account))) {
+               DEBUG(4,("sam_create_account in backend %s failed\n",
+                                tmp_methods->backendname));
+               return nt_status;
+       }
+
+       return NT_STATUS_OK;
+}
+
+NTSTATUS sam_add_account(const SAM_CONTEXT *context, const SAM_ACCOUNT_HANDLE *account)
+{
+       DOM_SID         domainsid;
+       const DOM_SID           *accountsid;
+       SAM_METHODS     *tmp_methods;
+       uint32          rid;
+       NTSTATUS        nt_status;
+       
+       DEBUG(5,("sam_add_account: %d\n", __LINE__));
+
+       SAM_SETUP_CONTEXT;
+
+       /* invalid parmaters */
+       SAM_ASSERT(account);
+
+       if (!NT_STATUS_IS_OK(nt_status = sam_get_account_sid(account, &accountsid))) {
+               DEBUG(0,("Can't get account SID\n"));
+               return nt_status;
+       }
+
+       sid_copy(&domainsid, accountsid);
+       if (!sid_split_rid(&domainsid, &rid)) {
+               DEBUG(3,("sam_get_account_by_sid: failed to split the sid\n"));
+               return NT_STATUS_INVALID_SID;
+       }
+
+       if (!NT_STATUS_IS_OK(nt_status = sam_get_methods_by_sid(context, &tmp_methods, &domainsid))) {
+               DEBUG(4,("sam_get_methods_by_sid failed\n"));
+               return nt_status;
+       }
+
+       if (!tmp_methods->sam_add_account) {
+               DEBUG(3, ("sam_add_account: sam_methods of the domain did not specify sam_add_account\n"));
+               return NT_STATUS_NOT_IMPLEMENTED;
+       }
+
+       if (!NT_STATUS_IS_OK(nt_status = tmp_methods->sam_add_account(tmp_methods, account))){
+               DEBUG(4,("sam_add_account in backend %s failed\n",
+                                tmp_methods->backendname));
+               return nt_status;
+       }
+
+       return NT_STATUS_OK;
+}
+
+NTSTATUS sam_update_account(const SAM_CONTEXT *context, const SAM_ACCOUNT_HANDLE *account)
+{
+       const SAM_METHODS *tmp_methods;
+       NTSTATUS     nt_status;
+       
+       DEBUG(5,("sam_update_account: %d\n", __LINE__));
+
+       SAM_SETUP_CONTEXT;
+
+       /* invalid account specified */
+       SAM_ASSERT(account && account->current_sam_methods);
+       
+       tmp_methods = account->current_sam_methods;
+               
+       if (!tmp_methods->sam_update_account) {
+               DEBUG(3, ("sam_update_account: sam_methods of the domain did not specify sam_update_account\n"));
+               return NT_STATUS_NOT_IMPLEMENTED;
+       }
+
+       if (!NT_STATUS_IS_OK(nt_status = tmp_methods->sam_update_account(tmp_methods, account))){
+               DEBUG(4,("sam_update_account in backend %s failed\n",
+                                tmp_methods->backendname));
+               return nt_status;
+       }
+
+       return NT_STATUS_OK;
+}
+
+NTSTATUS sam_delete_account(const SAM_CONTEXT *context, const SAM_ACCOUNT_HANDLE *account)
+{
+       const SAM_METHODS *tmp_methods;
+       NTSTATUS     nt_status;
+       
+       DEBUG(5,("sam_delete_account: %d\n", __LINE__));
+       
+       SAM_SETUP_CONTEXT;
+
+       /* invalid account specified */
+       SAM_ASSERT(account && account->current_sam_methods);
+       
+       tmp_methods = account->current_sam_methods;
+
+       if (!tmp_methods->sam_delete_account) {
+               DEBUG(3, ("sam_delete_account: sam_methods of the domain did not specify sam_delete_account\n"));
+               return NT_STATUS_NOT_IMPLEMENTED;
+       }
+
+       if (!NT_STATUS_IS_OK(nt_status = tmp_methods->sam_delete_account(tmp_methods, account))){
+               DEBUG(4,("sam_delete_account in backend %s failed\n",
+                                tmp_methods->backendname));
+               return nt_status;
+       }
+
+       return NT_STATUS_OK;
+}
+
+NTSTATUS sam_enum_accounts(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, const DOM_SID *domainsid, uint16 acct_ctrl, int32 *account_count, SAM_ACCOUNT_ENUM **accounts)
+{
+       SAM_METHODS     *tmp_methods;
+       NTSTATUS        nt_status;
+
+       DEBUG(5,("sam_enum_accounts: %d\n", __LINE__));
+
+       SAM_SETUP_CONTEXT;
+
+       SAM_ASSERT(access_token && domainsid && account_count && accounts);
+
+       if (!NT_STATUS_IS_OK(nt_status = sam_get_methods_by_sid(context, &tmp_methods, domainsid))) {
+               DEBUG(4,("sam_get_methods_by_sid failed\n"));
                return nt_status;
        }
 
        if (!tmp_methods->sam_enum_accounts) {
-               DEBUG(3, ("context_sam_enum_accounts: sam_methods of the domain did not specify sam_enum_accounts\n"));
+               DEBUG(3, ("sam_enum_accounts: sam_methods of the domain did not specify sam_enum_accounts\n"));
                return NT_STATUS_NOT_IMPLEMENTED;
        }
 
@@ -503,18 +912,22 @@ NTSTATUS context_sam_enum_accounts(const SAM_CONTEXT *context, const NT_USER_TOK
 }
 
 
-NTSTATUS context_sam_get_account_by_sid(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, uint32 access_desired, const DOM_SID *accountsid, SAM_ACCOUNT_HANDLE **account)
+NTSTATUS sam_get_account_by_sid(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, uint32 access_desired, const DOM_SID *accountsid, SAM_ACCOUNT_HANDLE **account)
 {
        SAM_METHODS     *tmp_methods;
        uint32          rid;
        DOM_SID         domainsid;
        NTSTATUS        nt_status;
 
-       DEBUG(5,("context_sam_get_account_by_sid: %d\n", __LINE__));
+       DEBUG(5,("sam_get_account_by_sid: %d\n", __LINE__));
+
+       SAM_SETUP_CONTEXT;
+
+       SAM_ASSERT(access_token && accountsid && account);
 
        sid_copy(&domainsid, accountsid);
        if (!sid_split_rid(&domainsid, &rid)) {
-               DEBUG(3,("context_sam_get_account_by_sid: failed to split the sid\n"));
+               DEBUG(3,("sam_get_account_by_sid: failed to split the sid\n"));
                return NT_STATUS_INVALID_SID;
        }
 
@@ -525,7 +938,7 @@ NTSTATUS context_sam_get_account_by_sid(const SAM_CONTEXT *context, const NT_USE
        }
 
        if (!tmp_methods->sam_get_account_by_sid) {
-               DEBUG(3, ("context_sam_get_account_by_sid: sam_methods of the domain did not specify sam_get_account_by_sid\n"));
+               DEBUG(3, ("sam_get_account_by_sid: sam_methods of the domain did not specify sam_get_account_by_sid\n"));
                return NT_STATUS_NOT_IMPLEMENTED;
        }
 
@@ -538,12 +951,16 @@ NTSTATUS context_sam_get_account_by_sid(const SAM_CONTEXT *context, const NT_USE
        return NT_STATUS_OK;
 }
 
-NTSTATUS context_sam_get_account_by_name(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, uint32 access_desired, const char *domain, const char *name, SAM_ACCOUNT_HANDLE **account)
+NTSTATUS sam_get_account_by_name(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, uint32 access_desired, const char *domain, const char *name, SAM_ACCOUNT_HANDLE **account)
 {
        SAM_METHODS     *tmp_methods;
        NTSTATUS        nt_status;
 
-       DEBUG(5,("context_sam_get_account_by_name: %d\n", __LINE__));
+       DEBUG(5,("sam_get_account_by_name: %d\n", __LINE__));
+
+       SAM_SETUP_CONTEXT;
+
+       SAM_ASSERT(access_token && domain && name && account);
 
        if (!NT_STATUS_IS_OK(nt_status = sam_get_methods_by_name(context, &tmp_methods, domain))) {
                DEBUG(4,("sam_get_methods_by_name failed\n"));
@@ -551,7 +968,7 @@ NTSTATUS context_sam_get_account_by_name(const SAM_CONTEXT *context, const NT_US
        }
 
        if (!tmp_methods->sam_get_account_by_name) {
-               DEBUG(3, ("context_sam_get_account_by_name: sam_methods of the domain did not specify sam_get_account_by_name\n"));
+               DEBUG(3, ("sam_get_account_by_name: sam_methods of the domain did not specify sam_get_account_by_name\n"));
                return NT_STATUS_NOT_IMPLEMENTED;
        }
 
@@ -564,12 +981,16 @@ NTSTATUS context_sam_get_account_by_name(const SAM_CONTEXT *context, const NT_US
        return NT_STATUS_OK;
 }
 
-NTSTATUS context_sam_create_group(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, uint32 access_desired, const DOM_SID *domainsid, const char *group_name, uint16 group_ctrl, SAM_GROUP_HANDLE **group)
+NTSTATUS sam_create_group(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, uint32 access_desired, const DOM_SID *domainsid, const char *group_name, uint16 group_ctrl, SAM_GROUP_HANDLE **group)
 {
        SAM_METHODS     *tmp_methods;
        NTSTATUS        nt_status;
 
-       DEBUG(5,("context_sam_create_group: %d\n", __LINE__));
+       DEBUG(5,("sam_create_group: %d\n", __LINE__));
+
+       SAM_SETUP_CONTEXT;
+
+       SAM_ASSERT(access_token && domainsid && group_name && group);
 
        if (!NT_STATUS_IS_OK(nt_status = sam_get_methods_by_sid(context, &tmp_methods, domainsid))) {
                DEBUG(4,("sam_get_methods_by_sid failed\n"));
@@ -577,7 +998,7 @@ NTSTATUS context_sam_create_group(const SAM_CONTEXT *context, const NT_USER_TOKE
        }
 
        if (!tmp_methods->sam_create_group) {
-               DEBUG(3, ("context_sam_create_group: sam_methods of the domain did not specify sam_create_group\n"));
+               DEBUG(3, ("sam_create_group: sam_methods of the domain did not specify sam_create_group\n"));
                return NT_STATUS_UNSUCCESSFUL; 
        }
 
@@ -590,7 +1011,7 @@ NTSTATUS context_sam_create_group(const SAM_CONTEXT *context, const NT_USER_TOKE
        return NT_STATUS_OK;
 }
 
-NTSTATUS context_sam_add_group(const SAM_CONTEXT *context, const SAM_GROUP_HANDLE *group)
+NTSTATUS sam_add_group(const SAM_CONTEXT *context, const SAM_GROUP_HANDLE *group)
 {
        DOM_SID         domainsid;
        const DOM_SID           *groupsid;
@@ -598,7 +1019,11 @@ NTSTATUS context_sam_add_group(const SAM_CONTEXT *context, const SAM_GROUP_HANDL
        uint32          rid;
        NTSTATUS        nt_status;
        
-       DEBUG(5,("context_sam_add_group: %d\n", __LINE__));
+       DEBUG(5,("sam_add_group: %d\n", __LINE__));
+
+       SAM_SETUP_CONTEXT;
+
+       SAM_ASSERT(group);
 
        if (!NT_STATUS_IS_OK(nt_status = sam_get_group_sid(group, &groupsid))) {
                DEBUG(0,("Can't get group SID\n"));
@@ -607,7 +1032,7 @@ NTSTATUS context_sam_add_group(const SAM_CONTEXT *context, const SAM_GROUP_HANDL
 
        sid_copy(&domainsid, groupsid);
        if (!sid_split_rid(&domainsid, &rid)) {
-               DEBUG(3,("context_sam_get_group_by_sid: failed to split the sid\n"));
+               DEBUG(3,("sam_get_group_by_sid: failed to split the sid\n"));
                return NT_STATUS_INVALID_SID;
        }
 
@@ -617,7 +1042,7 @@ NTSTATUS context_sam_add_group(const SAM_CONTEXT *context, const SAM_GROUP_HANDL
        }
 
        if (!tmp_methods->sam_add_group) {
-               DEBUG(3, ("context_sam_add_group: sam_methods of the domain did not specify sam_add_group\n"));
+               DEBUG(3, ("sam_add_group: sam_methods of the domain did not specify sam_add_group\n"));
                return NT_STATUS_NOT_IMPLEMENTED;
        }
 
@@ -630,20 +1055,22 @@ NTSTATUS context_sam_add_group(const SAM_CONTEXT *context, const SAM_GROUP_HANDL
        return NT_STATUS_OK;
 }
 
-NTSTATUS context_sam_update_group(const SAM_CONTEXT *context, const SAM_GROUP_HANDLE *group)
+NTSTATUS sam_update_group(const SAM_CONTEXT *context, const SAM_GROUP_HANDLE *group)
 {
        const SAM_METHODS *tmp_methods;
        NTSTATUS     nt_status;
        
-       DEBUG(5,("context_sam_update_group: %d\n", __LINE__));
+       DEBUG(5,("sam_update_group: %d\n", __LINE__));
        
+       SAM_SETUP_CONTEXT;
+
        /* invalid group specified */
        SAM_ASSERT(group && group->current_sam_methods);
        
        tmp_methods = group->current_sam_methods;
        
        if (!tmp_methods->sam_update_group) {
-               DEBUG(3, ("context_sam_update_group: sam_methods of the domain did not specify sam_update_group\n"));
+               DEBUG(3, ("sam_update_group: sam_methods of the domain did not specify sam_update_group\n"));
                return NT_STATUS_NOT_IMPLEMENTED;
        }
 
@@ -656,20 +1083,22 @@ NTSTATUS context_sam_update_group(const SAM_CONTEXT *context, const SAM_GROUP_HA
        return NT_STATUS_OK;
 }
 
-NTSTATUS context_sam_delete_group(const SAM_CONTEXT *context, const SAM_GROUP_HANDLE *group)
+NTSTATUS sam_delete_group(const SAM_CONTEXT *context, const SAM_GROUP_HANDLE *group)
 {
        const SAM_METHODS *tmp_methods;
        NTSTATUS     nt_status;
        
-       DEBUG(5,("context_sam_delete_group: %d\n", __LINE__));
+       DEBUG(5,("sam_delete_group: %d\n", __LINE__));
        
+       SAM_SETUP_CONTEXT;
+
        /* invalid group specified */
        SAM_ASSERT(group && group->current_sam_methods);
        
        tmp_methods = group->current_sam_methods;
 
        if (!tmp_methods->sam_delete_group) {
-               DEBUG(3, ("context_sam_delete_group: sam_methods of the domain did not specify sam_delete_group\n"));
+               DEBUG(3, ("sam_delete_group: sam_methods of the domain did not specify sam_delete_group\n"));
                return NT_STATUS_NOT_IMPLEMENTED;
        }
 
@@ -682,12 +1111,16 @@ NTSTATUS context_sam_delete_group(const SAM_CONTEXT *context, const SAM_GROUP_HA
        return NT_STATUS_OK;
 }
 
-NTSTATUS context_sam_enum_groups(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, const DOM_SID *domainsid, uint16 group_ctrl, uint32 *groups_count, SAM_GROUP_ENUM **groups)
+NTSTATUS sam_enum_groups(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, const DOM_SID *domainsid, uint16 group_ctrl, uint32 *groups_count, SAM_GROUP_ENUM **groups)
 {
        SAM_METHODS     *tmp_methods;
        NTSTATUS        nt_status;
 
-       DEBUG(5,("context_sam_enum_groups: %d\n", __LINE__));
+       DEBUG(5,("sam_enum_groups: %d\n", __LINE__));
+
+       SAM_SETUP_CONTEXT;
+
+       SAM_ASSERT(access_token && domainsid && groups_count && groups);
 
        if (!NT_STATUS_IS_OK(nt_status = sam_get_methods_by_sid(context, &tmp_methods, domainsid))) {
                DEBUG(4,("sam_get_methods_by_sid failed\n"));
@@ -695,7 +1128,7 @@ NTSTATUS context_sam_enum_groups(const SAM_CONTEXT *context, const NT_USER_TOKEN
        }
 
        if (!tmp_methods->sam_enum_accounts) {
-               DEBUG(3, ("context_sam_enum_groups: sam_methods of the domain did not specify sam_enum_groups\n"));
+               DEBUG(3, ("sam_enum_groups: sam_methods of the domain did not specify sam_enum_groups\n"));
                return NT_STATUS_NOT_IMPLEMENTED;
        }
 
@@ -708,18 +1141,22 @@ NTSTATUS context_sam_enum_groups(const SAM_CONTEXT *context, const NT_USER_TOKEN
        return NT_STATUS_OK;
 }
 
-NTSTATUS context_sam_get_group_by_sid(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, uint32 access_desired, const DOM_SID *groupsid, SAM_GROUP_HANDLE **group)
+NTSTATUS sam_get_group_by_sid(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, uint32 access_desired, const DOM_SID *groupsid, SAM_GROUP_HANDLE **group)
 {
        SAM_METHODS     *tmp_methods;
        uint32          rid;
        NTSTATUS        nt_status;
        DOM_SID         domainsid;
 
-       DEBUG(5,("context_sam_get_group_by_sid: %d\n", __LINE__));
+       DEBUG(5,("sam_get_group_by_sid: %d\n", __LINE__));
+
+       SAM_SETUP_CONTEXT;
+
+       SAM_ASSERT(access_token && groupsid && group);
 
        sid_copy(&domainsid, groupsid);
        if (!sid_split_rid(&domainsid, &rid)) {
-               DEBUG(3,("context_sam_get_group_by_sid: failed to split the sid\n"));
+               DEBUG(3,("sam_get_group_by_sid: failed to split the sid\n"));
                return NT_STATUS_INVALID_SID;
        }
 
@@ -730,7 +1167,7 @@ NTSTATUS context_sam_get_group_by_sid(const SAM_CONTEXT *context, const NT_USER_
        }
 
        if (!tmp_methods->sam_get_group_by_sid) {
-               DEBUG(3, ("context_sam_get_group_by_sid: sam_methods of the domain did not specify sam_get_group_by_sid\n"));
+               DEBUG(3, ("sam_get_group_by_sid: sam_methods of the domain did not specify sam_get_group_by_sid\n"));
                return NT_STATUS_NOT_IMPLEMENTED;
        }
 
@@ -743,12 +1180,16 @@ NTSTATUS context_sam_get_group_by_sid(const SAM_CONTEXT *context, const NT_USER_
        return NT_STATUS_OK;
 }
 
-NTSTATUS context_sam_get_group_by_name(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, uint32 access_desired, const char *domain, const char *name, SAM_GROUP_HANDLE **group)
+NTSTATUS sam_get_group_by_name(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, uint32 access_desired, const char *domain, const char *name, SAM_GROUP_HANDLE **group)
 {
        SAM_METHODS     *tmp_methods;
        NTSTATUS        nt_status;
 
-       DEBUG(5,("context_sam_get_group_by_name: %d\n", __LINE__));
+       DEBUG(5,("sam_get_group_by_name: %d\n", __LINE__));
+
+       SAM_SETUP_CONTEXT;
+
+       SAM_ASSERT(access_token && domain && name && group);
 
        if (!NT_STATUS_IS_OK(nt_status = sam_get_methods_by_name(context, &tmp_methods, domain))) {
                DEBUG(4,("sam_get_methods_by_name failed\n"));
@@ -756,7 +1197,7 @@ NTSTATUS context_sam_get_group_by_name(const SAM_CONTEXT *context, const NT_USER
        }
 
        if (!tmp_methods->sam_get_group_by_name) {
-               DEBUG(3, ("context_sam_get_group_by_name: sam_methods of the domain did not specify sam_get_group_by_name\n"));
+               DEBUG(3, ("sam_get_group_by_name: sam_methods of the domain did not specify sam_get_group_by_name\n"));
                return NT_STATUS_NOT_IMPLEMENTED;
        }
 
@@ -769,11 +1210,12 @@ NTSTATUS context_sam_get_group_by_name(const SAM_CONTEXT *context, const NT_USER
        return NT_STATUS_OK;
 }
 
-NTSTATUS context_sam_add_member_to_group(const SAM_CONTEXT *context, const SAM_GROUP_HANDLE *group, const SAM_GROUP_MEMBER *member)
+NTSTATUS sam_add_member_to_group(const SAM_CONTEXT *context, const SAM_GROUP_HANDLE *group, const SAM_GROUP_MEMBER *member)
 {
        const SAM_METHODS *tmp_methods;
        NTSTATUS     nt_status;
        
+       SAM_SETUP_CONTEXT;
        
        /* invalid group or member specified */
        SAM_ASSERT(group && group->current_sam_methods && member);
@@ -781,7 +1223,7 @@ NTSTATUS context_sam_add_member_to_group(const SAM_CONTEXT *context, const SAM_G
        tmp_methods = group->current_sam_methods;
                        
        if (!tmp_methods->sam_add_member_to_group) {
-               DEBUG(3, ("context_sam_add_member_to_group: sam_methods of the domain did not specify sam_add_member_to_group\n"));
+               DEBUG(3, ("sam_add_member_to_group: sam_methods of the domain did not specify sam_add_member_to_group\n"));
                return NT_STATUS_NOT_IMPLEMENTED;
        }
        
@@ -794,18 +1236,20 @@ NTSTATUS context_sam_add_member_to_group(const SAM_CONTEXT *context, const SAM_G
        
 }
 
-NTSTATUS context_sam_delete_member_from_group(const SAM_CONTEXT *context, const SAM_GROUP_HANDLE *group, const SAM_GROUP_MEMBER *member)
+NTSTATUS sam_delete_member_from_group(const SAM_CONTEXT *context, const SAM_GROUP_HANDLE *group, const SAM_GROUP_MEMBER *member)
 {
        const SAM_METHODS *tmp_methods;
        NTSTATUS     nt_status;
+
+       SAM_SETUP_CONTEXT;
        
        /* invalid group or member specified */
-       SAM_ASSERT(group && group->current_sam_methods &&member);
+       SAM_ASSERT(group && group->current_sam_methods && member);
        
        tmp_methods = group->current_sam_methods;
        
        if (!tmp_methods->sam_delete_member_from_group) {
-               DEBUG(3, ("context_sam_delete_member_from_group: sam_methods of the domain did not specify sam_delete_member_from_group\n"));
+               DEBUG(3, ("sam_delete_member_from_group: sam_methods of the domain did not specify sam_delete_member_from_group\n"));
                return NT_STATUS_NOT_IMPLEMENTED;
        }
        
@@ -817,18 +1261,20 @@ NTSTATUS context_sam_delete_member_from_group(const SAM_CONTEXT *context, const
        return NT_STATUS_OK;    
 }
 
-NTSTATUS context_sam_enum_groupmembers(const SAM_CONTEXT *context, const SAM_GROUP_HANDLE *group, uint32 *members_count, SAM_GROUP_MEMBER **members)
+NTSTATUS sam_enum_groupmembers(const SAM_CONTEXT *context, const SAM_GROUP_HANDLE *group, uint32 *members_count, SAM_GROUP_MEMBER **members)
 {
        const SAM_METHODS *tmp_methods;
        NTSTATUS     nt_status;
        
+       SAM_SETUP_CONTEXT;
+       
        /* invalid group specified */
-       SAM_ASSERT(group && group->current_sam_methods);
+       SAM_ASSERT(group && group->current_sam_methods && members_count && members);
        
        tmp_methods = group->current_sam_methods;
 
        if (!tmp_methods->sam_enum_groupmembers) {
-               DEBUG(3, ("context_sam_enum_groupmembers: sam_methods of the domain did not specify sam_enum_group_members\n"));
+               DEBUG(3, ("sam_enum_groupmembers: sam_methods of the domain did not specify sam_enum_group_members\n"));
                return NT_STATUS_NOT_IMPLEMENTED;
        }
        
@@ -840,7 +1286,7 @@ NTSTATUS context_sam_enum_groupmembers(const SAM_CONTEXT *context, const SAM_GRO
        return NT_STATUS_OK;    
 }
 
-NTSTATUS context_sam_get_groups_of_sid(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, const DOM_SID **sids, uint16 group_ctrl, uint32 *group_count, SAM_GROUP_ENUM **groups)
+NTSTATUS sam_get_groups_of_sid(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, const DOM_SID **sids, uint16 group_ctrl, uint32 *group_count, SAM_GROUP_ENUM **groups)
 {
        SAM_METHODS     *tmp_methods;
        NTSTATUS        nt_status;
@@ -848,10 +1294,12 @@ NTSTATUS context_sam_get_groups_of_sid(const SAM_CONTEXT *context, const NT_USER
        uint32          tmp_group_count;
        SAM_GROUP_ENUM *tmp_groups;
        
-       DEBUG(5,("context_sam_get_groups_of_sid: %d\n", __LINE__));
+       DEBUG(5,("sam_get_groups_of_sid: %d\n", __LINE__));
 
+       SAM_SETUP_CONTEXT;
+       
        /* invalid sam_context specified */
-       SAM_ASSERT(context && context->methods);
+       SAM_ASSERT(access_token && sids && context && context->methods);
        
        *group_count = 0;
        
@@ -862,7 +1310,7 @@ NTSTATUS context_sam_get_groups_of_sid(const SAM_CONTEXT *context, const NT_USER
        while (tmp_methods) {
                DEBUG(5,("getting groups from domain \n"));
                if (!tmp_methods->sam_get_groups_of_sid) {
-                       DEBUG(3, ("context_sam_get_groups_of_sid: sam_methods of domain did not specify sam_get_groups_of_sid\n"));
+                       DEBUG(3, ("sam_get_groups_of_sid: sam_methods of domain did not specify sam_get_groups_of_sid\n"));
                        SAFE_FREE(*groups);
                        return NT_STATUS_NOT_IMPLEMENTED;
                }
@@ -888,355 +1336,3 @@ NTSTATUS context_sam_get_groups_of_sid(const SAM_CONTEXT *context, const NT_USER
 }
 
 
-/******************************************************************
-  Free and cleanup a sam context, any associated data and anything
-  that the attached modules might have associated.
- *******************************************************************/
-
-void free_sam_context(SAM_CONTEXT **context)
-{
-       SAM_METHODS *sam_selected = (*context)->methods;
-
-       while (sam_selected) {
-               if (sam_selected->free_private_data) {
-                       sam_selected->free_private_data(&(sam_selected->private_data));
-               }
-               sam_selected = sam_selected->next;
-       }
-
-       talloc_destroy((*context)->mem_ctx);
-       *context = NULL;
-}
-
-/******************************************************************
-  Make a backend_entry from scratch
- *******************************************************************/
-static NTSTATUS make_backend_entry(SAM_BACKEND_ENTRY *backend_entry, char *sam_backend_string)
-{
-       char *tmp = NULL;
-       char *tmp_string = sam_backend_string;
-       
-       DEBUG(5,("make_backend_entry: %d\n", __LINE__));
-       
-       SAM_ASSERT(sam_backend_string && backend_entry);
-       
-       backend_entry->module_name = sam_backend_string;
-       
-       DEBUG(5,("makeing backend_entry for %s\n", backend_entry->module_name));
-       
-       if ((tmp = strchr(tmp_string, '|')) != NULL) {
-               DEBUGADD(20,("a domain name has been specified\n"));
-               *tmp = 0;
-               backend_entry->domain_name = smb_xstrdup(tmp + 1);
-               tmp_string = tmp + 1;
-       }
-       
-       if ((tmp = strchr(tmp_string, ':')) != NULL) {
-               DEBUG(20,("options for the backend have been specified\n"));
-               *tmp = 0;
-               backend_entry->module_params = smb_xstrdup(tmp + 1);
-               tmp_string = tmp + 1;
-       }
-               
-       if (backend_entry->domain_name == NULL) {
-               DEBUG(10,("make_backend_entry: no domain was specified for sam module %s. Using default domain %s\n",
-                       backend_entry->module_name, lp_workgroup()));
-               backend_entry->domain_name = smb_xstrdup(lp_workgroup());
-       }
-       
-       if ((backend_entry->domain_sid = (DOM_SID *)malloc(sizeof(DOM_SID))) == NULL) {
-               DEBUG(0,("make_backend_entry: failed to malloc domain_sid\n"));
-               return NT_STATUS_NO_MEMORY;
-       }
-       
-       DEBUG(10,("looking up sid for domain %s\n", backend_entry->domain_name));
-       
-       if (!secrets_fetch_domain_sid(backend_entry->domain_name, backend_entry->domain_sid)) {
-               DEBUG(2,("make_backend_entry: There is no SID stored for domain %s. Creating a new one.\n",
-                       backend_entry->domain_name));           
-               DEBUG(0, ("FIXME in %s:%d\n", __FILE__, __LINE__));
-               ZERO_STRUCTP(backend_entry->domain_sid);
-       }
-       
-       DEBUG(5,("make_backend_entry: module name: %s, module parameters: %s, domain name: %s, domain sid: %s\n",
-               backend_entry->module_name, backend_entry->module_params, backend_entry->domain_name, sid_string_static(backend_entry->domain_sid)));
-       
-       return NT_STATUS_OK;
-}
-
-/******************************************************************
- create sam_methods struct based on sam_backend_entry
- *****************************************************************/
-
-static NTSTATUS make_sam_methods_backend_entry(SAM_CONTEXT *context, SAM_METHODS **methods_ptr, SAM_BACKEND_ENTRY *backend_entry)
-{
-       NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
-       SAM_METHODS *methods;
-       int i;
-
-       DEBUG(5,("make_sam_methods_backend_entry: %d\n", __LINE__));
-
-       if (!NT_STATUS_IS_OK(nt_status = make_sam_methods(context->mem_ctx, methods_ptr))) {
-               return nt_status;
-       }
-
-       methods = *methods_ptr;
-       methods->backendname = talloc_strdup(context->mem_ctx, backend_entry->module_name);
-       methods->domain_name = talloc_strdup(context->mem_ctx, backend_entry->domain_name);
-       sid_copy(&methods->domain_sid, backend_entry->domain_sid);
-       methods->parent = context;
-
-       DEBUG(5,("Attempting to find sam backend %s\n", backend_entry->module_name));
-       for (i = 0; builtin_sam_init_functions[i].module_name; i++)
-       {
-               if (strequal(builtin_sam_init_functions[i].module_name, backend_entry->module_name))
-               {
-                       DEBUG(5,("Found sam backend %s (at pos %d)\n", backend_entry->module_name, i));
-                       DEBUGADD(5,("initialising it with options=%s for domain %s\n", backend_entry->module_params, sid_string_static(backend_entry->domain_sid)));
-                       nt_status = builtin_sam_init_functions[i].init(methods, backend_entry->module_params);
-                       if (NT_STATUS_IS_OK(nt_status)) {
-                               DEBUG(5,("sam backend %s has a valid init\n", backend_entry->module_name));
-                       } else {
-                               DEBUG(2,("sam backend %s did not correctly init (error was %s)\n",
-                                       backend_entry->module_name, nt_errstr(nt_status)));
-                       }
-                       return nt_status;
-               }
-       }
-       
-       DEBUG(2,("could not find backend %s\n", backend_entry->module_name));
-
-       return NT_STATUS_INVALID_PARAMETER;
-}
-
-static NTSTATUS sam_context_check_default_backends(SAM_CONTEXT *context)
-{
-       SAM_BACKEND_ENTRY entry;
-       DOM_SID *global_sam_sid  = get_global_sam_sid(); /* lp_workgroup doesn't play nicely with multiple domains */
-       SAM_METHODS *methods, *tmpmethods;
-       NTSTATUS ntstatus;
-       
-       DEBUG(5,("sam_context_check_default_backends: %d\n", __LINE__));
-
-       /* Make sure domain lp_workgroup() is available */
-       
-       ntstatus = sam_get_methods_by_sid(context, &methods, &global_sid_Builtin);
-
-       if (NT_STATUS_EQUAL(ntstatus, NT_STATUS_NO_SUCH_DOMAIN)) {
-               DEBUG(4,("There was no backend specified for domain %s(%s); using %s\n",
-                       lp_workgroup(), sid_string_static(global_sam_sid), SAM_DEFAULT_BACKEND));
-
-               SAM_ASSERT(global_sam_sid);
-
-               entry.module_name = SAM_DEFAULT_BACKEND;
-               entry.module_params = NULL;
-               entry.domain_name = lp_workgroup();
-               entry.domain_sid = (DOM_SID *)malloc(sizeof(DOM_SID));
-               sid_copy(entry.domain_sid, global_sam_sid);
-
-               if (!NT_STATUS_IS_OK(ntstatus = make_sam_methods_backend_entry(context, &methods, &entry))) {
-                       DEBUG(4,("make_sam_methods_backend_entry failed\n"));
-                       return ntstatus;
-               }
-
-               DLIST_ADD_END(context->methods, methods, tmpmethods);
-
-       } else if (!NT_STATUS_IS_OK(ntstatus)) {
-               DEBUG(2, ("sam_get_methods_by_sid failed for %s\n", lp_workgroup()));
-               return ntstatus;
-       }
-
-       /* Make sure the BUILTIN domain is available */
-
-       ntstatus = sam_get_methods_by_sid(context, &methods, global_sam_sid);
-       
-       if (NT_STATUS_EQUAL(ntstatus, NT_STATUS_NO_SUCH_DOMAIN)) {
-               DEBUG(4,("There was no backend specified for domain BUILTIN; using %s\n", 
-                                SAM_DEFAULT_BACKEND));
-               entry.module_name = SAM_DEFAULT_BACKEND;
-               entry.module_params = NULL;
-               entry.domain_name = "BUILTIN";
-               entry.domain_sid    = (DOM_SID *)malloc(sizeof(DOM_SID)); 
-               sid_copy(entry.domain_sid, &global_sid_Builtin);
-
-               if (!NT_STATUS_IS_OK(ntstatus = make_sam_methods_backend_entry(context, &methods,  &entry))) {
-                       DEBUG(4,("make_sam_methods_backend_entry failed\n"));
-                       return ntstatus;
-               }
-
-               DLIST_ADD_END(context->methods, methods, tmpmethods);
-       } else if (!NT_STATUS_IS_OK(ntstatus)) {
-               DEBUG(2, ("sam_get_methods_by_sid failed for BUILTIN\n"));
-               return ntstatus;
-       }
-
-       return NT_STATUS_OK;
-}
-
-static NTSTATUS check_duplicate_backend_entries(SAM_BACKEND_ENTRY **backend_entries, int *nBackends)
-{
-       int i, j;
-       
-       DEBUG(5,("check_duplicate_backend_entries: %d\n", __LINE__));
-       
-       for (i = 0; i < *nBackends; i++) {
-               for (j = i + 1; j < *nBackends; j++) {
-                       if (sid_equal((*backend_entries)[i].domain_sid, (*backend_entries)[j].domain_sid)) {
-                               DEBUG(0,("two backend modules claim the same domain %s\n",
-                                       sid_string_static((*backend_entries)[j].domain_sid)));
-                               return NT_STATUS_INVALID_PARAMETER;                     
-                       }
-               }               
-       }
-
-       return NT_STATUS_OK;
-}
-
-NTSTATUS make_sam_context_list(SAM_CONTEXT **context, char **sam_backends_param)
-{
-       int i = 0, j = 0;
-       SAM_METHODS *curmethods, *tmpmethods;
-       int nBackends               = 0;
-       SAM_BACKEND_ENTRY *backends = NULL;
-       NTSTATUS nt_status          = NT_STATUS_UNSUCCESSFUL;
-
-       DEBUG(5,("make_sam_context_from_conf: %d\n", __LINE__));
-
-       if (!NT_STATUS_IS_OK(nt_status = make_sam_context(context))) {
-               DEBUG(4,("make_sam_context failed\n"));
-               return nt_status;
-       }
-
-       while (sam_backends_param[nBackends])
-               nBackends++;
-
-       DEBUG(6,("There are %d domains listed with their backends\n", nBackends));
-
-       if ((backends = (SAM_BACKEND_ENTRY *)malloc(sizeof(*backends)*nBackends)) == NULL) {
-               DEBUG(0,("make_sam_context_list: failed to allocate backends\n"));
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       memset(backends, '\0', sizeof(*backends)*nBackends);
-
-       for (i = 0; i < nBackends; i++) {
-               DEBUG(8,("processing %s\n",sam_backends_param[i]));
-               if (!NT_STATUS_IS_OK(nt_status = make_backend_entry(&backends[i], sam_backends_param[i]))) {
-                       DEBUG(4,("make_backend_entry failed\n"));
-                       for (j = 0; j < nBackends; j++) SAFE_FREE(backends[j].domain_sid);
-                       SAFE_FREE(backends);
-                       free_sam_context(context);
-                       return nt_status;
-               }
-       }
-
-       if (!NT_STATUS_IS_OK(nt_status = check_duplicate_backend_entries(&backends, &nBackends))) {
-               DEBUG(4,("check_duplicate_backend_entries failed\n"));
-               for (j = 0; j < nBackends; j++) SAFE_FREE(backends[j].domain_sid);
-               SAFE_FREE(backends);
-               free_sam_context(context);
-               return nt_status;
-       }
-
-       for (i = 0; i < nBackends; i++) {
-               if (!NT_STATUS_IS_OK(nt_status = make_sam_methods_backend_entry(*context, &curmethods,  &backends[i]))) {
-                       DEBUG(4,("make_sam_methods_backend_entry failed\n"));
-                       for (j = 0; j < nBackends; j++) SAFE_FREE(backends[j].domain_sid);
-                       SAFE_FREE(backends);
-                       free_sam_context(context);
-                       return nt_status;
-               }
-               DLIST_ADD_END((*context)->methods, curmethods, tmpmethods);
-       }
-       
-       for (i = 0; i < nBackends; i++) SAFE_FREE(backends[i].domain_sid);
-
-       SAFE_FREE(backends);
-       return NT_STATUS_OK;
-}
-
-/******************************************************************
-  Make a sam_context from scratch.
- *******************************************************************/
-
-NTSTATUS make_sam_context(SAM_CONTEXT **context) 
-{
-       TALLOC_CTX *mem_ctx;
-
-       mem_ctx = talloc_init_named("sam_context internal allocation context");
-
-       if (!mem_ctx) {
-               DEBUG(0, ("make_sam_context: talloc init failed!\n"));
-               return NT_STATUS_NO_MEMORY;
-       }               
-
-       *context = talloc(mem_ctx, sizeof(**context));
-       if (!*context) {
-               DEBUG(0, ("make_sam_context: talloc failed!\n"));
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       ZERO_STRUCTP(*context);
-
-       (*context)->mem_ctx = mem_ctx;
-
-       (*context)->free_fn = free_sam_context;
-
-       return NT_STATUS_OK;
-}
-
-/******************************************************************
-  Return an already initialised sam_context, to facilitate backward 
-  compatibility (see functions below).
- *******************************************************************/
-
-struct sam_context *sam_get_static_context(BOOL reload) 
-{
-       static SAM_CONTEXT *sam_context = NULL;
-
-       if ((sam_context) && (reload)) {
-               sam_context->free_fn(&sam_context);
-               sam_context = NULL;
-       }
-
-       if (!sam_context) {
-               if (!NT_STATUS_IS_OK(make_sam_context_list(&sam_context, lp_sam_backend()))) {
-                       DEBUG(4,("make_sam_context_list failed\n"));
-                       return NULL;
-               }
-
-               /* Make sure the required domains (default domain, builtin) are available */
-               if (!NT_STATUS_IS_OK(sam_context_check_default_backends(sam_context))) {
-                       DEBUG(4,("sam_context_check_default_backends failed\n"));
-                       return NULL;
-               }
-       }
-
-       return sam_context;
-}
-
-/***************************************************************
-  Initialize the static context (at smbd startup etc). 
-
-  If uninitialised, context will auto-init on first use.
- ***************************************************************/
-
-BOOL initialize_sam(BOOL reload)
-{      
-       return (sam_get_static_context(reload) != NULL);
-}
-
-
-NTSTATUS make_sam_methods(TALLOC_CTX *mem_ctx, SAM_METHODS **methods)
-{
-       *methods = talloc(mem_ctx, sizeof(SAM_METHODS));
-
-       if (!*methods) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       ZERO_STRUCTP(*methods);
-
-       return NT_STATUS_OK;
-}
index 9f162f2a07c9598996cbe39d9b60fc9f9e0094f5..0cd219cb459526e7e19fe187181f7be1ca783413 100644 (file)
@@ -104,8 +104,8 @@ static NTSTATUS cmd_lookup_sid(struct samtest_state *st, TALLOC_CTX *mem_ctx, in
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       if (!NT_STATUS_IS_OK(status = context_sam_lookup_sid(st->context, st->token, mem_ctx, &sid, &name, &type))) {
-               printf("context_sam_lookup_sid failed!\n");
+       if (!NT_STATUS_IS_OK(status = sam_lookup_sid(st->context, st->token, mem_ctx, &sid, &name, &type))) {
+               printf("sam_lookup_sid failed!\n");
                return status;
        }
 
@@ -125,8 +125,8 @@ static NTSTATUS cmd_lookup_name(struct samtest_state *st, TALLOC_CTX *mem_ctx, i
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       if (!NT_STATUS_IS_OK(status = context_sam_lookup_name(st->context, st->token, argv[1], argv[2], &sid, &type))) {
-               printf("context_sam_lookup_name failed!\n");
+       if (!NT_STATUS_IS_OK(status = sam_lookup_name(st->context, st->token, argv[1], argv[2], &sid, &type))) {
+               printf("sam_lookup_name failed!\n");
                return status;
        }
 
@@ -155,8 +155,8 @@ static NTSTATUS cmd_lookup_domain(struct samtest_state *st, TALLOC_CTX *mem_ctx,
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       if (!NT_STATUS_IS_OK(status = context_sam_lookup_domain(st->context, st->token, argv[1], &sid))) {
-               printf("context_sam_lookup_name failed!\n");
+       if (!NT_STATUS_IS_OK(status = sam_lookup_domain(st->context, st->token, argv[1], &sid))) {
+               printf("sam_lookup_name failed!\n");
                return status;
        }
 
@@ -172,8 +172,8 @@ static NTSTATUS cmd_enum_domains(struct samtest_state *st, TALLOC_CTX *mem_ctx,
        char **domain_names;
        NTSTATUS status;
 
-       if (!NT_STATUS_IS_OK(status = context_sam_enum_domains(st->context, st->token, &domain_count, &domain_sids, &domain_names))) {
-               printf("context_sam_enum_domains failed!\n");
+       if (!NT_STATUS_IS_OK(status = sam_enum_domains(st->context, st->token, &domain_count, &domain_sids, &domain_names))) {
+               printf("sam_enum_domains failed!\n");
                return status;
        }
 
@@ -218,8 +218,8 @@ static NTSTATUS cmd_show_domain(struct samtest_state *st, TALLOC_CTX *mem_ctx, i
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       if (!NT_STATUS_IS_OK(status = context_sam_get_domain_by_sid(st->context, st->token, DOMAIN_ALL_ACCESS, &sid, &domain))) {
-               printf("context_sam_get_domain_by_sid failed\n");
+       if (!NT_STATUS_IS_OK(status = sam_get_domain_by_sid(st->context, st->token, DOMAIN_ALL_ACCESS, &sid, &domain))) {
+               printf("sam_get_domain_by_sid failed\n");
                return status;
        }
 
@@ -331,7 +331,6 @@ static NTSTATUS cmd_enum_accounts(struct samtest_state *st, TALLOC_CTX *mem_ctx,
        DOM_SID sid;
        int32 account_count, i;
        SAM_ACCOUNT_ENUM *accounts;
-       uint16 acct_ctrl = (ACB_NORMAL |ACB_WSTRUST |ACB_SVRTRUST |ACB_DOMTRUST | ACB_MNS);
 
        if (argc != 2) {
                printf("Usage: enum_accounts <domain-sid>\n");
@@ -343,8 +342,8 @@ static NTSTATUS cmd_enum_accounts(struct samtest_state *st, TALLOC_CTX *mem_ctx,
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       if (!NT_STATUS_IS_OK(status = context_sam_enum_accounts(st->context, st->token, &sid, acct_ctrl, &account_count, &accounts))) {
-               printf("context_sam_enum_accounts failed: %s\n", nt_errstr(status));
+       if (!NT_STATUS_IS_OK(status = sam_enum_accounts(st->context, st->token, &sid, 0, &account_count, &accounts))) {
+               printf("sam_enum_accounts failed: %s\n", nt_errstr(status));
                return status;
        }
 
index b5f7ed9f76589d2164cd5a6d45de50a653f723c0..d3268d8b5b25b243157d730ce09621178ff54abf 100644 (file)
@@ -360,7 +360,6 @@ int main(int argc, char *argv[])
        struct cmd_set          **cmd_set;
        struct samtest_state st;
 
-
        /* make sure the vars that get altered (4th field) are in
           a fixed location or certain compilers complain */
        poptContext pc;
@@ -375,6 +374,8 @@ int main(int argc, char *argv[])
 
        ZERO_STRUCT(st);
 
+       st.token = get_system_token();
+
        setlinebuf(stdout);
 
        DEBUGLEVEL = 1;