mirror of
https://github.com/samba-team/samba.git
synced 2025-03-27 22:50:26 +03:00
r13494: Merge the stuff I've done in head the last days.
Volker (This used to be commit bb40e544de68f01a6e774753f508e69373b39899)
This commit is contained in:
parent
3b67210eec
commit
301d51e13a
@ -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 \
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
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;
|
||||
}
|
||||
|
||||
sid_peek_rid(&user_sid, rid);
|
||||
*type = SID_NAME_USER;
|
||||
return True;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Maybe it was a group ?
|
||||
* Maybe it is a group ?
|
||||
*/
|
||||
|
||||
/* check if it's a mapped group */
|
||||
if (pdb_getgrnam(&map, user)) {
|
||||
|
||||
unbecome_root();
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* yes it's a mapped group */
|
||||
sid_peek_rid(&map.sid, rid);
|
||||
*type = map.sid_name_use;
|
||||
return True;
|
||||
}
|
||||
|
||||
return False;
|
||||
|
||||
/* it's not a mapped group */
|
||||
grp = getgrnam(user);
|
||||
if(!grp) {
|
||||
unbecome_root(); /* ---> exit form block */
|
||||
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 */
|
||||
return False;
|
||||
}
|
||||
become_root();
|
||||
ret = pdb_getgrnam(&map, user);
|
||||
unbecome_root();
|
||||
/* END ROOT BLOCK */
|
||||
|
||||
*rid = pdb_gid_to_group_rid(grp->gr_gid);
|
||||
*type = SID_NAME_ALIAS;
|
||||
if (!ret) {
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
nt_status = pdb_create_user(p->mem_ctx, account, acb_info,
|
||||
&r_u->user_rid);
|
||||
|
||||
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 */
|
||||
|
||||
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(!NT_STATUS_IS_OK(pdb_update_sam_account(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 False;
|
||||
return status;
|
||||
}
|
||||
|
||||
if(!NT_STATUS_IS_OK(status = pdb_update_sam_account(pwd))) {
|
||||
pdb_free_sam(&pwd);
|
||||
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));
|
||||
DEBUG(10, ("sid is %s\n", sid_string_static(&group_sid)));
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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();
|
||||
|
||||
r_u->status = pdb_add_groupmem(p->mem_ctx, group_rid, q_u->rid);
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
||||
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,37 +3853,12 @@ 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 (!sid_peek_check_rid(get_global_sam_sid(), &group_sid,
|
||||
&group_rid)) {
|
||||
return NT_STATUS_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
178
source3/smbd/map_username.c
Normal file
178
source3/smbd/map_username.c
Normal file
@ -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;
|
||||
}
|
@ -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.
|
||||
****************************************************************************/
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -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",
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user