summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVolker Lendecke <vlendec@samba.org>2006-02-13 17:08:25 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 11:10:06 -0500
commit301d51e13a1aa4e633e2da161b0dd260a8a499cd (patch)
tree7e8b9acef42b06f5ca2eac42f5b6403a035c8612
parent3b67210eec560d0c79b625ac11acb940e29fe8e0 (diff)
downloadsamba-301d51e13a1aa4e633e2da161b0dd260a8a499cd.tar.gz
samba-301d51e13a1aa4e633e2da161b0dd260a8a499cd.tar.bz2
samba-301d51e13a1aa4e633e2da161b0dd260a8a499cd.zip
r13494: Merge the stuff I've done in head the last days.
Volker (This used to be commit bb40e544de68f01a6e774753f508e69373b39899)
-rw-r--r--source3/Makefile.in8
-rw-r--r--source3/auth/auth_util.c66
-rw-r--r--source3/groupdb/mapping.c17
-rw-r--r--source3/include/passdb.h26
-rw-r--r--source3/lib/system_smbd.c77
-rw-r--r--source3/lib/username.c510
-rw-r--r--source3/lib/util_getent.c337
-rw-r--r--source3/passdb/passdb.c126
-rw-r--r--source3/passdb/pdb_interface.c512
-rw-r--r--source3/rpc_server/srv_samr_nt.c527
-rw-r--r--source3/smbd/chgpasswd.c2
-rw-r--r--source3/smbd/map_username.c178
-rw-r--r--source3/smbd/password.c129
-rw-r--r--source3/smbd/posix_acls.c10
-rw-r--r--source3/smbd/service.c2
-rw-r--r--source3/utils/net_groupmap.c4
-rw-r--r--source3/utils/net_rpc_samsync.c2
17 files changed, 1066 insertions, 1467 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in
index d8f7dcf519..135c757fd8 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -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 \
diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c
index 1567b6e40b..ad02b24a42 100644
--- a/source3/auth/auth_util.c
+++ b/source3/auth/auth_util.c
@@ -1019,6 +1019,72 @@ NTSTATUS create_token_from_username(TALLOC_CTX *mem_ctx, const char *username,
}
/***************************************************************************
+ 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
***************************************************************************/
diff --git a/source3/groupdb/mapping.c b/source3/groupdb/mapping.c
index 2790d47587..07116f41fb 100644
--- a/source3/groupdb/mapping.c
+++ b/source3/groupdb/mapping.c
@@ -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,
diff --git a/source3/include/passdb.h b/source3/include/passdb.h
index 35f377ad86..1f3c8cb28b 100644
--- a/source3/include/passdb.h
+++ b/source3/include/passdb.h
@@ -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);
diff --git a/source3/lib/system_smbd.c b/source3/lib/system_smbd.c
index 3fc2d69a03..081a07c019 100644
--- a/source3/lib/system_smbd.c
+++ b/source3/lib/system_smbd.c
@@ -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;
-}
diff --git a/source3/lib/username.c b/source3/lib/username.c
index c04dfd05da..52994557f7 100644
--- a/source3/lib/username.c
+++ b/source3/lib/username.c
@@ -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
index 7c045fccb2..0000000000
--- a/source3/lib/util_getent.c
+++ /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);
- }
-}
diff --git a/source3/passdb/passdb.c b/source3/passdb/passdb.c
index 4d20352312..2b1da6ecce 100644
--- a/source3/passdb/passdb.c
+++ b/source3/passdb/passdb.c
@@ -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;
diff --git a/source3/passdb/pdb_interface.c b/source3/passdb/pdb_interface.c
index 479ce18c05..c8917b9356 100644
--- a/source3/passdb/pdb_interface.c
+++ b/source3/passdb/pdb_interface.c
@@ -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;
diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c
index b3be0cccc1..133178bd0d 100644
--- a/source3/rpc_server/srv_samr_nt.c
+++ b/source3/rpc_server/srv_samr_nt.c
@@ -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;
}
@@ -3098,41 +3041,6 @@ static BOOL set_user_info_18(SAM_USER_INFO_18 *id18, SAM_ACCOUNT *pwd)
}
/*******************************************************************
- 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);
diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c
index e04e902b3a..8f3e7236c4 100644
--- a/source3/smbd/chgpasswd.c
+++ b/source3/smbd/chgpasswd.c
@@ -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
index 0000000000..a6025fcf47
--- /dev/null
+++ b/source3/smbd/map_username.c
@@ -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;
+}
diff --git a/source3/smbd/password.c b/source3/smbd/password.c
index e644550400..0eeb537ded 100644
--- a/source3/smbd/password.c
+++ b/source3/smbd/password.c
@@ -402,6 +402,135 @@ void add_session_user(const char *user)
}
/****************************************************************************
+ 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.
****************************************************************************/
diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c
index d4dd926089..2befca40c2 100644
--- a/source3/smbd/posix_acls.c
+++ b/source3/smbd/posix_acls.c
@@ -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);
}
/****************************************************************************
diff --git a/source3/smbd/service.c b/source3/smbd/service.c
index cf0116cc09..0fce677ea9 100644
--- a/source3/smbd/service.c
+++ b/source3/smbd/service.c
@@ -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",
diff --git a/source3/utils/net_groupmap.c b/source3/utils/net_groupmap.c
index 96a6aa531a..de31ceb1f3 100644
--- a/source3/utils/net_groupmap.c
+++ b/source3/utils/net_groupmap.c
@@ -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;
}
diff --git a/source3/utils/net_rpc_samsync.c b/source3/utils/net_rpc_samsync.c
index 45fdfbfad3..f8cd0e090d 100644
--- a/source3/utils/net_rpc_samsync.c
+++ b/source3/utils/net_rpc_samsync.c
@@ -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;