r13494: Merge the stuff I've done in head the last days.
authorVolker Lendecke <vlendec@samba.org>
Mon, 13 Feb 2006 17:08:25 +0000 (17:08 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 16:10:06 +0000 (11:10 -0500)
Volker
(This used to be commit bb40e544de68f01a6e774753f508e69373b39899)

17 files changed:
source3/Makefile.in
source3/auth/auth_util.c
source3/groupdb/mapping.c
source3/include/passdb.h
source3/lib/system_smbd.c
source3/lib/username.c
source3/lib/util_getent.c [deleted file]
source3/passdb/passdb.c
source3/passdb/pdb_interface.c
source3/rpc_server/srv_samr_nt.c
source3/smbd/chgpasswd.c
source3/smbd/map_username.c [new file with mode: 0644]
source3/smbd/password.c
source3/smbd/posix_acls.c
source3/smbd/service.c
source3/utils/net_groupmap.c
source3/utils/net_rpc_samsync.c

index d8f7dcf5197618bcfcfd6986b365e0cfb83c0d71..135c757fd881eccfa6fc142636182259ff7d0d85 100644 (file)
@@ -194,7 +194,7 @@ LIB_OBJ = $(VERSION_OBJ) lib/charcnv.o lib/debug.o lib/fault.o \
           lib/interfaces.o lib/pidfile.o lib/replace.o lib/replace1.o \
           lib/signal.o lib/system.o lib/sendfile.o lib/time.o \
          lib/ufc.o lib/genrand.o lib/username.o \
-         lib/util_getent.o lib/util_pw.o lib/access.o lib/smbrun.o \
+         lib/util_pw.o lib/access.o lib/smbrun.o \
          lib/bitmap.o lib/crc32.o $(SNPRINTF_OBJ) lib/dprintf.o \
          lib/xfile.o lib/wins_srv.o \
          lib/util_str.o lib/clobber.o lib/util_sid.o lib/util_uuid.o \
@@ -209,7 +209,7 @@ LIB_OBJ = $(VERSION_OBJ) lib/charcnv.o lib/debug.o lib/fault.o \
          lib/adt_tree.o lib/gencache.o $(TDB_OBJ) \
          lib/module.o lib/events.o lib/ldap_escape.o @CHARSET_STATIC@ \
          lib/secdesc.o lib/util_seaccess.o lib/secace.o lib/secacl.o @SOCKWRAP@ \
-         libads/krb5_errs.o
+         libads/krb5_errs.o lib/system_smbd.o 
 
 LIB_DUMMY_OBJ = lib/dummysmbd.o lib/dummyroot.o
 LIB_NONSMBD_OBJ = $(LIB_OBJ) $(LIB_DUMMY_OBJ)
@@ -326,7 +326,7 @@ PASSDB_OBJ = $(PASSDB_GET_SET_OBJ) passdb/passdb.o passdb/pdb_interface.o \
                passdb/util_wellknown.o passdb/util_builtin.o passdb/pdb_compat.o \
                passdb/util_unixsids.o passdb/lookup_sid.o \
                passdb/login_cache.o @PDB_STATIC@ \
-               lib/system_smbd.o lib/account_pol.o lib/privileges.o
+               lib/account_pol.o lib/privileges.o
 
 DEVEL_HELP_WEIRD_OBJ = modules/weird.o
 CP850_OBJ = modules/CP850.o
@@ -386,7 +386,7 @@ SMBD_OBJ_MAIN = smbd/server.o
 BUILDOPT_OBJ = smbd/build_options.o
 
 SMBD_OBJ_SRV = smbd/files.o smbd/chgpasswd.o smbd/connection.o \
-              smbd/utmp.o smbd/session.o \
+              smbd/utmp.o smbd/session.o smbd/map_username.o \
                smbd/dfree.o smbd/dir.o smbd/password.o smbd/conn.o \
               smbd/share_access.o smbd/fileio.o \
                smbd/ipc.o smbd/lanman.o smbd/negprot.o \
index 1567b6e40b6502b78d1fe9459df3225948fac5ac..ad02b24a428a61fcefbfd87e57b394d4291c204c 100644 (file)
@@ -1018,6 +1018,72 @@ NTSTATUS create_token_from_username(TALLOC_CTX *mem_ctx, const char *username,
        return result;
 }
 
+/***************************************************************************
+ Build upon create_token_from_username:
+
+ Expensive helper function to figure out whether a user given its name is
+ member of a particular group.
+***************************************************************************/
+BOOL user_in_group_sid(const char *username, const DOM_SID *group_sid)
+{
+       NTSTATUS status;
+       uid_t uid;
+       gid_t gid;
+       char *found_username;
+       struct nt_user_token *token;
+       BOOL result;
+
+       TALLOC_CTX *mem_ctx;
+
+       mem_ctx = talloc_new(NULL);
+       if (mem_ctx == NULL) {
+               DEBUG(0, ("talloc_new failed\n"));
+               return False;
+       }
+
+       status = create_token_from_username(mem_ctx, username, False,
+                                           &uid, &gid, &found_username,
+                                           &token);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(10, ("could not create token for %s\n", username));
+               return False;
+       }
+
+       result = nt_token_check_sid(group_sid, token);
+
+       talloc_free(mem_ctx);
+       return result;
+       
+}
+
+BOOL user_in_group(const char *username, const char *groupname)
+{
+       TALLOC_CTX *mem_ctx;
+       DOM_SID group_sid;
+       NTSTATUS status;
+       BOOL ret;
+
+       mem_ctx = talloc_new(NULL);
+       if (mem_ctx == NULL) {
+               DEBUG(0, ("talloc_new failed\n"));
+               return False;
+       }
+
+       ret = lookup_name(mem_ctx, groupname, LOOKUP_NAME_ALL,
+                         NULL, NULL, &group_sid, NULL);
+       talloc_free(mem_ctx);
+
+       if (!ret) {
+               DEBUG(10, ("lookup_name(%s) failed: %s\n", groupname,
+                          nt_errstr(status)));
+               return False;
+       }
+
+       return user_in_group_sid(username, &group_sid);
+}
+
+
 /***************************************************************************
  Make (and fill) a user_info struct from a Kerberos PAC logon_info by
  conversion to a SAM_ACCOUNT
index 2790d4758770964df2f652bbbd2df205502a6b05..07116f41fb606b2a827457f8cead55cb6e2c0667 100644 (file)
@@ -157,26 +157,26 @@ static BOOL add_mapping_entry(GROUP_MAP *map, int flag)
 /****************************************************************************
 initialise first time the mapping list
 ****************************************************************************/
-BOOL add_initial_entry(gid_t gid, const char *sid, enum SID_NAME_USE sid_name_use, const char *nt_name, const char *comment)
+NTSTATUS add_initial_entry(gid_t gid, const char *sid, enum SID_NAME_USE sid_name_use, const char *nt_name, const char *comment)
 {
        GROUP_MAP map;
 
        if(!init_group_mapping()) {
                DEBUG(0,("failed to initialize group mapping\n"));
-               return(False);
+               return NT_STATUS_UNSUCCESSFUL;
        }
        
        map.gid=gid;
        if (!string_to_sid(&map.sid, sid)) {
                DEBUG(0, ("string_to_sid failed: %s", sid));
-               return False;
+               return NT_STATUS_UNSUCCESSFUL;
        }
        
        map.sid_name_use=sid_name_use;
        fstrcpy(map.nt_name, nt_name);
        fstrcpy(map.comment, comment);
 
-       return NT_STATUS_IS_OK(pdb_add_group_mapping_entry(&map));
+       return pdb_add_group_mapping_entry(&map);
 }
 
 /****************************************************************************
@@ -856,7 +856,7 @@ BOOL get_domain_group_from_sid(DOM_SID sid, GROUP_MAP *map)
  Create a UNIX group on demand.
 ****************************************************************************/
 
-int smb_create_group(char *unix_group, gid_t *new_gid)
+int smb_create_group(const char *unix_group, gid_t *new_gid)
 {
        pstring add_script;
        int     ret = -1;
@@ -901,7 +901,7 @@ int smb_create_group(char *unix_group, gid_t *new_gid)
  Delete a UNIX group on demand.
 ****************************************************************************/
 
-int smb_delete_group(char *unix_group)
+int smb_delete_group(const char *unix_group)
 {
        pstring del_script;
        int ret;
@@ -947,7 +947,7 @@ int smb_set_primary_group(const char *unix_group, const char* unix_user)
  Add a user to a UNIX group.
 ****************************************************************************/
 
-int smb_add_user_group(char *unix_group, char *unix_user)
+int smb_add_user_group(const char *unix_group, const char *unix_user)
 {
        pstring add_script;
        int ret;
@@ -1122,8 +1122,7 @@ NTSTATUS pdb_default_create_alias(struct pdb_methods *methods,
 NTSTATUS pdb_default_delete_alias(struct pdb_methods *methods,
                                  const DOM_SID *sid)
 {
-       return pdb_delete_group_mapping_entry(*sid) ?
-               NT_STATUS_OK : NT_STATUS_ACCESS_DENIED;
+       return pdb_delete_group_mapping_entry(*sid);
 }
 
 NTSTATUS pdb_default_get_aliasinfo(struct pdb_methods *methods,
index 35f377ad86805e53ab465172ace7430190f4f5f9..1f3c8cb28b3fa8dcd675ae506be7281d6e777615 100644 (file)
@@ -262,6 +262,13 @@ struct pdb_methods
        NTSTATUS (*getsampwnam)(struct pdb_methods *, SAM_ACCOUNT *sam_acct, const char *username);
        
        NTSTATUS (*getsampwsid)(struct pdb_methods *, SAM_ACCOUNT *sam_acct, const DOM_SID *sid);
+
+       NTSTATUS (*create_user)(struct pdb_methods *, TALLOC_CTX *tmp_ctx,
+                               const char *name, uint32 acct_flags,
+                               uint32 *rid);
+
+       NTSTATUS (*delete_user)(struct pdb_methods *, TALLOC_CTX *tmp_ctx,
+                               SAM_ACCOUNT *sam_acct);
        
        NTSTATUS (*add_sam_account)(struct pdb_methods *, SAM_ACCOUNT *sampass);
        
@@ -279,6 +286,13 @@ struct pdb_methods
 
        NTSTATUS (*getgrnam)(struct pdb_methods *methods, GROUP_MAP *map, const char *name);
 
+       NTSTATUS (*create_dom_group)(struct pdb_methods *methods,
+                                    TALLOC_CTX *mem_ctx, const char *name,
+                                    uint32 *rid);
+
+       NTSTATUS (*delete_dom_group)(struct pdb_methods *methods,
+                                    TALLOC_CTX *mem_ctx, uint32 rid);
+
        NTSTATUS (*add_group_mapping_entry)(struct pdb_methods *methods,
                                            GROUP_MAP *map);
 
@@ -305,6 +319,18 @@ struct pdb_methods
                                           DOM_SID **pp_sids, gid_t **pp_gids,
                                           size_t *p_num_groups);
 
+       NTSTATUS (*set_unix_primary_group)(struct pdb_methods *methods,
+                                          TALLOC_CTX *mem_ctx,
+                                          SAM_ACCOUNT *user);
+
+       NTSTATUS (*add_groupmem)(struct pdb_methods *methods,
+                                TALLOC_CTX *mem_ctx,
+                                uint32 group_rid, uint32 member_rid);
+
+       NTSTATUS (*del_groupmem)(struct pdb_methods *methods,
+                                TALLOC_CTX *mem_ctx,
+                                uint32 group_rid, uint32 member_rid);
+
        NTSTATUS (*find_alias)(struct pdb_methods *methods,
                               const char *name, DOM_SID *sid);
 
index 3fc2d69a036ed4a5d687517bf7e230b32a20729e..081a07c01950bcfd6f537192689589fbcccb8859 100644 (file)
@@ -123,14 +123,16 @@ static int sys_getgrouplist(const char *user, gid_t gid, gid_t *groups, int *grp
 
        DEBUG(10,("sys_getgrouplist: user [%s]\n", user));
        
-       /* see if we should disable winbindd lookups for local users */
-       if (strchr(user, *lp_winbind_separator()) == NULL) {
-               if ( !winbind_off() )
-                       DEBUG(0,("sys_getgroup_list: Insufficient environment space "
-                                "for %s\n", WINBINDD_DONT_ENV));
-               else
-                       DEBUG(10,("sys_getgrouplist(): disabled winbindd for group "
-                                 "lookup [user == %s]\n", user));
+       /* This is only ever called for Unix users, remote memberships are
+        * always determined by the info3 coming back from auth3 or the
+        * PAC. */
+
+       if ( !winbind_off() ) {
+               DEBUG(0,("sys_getgroup_list: Insufficient environment space "
+                        "for %s\n", WINBINDD_DONT_ENV));
+       } else {
+               DEBUG(10,("sys_getgrouplist(): disabled winbindd for group "
+                         "lookup [user == %s]\n", user));
        }
 
 #ifdef HAVE_GETGROUPLIST
@@ -198,62 +200,3 @@ BOOL getgroups_unix_user(TALLOC_CTX *mem_ctx, const char *user,
        SAFE_FREE(temp_groups);
        return True;
 }
-
-NTSTATUS pdb_default_enum_group_memberships(struct pdb_methods *methods,
-                                           TALLOC_CTX *mem_ctx,
-                                           SAM_ACCOUNT *user,
-                                           DOM_SID **pp_sids,
-                                           gid_t **pp_gids,
-                                           size_t *p_num_groups)
-{
-       size_t i;
-       gid_t gid;
-
-       if ( !sid_to_gid(pdb_get_group_sid(user), &gid) ) 
-       {
-               uint32 rid;
-               struct passwd *pwd;
-       
-               /* second try, allow the DOMAIN_USERS group to pass */
-               
-               if ( !sid_peek_check_rid( get_global_sam_sid(), pdb_get_group_sid(user), &rid ) )
-                       return NT_STATUS_NO_SUCH_USER;
-                       
-               if ( rid != DOMAIN_GROUP_RID_USERS ) {
-                       DEBUG(10, ("sid_to_gid failed\n"));
-                       return NT_STATUS_NO_SUCH_USER;
-               }
-               
-               DEBUG(5,("pdb_default_enum_group_memberships: sid_to_gid() failed but giving "
-                       "free pass to 'Domain Users' as primary group\n"));
-               
-               if ( !(pwd = getpwnam_alloc( NULL, pdb_get_username(user) ) ) ) 
-                       return NT_STATUS_NO_SUCH_USER;
-                       
-               gid = pwd->pw_gid;
-               
-               TALLOC_FREE( pwd );             
-       }
-
-       if (!getgroups_unix_user(mem_ctx, pdb_get_username(user), gid,
-                                pp_gids, p_num_groups)) {
-               return NT_STATUS_NO_SUCH_USER;
-       }
-
-       if (*p_num_groups == 0) {
-               smb_panic("primary group missing");
-       }
-
-       *pp_sids = TALLOC_ARRAY(mem_ctx, DOM_SID, *p_num_groups);
-
-       if (*pp_sids == NULL) {
-               talloc_free(*pp_gids);
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       for (i=0; i<*p_num_groups; i++) {
-               gid_to_sid(&(*pp_sids)[i], (*pp_gids)[i]);
-       }
-
-       return NT_STATUS_OK;
-}
index c04dfd05da10ba05fca94ff264f190b6be1d3234..52994557f79810cb060aa53421b6885d6938909a 100644 (file)
@@ -29,16 +29,6 @@ static struct passwd *uname_string_combinations2(char *s, TALLOC_CTX *mem_ctx, i
                                                 struct passwd * (*fn) (TALLOC_CTX *mem_ctx, const char *),
                                                 int N);
 
-/*****************************************************************
- Check if a user or group name is local (this is a *local* name for
- *local* people, there's nothing for you here...).
-*****************************************************************/
-
-static BOOL name_is_local(const char *name)
-{
-       return !(strchr_m(name, *lp_winbind_separator()));
-}
-
 /****************************************************************************
  Get a users home directory.
 ****************************************************************************/
@@ -58,161 +48,6 @@ char *get_user_home_dir(const char *user)
        return(pass->pw_dir);      
 }
 
-/*******************************************************************
- Map a username from a dos name to a unix name by looking in the username
- map. Note that this modifies the name in place.
- This is the main function that should be called *once* on
- any incoming or new username - in order to canonicalize the name.
- This is being done to de-couple the case conversions from the user mapping
- function. Previously, the map_username was being called
- every time Get_Pwnam was called.
- Returns True if username was changed, false otherwise.
-********************************************************************/
-
-BOOL map_username(fstring user)
-{
-       static BOOL initialised=False;
-       static fstring last_from,last_to;
-       XFILE *f;
-       char *mapfile = lp_username_map();
-       char *s;
-       pstring buf;
-       BOOL mapped_user = False;
-       char *cmd = lp_username_map_script();
-       
-       if (!*user)
-               return False;
-               
-       if (strequal(user,last_to))
-               return False;
-
-       if (strequal(user,last_from)) {
-               DEBUG(3,("Mapped user %s to %s\n",user,last_to));
-               fstrcpy(user,last_to);
-               return True;
-       }
-       
-       /* first try the username map script */
-       
-       if ( *cmd ) {
-               char **qlines;
-               pstring command;
-               int numlines, ret, fd;
-
-               pstr_sprintf( command, "%s \"%s\"", cmd, user );
-
-               DEBUG(10,("Running [%s]\n", command));
-               ret = smbrun(command, &fd);
-               DEBUGADD(10,("returned [%d]\n", ret));
-
-               if ( ret != 0 ) {
-                       if (fd != -1)
-                               close(fd);
-                       return False;
-               }
-
-               numlines = 0;
-               qlines = fd_lines_load(fd, &numlines,0);
-               DEBUGADD(10,("Lines returned = [%d]\n", numlines));
-               close(fd);
-
-               /* should be either no lines or a single line with the mapped username */
-
-               if (numlines) {
-                       DEBUG(3,("Mapped user %s to %s\n", user, qlines[0] ));
-                       fstrcpy( user, qlines[0] );
-               }
-
-               file_lines_free(qlines);
-               
-               return numlines != 0;
-       }
-
-       /* ok.  let's try the mapfile */
-       
-       if (!*mapfile)
-               return False;
-
-       if (!initialised) {
-               *last_from = *last_to = 0;
-               initialised = True;
-       }
-  
-       f = x_fopen(mapfile,O_RDONLY, 0);
-       if (!f) {
-               DEBUG(0,("can't open username map %s. Error %s\n",mapfile, strerror(errno) ));
-               return False;
-       }
-
-       DEBUG(4,("Scanning username map %s\n",mapfile));
-
-       while((s=fgets_slash(buf,sizeof(buf),f))!=NULL) {
-               char *unixname = s;
-               char *dosname = strchr_m(unixname,'=');
-               char **dosuserlist;
-               BOOL return_if_mapped = False;
-
-               if (!dosname)
-                       continue;
-
-               *dosname++ = 0;
-
-               while (isspace((int)*unixname))
-                       unixname++;
-
-               if ('!' == *unixname) {
-                       return_if_mapped = True;
-                       unixname++;
-                       while (*unixname && isspace((int)*unixname))
-                               unixname++;
-               }
-    
-               if (!*unixname || strchr_m("#;",*unixname))
-                       continue;
-
-               {
-                       int l = strlen(unixname);
-                       while (l && isspace((int)unixname[l-1])) {
-                               unixname[l-1] = 0;
-                               l--;
-                       }
-               }
-
-               dosuserlist = str_list_make(dosname, NULL);
-               if (!dosuserlist) {
-                       DEBUG(0,("Unable to build user list\n"));
-                       return False;
-               }
-
-               if (strchr_m(dosname,'*') ||
-                   user_in_list(user, (const char **)dosuserlist)) {
-                       DEBUG(3,("Mapped user %s to %s\n",user,unixname));
-                       mapped_user = True;
-                       fstrcpy( last_from,user );
-                       fstrcpy( user, unixname );
-                       fstrcpy( last_to,user );
-                       if ( return_if_mapped ) {
-                               str_list_free (&dosuserlist);
-                               x_fclose(f);
-                               return True;
-                       }
-               }
-    
-               str_list_free (&dosuserlist);
-       }
-
-       x_fclose(f);
-
-       /*
-        * Setup the last_from and last_to as an optimization so 
-        * that we don't scan the file again for the same user.
-        */
-       fstrcpy(last_from,user);
-       fstrcpy(last_to,user);
-
-       return mapped_user;
-}
-
 /****************************************************************************
  * A wrapper for sys_getpwnam().  The following variations are tried:
  *   - as transmitted
@@ -334,351 +169,6 @@ struct passwd *Get_Pwnam(const char *user)
        return ret;  
 }
 
-/****************************************************************************
- Check if a user is in a netgroup user list. If at first we don't succeed,
- try lower case.
-****************************************************************************/
-
-BOOL user_in_netgroup(const char *user, const char *ngname)
-{
-#ifdef HAVE_NETGROUP
-       static char *mydomain = NULL;
-       fstring lowercase_user;
-
-       if (mydomain == NULL)
-               yp_get_default_domain(&mydomain);
-
-       if(mydomain == NULL) {
-               DEBUG(5,("Unable to get default yp domain\n"));
-               return False;
-       }
-
-       DEBUG(5,("looking for user %s of domain %s in netgroup %s\n",
-               user, mydomain, ngname));
-
-       if (innetgr(ngname, NULL, user, mydomain)) {
-               DEBUG(5,("user_in_netgroup: Found\n"));
-               return (True);
-       } else {
-
-               /*
-                * Ok, innetgr is case sensitive. Try once more with lowercase
-                * just in case. Attempt to fix #703. JRA.
-                */
-
-               fstrcpy(lowercase_user, user);
-               strlower_m(lowercase_user);
-       
-               DEBUG(5,("looking for user %s of domain %s in netgroup %s\n",
-                       lowercase_user, mydomain, ngname));
-
-               if (innetgr(ngname, NULL, lowercase_user, mydomain)) {
-                       DEBUG(5,("user_in_netgroup: Found\n"));
-                       return (True);
-               }
-       }
-#endif /* HAVE_NETGROUP */
-       return False;
-}
-
-/****************************************************************************
- Check if a user is in a winbind group.
-****************************************************************************/
-  
-static BOOL user_in_winbind_group(const char *user, const char *gname,
-                                 BOOL *winbind_answered)
-{
-       int i;
-       gid_t gid, gid_low, gid_high;
-       BOOL ret = False;
-       static gid_t *groups = NULL;
-       static int num_groups = 0;
-       static fstring last_user = "";
-       *winbind_answered = False;
-       if ((gid = nametogid(gname)) == (gid_t)-1) {
-               DEBUG(0,("user_in_winbind_group: nametogid for group %s "
-                        "failed.\n", gname ));
-               goto err;
-       }
-
-       if (!lp_idmap_gid(&gid_low, &gid_high)) {
-               DEBUG(4, ("winbind gid range not configured, therefore %s "
-                         "cannot be a winbind group\n", gname));
-               goto err;
-       }
-
-       if (gid < gid_low || gid > gid_high) {
-               DEBUG(4, ("group %s is not a winbind group\n", gname));
-               goto err;
-       }
-       /* try to user the last user we looked up */
-       /* otherwise fall back to lookups */
-       
-       if ( !strequal( last_user, user ) || !groups )
-       {
-               /* clear any cached information */
-               
-               SAFE_FREE(groups);
-               fstrcpy( last_user, "" );
-
-               /*
-                * Get the gid's that this user belongs to.
-                */
-               if ((num_groups = winbind_getgroups(user, &groups)) == -1)
-                       return False;
-                       
-               if ( num_groups == -1 )
-                       return False;
-               if ( num_groups == 0 ) {
-                       *winbind_answered = True;
-                       return False;
-               }
-               
-               /* save the last username */
-               
-               fstrcpy( last_user, user );
-               
-       }
-       else 
-               DEBUG(10,("user_in_winbind_group: using cached user "
-                         "groups for [%s]\n", user));
-       if ( DEBUGLEVEL >= 10 ) {
-               DEBUG(10,("user_in_winbind_group: using groups -- "));
-               for ( i=0; i<num_groups; i++ )
-                       DEBUGADD(10,("%lu ", (unsigned long)groups[i]));
-               DEBUGADD(10,("\n"));    
-       }
-       /*
-        * Now we have the gid list for this user - convert the gname to a
-        * gid_t via either winbind or the local UNIX lookup and do the
-        * comparison.
-        */
-       for (i = 0; i < num_groups; i++) {
-               if (gid == groups[i]) {
-                       ret = True;
-                       break;
-               }
-       }
-       *winbind_answered = True;
-       SAFE_FREE(groups);
-       return ret;
-   err:
-       *winbind_answered = False;
-       SAFE_FREE(groups);
-       return False;
-}            
-/****************************************************************************
- Check if a user is in a UNIX group.
-****************************************************************************/
-
-BOOL user_in_unix_group(const char *user,const char *gname)
-{
-       struct passwd *pass = Get_Pwnam(user);
-       struct sys_userlist *user_list;
-       struct sys_userlist *member;
-
-       DEBUG(10,("user_in_unix_group: checking user %s in group %s\n",
-                 user, gname));
-
-       /*
-        * We need to check the users primary group as this
-        * group is implicit and often not listed in the group database.
-        */
-       if (pass) {
-               if (strequal(gname,gidtoname(pass->pw_gid))) {
-                       DEBUG(10,("user_in_unix_group: group %s is "
-                                 "primary group.\n", gname ));
-                       return True;
-               }
-       }
-       user_list = get_users_in_group(gname);
-       if (user_list == NULL) {
-               DEBUG(10,("user_in_unix_group: no such group %s\n",
-                         gname ));
-               return False;
-       }
-
-       for (member = user_list; member; member = member->next) {
-               DEBUG(10,("user_in_unix_group: checking user %s against "
-                         "member %s\n", user, member->unix_name ));
-               if (strequal(member->unix_name,user)) {
-                       free_userlist(user_list);
-                       return(True);
-               }
-       }
-
-       free_userlist(user_list);
-       return False;
-}            
-
-/****************************************************************************
- Check if a user is in a group list. Ask winbind first, then use UNIX.
-****************************************************************************/
-
-BOOL user_in_group(const char *user, const char *gname)
-{
-       BOOL winbind_answered = False;
-       BOOL ret;
-
-       ret = user_in_winbind_group(user, gname, &winbind_answered);
-       if (!winbind_answered)
-               ret = user_in_unix_group(user, gname);
-
-       if (ret)
-               DEBUG(10,("user_in_group: user |%s| is in group |%s|\n",
-                         user, gname));
-       return ret;
-}
-
-/****************************************************************************
- Check if a user is in a user list - can check combinations of UNIX
- and netgroup lists.
-****************************************************************************/
-
-BOOL user_in_list(const char *user,const char **list)
-{
-       if (!list || !*list)
-               return False;
-
-       DEBUG(10,("user_in_list: checking user %s in list\n", user));
-
-       while (*list) {
-
-               DEBUG(10,("user_in_list: checking user |%s| against |%s|\n",
-                         user, *list));
-
-               /*
-                * Check raw username.
-                */
-               if (strequal(user, *list))
-                       return(True);
-
-               /*
-                * Now check to see if any combination
-                * of UNIX and netgroups has been specified.
-                */
-
-               if(**list == '@') {
-                       /*
-                        * Old behaviour. Check netgroup list
-                        * followed by UNIX list.
-                        */
-                       if(user_in_netgroup(user, *list +1))
-                               return True;
-                       if(user_in_group(user, *list +1))
-                               return True;
-               } else if (**list == '+') {
-
-                       if((*(*list +1)) == '&') {
-                               /*
-                                * Search UNIX list followed by netgroup.
-                                */
-                               if(user_in_group(user, *list +2))
-                                       return True;
-                               if(user_in_netgroup(user, *list +2))
-                                       return True;
-
-                       } else {
-
-                               /*
-                                * Just search UNIX list.
-                                */
-
-                               if(user_in_group(user, *list +1))
-                                       return True;
-                       }
-
-               } else if (**list == '&') {
-
-                       if(*(*list +1) == '+') {
-                               /*
-                                * Search netgroup list followed by UNIX list.
-                                */
-                               if(user_in_netgroup(user, *list +2))
-                                       return True;
-                               if(user_in_group(user, *list +2))
-                                       return True;
-                       } else {
-                               /*
-                                * Just search netgroup list.
-                                */
-                               if(user_in_netgroup(user, *list +1))
-                                       return True;
-                       }
-               } else if (!name_is_local(*list)) {
-                       /*
-                        * If user name did not match and token is not a unix
-                        * group and the token has a winbind separator in the
-                        * name then see if it is a Windows group.
-                        */
-
-                       DOM_SID g_sid;
-                       enum SID_NAME_USE name_type;
-                       BOOL winbind_answered = False;
-                       BOOL ret;
-                       fstring groupname, domain;
-                       
-                       /* Parse a string of the form DOMAIN/user into a
-                        * domain and a user */
-
-                       char *p = strchr(*list,*lp_winbind_separator());
-                       
-                       DEBUG(10,("user_in_list: checking if user |%s| is in "
-                                 "winbind group |%s|\n", user, *list));
-
-                       if (p) {
-                               fstrcpy(groupname, p+1);
-                               fstrcpy(domain, *list);
-                               domain[PTR_DIFF(p, *list)] = 0;
-
-                               /* Check to see if name is a Windows group;
-                                  Win2k native mode DCs will return domain
-                                  local groups; while NT4 or mixed mode 2k
-                                  DCs will not */
-                       
-                               if ( winbind_lookup_name(domain, groupname,
-                                                        &g_sid, &name_type) 
-                                    && ( name_type==SID_NAME_DOM_GRP || 
-                                         (strequal(lp_workgroup(), domain) &&
-                                          name_type==SID_NAME_ALIAS) ) )
-                               {
-                                       
-                                       /* Check if user name is in the
-                                        * Windows group */
-                                       ret = user_in_winbind_group(
-                                               user, *list,
-                                               &winbind_answered);
-                                       
-                                       if (winbind_answered && ret == True) {
-                                               DEBUG(10,("user_in_list: user "
-                                                         "|%s| is in winbind "
-                                                         "group |%s|\n",
-                                                         user, *list));
-                                               return ret;
-                                       }
-                               }
-                       }
-               }
-    
-               list++;
-       }
-       return(False);
-}
-
 /* The functions below have been taken from password.c and slightly modified */
 /****************************************************************************
  Apply a function to upper/lower case combinations
diff --git a/source3/lib/util_getent.c b/source3/lib/util_getent.c
deleted file mode 100644 (file)
index 7c045fc..0000000
+++ /dev/null
@@ -1,337 +0,0 @@
-/*
-   Unix SMB/CIFS implementation.
-   Samba utility functions
-   Copyright (C) Simo Sorce 2001
-   Copyright (C) Jeremy Allison 2001
-
-   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"
-
-
-/****************************************************************
- Returns a single linked list of group entries.
- Use grent_free() to free it after use.
-****************************************************************/
-
-struct sys_grent * getgrent_list(void)
-{
-       struct sys_grent *glist;
-       struct sys_grent *gent;
-       struct group *grp;
-       
-       gent = SMB_MALLOC_P(struct sys_grent);
-       if (gent == NULL) {
-               DEBUG (0, ("Out of memory in getgrent_list!\n"));
-               return NULL;
-       }
-       memset(gent, '\0', sizeof(struct sys_grent));
-       glist = gent;
-       
-       setgrent();
-       grp = getgrent();
-       if (grp == NULL) {
-               endgrent();
-               SAFE_FREE(glist);
-               return NULL;
-       }
-
-       while (grp != NULL) {
-               int i,num;
-               
-               if (grp->gr_name) {
-                       if ((gent->gr_name = SMB_STRDUP(grp->gr_name)) == NULL)
-                               goto err;
-               }
-               if (grp->gr_passwd) {
-                       if ((gent->gr_passwd = SMB_STRDUP(grp->gr_passwd)) == NULL)
-                               goto err;
-               }
-               gent->gr_gid = grp->gr_gid;
-               
-               /* number of strings in gr_mem */
-               for (num = 0; grp->gr_mem[num]; num++)
-                       ;
-               
-               /* alloc space for gr_mem string pointers */
-               if ((gent->gr_mem = SMB_MALLOC_ARRAY(char *, num+1)) == NULL)
-                       goto err;
-
-               memset(gent->gr_mem, '\0', (num+1) * sizeof(char *));
-
-               for (i=0; i < num; i++) {
-                       if ((gent->gr_mem[i] = SMB_STRDUP(grp->gr_mem[i])) == NULL)
-                               goto err;
-               }
-               gent->gr_mem[num] = NULL;
-               
-               grp = getgrent();
-               if (grp) {
-                       gent->next = SMB_MALLOC_P(struct sys_grent);
-                       if (gent->next == NULL)
-                               goto err;
-                       gent = gent->next;
-                       memset(gent, '\0', sizeof(struct sys_grent));
-               }
-       }
-       
-       endgrent();
-       return glist;
-
-  err:
-
-       endgrent();
-       DEBUG(0, ("Out of memory in getgrent_list!\n"));
-       grent_free(glist);
-       return NULL;
-}
-
-/****************************************************************
- Free the single linked list of group entries made by
- getgrent_list()
-****************************************************************/
-
-void grent_free (struct sys_grent *glist)
-{
-       while (glist) {
-               struct sys_grent *prev;
-               
-               SAFE_FREE(glist->gr_name);
-               SAFE_FREE(glist->gr_passwd);
-               if (glist->gr_mem) {
-                       int i;
-                       for (i = 0; glist->gr_mem[i]; i++)
-                               SAFE_FREE(glist->gr_mem[i]);
-                       SAFE_FREE(glist->gr_mem);
-               }
-               prev = glist;
-               glist = glist->next;
-               SAFE_FREE(prev);
-       }
-}
-
-/****************************************************************
- Returns a single linked list of passwd entries.
- Use pwent_free() to free it after use.
-****************************************************************/
-
-struct sys_pwent * getpwent_list(void)
-{
-       struct sys_pwent *plist;
-       struct sys_pwent *pent;
-       struct passwd *pwd;
-       
-       pent = SMB_MALLOC_P(struct sys_pwent);
-       if (pent == NULL) {
-               DEBUG (0, ("Out of memory in getpwent_list!\n"));
-               return NULL;
-       }
-       plist = pent;
-       
-       setpwent();
-       pwd = getpwent();
-       while (pwd != NULL) {
-               memset(pent, '\0', sizeof(struct sys_pwent));
-               if (pwd->pw_name) {
-                       if ((pent->pw_name = SMB_STRDUP(pwd->pw_name)) == NULL)
-                               goto err;
-               }
-               if (pwd->pw_passwd) {
-                       if ((pent->pw_passwd = SMB_STRDUP(pwd->pw_passwd)) == NULL)
-                               goto err;
-               }
-               pent->pw_uid = pwd->pw_uid;
-               pent->pw_gid = pwd->pw_gid;
-               if (pwd->pw_gecos) {
-                       if ((pent->pw_gecos = SMB_STRDUP(pwd->pw_gecos)) == NULL)
-                               goto err;
-               }
-               if (pwd->pw_dir) {
-                       if ((pent->pw_dir = SMB_STRDUP(pwd->pw_dir)) == NULL)
-                               goto err;
-               }
-               if (pwd->pw_shell) {
-                       if ((pent->pw_shell = SMB_STRDUP(pwd->pw_shell)) == NULL)
-                               goto err;
-               }
-
-               pwd = getpwent();
-               if (pwd) {
-                       pent->next = SMB_MALLOC_P(struct sys_pwent);
-                       if (pent->next == NULL)
-                               goto err;
-                       pent = pent->next;
-               }
-       }
-       
-       endpwent();
-       return plist;
-
-  err:
-
-       endpwent();
-       DEBUG(0, ("Out of memory in getpwent_list!\n"));
-       pwent_free(plist);
-       return NULL;
-}
-
-/****************************************************************
- Free the single linked list of passwd entries made by
- getpwent_list()
-****************************************************************/
-
-void pwent_free (struct sys_pwent *plist)
-{
-       while (plist) {
-               struct sys_pwent *prev;
-               
-               SAFE_FREE(plist->pw_name);
-               SAFE_FREE(plist->pw_passwd);
-               SAFE_FREE(plist->pw_gecos);
-               SAFE_FREE(plist->pw_dir);
-               SAFE_FREE(plist->pw_shell);
-
-               prev = plist;
-               plist = plist->next;
-               SAFE_FREE(prev);
-       }
-}
-
-/****************************************************************
- Add the individual group users onto the list.
-****************************************************************/
-
-static struct sys_userlist *add_members_to_userlist(struct sys_userlist *list_head, const struct group *grp)
-{
-       size_t num_users, i;
-
-       /* Count the number of users. */
-       for (num_users = 0; grp->gr_mem[num_users]; num_users++)
-               ;
-
-       for (i = 0; i < num_users; i++) {
-               struct sys_userlist *entry = SMB_MALLOC_P(struct sys_userlist);
-               if (entry == NULL) {
-                       free_userlist(list_head);
-                       return NULL;
-               }
-               entry->unix_name = (char *)SMB_STRDUP(grp->gr_mem[i]);
-               if (entry->unix_name == NULL) {
-                       SAFE_FREE(entry);
-                       free_userlist(list_head);
-                       return NULL;
-               }
-               DLIST_ADD(list_head, entry);
-       }
-       return list_head;
-}
-
-/*****************************************************************
- Splits passed user or group name to domain and user/group name parts
- Returns True if name was splitted and False otherwise.
-*****************************************************************/
-
-static BOOL split_domain_and_name(const char *name, char *domain,
-                                 char* username)
-{
-       char *p = strchr(name,*lp_winbind_separator());
-       
-       
-       /* Parse a string of the form DOMAIN/user into a domain and a user */
-       DEBUG(10,("split_domain_and_name: checking whether name |%s| local or "
-                 "not\n", name));
-       
-       if (p) {
-               fstrcpy(username, p+1);
-               fstrcpy(domain, name);
-               domain[PTR_DIFF(p, name)] = 0;
-       } else if (lp_winbind_use_default_domain()) {
-               fstrcpy(username, name);
-               fstrcpy(domain, lp_workgroup());
-       } else {
-               return False;
-       }
-
-       DEBUG(10,("split_domain_and_name: all is fine, domain is |%s| and "
-                 "name is |%s|\n", domain, username));
-       return True;
-}
-
-/****************************************************************
- Get the list of UNIX users in a group.
- We have to enumerate the /etc/group file as some UNIX getgrnam()
- calls won't do that for us (notably Tru64 UNIX).
-****************************************************************/
-
-struct sys_userlist *get_users_in_group(const char *gname)
-{
-       struct sys_userlist *list_head = NULL;
-       struct group *gptr;
-       fstring domain;
-       fstring groupname;
-       DOM_SID sid;
-       enum SID_NAME_USE name_type;
-
-       /* No point using winbind if we can't split it in the
-          first place */
-       if (split_domain_and_name(gname, domain, groupname)) {
-
-               /*
-                * If we're doing this via winbindd, don't do the
-                * entire group list enumeration as we know this is
-                * pointless (and slow).
-                */
-               
-               if (winbind_lookup_name(domain, groupname, &sid, &name_type) 
-                   && name_type == SID_NAME_DOM_GRP) {
-                       if ((gptr = (struct group *)getgrnam(gname)) == NULL)
-                               return NULL;
-                       return add_members_to_userlist(list_head, gptr);
-               }
-       }
-       
-#if !defined(BROKEN_GETGRNAM)
-       if ((gptr = (struct group *)getgrnam(gname)) == NULL)
-               return NULL;
-       return add_members_to_userlist(list_head, gptr);
-#else
-       /* BROKEN_GETGRNAM - True64 */
-       setgrent();
-       while((gptr = getgrent()) != NULL) {
-               if (strequal(gname, gptr->gr_name)) {
-                       list_head = add_members_to_userlist(list_head, gptr);
-                       if (list_head == NULL)
-                               return NULL;
-               }
-       }
-       endgrent();
-       return list_head;
-#endif
-}
-
-/****************************************************************
- Free list allocated above.
-****************************************************************/
-
-void free_userlist(struct sys_userlist *list_head)
-{
-       while (list_head) {
-               struct sys_userlist *old_head = list_head;
-               DLIST_REMOVE(list_head, list_head);
-               SAFE_FREE(old_head->unix_name);
-               SAFE_FREE(old_head);
-       }
-}
index 4d203523127ff43e4aeceda2510f6d2850ae6a9d..2b1da6ecce739610ff55c0082f0de5504f052266 100644 (file)
@@ -6,6 +6,7 @@
    Copyright (C) Gerald (Jerry) Carter         2000-2001
    Copyright (C) Andrew Bartlett               2001-2002
    Copyright (C) Simo Sorce                    2003
+   Copyright (C) Volker Lendecke               2006
       
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -844,111 +845,70 @@ BOOL algorithmic_pdb_rid_is_user(uint32 rid)
  Convert a name into a SID. Used in the lookup name rpc.
  ********************************************************************/
 
-BOOL lookup_global_sam_name(const char *c_user, int flags, uint32_t *rid,
+BOOL lookup_global_sam_name(const char *user, int flags, uint32_t *rid,
                            enum SID_NAME_USE *type)
 {
-       fstring user;
-       SAM_ACCOUNT *sam_account = NULL;
-       struct group *grp;
        GROUP_MAP map;
-
-       /*
-        * user may be quoted a const string, and map_username and
-        * friends can modify it. Make a modifiable copy. JRA.
-        */
-
-       fstrcpy(user, c_user);
-
-       (void)map_username(user);
-
-       if (!NT_STATUS_IS_OK(pdb_init_sam(&sam_account))) {
-               return False;
-       }
-       
-       /* BEGIN ROOT BLOCK */
-       
-       become_root();
+       BOOL ret;
 
        /* LOOKUP_NAME_GROUP is a hack to allow valid users = @foo to work
         * correctly in the case where foo also exists as a user. If the flag
         * is set, don't look for users at all. */
 
-       if (((flags & LOOKUP_NAME_GROUP) == 0) &&
-           pdb_getsampwnam(sam_account, user)) {
-               const DOM_SID *user_sid;
+       if ((flags & LOOKUP_NAME_GROUP) == 0) {
+               SAM_ACCOUNT *sam_account = NULL;
+               DOM_SID user_sid;
 
-               unbecome_root();
-
-               user_sid = pdb_get_user_sid(sam_account);
-
-               if (!sid_check_is_in_our_domain(user_sid)) {
-                       DEBUG(0, ("User %s with invalid SID %s in passdb\n",
-                                 user, sid_string_static(user_sid)));
+               if (!NT_STATUS_IS_OK(pdb_init_sam(&sam_account))) {
                        return False;
                }
+       
+               become_root();
+               ret =  pdb_getsampwnam(sam_account, user);
+               unbecome_root();
 
-               sid_peek_rid(user_sid, rid);
-               *type = SID_NAME_USER;
+               if (ret) {
+                       sid_copy(&user_sid, pdb_get_user_sid(sam_account));
+               }
+               
                pdb_free_sam(&sam_account);
-               return True;
-       }
 
-       pdb_free_sam(&sam_account);
-
-       /*
-        * Maybe it was a group ?
-        */
-
-       /* check if it's a mapped group */
-       if (pdb_getgrnam(&map, user)) {
-
-               unbecome_root();
+               if (ret) {
+                       if (!sid_check_is_in_our_domain(&user_sid)) {
+                               DEBUG(0, ("User %s with invalid SID %s in passdb\n",
+                                         user, sid_string_static(&user_sid)));
+                               return False;
+                       }
 
-               /* BUILTIN groups are looked up elsewhere */
-               if (!sid_check_is_in_our_domain(&map.sid)) {
-                       DEBUG(10, ("Found group %s (%s) not in our domain -- "
-                                  "ignoring.", user,
-                                  sid_string_static(&map.sid)));
-                       return False;
+                       sid_peek_rid(&user_sid, rid);
+                       *type = SID_NAME_USER;
+                       return True;
                }
-               
-               /* yes it's a mapped group */
-               sid_peek_rid(&map.sid, rid);
-               *type = map.sid_name_use;
-               return True;
        }
 
-       return False;
+       /*
+        * Maybe it is a group ?
+        */
+
+       become_root();
+       ret = pdb_getgrnam(&map, user);
+       unbecome_root();
 
-       /* it's not a mapped group */
-       grp = getgrnam(user);
-       if(!grp) {
-               unbecome_root();                /* ---> exit form block */      
+       if (!ret) {
                return False;
        }
-               
-       /* 
-        *check if it's mapped, if it is reply it doesn't exist
-        *
-        * that's to prevent this case:
-        *
-        * unix group ug is mapped to nt group ng
-        * someone does a lookup on ug
-        * we must not reply as it doesn't "exist" anymore
-        * for NT. For NT only ng exists.
-        * JFM, 30/11/2001
-        */
-               
-       if (pdb_getgrgid(&map, grp->gr_gid)) {
-               unbecome_root();                /* ---> exit form block */
+
+       /* BUILTIN groups are looked up elsewhere */
+       if (!sid_check_is_in_our_domain(&map.sid)) {
+               DEBUG(10, ("Found group %s (%s) not in our domain -- "
+                          "ignoring.", user,
+                          sid_string_static(&map.sid)));
                return False;
        }
-       unbecome_root();
-       /* END ROOT BLOCK */
-
-       *rid = pdb_gid_to_group_rid(grp->gr_gid);
-       *type = SID_NAME_ALIAS;
 
+       /* yes it's a mapped group */
+       sid_peek_rid(&map.sid, rid);
+       *type = map.sid_name_use;
        return True;
 }
 
@@ -1086,7 +1046,7 @@ NTSTATUS local_password_change(const char *user_name, int local_flags,
        }       
 
        if (local_flags & LOCAL_ADD_USER) {
-               if (pdb_add_sam_account(sam_pass)) {
+               if (NT_STATUS_IS_OK(pdb_add_sam_account(sam_pass))) {
                        slprintf(msg_str, msg_str_len-1, "Added user %s.\n", user_name);
                        pdb_free_sam(&sam_pass);
                        return NT_STATUS_OK;
@@ -1096,7 +1056,7 @@ NTSTATUS local_password_change(const char *user_name, int local_flags,
                        return NT_STATUS_UNSUCCESSFUL;
                }
        } else if (local_flags & LOCAL_DELETE_USER) {
-               if (!pdb_delete_sam_account(sam_pass)) {
+               if (!NT_STATUS_IS_OK(pdb_delete_sam_account(sam_pass))) {
                        slprintf(err_str,err_str_len-1, "Failed to delete entry for user %s.\n", user_name);
                        pdb_free_sam(&sam_pass);
                        return NT_STATUS_UNSUCCESSFUL;
index 479ce18c05c308f0caad10ab050b1ac534d8c7a7..c8917b935646097b6c4688c10fadedf4e9c49fd9 100644 (file)
@@ -4,6 +4,7 @@
    Copyright (C) Andrew Bartlett                       2002
    Copyright (C) Jelmer Vernooij                       2002
    Copyright (C) Simo Sorce                            2003
+   Copyright (C) Volker Lendecke                       2006
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -331,15 +332,141 @@ BOOL pdb_getsampwsid(SAM_ACCOUNT *sam_acct, const DOM_SID *sid)
        return NT_STATUS_IS_OK(pdb->getsampwsid(pdb, sam_acct, sid));
 }
 
-BOOL pdb_add_sam_account(SAM_ACCOUNT *sam_acct) 
+static NTSTATUS pdb_default_create_user(struct pdb_methods *methods,
+                                       TALLOC_CTX *tmp_ctx, const char *name,
+                                       uint32 acb_info, uint32 *rid)
+{
+       SAM_ACCOUNT *sam_pass = NULL;
+       NTSTATUS status;
+
+       if (Get_Pwnam_alloc(tmp_ctx, name) == NULL) {
+               pstring add_script;
+               int add_ret;
+
+               if ((acb_info & ACB_NORMAL) && name[strlen(name)-1] != '$') {
+                       pstrcpy(add_script, lp_adduser_script());
+               } else {
+                       pstrcpy(add_script, lp_addmachine_script());
+               }
+
+               if (add_script[0] == '\0') {
+                       DEBUG(3, ("Could not find user %s and no add script "
+                                 "defined\n", name));
+                       return NT_STATUS_NO_SUCH_USER;
+               }
+
+               all_string_sub(add_script, "%u", name, sizeof(add_script));
+               add_ret = smbrun(add_script,NULL);
+               DEBUG(add_ret ? 0 : 3, ("_samr_create_user: Running the "
+                                       "command `%s' gave %d\n",
+                                       add_script, add_ret));
+       }
+
+       /* implicit call to getpwnam() next.  we have a valid SID coming out
+        * of this call */
+
+       flush_pwnam_cache();
+       status = pdb_init_sam_new(&sam_pass, name);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(3, ("pdb_init_sam_new failed: %s\n", nt_errstr(status)));
+               return status;
+       }
+
+       if (!sid_peek_check_rid(get_global_sam_sid(),
+                               pdb_get_user_sid(sam_pass), rid)) {
+               DEBUG(0, ("Could not get RID of fresh user\n"));
+               return NT_STATUS_INTERNAL_ERROR;
+       }
+
+       /* Disable the account on creation, it does not have a reasonable
+        * password yet. */
+
+       acb_info |= ACB_DISABLED;
+
+       pdb_set_acct_ctrl(sam_pass, acb_info, PDB_CHANGED);
+
+       status = pdb_add_sam_account(sam_pass);
+
+       pdb_free_sam(&sam_pass);
+
+       return status;
+}
+
+NTSTATUS pdb_create_user(TALLOC_CTX *mem_ctx, const char *name, uint32 flags,
+                        uint32 *rid)
 {
        struct pdb_methods *pdb = pdb_get_methods(False);
 
        if ( !pdb ) {
-               return False;
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+
+       return pdb->create_user(pdb, mem_ctx, name, flags, rid);
+}
+
+/****************************************************************************
+ Delete a UNIX user on demand.
+****************************************************************************/
+
+static int smb_delete_user(const char *unix_user)
+{
+       pstring del_script;
+       int ret;
+
+       pstrcpy(del_script, lp_deluser_script());
+       if (! *del_script)
+               return -1;
+       all_string_sub(del_script, "%u", unix_user, sizeof(del_script));
+       ret = smbrun(del_script,NULL);
+       flush_pwnam_cache();
+       DEBUG(ret ? 0 : 3,("smb_delete_user: Running the command `%s' gave %d\n",del_script,ret));
+
+       return ret;
+}
+
+static NTSTATUS pdb_default_delete_user(struct pdb_methods *methods,
+                                       TALLOC_CTX *mem_ctx,
+                                       SAM_ACCOUNT *sam_acct)
+{
+       NTSTATUS status;
+
+       status = pdb_delete_sam_account(sam_acct);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       /*
+        * Now delete the unix side ....
+        * note: we don't check if the delete really happened as the script is
+        * not necessary present and maybe the sysadmin doesn't want to delete
+        * the unix side
+        */
+       smb_delete_user( pdb_get_username(sam_acct) );
+       
+       return status;
+}
+
+NTSTATUS pdb_delete_user(TALLOC_CTX *mem_ctx, SAM_ACCOUNT *sam_acct)
+{
+       struct pdb_methods *pdb = pdb_get_methods(False);
+
+       if ( !pdb ) {
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+
+       return pdb->delete_user(pdb, mem_ctx, sam_acct);
+}
+
+NTSTATUS pdb_add_sam_account(SAM_ACCOUNT *sam_acct) 
+{
+       struct pdb_methods *pdb = pdb_get_methods(False);
+
+       if ( !pdb ) {
+               return NT_STATUS_UNSUCCESSFUL;
        }
        
-       return NT_STATUS_IS_OK(pdb->add_sam_account(pdb, sam_acct));
+       return pdb->add_sam_account(pdb, sam_acct);
 }
 
 NTSTATUS pdb_update_sam_account(SAM_ACCOUNT *sam_acct) 
@@ -358,12 +485,12 @@ NTSTATUS pdb_update_sam_account(SAM_ACCOUNT *sam_acct)
        return pdb->update_sam_account(pdb, sam_acct);
 }
 
-BOOL pdb_delete_sam_account(SAM_ACCOUNT *sam_acct) 
+NTSTATUS pdb_delete_sam_account(SAM_ACCOUNT *sam_acct) 
 {
        struct pdb_methods *pdb = pdb_get_methods(False);
 
        if ( !pdb ) {
-               return False;
+               return NT_STATUS_UNSUCCESSFUL;
        }
 
        if (csamuser != NULL) {
@@ -371,7 +498,7 @@ BOOL pdb_delete_sam_account(SAM_ACCOUNT *sam_acct)
                csamuser = NULL;
        }
 
-       return NT_STATUS_IS_OK(pdb->delete_sam_account(pdb, sam_acct));
+       return pdb->delete_sam_account(pdb, sam_acct);
 }
 
 NTSTATUS pdb_rename_sam_account(SAM_ACCOUNT *oldname, const char *newname)
@@ -434,6 +561,115 @@ BOOL pdb_getgrnam(GROUP_MAP *map, const char *name)
        return NT_STATUS_IS_OK(pdb->getgrnam(pdb, map, name));
 }
 
+static NTSTATUS pdb_default_create_dom_group(struct pdb_methods *methods,
+                                            TALLOC_CTX *mem_ctx,
+                                            const char *name,
+                                            uint32 *rid)
+{
+       DOM_SID group_sid;
+       struct group *grp;
+
+       grp = getgrnam(name);
+
+       if (grp == NULL) {
+               gid_t gid;
+
+               if (smb_create_group(name, &gid) != 0) {
+                       return NT_STATUS_ACCESS_DENIED;
+               }
+
+               grp = getgrgid(gid);
+       }
+
+       if (grp == NULL) {
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
+       if (pdb_rid_algorithm()) {
+               *rid = pdb_gid_to_group_rid( grp->gr_gid );
+       } else {
+               if (!pdb_new_rid(rid)) {
+                       return NT_STATUS_ACCESS_DENIED;
+               }
+       }
+
+       sid_compose(&group_sid, get_global_sam_sid(), *rid);
+               
+       return add_initial_entry(grp->gr_gid, sid_string_static(&group_sid),
+                                SID_NAME_DOM_GRP, name, NULL);
+}
+
+NTSTATUS pdb_create_dom_group(TALLOC_CTX *mem_ctx, const char *name,
+                             uint32 *rid)
+{
+       struct pdb_methods *pdb = pdb_get_methods(False);
+
+       if ( !pdb ) {
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+
+       return pdb->create_dom_group(pdb, mem_ctx, name, rid);
+}
+
+static NTSTATUS pdb_default_delete_dom_group(struct pdb_methods *methods,
+                                            TALLOC_CTX *mem_ctx,
+                                            uint32 rid)
+{
+       DOM_SID group_sid;
+       GROUP_MAP map;
+       NTSTATUS status;
+       struct group *grp;
+       const char *grp_name;
+
+       sid_compose(&group_sid, get_global_sam_sid(), rid);
+
+       if (!get_domain_group_from_sid(group_sid, &map)) {
+               DEBUG(10, ("Could not find group for rid %d\n", rid));
+               return NT_STATUS_NO_SUCH_GROUP;
+       }
+
+       /* We need the group name for the smb_delete_group later on */
+
+       if (map.gid == (gid_t)-1) {
+               return NT_STATUS_NO_SUCH_GROUP;
+       }
+
+       grp = getgrgid(map.gid);
+       if (grp == NULL) {
+               return NT_STATUS_NO_SUCH_GROUP;
+       }
+
+       /* Copy the name, no idea what pdb_delete_group_mapping_entry does.. */
+
+       grp_name = talloc_strdup(mem_ctx, grp->gr_name);
+       if (grp_name == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       status = pdb_delete_group_mapping_entry(group_sid);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       /* Don't check the result of smb_delete_group */
+       
+       smb_delete_group(grp_name);
+
+       return NT_STATUS_OK;
+}
+
+NTSTATUS pdb_delete_dom_group(TALLOC_CTX *mem_ctx, uint32 rid)
+{
+       struct pdb_methods *pdb = pdb_get_methods(False);
+
+       if ( !pdb ) {
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+
+       return pdb->delete_dom_group(pdb, mem_ctx, rid);
+}
+
 NTSTATUS pdb_add_group_mapping_entry(GROUP_MAP *map)
 {
        struct pdb_methods *pdb = pdb_get_methods(False);
@@ -456,15 +692,15 @@ NTSTATUS pdb_update_group_mapping_entry(GROUP_MAP *map)
        return pdb->update_group_mapping_entry(pdb, map);
 }
 
-BOOL pdb_delete_group_mapping_entry(DOM_SID sid)
+NTSTATUS pdb_delete_group_mapping_entry(DOM_SID sid)
 {
        struct pdb_methods *pdb = pdb_get_methods(False);
 
        if ( !pdb ) {
-               return False;
+               return NT_STATUS_UNSUCCESSFUL;
        }
 
-       return NT_STATUS_IS_OK(pdb->delete_group_mapping_entry(pdb, sid));
+       return pdb->delete_group_mapping_entry(pdb, sid);
 }
 
 BOOL pdb_enum_group_mapping(enum SID_NAME_USE sid_name_use, GROUP_MAP **pp_rmap,
@@ -510,6 +746,200 @@ NTSTATUS pdb_enum_group_memberships(TALLOC_CTX *mem_ctx, SAM_ACCOUNT *user,
                pp_sids, pp_gids, p_num_groups);
 }
 
+static NTSTATUS pdb_default_set_unix_primary_group(struct pdb_methods *methods,
+                                                  TALLOC_CTX *mem_ctx,
+                                                  SAM_ACCOUNT *sampass)
+{
+       struct group *grp;
+       gid_t gid;
+
+       if (!sid_to_gid(pdb_get_group_sid(sampass), &gid) ||
+           (grp = getgrgid(gid)) == NULL) {
+               return NT_STATUS_INVALID_PRIMARY_GROUP;
+       }
+
+       if (smb_set_primary_group(grp->gr_name,
+                                 pdb_get_username(sampass)) != 0) {
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
+       return NT_STATUS_OK;
+}
+
+NTSTATUS pdb_set_unix_primary_group(TALLOC_CTX *mem_ctx, SAM_ACCOUNT *user)
+{
+       struct pdb_methods *pdb = pdb_get_methods(False);
+
+       if ( !pdb ) {
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+
+       return pdb->set_unix_primary_group(pdb, mem_ctx, user);
+}
+
+/*
+ * Helper function to see whether a user is in a group. We can't use
+ * user_in_group_sid here because this creates dependencies only smbd can
+ * fulfil.
+ */
+
+static BOOL pdb_user_in_group(TALLOC_CTX *mem_ctx, SAM_ACCOUNT *account,
+                             const DOM_SID *group_sid)
+{
+       DOM_SID *sids;
+       gid_t *gids;
+       size_t i, num_groups;
+
+       if (!NT_STATUS_IS_OK(pdb_enum_group_memberships(mem_ctx, account,
+                                                       &sids, &gids,
+                                                       &num_groups))) {
+               return False;
+       }
+
+       for (i=0; i<num_groups; i++) {
+               if (sid_equal(group_sid, &sids[i])) {
+                       return True;
+               }
+       }
+       return False;
+}
+
+static NTSTATUS pdb_default_add_groupmem(struct pdb_methods *methods,
+                                        TALLOC_CTX *mem_ctx,
+                                        uint32 group_rid,
+                                        uint32 member_rid)
+{
+       DOM_SID group_sid, member_sid;
+       SAM_ACCOUNT *account = NULL;
+       GROUP_MAP map;
+       struct group *grp;
+       struct passwd *pwd;
+       const char *group_name;
+       uid_t uid;
+       NTSTATUS status;
+
+       sid_compose(&group_sid, get_global_sam_sid(), group_rid);
+       sid_compose(&member_sid, get_global_sam_sid(), member_rid);
+
+       if (!get_domain_group_from_sid(group_sid, &map) ||
+           (map.gid == (gid_t)-1) ||
+           ((grp = getgrgid(map.gid)) == NULL)) {
+               return NT_STATUS_NO_SUCH_GROUP;
+       }
+
+       group_name = talloc_strdup(mem_ctx, grp->gr_name);
+       if (group_name == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       if (!NT_STATUS_IS_OK(status = pdb_init_sam(&account))) {
+               return status;
+       }
+
+       if (!pdb_getsampwsid(account, &member_sid) ||
+           !sid_to_uid(&member_sid, &uid) ||
+           ((pwd = getpwuid_alloc(mem_ctx, uid)) == NULL)) {
+               return NT_STATUS_NO_SUCH_USER;
+       }
+
+       if (pdb_user_in_group(mem_ctx, account, &group_sid)) {
+               return NT_STATUS_MEMBER_IN_GROUP;
+       }
+
+       /* 
+        * ok, the group exist, the user exist, the user is not in the group,
+        * we can (finally) add it to the group !
+        */
+
+       smb_add_user_group(group_name, pwd->pw_name);
+
+       if (!pdb_user_in_group(mem_ctx, account, &group_sid)) {
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
+       return NT_STATUS_OK;
+}
+
+NTSTATUS pdb_add_groupmem(TALLOC_CTX *mem_ctx, uint32 group_rid,
+                         uint32 member_rid)
+{
+       struct pdb_methods *pdb = pdb_get_methods(False);
+
+       if ( !pdb ) {
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+
+       return pdb->add_groupmem(pdb, mem_ctx, group_rid, member_rid);
+}
+
+static NTSTATUS pdb_default_del_groupmem(struct pdb_methods *methods,
+                                        TALLOC_CTX *mem_ctx,
+                                        uint32 group_rid,
+                                        uint32 member_rid)
+{
+       DOM_SID group_sid, member_sid;
+       SAM_ACCOUNT *account = NULL;
+       GROUP_MAP map;
+       struct group *grp;
+       struct passwd *pwd;
+       const char *group_name;
+       uid_t uid;
+       NTSTATUS status;
+
+       sid_compose(&group_sid, get_global_sam_sid(), group_rid);
+       sid_compose(&member_sid, get_global_sam_sid(), member_rid);
+
+       if (!get_domain_group_from_sid(group_sid, &map) ||
+           (map.gid == (gid_t)-1) ||
+           ((grp = getgrgid(map.gid)) == NULL)) {
+               return NT_STATUS_NO_SUCH_GROUP;
+       }
+
+       group_name = talloc_strdup(mem_ctx, grp->gr_name);
+       if (group_name == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       if (!NT_STATUS_IS_OK(status = pdb_init_sam(&account))) {
+               return status;
+       }
+
+       if (!pdb_getsampwsid(account, &member_sid) ||
+           !sid_to_uid(&member_sid, &uid) ||
+           ((pwd = getpwuid_alloc(mem_ctx, uid)) == NULL)) {
+               return NT_STATUS_NO_SUCH_USER;
+       }
+
+       if (!pdb_user_in_group(mem_ctx, account, &group_sid)) {
+               return NT_STATUS_MEMBER_NOT_IN_GROUP;
+       }
+
+       /* 
+        * ok, the group exist, the user exist, the user is in the group,
+        * we can (finally) delete it from the group!
+        */
+
+       smb_delete_user_group(group_name, pwd->pw_name);
+
+       if (pdb_user_in_group(mem_ctx, account, &group_sid)) {
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
+       return NT_STATUS_OK;
+}
+
+NTSTATUS pdb_del_groupmem(TALLOC_CTX *mem_ctx, uint32 group_rid,
+                         uint32 member_rid)
+{
+       struct pdb_methods *pdb = pdb_get_methods(False);
+
+       if ( !pdb ) {
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+
+       return pdb->del_groupmem(pdb, mem_ctx, group_rid, member_rid);
+}
+
 BOOL pdb_find_alias(const char *name, DOM_SID *sid)
 {
        struct pdb_methods *pdb = pdb_get_methods(False);
@@ -977,7 +1407,7 @@ static BOOL get_memberuids(TALLOC_CTX *mem_ctx, gid_t gid, uid_t **pp_uids, size
 {
        struct group *grp;
        char **gr;
-       struct sys_pwent *userlist, *user;
+       struct passwd *pwd;
  
        *pp_uids = NULL;
        *p_num = 0;
@@ -993,15 +1423,14 @@ static BOOL get_memberuids(TALLOC_CTX *mem_ctx, gid_t gid, uid_t **pp_uids, size
 
        /* Primary group members */
 
-       userlist = getpwent_list();
-
-       for (user = userlist; user != NULL; user = user->next) {
-               if (user->pw_gid != gid)
-                       continue;
-               add_uid_to_array_unique(mem_ctx, user->pw_uid, pp_uids, p_num);
+       setpwent();
+       while ((pwd = getpwent()) != NULL) {
+               if (pwd->pw_gid == gid) {
+                       add_uid_to_array_unique(mem_ctx, pwd->pw_uid,
+                                               pp_uids, p_num);
+               }
        }
-
-       pwent_free(userlist);
+       endpwent();
 
        /* Secondary group members */
 
@@ -1048,7 +1477,7 @@ NTSTATUS pdb_default_enum_group_members(struct pdb_methods *methods,
                uid_to_sid(&sid, uids[i]);
 
                if (!sid_check_is_in_our_domain(&sid)) {
-                       DEBUG(1, ("Inconsistent SAM -- group member uid not "
+                       DEBUG(5, ("Inconsistent SAM -- group member uid not "
                                  "in our domain\n"));
                        continue;
                }
@@ -1060,6 +1489,44 @@ NTSTATUS pdb_default_enum_group_members(struct pdb_methods *methods,
        return NT_STATUS_OK;
 }
 
+NTSTATUS pdb_default_enum_group_memberships(struct pdb_methods *methods,
+                                           TALLOC_CTX *mem_ctx,
+                                           SAM_ACCOUNT *user,
+                                           DOM_SID **pp_sids,
+                                           gid_t **pp_gids,
+                                           size_t *p_num_groups)
+{
+       size_t i;
+       gid_t gid;
+
+       if (!sid_to_gid(pdb_get_group_sid(user), &gid)) {
+               DEBUG(10, ("sid_to_gid failed\n"));
+               return NT_STATUS_NO_SUCH_USER;
+       }
+
+       if (!getgroups_unix_user(mem_ctx, pdb_get_username(user), gid,
+                                pp_gids, p_num_groups)) {
+               return NT_STATUS_NO_SUCH_USER;
+       }
+
+       if (*p_num_groups == 0) {
+               smb_panic("primary group missing");
+       }
+
+       *pp_sids = TALLOC_ARRAY(mem_ctx, DOM_SID, *p_num_groups);
+
+       if (*pp_sids == NULL) {
+               talloc_free(*pp_gids);
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       for (i=0; i<*p_num_groups; i++) {
+               gid_to_sid(&(*pp_sids)[i], (*pp_gids)[i]);
+       }
+
+       return NT_STATUS_OK;
+}
+
 /*******************************************************************
  Look up a rid in the SAM we're responsible for (i.e. passdb)
  ********************************************************************/
@@ -1603,6 +2070,8 @@ NTSTATUS make_pdb_method( struct pdb_methods **methods )
        (*methods)->getsampwent = pdb_default_getsampwent;
        (*methods)->getsampwnam = pdb_default_getsampwnam;
        (*methods)->getsampwsid = pdb_default_getsampwsid;
+       (*methods)->create_user = pdb_default_create_user;
+       (*methods)->delete_user = pdb_default_delete_user;
        (*methods)->add_sam_account = pdb_default_add_sam_account;
        (*methods)->update_sam_account = pdb_default_update_sam_account;
        (*methods)->delete_sam_account = pdb_default_delete_sam_account;
@@ -1612,12 +2081,17 @@ NTSTATUS make_pdb_method( struct pdb_methods **methods )
        (*methods)->getgrsid = pdb_default_getgrsid;
        (*methods)->getgrgid = pdb_default_getgrgid;
        (*methods)->getgrnam = pdb_default_getgrnam;
+       (*methods)->create_dom_group = pdb_default_create_dom_group;
+       (*methods)->delete_dom_group = pdb_default_delete_dom_group;
        (*methods)->add_group_mapping_entry = pdb_default_add_group_mapping_entry;
        (*methods)->update_group_mapping_entry = pdb_default_update_group_mapping_entry;
        (*methods)->delete_group_mapping_entry = pdb_default_delete_group_mapping_entry;
        (*methods)->enum_group_mapping = pdb_default_enum_group_mapping;
        (*methods)->enum_group_members = pdb_default_enum_group_members;
        (*methods)->enum_group_memberships = pdb_default_enum_group_memberships;
+       (*methods)->set_unix_primary_group = pdb_default_set_unix_primary_group;
+       (*methods)->add_groupmem = pdb_default_add_groupmem;
+       (*methods)->del_groupmem = pdb_default_del_groupmem;
        (*methods)->find_alias = pdb_default_find_alias;
        (*methods)->create_alias = pdb_default_create_alias;
        (*methods)->delete_alias = pdb_default_delete_alias;
index b3be0cccc1565fbcc4c4fbadab1c3f7361bb45bb..133178bd0dffb048fedeaab43b24d1b6e41c8e58 100644 (file)
@@ -2410,18 +2410,13 @@ static NTSTATUS can_create(TALLOC_CTX *mem_ctx, const char *new_name)
 NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u,
                           SAMR_R_CREATE_USER *r_u)
 {
-       SAM_ACCOUNT *sam_pass=NULL;
-       fstring account;
+       char *account;
        DOM_SID sid;
-       pstring add_script;
        POLICY_HND dom_pol = q_u->domain_pol;
-       UNISTR2 user_account = q_u->uni_name;
        uint16 acb_info = q_u->acb_info;
        POLICY_HND *user_pol = &r_u->user_pol;
        struct samr_info *info = NULL;
-       BOOL ret;
        NTSTATUS nt_status;
-       struct passwd *pw;
        uint32 acc_granted;
        SEC_DESC *psd;
        size_t    sd_size;
@@ -2450,33 +2445,20 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u,
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       rpcstr_pull(account, user_account.buffer, sizeof(account),
-                   user_account.uni_str_len*2, 0);
-       strlower_m(account);
+       account = rpcstr_pull_unistr2_talloc(p->mem_ctx, &q_u->uni_name);
+       if (account == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
 
        nt_status = can_create(p->mem_ctx, account);
        if (!NT_STATUS_IS_OK(nt_status)) {
                return nt_status;
        }
 
-       /*********************************************************************
-        * HEADS UP!  If we have to create a new user account, we have to get
-        * a new RID from somewhere.  This used to be done by the passdb
-        * backend. It has been moved into idmap now.  Since idmap is now
-        * wrapped up behind winbind, this means you have to run winbindd if
-        * you want new accounts to get a new RID when "enable rid algorithm =
-        * no".  Tough.  We now have a uniform way of allocating RIDs
-        * regardless of what ever passdb backend people may use.  --jerry
-        * (2003-07-10)
-        *********************************************************************/
-
-       pw = Get_Pwnam(account);
-
        /* determine which user right we need to check based on the acb_info */
        
        if ( acb_info & ACB_WSTRUST )
        {
-               pstrcpy(add_script, lp_addmachine_script());
                se_priv_copy( &se_rights, &se_machine_account );
                can_add_account = user_has_privileges(
                        p->pipe_user.nt_user_token, &se_rights );
@@ -2486,7 +2468,6 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u,
        else if ( acb_info & ACB_NORMAL &&
                  (account[strlen(account)-1] != '$') )
        {
-               pstrcpy(add_script, lp_adduser_script());
                se_priv_copy( &se_rights, &se_add_users );
                can_add_account = user_has_privileges(
                        p->pipe_user.nt_user_token, &se_rights );
@@ -2494,7 +2475,6 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u,
        else    /* implicit assumption of a BDC or domain trust account here
                 * (we already check the flags earlier) */
        {
-               pstrcpy(add_script, lp_addmachine_script());
                if ( lp_enable_privileges() ) {
                        /* only Domain Admins can add a BDC or domain trust */
                        se_priv_copy( &se_rights, &se_priv_none );
@@ -2512,40 +2492,9 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u,
        if ( can_add_account )
                become_root();
 
-       if ( !pw ) {
-               if (*add_script) {
-                       int add_ret;
-
-                       all_string_sub(add_script, "%u", account,
-                                      sizeof(add_script));
-                       add_ret = smbrun(add_script,NULL);
-                       DEBUG(add_ret ? 0 : 3,("_samr_create_user: Running "
-                                              "the command `%s' gave %d\n",
-                                              add_script, add_ret));
-               }
-       }
-
-       /* implicit call to getpwnam() next.  we have a valid SID coming out
-        * of this call */
+       nt_status = pdb_create_user(p->mem_ctx, account, acb_info,
+                                   &r_u->user_rid);
 
-       flush_pwnam_cache();
-       nt_status = pdb_init_sam_new(&sam_pass, account);
-
-       /* this code is order such that we have no unnecessary retuns 
-          out of the admin block of code */    
-          
-       if ( NT_STATUS_IS_OK(nt_status) ) {
-               pdb_set_acct_ctrl(sam_pass, acb_info, PDB_CHANGED);
-       
-               if ( !(ret = pdb_add_sam_account(sam_pass)) ) {
-                       pdb_free_sam(&sam_pass);
-                       DEBUG(0, ("could not add user/computer %s to passdb. "
-                                 "Check permissions?\n", 
-                               account));
-                       nt_status = NT_STATUS_ACCESS_DENIED;
-               }
-       }
-               
        if ( can_add_account )
                unbecome_root();
 
@@ -2557,8 +2506,8 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u,
                return nt_status;
                        
        /* Get the user's SID */
-       
-       sid_copy(&sid, pdb_get_user_sid(sam_pass));
+
+       sid_compose(&sid, get_global_sam_sid(), r_u->user_rid);
        
        make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &usr_generic_mapping,
                            &sid, SAMR_USR_RIGHTS_WRITE_PW);
@@ -2574,7 +2523,6 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u,
 
        /* associate the user's SID with the new handle. */
        if ((info = get_samr_info_by_sid(&sid)) == NULL) {
-               pdb_free_sam(&sam_pass);
                return NT_STATUS_NO_MEMORY;
        }
 
@@ -2584,19 +2532,14 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u,
 
        /* get a (unique) handle.  open a policy on it. */
        if (!create_policy_hnd(p, user_pol, free_samr_info, (void *)info)) {
-               pdb_free_sam(&sam_pass);
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
        }
 
        /* After a "set" ensure we have no cached display info. */
        force_flush_samr_cache(info->disp_info);
 
-       r_u->user_rid=pdb_get_user_rid(sam_pass);
-
        r_u->access_granted = acc_granted;
 
-       pdb_free_sam(&sam_pass);
-
        return NT_STATUS_OK;
 }
 
@@ -3097,41 +3040,6 @@ static BOOL set_user_info_18(SAM_USER_INFO_18 *id18, SAM_ACCOUNT *pwd)
        return True;
 }
 
-/*******************************************************************
- The GROUPSID field in the SAM_ACCOUNT changed. Try to tell unix.
- ********************************************************************/
-static BOOL set_unix_primary_group(SAM_ACCOUNT *sampass)
-{
-       struct group *grp;
-       gid_t gid;
-
-       if (!sid_to_gid(pdb_get_group_sid(sampass), &gid)) {
-               DEBUG(2,("Could not get gid for primary group of "
-                        "user %s\n", pdb_get_username(sampass)));
-               return False;
-       }
-
-       grp = getgrgid(gid);
-
-       if (grp == NULL) {
-               DEBUG(2,("Could not find primary group %lu for "
-                        "user %s\n", (unsigned long)gid, 
-                        pdb_get_username(sampass)));
-               return False;
-       }
-
-       if (smb_set_primary_group(grp->gr_name,
-                                 pdb_get_username(sampass)) != 0) {
-               DEBUG(2,("Could not set primary group for user %s to "
-                        "%s\n",
-                        pdb_get_username(sampass), grp->gr_name));
-               return False;
-       }
-
-       return True;
-}
-       
-
 /*******************************************************************
  set_user_info_20
  ********************************************************************/
@@ -3159,12 +3067,14 @@ static BOOL set_user_info_20(SAM_USER_INFO_20 *id20, SAM_ACCOUNT *pwd)
  set_user_info_21
  ********************************************************************/
 
-static BOOL set_user_info_21(SAM_USER_INFO_21 *id21, SAM_ACCOUNT *pwd)
+static NTSTATUS set_user_info_21(TALLOC_CTX *mem_ctx, SAM_USER_INFO_21 *id21,
+                                SAM_ACCOUNT *pwd)
 {
+       NTSTATUS status;
+
        if (id21 == NULL) {
                DEBUG(5, ("set_user_info_21: NULL id21\n"));
-               return False;
+               return NT_STATUS_INVALID_PARAMETER;
        }
  
        copy_id21_to_sam_passwd(pwd, id21);
@@ -3176,33 +3086,38 @@ static BOOL set_user_info_21(SAM_USER_INFO_21 *id21, SAM_ACCOUNT *pwd)
         * id21.  I don't know if they need to be set.    --jerry
         */
  
-       if (IS_SAM_CHANGED(pwd, PDB_GROUPSID))
-               set_unix_primary_group(pwd);
+       if (IS_SAM_CHANGED(pwd, PDB_GROUPSID) &&
+           !NT_STATUS_IS_OK(status = pdb_set_unix_primary_group(mem_ctx,
+                                                                pwd))) {
+               return status;
+       }
 
        /* write the change out */
-       if(!NT_STATUS_IS_OK(pdb_update_sam_account(pwd))) {
+       if(!NT_STATUS_IS_OK(status = pdb_update_sam_account(pwd))) {
                pdb_free_sam(&pwd);
-               return False;
+               return status;
        }
 
        pdb_free_sam(&pwd);
 
-       return True;
+       return NT_STATUS_OK;
 }
 
 /*******************************************************************
  set_user_info_23
  ********************************************************************/
 
-static BOOL set_user_info_23(SAM_USER_INFO_23 *id23, SAM_ACCOUNT *pwd)
+static NTSTATUS set_user_info_23(TALLOC_CTX *mem_ctx, SAM_USER_INFO_23 *id23,
+                                SAM_ACCOUNT *pwd)
 {
        pstring plaintext_buf;
        uint32 len;
        uint16 acct_ctrl;
+       NTSTATUS status;
  
        if (id23 == NULL) {
                DEBUG(5, ("set_user_info_23: NULL id23\n"));
-               return False;
+               return NT_STATUS_INVALID_PARAMETER;
        }
  
        DEBUG(5, ("Attempting administrator password change (level 23) for user %s\n",
@@ -3212,12 +3127,12 @@ static BOOL set_user_info_23(SAM_USER_INFO_23 *id23, SAM_ACCOUNT *pwd)
 
        if (!decode_pw_buffer(id23->pass, plaintext_buf, 256, &len, STR_UNICODE)) {
                pdb_free_sam(&pwd);
-               return False;
+               return NT_STATUS_INVALID_PARAMETER;
        }
   
        if (!pdb_set_plaintext_passwd (pwd, plaintext_buf)) {
                pdb_free_sam(&pwd);
-               return False;
+               return NT_STATUS_ACCESS_DENIED;
        }
  
        copy_id23_to_sam_passwd(pwd, id23);
@@ -3237,24 +3152,28 @@ static BOOL set_user_info_23(SAM_USER_INFO_23 *id23, SAM_ACCOUNT *pwd)
                        
                        if(!chgpasswd(pdb_get_username(pwd), passwd, "", plaintext_buf, True)) {
                                pdb_free_sam(&pwd);
-                               return False;
+                               return NT_STATUS_ACCESS_DENIED;
                        }
                }
        }
  
        ZERO_STRUCT(plaintext_buf);
  
-       if (IS_SAM_CHANGED(pwd, PDB_GROUPSID))
-               set_unix_primary_group(pwd);
+       if (IS_SAM_CHANGED(pwd, PDB_GROUPSID) &&
+           (!NT_STATUS_IS_OK(status =  pdb_set_unix_primary_group(mem_ctx,
+                                                                  pwd)))) {
+               pdb_free_sam(&pwd);
+               return status;
+       }
 
-       if(!NT_STATUS_IS_OK(pdb_update_sam_account(pwd))) {
+       if(!NT_STATUS_IS_OK(status = pdb_update_sam_account(pwd))) {
                pdb_free_sam(&pwd);
-               return False;
+               return status;
        }
  
        pdb_free_sam(&pwd);
 
-       return True;
+       return NT_STATUS_OK;
 }
 
 /*******************************************************************
@@ -3444,8 +3363,8 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE
 
                        dump_data(100, (char *)ctr->info.id23->pass, 516);
 
-                       if (!set_user_info_23(ctr->info.id23, pwd))
-                               r_u->status = NT_STATUS_ACCESS_DENIED;
+                       r_u->status = set_user_info_23(p->mem_ctx,
+                                                      ctr->info.id23, pwd);
                        break;
 
                default:
@@ -3558,8 +3477,8 @@ NTSTATUS _samr_set_userinfo2(pipes_struct *p, SAMR_Q_SET_USERINFO2 *q_u, SAMR_R_
                                r_u->status = NT_STATUS_ACCESS_DENIED;
                        break;
                case 21:
-                       if (!set_user_info_21(ctr->info.id21, pwd))
-                               return NT_STATUS_ACCESS_DENIED;
+                       r_u->status = set_user_info_21(p->mem_ctx,
+                                                      ctr->info.id21, pwd);
                        break;
                case 23:
                        if (!p->session_key.length) {
@@ -3569,8 +3488,8 @@ NTSTATUS _samr_set_userinfo2(pipes_struct *p, SAMR_Q_SET_USERINFO2 *q_u, SAMR_R_
 
                        dump_data(100, (char *)ctr->info.id23->pass, 516);
 
-                       if (!set_user_info_23(ctr->info.id23, pwd))
-                               r_u->status = NT_STATUS_ACCESS_DENIED;
+                       r_u->status = set_user_info_23(p->mem_ctx,
+                                                      ctr->info.id23, pwd);
                        break;
                case 26:
                        if (!p->session_key.length) {
@@ -3713,70 +3632,6 @@ NTSTATUS _samr_query_aliasmem(pipes_struct *p, SAMR_Q_QUERY_ALIASMEM *q_u, SAMR_
        return NT_STATUS_OK;
 }
 
-static void add_uid_to_array_unique(uid_t uid, uid_t **uids, int *num)
-{
-       int i;
-
-       for (i=0; i<*num; i++) {
-               if ((*uids)[i] == uid)
-                       return;
-       }
-       
-       *uids = SMB_REALLOC_ARRAY(*uids, uid_t, *num+1);
-
-       if (*uids == NULL)
-               return;
-
-       (*uids)[*num] = uid;
-       *num += 1;
-}
-
-
-static BOOL get_memberuids(gid_t gid, uid_t **uids, int *num)
-{
-       struct group *grp;
-       char **gr;
-       struct sys_pwent *userlist, *user;
-       *uids = NULL;
-       *num = 0;
-
-       /* We only look at our own sam, so don't care about imported stuff */
-
-       winbind_off();
-
-       if ((grp = getgrgid(gid)) == NULL) {
-               winbind_on();
-               return False;
-       }
-
-       /* Primary group members */
-
-       userlist = getpwent_list();
-
-       for (user = userlist; user != NULL; user = user->next) {
-               if (user->pw_gid != gid)
-                       continue;
-               add_uid_to_array_unique(user->pw_uid, uids, num);
-       }
-
-       pwent_free(userlist);
-
-       /* Secondary group members */
-
-       for (gr = grp->gr_mem; (*gr != NULL) && ((*gr)[0] != '\0'); gr += 1) {
-               struct passwd *pw = getpwnam(*gr);
-
-               if (pw == NULL)
-                       continue;
-               add_uid_to_array_unique(pw->pw_uid, uids, num);
-       }
-
-       winbind_on();
-
-       return True;
-}      
-
 /*********************************************************************
  _samr_query_groupmem
 *********************************************************************/
@@ -3931,16 +3786,7 @@ NTSTATUS _samr_del_aliasmem(pipes_struct *p, SAMR_Q_DEL_ALIASMEM *q_u, SAMR_R_DE
 NTSTATUS _samr_add_groupmem(pipes_struct *p, SAMR_Q_ADD_GROUPMEM *q_u, SAMR_R_ADD_GROUPMEM *r_u)
 {
        DOM_SID group_sid;
-       DOM_SID user_sid;
-       fstring group_sid_str;
-       uid_t uid;
-       struct passwd *pwd;
-       struct group *grp;
-       fstring grp_name;
-       GROUP_MAP map;
-       NTSTATUS ret;
-       SAM_ACCOUNT *sam_user=NULL;
-       BOOL check;
+       uint32 group_rid;
        uint32 acc_granted;
        SE_PRIV se_rights;
        BOOL can_add_accounts;
@@ -3954,53 +3800,11 @@ NTSTATUS _samr_add_groupmem(pipes_struct *p, SAMR_Q_ADD_GROUPMEM *q_u, SAMR_R_AD
                return r_u->status;
        }
 
-       sid_to_string(group_sid_str, &group_sid);
-       DEBUG(10, ("sid is %s\n", group_sid_str));
-
-       if (sid_compare(&group_sid, get_global_sam_sid())<=0)
-               return NT_STATUS_NO_SUCH_GROUP;
-
-       DEBUG(10, ("lookup on Domain SID\n"));
-
-       if(!get_domain_group_from_sid(group_sid, &map))
-               return NT_STATUS_NO_SUCH_GROUP;
-
-       sid_copy(&user_sid, get_global_sam_sid());
-       sid_append_rid(&user_sid, q_u->rid);
-
-       ret = pdb_init_sam(&sam_user);
-       if (!NT_STATUS_IS_OK(ret))
-               return ret;
-       
-       check = pdb_getsampwsid(sam_user, &user_sid);
-       
-       if (check != True) {
-               pdb_free_sam(&sam_user);
-               return NT_STATUS_NO_SUCH_USER;
-       }
+       DEBUG(10, ("sid is %s\n", sid_string_static(&group_sid)));
 
-       /* check a real user exist before we run the script to add a user to a group */
-       if (!sid_to_uid(pdb_get_user_sid(sam_user), &uid)) {
-               pdb_free_sam(&sam_user);
-               return NT_STATUS_NO_SUCH_USER;
-       }
-
-       pdb_free_sam(&sam_user);
-
-       if ((pwd=getpwuid_alloc(p->mem_ctx, uid)) == NULL) {
-               return NT_STATUS_NO_SUCH_USER;
-       }
-
-       if ((grp=getgrgid(map.gid)) == NULL) {
-               return NT_STATUS_NO_SUCH_GROUP;
-       }
-
-       /* we need to copy the name otherwise it's overloaded in user_in_unix_group_list */
-       fstrcpy(grp_name, grp->gr_name);
-
-       /* if the user is already in the group */
-       if(user_in_unix_group(pwd->pw_name, grp_name)) {
-               return NT_STATUS_MEMBER_IN_GROUP;
+       if (!sid_peek_check_rid(get_global_sam_sid(), &group_sid,
+                               &group_rid)) {
+               return NT_STATUS_INVALID_HANDLE;
        }
 
        se_priv_copy( &se_rights, &se_add_users );
@@ -4010,28 +3814,17 @@ NTSTATUS _samr_add_groupmem(pipes_struct *p, SAMR_Q_ADD_GROUPMEM *q_u, SAMR_R_AD
        
        if ( can_add_accounts )
                become_root();
-               
-       /* 
-        * ok, the group exist, the user exist, the user is not in the group,
-        *
-        * we can (finally) add it to the group !
-        */
-
-       smb_add_user_group(grp_name, pwd->pw_name);
 
+       r_u->status = pdb_add_groupmem(p->mem_ctx, group_rid, q_u->rid);
+               
        if ( can_add_accounts )
                unbecome_root();
                
        /******** END SeAddUsers BLOCK *********/
        
-       /* check if the user has been added then ... */
-       if(!user_in_unix_group(pwd->pw_name, grp_name)) {
-               return NT_STATUS_MEMBER_NOT_IN_GROUP;           /* don't know what to reply else */
-       }
-
        force_flush_samr_cache(disp_info);
 
-       return NT_STATUS_OK;
+       return r_u->status;
 }
 
 /*********************************************************************
@@ -4041,11 +3834,7 @@ NTSTATUS _samr_add_groupmem(pipes_struct *p, SAMR_Q_ADD_GROUPMEM *q_u, SAMR_R_AD
 NTSTATUS _samr_del_groupmem(pipes_struct *p, SAMR_Q_DEL_GROUPMEM *q_u, SAMR_R_DEL_GROUPMEM *r_u)
 {
        DOM_SID group_sid;
-       DOM_SID user_sid;
-       SAM_ACCOUNT *sam_pass=NULL;
-       GROUP_MAP map;
-       fstring grp_name;
-       struct group *grp;
+       uint32 group_rid;
        uint32 acc_granted;
        SE_PRIV se_rights;
        BOOL can_add_accounts;
@@ -4064,36 +3853,11 @@ NTSTATUS _samr_del_groupmem(pipes_struct *p, SAMR_Q_DEL_GROUPMEM *q_u, SAMR_R_DE
        if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, SA_RIGHT_GROUP_REMOVE_MEMBER, "_samr_del_groupmem"))) {
                return r_u->status;
        }
-               
-       if (!sid_check_is_in_our_domain(&group_sid))
-               return NT_STATUS_NO_SUCH_GROUP;
-
-       sid_copy(&user_sid, get_global_sam_sid());
-       sid_append_rid(&user_sid, q_u->rid);
-
-       if (!get_domain_group_from_sid(group_sid, &map))
-               return NT_STATUS_NO_SUCH_GROUP;
-
-       if ((grp=getgrgid(map.gid)) == NULL)
-               return NT_STATUS_NO_SUCH_GROUP;
-
-       /* we need to copy the name otherwise it's overloaded in user_in_group_list */
-       fstrcpy(grp_name, grp->gr_name);
-
-       /* check if the user exists before trying to remove it from the group */
-       pdb_init_sam(&sam_pass);
-       if (!pdb_getsampwsid(sam_pass, &user_sid)) {
-               DEBUG(5,("User %s doesn't exist.\n", pdb_get_username(sam_pass)));
-               pdb_free_sam(&sam_pass);
-               return NT_STATUS_NO_SUCH_USER;
-       }
 
-       /* if the user is not in the group */
-       if (!user_in_unix_group(pdb_get_username(sam_pass), grp_name)) {
-               pdb_free_sam(&sam_pass);
-               return NT_STATUS_MEMBER_NOT_IN_GROUP;
+       if (!sid_peek_check_rid(get_global_sam_sid(), &group_sid,
+                               &group_rid)) {
+               return NT_STATUS_INVALID_HANDLE;
        }
-       
 
        se_priv_copy( &se_rights, &se_add_users );
        can_add_accounts = user_has_privileges( p->pipe_user.nt_user_token, &se_rights );
@@ -4103,45 +3867,16 @@ NTSTATUS _samr_del_groupmem(pipes_struct *p, SAMR_Q_DEL_GROUPMEM *q_u, SAMR_R_DE
        if ( can_add_accounts )
                become_root();
                
-       smb_delete_user_group(grp_name, pdb_get_username(sam_pass));
+       r_u->status = pdb_del_groupmem(p->mem_ctx, group_rid, q_u->rid);
 
        if ( can_add_accounts )
                unbecome_root();
                
        /******** END SeAddUsers BLOCK *********/
        
-       /* check if the user has been removed then ... */
-       if (user_in_unix_group(pdb_get_username(sam_pass), grp_name)) {
-               pdb_free_sam(&sam_pass);
-               return NT_STATUS_ACCESS_DENIED;         /* don't know what to reply else */
-       }
-       
-       pdb_free_sam(&sam_pass);
-
        force_flush_samr_cache(disp_info);
 
-       return NT_STATUS_OK;
-
-}
-
-/****************************************************************************
- Delete a UNIX user on demand.
-****************************************************************************/
-
-static int smb_delete_user(const char *unix_user)
-{
-       pstring del_script;
-       int ret;
-
-       pstrcpy(del_script, lp_deluser_script());
-       if (! *del_script)
-               return -1;
-       all_string_sub(del_script, "%u", unix_user, sizeof(del_script));
-       ret = smbrun(del_script,NULL);
-       flush_pwnam_cache();
-       DEBUG(ret ? 0 : 3,("smb_delete_user: Running the command `%s' gave %d\n",del_script,ret));
-
-       return ret;
+       return r_u->status;
 }
 
 /*********************************************************************
@@ -4154,7 +3889,6 @@ NTSTATUS _samr_delete_dom_user(pipes_struct *p, SAMR_Q_DELETE_DOM_USER *q_u, SAM
        SAM_ACCOUNT *sam_pass=NULL;
        uint32 acc_granted;
        BOOL can_add_accounts;
-       BOOL ret;
        DISP_INFO *disp_info = NULL;
 
        DEBUG(5, ("_samr_delete_dom_user: %d\n", __LINE__));
@@ -4186,29 +3920,19 @@ NTSTATUS _samr_delete_dom_user(pipes_struct *p, SAMR_Q_DELETE_DOM_USER *q_u, SAM
        if ( can_add_accounts )
                become_root();
 
-       /* First delete the samba side....
-          code is order to prevent unnecessary returns out of the admin 
-          block of code */
-          
-       if ( (ret = pdb_delete_sam_account(sam_pass)) == True ) {
-               /*
-                * Now delete the unix side ....
-                * note: we don't check if the delete really happened
-                * as the script is not necessary present
-                * and maybe the sysadmin doesn't want to delete the unix side
-                */
-               smb_delete_user( pdb_get_username(sam_pass) );
-       }
-       
+       r_u->status = pdb_delete_user(p->mem_ctx, sam_pass);
+
        if ( can_add_accounts )
                unbecome_root();
                
        /******** END SeAddUsers BLOCK *********/
                
-       if ( !ret ) {
-               DEBUG(5,("_samr_delete_dom_user:Failed to delete entry for user %s.\n", pdb_get_username(sam_pass)));
+       if ( !NT_STATUS_IS_OK(r_u->status) ) {
+               DEBUG(5,("_samr_delete_dom_user: Failed to delete entry for "
+                        "user %s: %s.\n", pdb_get_username(sam_pass),
+                        nt_errstr(r_u->status)));
                pdb_free_sam(&sam_pass);
-               return NT_STATUS_CANNOT_DELETE;
+               return r_u->status;
        }
 
 
@@ -4229,16 +3953,10 @@ NTSTATUS _samr_delete_dom_user(pipes_struct *p, SAMR_Q_DELETE_DOM_USER *q_u, SAM
 NTSTATUS _samr_delete_dom_group(pipes_struct *p, SAMR_Q_DELETE_DOM_GROUP *q_u, SAMR_R_DELETE_DOM_GROUP *r_u)
 {
        DOM_SID group_sid;
-       DOM_SID dom_sid;
        uint32 group_rid;
-       fstring group_sid_str;
-       gid_t gid;
-       struct group *grp;
-       GROUP_MAP map;
        uint32 acc_granted;
        SE_PRIV se_rights;
        BOOL can_add_accounts;
-       BOOL ret;
        DISP_INFO *disp_info = NULL;
 
        DEBUG(5, ("samr_delete_dom_group: %d\n", __LINE__));
@@ -4250,27 +3968,13 @@ NTSTATUS _samr_delete_dom_group(pipes_struct *p, SAMR_Q_DELETE_DOM_GROUP *q_u, S
        if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, STD_RIGHT_DELETE_ACCESS, "_samr_delete_dom_group"))) {
                return r_u->status;
        }
-               
-       sid_copy(&dom_sid, &group_sid);
-       sid_to_string(group_sid_str, &dom_sid);
-       sid_split_rid(&dom_sid, &group_rid);
 
-       DEBUG(10, ("sid is %s\n", group_sid_str));
+       DEBUG(10, ("sid is %s\n", sid_string_static(&group_sid)));
 
-       /* we check if it's our SID before deleting */
-       if (!sid_equal(&dom_sid, get_global_sam_sid()))
-               return NT_STATUS_NO_SUCH_GROUP;
-
-       DEBUG(10, ("lookup on Domain SID\n"));
-
-       if(!get_domain_group_from_sid(group_sid, &map))
-               return NT_STATUS_NO_SUCH_GROUP;
-
-       gid=map.gid;
-
-       /* check if group really exists */
-       if ( (grp=getgrgid(gid)) == NULL) 
+       if (!sid_peek_check_rid(get_global_sam_sid(), &group_sid,
+                               &group_rid)) {
                return NT_STATUS_NO_SUCH_GROUP;
+       }
 
        se_priv_copy( &se_rights, &se_add_users );
        can_add_accounts = user_has_privileges( p->pipe_user.nt_user_token, &se_rights );
@@ -4280,26 +3984,21 @@ NTSTATUS _samr_delete_dom_group(pipes_struct *p, SAMR_Q_DELETE_DOM_GROUP *q_u, S
        if ( can_add_accounts )
                become_root();
 
-       /* delete mapping first */
-       
-       if ( (ret = pdb_delete_group_mapping_entry(group_sid)) == True ) {
-               smb_delete_group( grp->gr_name );
-       }
+       r_u->status = pdb_delete_dom_group(p->mem_ctx, group_rid);
 
        if ( can_add_accounts )
                unbecome_root();
                
        /******** END SeAddUsers BLOCK *********/
        
-       if ( !ret ) {
-               DEBUG(5,("_samr_delete_dom_group: Failed to delete mapping entry for group %s.\n", 
-                       group_sid_str));
-               return NT_STATUS_ACCESS_DENIED;
+       if ( !NT_STATUS_IS_OK(r_u->status) ) {
+               DEBUG(5,("_samr_delete_dom_group: Failed to delete mapping "
+                        "entry for group %s: %s\n",
+                        sid_string_static(&group_sid),
+                        nt_errstr(r_u->status)));
+               return r_u->status;
        }
        
-       /* don't check that the unix group has been deleted.  Work like 
-          _samr_delet_dom_user() */
-
        if (!close_policy_hnd(p, &q_u->group_pol))
                return NT_STATUS_OBJECT_NAME_INVALID;
 
@@ -4373,15 +4072,11 @@ NTSTATUS _samr_create_dom_group(pipes_struct *p, SAMR_Q_CREATE_DOM_GROUP *q_u, S
 {
        DOM_SID dom_sid;
        DOM_SID info_sid;
-       fstring name;
-       fstring sid_string;
-       struct group *grp;
+       const char *name;
        struct samr_info *info;
        uint32 acc_granted;
-       gid_t gid;
        SE_PRIV se_rights;
        BOOL can_add_accounts;
-       NTSTATUS result;
        DISP_INFO *disp_info = NULL;
 
        /* Find the policy handle. Open a policy on it. */
@@ -4395,7 +4090,10 @@ NTSTATUS _samr_create_dom_group(pipes_struct *p, SAMR_Q_CREATE_DOM_GROUP *q_u, S
        if (!sid_equal(&dom_sid, get_global_sam_sid()))
                return NT_STATUS_ACCESS_DENIED;
 
-       unistr2_to_ascii(name, &q_u->uni_acct_desc, sizeof(name)-1);
+       name = rpcstr_pull_unistr2_talloc(p->mem_ctx, &q_u->uni_acct_desc);
+       if (name == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
 
        r_u->status = can_create(p->mem_ctx, name);
        if (!NT_STATUS_IS_OK(r_u->status)) {
@@ -4412,35 +4110,7 @@ NTSTATUS _samr_create_dom_group(pipes_struct *p, SAMR_Q_CREATE_DOM_GROUP *q_u, S
        
        /* check that we successfully create the UNIX group */
        
-       result = NT_STATUS_ACCESS_DENIED;
-       if ( (smb_create_group(name, &gid) == 0) && ((grp=getgrgid(gid)) != NULL) ) {
-       
-               /* so far, so good */
-               
-               result = NT_STATUS_OK;
-
-               if (pdb_rid_algorithm()) {
-                       r_u->rid = pdb_gid_to_group_rid( grp->gr_gid );
-               } else {
-                       if (!pdb_new_rid(&r_u->rid)) {
-                               result = NT_STATUS_ACCESS_DENIED;
-                       }
-               }
-
-               if (NT_STATUS_IS_OK(result)) {
-
-                       /* add the group to the mapping table */
-               
-                       sid_copy( &info_sid, get_global_sam_sid() );
-                       sid_append_rid( &info_sid, r_u->rid );
-                       sid_to_string( sid_string, &info_sid );
-               
-                       /* reset the error code if we fail to add the mapping entry */
-               
-                       if ( !add_initial_entry(grp->gr_gid, sid_string, SID_NAME_DOM_GRP, name, NULL) )
-                               result = NT_STATUS_ACCESS_DENIED;
-               }
-       }
+       r_u->status = pdb_create_dom_group(p->mem_ctx, name, &r_u->rid);
 
        if ( can_add_accounts )
                unbecome_root();
@@ -4449,13 +4119,14 @@ NTSTATUS _samr_create_dom_group(pipes_struct *p, SAMR_Q_CREATE_DOM_GROUP *q_u, S
        
        /* check if we should bail out here */
        
-       if ( !NT_STATUS_IS_OK(result) )
-               return result;
+       if ( !NT_STATUS_IS_OK(r_u->status) )
+               return r_u->status;
+
+       sid_compose(&info_sid, get_global_sam_sid(), r_u->rid);
        
        if ((info = get_samr_info_by_sid(&info_sid)) == NULL)
                return NT_STATUS_NO_MEMORY;
 
-
        /* they created it; let the user do what he wants with it */
 
        info->acc_granted = GENERIC_RIGHTS_GROUP_ALL_ACCESS;
@@ -4568,9 +4239,6 @@ NTSTATUS _samr_query_groupinfo(pipes_struct *p, SAMR_Q_QUERY_GROUPINFO *q_u, SAM
 {
        DOM_SID group_sid;
        GROUP_MAP map;
-       DOM_SID *sids=NULL;
-       uid_t *uids;
-       int num=0;
        GROUP_INFO_CTR *ctr;
        uint32 acc_granted;
        BOOL ret;
@@ -4593,14 +4261,25 @@ NTSTATUS _samr_query_groupinfo(pipes_struct *p, SAMR_Q_QUERY_GROUPINFO *q_u, SAM
                return NT_STATUS_NO_MEMORY;
 
        switch (q_u->switch_level) {
-               case 1:
+               case 1: {
+                       uint32 *members;
+                       size_t num_members;
+
                        ctr->switch_value1 = 1;
-                       if(!get_memberuids(map.gid, &uids, &num))
-                               return NT_STATUS_NO_SUCH_GROUP;
-                       SAFE_FREE(uids);
-                       init_samr_group_info1(&ctr->group.info1, map.nt_name, map.comment, num);
-                       SAFE_FREE(sids);
+
+                       become_root();
+                       r_u->status = pdb_enum_group_members(
+                               p->mem_ctx, &group_sid, &members, &num_members);
+                       unbecome_root();
+       
+                       if (!NT_STATUS_IS_OK(r_u->status)) {
+                               return r_u->status;
+                       }
+
+                       init_samr_group_info1(&ctr->group.info1, map.nt_name,
+                                     map.comment, num_members);
                        break;
+               }
                case 3:
                        ctr->switch_value1 = 3;
                        init_samr_group_info3(&ctr->group.info3);
index e04e902b3a37cef243cef6414ce077d79d4e34dc..8f3e7236c40f8dabf9bfaf55296f1f05a179d595 100644 (file)
@@ -1067,7 +1067,7 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw
 
        pass = Get_Pwnam(username);
        if (!pass) {
-               DEBUG(1, ("check_oem_password: Username %s does not exist in system !?!\n", username));
+               DEBUG(1, ("change_oem_password: Username %s does not exist in system !?!\n", username));
                return NT_STATUS_ACCESS_DENIED;
        }
 
diff --git a/source3/smbd/map_username.c b/source3/smbd/map_username.c
new file mode 100644 (file)
index 0000000..a6025fc
--- /dev/null
@@ -0,0 +1,178 @@
+/* 
+   Unix SMB/CIFS implementation.
+   Username handling
+   Copyright (C) Andrew Tridgell 1992-1998
+   Copyright (C) Jeremy Allison 1997-2001.
+   Copyright (C) Volker Lendecke 2006
+   
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+
+/*******************************************************************
+ Map a username from a dos name to a unix name by looking in the username
+ map. Note that this modifies the name in place.
+ This is the main function that should be called *once* on
+ any incoming or new username - in order to canonicalize the name.
+ This is being done to de-couple the case conversions from the user mapping
+ function. Previously, the map_username was being called
+ every time Get_Pwnam was called.
+ Returns True if username was changed, false otherwise.
+********************************************************************/
+
+BOOL map_username(fstring user)
+{
+       static BOOL initialised=False;
+       static fstring last_from,last_to;
+       XFILE *f;
+       char *mapfile = lp_username_map();
+       char *s;
+       pstring buf;
+       BOOL mapped_user = False;
+       char *cmd = lp_username_map_script();
+       
+       if (!*user)
+               return False;
+               
+       if (strequal(user,last_to))
+               return False;
+
+       if (strequal(user,last_from)) {
+               DEBUG(3,("Mapped user %s to %s\n",user,last_to));
+               fstrcpy(user,last_to);
+               return True;
+       }
+       
+       /* first try the username map script */
+       
+       if ( *cmd ) {
+               char **qlines;
+               pstring command;
+               int numlines, ret, fd;
+
+               pstr_sprintf( command, "%s \"%s\"", cmd, user );
+
+               DEBUG(10,("Running [%s]\n", command));
+               ret = smbrun(command, &fd);
+               DEBUGADD(10,("returned [%d]\n", ret));
+
+               if ( ret != 0 ) {
+                       if (fd != -1)
+                               close(fd);
+                       return False;
+               }
+
+               numlines = 0;
+               qlines = fd_lines_load(fd, &numlines,0);
+               DEBUGADD(10,("Lines returned = [%d]\n", numlines));
+               close(fd);
+
+               /* should be either no lines or a single line with the mapped username */
+
+               if (numlines) {
+                       DEBUG(3,("Mapped user %s to %s\n", user, qlines[0] ));
+                       fstrcpy( user, qlines[0] );
+               }
+
+               file_lines_free(qlines);
+               
+               return numlines != 0;
+       }
+
+       /* ok.  let's try the mapfile */
+       
+       if (!*mapfile)
+               return False;
+
+       if (!initialised) {
+               *last_from = *last_to = 0;
+               initialised = True;
+       }
+  
+       f = x_fopen(mapfile,O_RDONLY, 0);
+       if (!f) {
+               DEBUG(0,("can't open username map %s. Error %s\n",mapfile, strerror(errno) ));
+               return False;
+       }
+
+       DEBUG(4,("Scanning username map %s\n",mapfile));
+
+       while((s=fgets_slash(buf,sizeof(buf),f))!=NULL) {
+               char *unixname = s;
+               char *dosname = strchr_m(unixname,'=');
+               char **dosuserlist;
+               BOOL return_if_mapped = False;
+
+               if (!dosname)
+                       continue;
+
+               *dosname++ = 0;
+
+               while (isspace((int)*unixname))
+                       unixname++;
+
+               if ('!' == *unixname) {
+                       return_if_mapped = True;
+                       unixname++;
+                       while (*unixname && isspace((int)*unixname))
+                               unixname++;
+               }
+    
+               if (!*unixname || strchr_m("#;",*unixname))
+                       continue;
+
+               {
+                       int l = strlen(unixname);
+                       while (l && isspace((int)unixname[l-1])) {
+                               unixname[l-1] = 0;
+                               l--;
+                       }
+               }
+
+               dosuserlist = str_list_make(dosname, NULL);
+               if (!dosuserlist) {
+                       DEBUG(0,("Unable to build user list\n"));
+                       return False;
+               }
+
+               if (strchr_m(dosname,'*') ||
+                   user_in_list(user, (const char **)dosuserlist)) {
+                       DEBUG(3,("Mapped user %s to %s\n",user,unixname));
+                       mapped_user = True;
+                       fstrcpy( last_from,user );
+                       fstrcpy( user, unixname );
+                       fstrcpy( last_to,user );
+                       if ( return_if_mapped ) {
+                               str_list_free (&dosuserlist);
+                               x_fclose(f);
+                               return True;
+                       }
+               }
+    
+               str_list_free (&dosuserlist);
+       }
+
+       x_fclose(f);
+
+       /*
+        * Setup the last_from and last_to as an optimization so 
+        * that we don't scan the file again for the same user.
+        */
+       fstrcpy(last_from,user);
+       fstrcpy(last_to,user);
+
+       return mapped_user;
+}
index e64455040090ef5f7e2b5a04b3e5ce29f1f76e91..0eeb537ded74851e9a765ce9f95b0417fc6e4974 100644 (file)
@@ -401,6 +401,135 @@ void add_session_user(const char *user)
        safe_strcat(session_userlist,suser,len_session_userlist-1);
 }
 
+/****************************************************************************
+ Check if a user is in a netgroup user list. If at first we don't succeed,
+ try lower case.
+****************************************************************************/
+
+BOOL user_in_netgroup(const char *user, const char *ngname)
+{
+#ifdef HAVE_NETGROUP
+       static char *mydomain = NULL;
+       fstring lowercase_user;
+
+       if (mydomain == NULL)
+               yp_get_default_domain(&mydomain);
+
+       if(mydomain == NULL) {
+               DEBUG(5,("Unable to get default yp domain\n"));
+               return False;
+       }
+
+       DEBUG(5,("looking for user %s of domain %s in netgroup %s\n",
+               user, mydomain, ngname));
+
+       if (innetgr(ngname, NULL, user, mydomain)) {
+               DEBUG(5,("user_in_netgroup: Found\n"));
+               return (True);
+       } else {
+
+               /*
+                * Ok, innetgr is case sensitive. Try once more with lowercase
+                * just in case. Attempt to fix #703. JRA.
+                */
+
+               fstrcpy(lowercase_user, user);
+               strlower_m(lowercase_user);
+       
+               DEBUG(5,("looking for user %s of domain %s in netgroup %s\n",
+                       lowercase_user, mydomain, ngname));
+
+               if (innetgr(ngname, NULL, lowercase_user, mydomain)) {
+                       DEBUG(5,("user_in_netgroup: Found\n"));
+                       return (True);
+               }
+       }
+#endif /* HAVE_NETGROUP */
+       return False;
+}
+
+/****************************************************************************
+ Check if a user is in a user list - can check combinations of UNIX
+ and netgroup lists.
+****************************************************************************/
+
+BOOL user_in_list(const char *user,const char **list)
+{
+       if (!list || !*list)
+               return False;
+
+       DEBUG(10,("user_in_list: checking user %s in list\n", user));
+
+       while (*list) {
+
+               DEBUG(10,("user_in_list: checking user |%s| against |%s|\n",
+                         user, *list));
+
+               /*
+                * Check raw username.
+                */
+               if (strequal(user, *list))
+                       return(True);
+
+               /*
+                * Now check to see if any combination
+                * of UNIX and netgroups has been specified.
+                */
+
+               if(**list == '@') {
+                       /*
+                        * Old behaviour. Check netgroup list
+                        * followed by UNIX list.
+                        */
+                       if(user_in_netgroup(user, *list +1))
+                               return True;
+                       if(user_in_group(user, *list +1))
+                               return True;
+               } else if (**list == '+') {
+
+                       if((*(*list +1)) == '&') {
+                               /*
+                                * Search UNIX list followed by netgroup.
+                                */
+                               if(user_in_group(user, *list +2))
+                                       return True;
+                               if(user_in_netgroup(user, *list +2))
+                                       return True;
+
+                       } else {
+
+                               /*
+                                * Just search UNIX list.
+                                */
+
+                               if(user_in_group(user, *list +1))
+                                       return True;
+                       }
+
+               } else if (**list == '&') {
+
+                       if(*(*list +1) == '+') {
+                               /*
+                                * Search netgroup list followed by UNIX list.
+                                */
+                               if(user_in_netgroup(user, *list +2))
+                                       return True;
+                               if(user_in_group(user, *list +2))
+                                       return True;
+                       } else {
+                               /*
+                                * Just search netgroup list.
+                                */
+                               if(user_in_netgroup(user, *list +1))
+                                       return True;
+                       }
+               }
+    
+               list++;
+       }
+       return(False);
+}
+
 /****************************************************************************
  Check if a username is valid.
 ****************************************************************************/
index d4dd92608972b952af3815f39c86470b1f82f728..2befca40c2a2cff3d8edae0880d173005afa2edd 100644 (file)
@@ -1015,7 +1015,6 @@ static void apply_default_perms(files_struct *fsp, canon_ace *pace, mode_t type)
 static BOOL uid_entry_in_group( canon_ace *uid_ace, canon_ace *group_ace )
 {
        fstring u_name;
-       fstring g_name;
 
        /* "Everyone" always matches every uid. */
 
@@ -1028,14 +1027,7 @@ static BOOL uid_entry_in_group( canon_ace *uid_ace, canon_ace *group_ace )
                return True;
 
        fstrcpy(u_name, uidtoname(uid_ace->unix_ug.uid));
-       fstrcpy(g_name, gidtoname(group_ace->unix_ug.gid));
-
-       /*
-        * Due to the winbind interfaces we need to do this via names,
-        * not uids/gids.
-        */
-
-       return user_in_group(u_name, g_name);
+       return user_in_group_sid(u_name, &group_ace->trustee);
 }
 
 /****************************************************************************
index cf0116cc091fbc1a449937adee7dcab947258544..0fce677ea99a2de142277b2163ba57dd90805c14 100644 (file)
@@ -473,7 +473,7 @@ static NTSTATUS find_forced_group(BOOL force_user,
         */
 
        if (force_user && user_must_be_member) {
-               if (user_in_group(username, groupname)) {
+               if (user_in_group_sid(username, &group_sid)) {
                        sid_copy(pgroup_sid, &group_sid);
                        *pgid = gid;
                        DEBUG(3,("Forced group %s for member %s\n",
index 96a6aa531aabc98bd007ac911cfbe38169ec1134..de31ceb1f329d1ca48b8c5f9fb2db55b497bf10c 100644 (file)
@@ -312,7 +312,7 @@ static int net_groupmap_add(int argc, const char **argv)
                fstrcpy( ntgroup, unixgrp );
                
        
-       if (!add_initial_entry(gid, string_sid, sid_type, ntgroup, ntcomment)) {
+       if (!NT_STATUS_IS_OK(add_initial_entry(gid, string_sid, sid_type, ntgroup, ntcomment))) {
                d_fprintf(stderr, "adding entry for group %s failed!\n", ntgroup);
                return -1;
        }
@@ -494,7 +494,7 @@ static int net_groupmap_delete(int argc, const char **argv)
                return -1;
        }
 
-       if ( !pdb_delete_group_mapping_entry(sid) ) {
+       if ( !NT_STATUS_IS_OK(pdb_delete_group_mapping_entry(sid)) ) {
                d_fprintf(stderr, "Failed to removing group %s from the mapping db!\n", ntgroup);
                return -1;
        }
index 45fdfbfad3ef2ed06dc7ba60fce3e1a4a05573b5..f8cd0e090d430695e71289b5c1c0342a22f760b0 100644 (file)
@@ -550,7 +550,7 @@ static NTSTATUS fetch_account_info(uint32 rid, SAM_ACCOUNT_INFO *delta)
                sam_account_from_delta(sam_account, delta);
                DEBUG(3, ("Attempting to add user SID %s for user %s in the passdb\n", 
                          sid_to_string(sid_string, &user_sid), pdb_get_username(sam_account)));
-               if (!pdb_add_sam_account(sam_account)) {
+               if (!NT_STATUS_IS_OK(pdb_add_sam_account(sam_account))) {
                        DEBUG(1, ("SAM Account for %s failed to be added to the passdb!\n",
                                  account));
                        return NT_STATUS_ACCESS_DENIED;