mirror of
https://github.com/samba-team/samba.git
synced 2025-02-01 05:47:28 +03:00
Large set of changes to add UNIX account/group management
to winbindd. See README.idmap-and-winbind-changes for details. (This used to be commit 1111bc7b0c7165e1cdf8d90eb49f4c368d2eded6)
This commit is contained in:
parent
816724fb39
commit
16ff7b26f6
73
docs/README.idmap-and-winbind-changes
Normal file
73
docs/README.idmap-and-winbind-changes
Normal file
@ -0,0 +1,73 @@
|
||||
## Date : 2003-07-09
|
||||
## Author: Gerald (Jerry) Carter <jerry@samba.org>
|
||||
## Title: README.idmap-and-winbind-changes
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
Beginning with Samba3.0.0beta3, winbindd has been given new account
|
||||
manage functionality equivalent to the 'add user script' family of
|
||||
smb.conf parameters. The idmap design has also been changed to centralize
|
||||
control of foreign SID lookups and matching to UNIX uids and gids.
|
||||
|
||||
|
||||
Brief Description of Changes
|
||||
----------------------------
|
||||
|
||||
1) The sid_to_uid() family of functions (smbd/uid.c) have been reverted
|
||||
to the 2.2.x design. This means that when resolving a SID to a UID
|
||||
or similar mapping:
|
||||
|
||||
a) First consult winbindd
|
||||
b) perform a local lookup only if winbindd fails to
|
||||
return a successful answer
|
||||
|
||||
There are some variations to this, but these two rules generally
|
||||
apply.
|
||||
|
||||
2) All idmap lookups have been moved into winbindd. This means that
|
||||
a server must run winbindd (and support NSS) in order to achieve
|
||||
any mappings of SID to dynamically allocated UNIX ids. This was
|
||||
a conscious design choice.
|
||||
|
||||
3) New functions have been added to winbindd to emulate the 'add user script'
|
||||
family of smbd functions without requiring that external scripts
|
||||
be defined. This functionality is controlled by the 'winbind enable local
|
||||
accounts' smb.conf parameter (enabled by default).
|
||||
|
||||
However, this account management functionality is only supported in
|
||||
a local tdb (winbindd_idmap.tdb). If these new UNIX accounts must be
|
||||
shared among multiple Samba servers (such as a PDC and BDCs), it
|
||||
will be necessary to define your own 'add user script', et. al.
|
||||
programs that place the accounts/groups in some form of directory
|
||||
such as NIS or LDAP. This requirement was deemed beyond the scope
|
||||
of winbind's account management functions. Solutions for distributing
|
||||
UNIX system information have been deployed and tested for many years.
|
||||
We saw no need to reinvent the wheel.
|
||||
|
||||
4) A member of a Samba controlled domain running winbindd is now able to
|
||||
map domain users directly onto existing UNIX accounts while still
|
||||
automatically creating accounts for trusted users and groups. This
|
||||
behavior is controlled by the 'winbind trusted domains only' smb.conf
|
||||
parameter (disabled by default to provide 2.2.x winbind behavior).
|
||||
|
||||
5) Group mapping support is wrapped in the local_XX_to_XX() functions
|
||||
in smbd/uid.c. The reason that group mappings are not included
|
||||
in winbindd is because the purpose of Samba's group map is to
|
||||
match any Windows SID with an existing UNIX group. These UNIX
|
||||
groups can be created by winbindd (see next section), but the
|
||||
SID<->gid mapping is retreived by smbd, not winbindd.
|
||||
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
* security = server running winbindd to allocate accounts on demand
|
||||
|
||||
* Samba PDC running winbindd to handle the automatic creation of UNIX
|
||||
identities for machine trust accounts
|
||||
|
||||
* Automtically creating UNIX user and groups when migrating a Windows NT
|
||||
4.0 PDC to a Samba PDC. Winbindd must be running when executing
|
||||
'net rpc vampire' for this to work.
|
||||
|
@ -182,10 +182,12 @@ find $RPM_BUILD_ROOT -name "*.old" -exec rm -f {} \;
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
%post
|
||||
/sbin/chkconfig --add smb
|
||||
/sbin/chkconfig --add winbind
|
||||
/sbin/chkconfig smb off
|
||||
/sbin/chkconfig winbind off
|
||||
if [ "$1" -eq "1" ]; then
|
||||
/sbin/chkconfig --add smb
|
||||
/sbin/chkconfig --add winbind
|
||||
/sbin/chkconfig smb off
|
||||
/sbin/chkconfig winbind off
|
||||
fi
|
||||
|
||||
echo "Looking for old /etc/smb.conf..."
|
||||
if [ -f /etc/smb.conf -a ! -f /etc/samba/smb.conf ]; then
|
||||
|
@ -593,7 +593,8 @@ WINBINDD_OBJ1 = \
|
||||
nsswitch/winbindd_wins.o \
|
||||
nsswitch/winbindd_rpc.o \
|
||||
nsswitch/winbindd_ads.o \
|
||||
nsswitch/winbindd_dual.o
|
||||
nsswitch/winbindd_dual.o \
|
||||
nsswitch/winbindd_acct.o
|
||||
|
||||
WINBINDD_OBJ = \
|
||||
$(WINBINDD_OBJ1) $(PASSDB_OBJ) $(GROUPDB_OBJ) \
|
||||
|
@ -60,16 +60,23 @@ static int smb_create_user(const char *domain, const char *unix_username, const
|
||||
|
||||
void auth_add_user_script(const char *domain, const char *username)
|
||||
{
|
||||
struct passwd *pwd=NULL;
|
||||
|
||||
/*
|
||||
* User validated ok against Domain controller.
|
||||
* If the admin wants us to try and create a UNIX
|
||||
* user on the fly, do so.
|
||||
*/
|
||||
|
||||
if(lp_adduser_script() && !(pwd = Get_Pwnam(username))) {
|
||||
if ( lp_adduser_script() )
|
||||
smb_create_user(domain, username, NULL);
|
||||
else {
|
||||
DEBUG(10,("auth_add_user_script: no 'add user script'. Asking winbindd\n"));
|
||||
|
||||
/* should never get here is we a re a domain member running winbindd
|
||||
However, a host set for 'security = server' might run winbindd for
|
||||
account allocation */
|
||||
|
||||
if ( !winbind_create_user(username) )
|
||||
DEBUG(5,("auth_add_user_script: winbindd_create_user() failed\n"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -719,37 +719,50 @@ int smb_create_group(char *unix_group, gid_t *new_gid)
|
||||
int ret;
|
||||
int fd = 0;
|
||||
|
||||
pstrcpy(add_script, lp_addgroup_script());
|
||||
if (! *add_script) return -1;
|
||||
pstring_sub(add_script, "%g", unix_group);
|
||||
ret = smbrun(add_script, (new_gid!=NULL) ? &fd : NULL);
|
||||
DEBUG(3,("smb_create_group: Running the command `%s' gave %d\n",add_script,ret));
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
/* defer to scripts */
|
||||
|
||||
if ( *lp_addgroup_script() ) {
|
||||
pstrcpy(add_script, lp_addgroup_script());
|
||||
pstring_sub(add_script, "%g", unix_group);
|
||||
ret = smbrun(add_script, (new_gid!=NULL) ? &fd : NULL);
|
||||
DEBUG(3,("smb_create_group: Running the command `%s' gave %d\n",add_script,ret));
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
if (fd != 0) {
|
||||
fstring output;
|
||||
|
||||
if (fd != 0) {
|
||||
fstring output;
|
||||
*new_gid = 0;
|
||||
if (read(fd, output, sizeof(output)) > 0) {
|
||||
*new_gid = (gid_t)strtoul(output, NULL, 10);
|
||||
}
|
||||
close(fd);
|
||||
|
||||
*new_gid = 0;
|
||||
if (read(fd, output, sizeof(output)) > 0) {
|
||||
*new_gid = (gid_t)strtoul(output, NULL, 10);
|
||||
}
|
||||
close(fd);
|
||||
|
||||
if (*new_gid == 0) {
|
||||
/* The output was garbage. We assume nobody
|
||||
will create group 0 via smbd. Now we try to
|
||||
get the group via getgrnam. */
|
||||
|
||||
struct group *grp = getgrnam(unix_group);
|
||||
if (grp != NULL)
|
||||
*new_gid = grp->gr_gid;
|
||||
else
|
||||
return 1;
|
||||
if (*new_gid == 0) {
|
||||
/* The output was garbage. We assume nobody
|
||||
will create group 0 via smbd. Now we try to
|
||||
get the group via getgrnam. */
|
||||
|
||||
struct group *grp = getgrnam(unix_group);
|
||||
if (grp != NULL)
|
||||
*new_gid = grp->gr_gid;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
/* Try winbindd */
|
||||
|
||||
if ( winbind_create_group( unix_group ) ) {
|
||||
DEBUG(3,("smb_create_group: winbindd created the group (%s)\n",
|
||||
unix_group));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -761,12 +774,25 @@ int smb_delete_group(char *unix_group)
|
||||
pstring del_script;
|
||||
int ret;
|
||||
|
||||
pstrcpy(del_script, lp_delgroup_script());
|
||||
if (! *del_script) return -1;
|
||||
pstring_sub(del_script, "%g", unix_group);
|
||||
ret = smbrun(del_script,NULL);
|
||||
DEBUG(3,("smb_delete_group: Running the command `%s' gave %d\n",del_script,ret));
|
||||
return ret;
|
||||
/* defer to scripts */
|
||||
|
||||
if ( *lp_delgroup_script() ) {
|
||||
pstrcpy(del_script, lp_delgroup_script());
|
||||
pstring_sub(del_script, "%g", unix_group);
|
||||
ret = smbrun(del_script,NULL);
|
||||
DEBUG(3,("smb_delete_group: Running the command `%s' gave %d\n",del_script,ret));
|
||||
return ret;
|
||||
}
|
||||
#if 0
|
||||
if ( winbind_delete_group( unix_group ) ) {
|
||||
DEBUG(3,("smb_delete_group: winbindd deleted the group (%s)\n",
|
||||
unix_group));
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -777,14 +803,27 @@ int smb_set_primary_group(const char *unix_group, const char* unix_user)
|
||||
pstring add_script;
|
||||
int ret;
|
||||
|
||||
pstrcpy(add_script, lp_setprimarygroup_script());
|
||||
if (! *add_script) return -1;
|
||||
all_string_sub(add_script, "%g", unix_group, sizeof(add_script));
|
||||
all_string_sub(add_script, "%u", unix_user, sizeof(add_script));
|
||||
ret = smbrun(add_script,NULL);
|
||||
DEBUG(3,("smb_set_primary_group: "
|
||||
"Running the command `%s' gave %d\n",add_script,ret));
|
||||
return ret;
|
||||
/* defer to scripts */
|
||||
|
||||
if ( *lp_setprimarygroup_script() ) {
|
||||
pstrcpy(add_script, lp_setprimarygroup_script());
|
||||
all_string_sub(add_script, "%g", unix_group, sizeof(add_script));
|
||||
all_string_sub(add_script, "%u", unix_user, sizeof(add_script));
|
||||
ret = smbrun(add_script,NULL);
|
||||
DEBUG(3,("smb_set_primary_group: "
|
||||
"Running the command `%s' gave %d\n",add_script,ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Try winbindd */
|
||||
|
||||
if ( winbind_set_user_primary_group( unix_user, unix_group ) ) {
|
||||
DEBUG(3,("smb_delete_group: winbindd set the group (%s) as the primary group for user (%s)\n",
|
||||
unix_group, unix_user));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -796,13 +835,26 @@ int smb_add_user_group(char *unix_group, char *unix_user)
|
||||
pstring add_script;
|
||||
int ret;
|
||||
|
||||
pstrcpy(add_script, lp_addusertogroup_script());
|
||||
if (! *add_script) return -1;
|
||||
pstring_sub(add_script, "%g", unix_group);
|
||||
pstring_sub(add_script, "%u", unix_user);
|
||||
ret = smbrun(add_script,NULL);
|
||||
DEBUG(3,("smb_add_user_group: Running the command `%s' gave %d\n",add_script,ret));
|
||||
return ret;
|
||||
/* defer to scripts */
|
||||
|
||||
if ( *lp_addusertogroup_script() ) {
|
||||
pstrcpy(add_script, lp_addusertogroup_script());
|
||||
pstring_sub(add_script, "%g", unix_group);
|
||||
pstring_sub(add_script, "%u", unix_user);
|
||||
ret = smbrun(add_script,NULL);
|
||||
DEBUG(3,("smb_add_user_group: Running the command `%s' gave %d\n",add_script,ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Try winbindd */
|
||||
|
||||
if ( winbind_add_user_to_group( unix_user, unix_group ) ) {
|
||||
DEBUG(3,("smb_delete_group: winbindd added user (%s) to the group (%s)\n",
|
||||
unix_user, unix_group));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -814,13 +866,26 @@ int smb_delete_user_group(const char *unix_group, const char *unix_user)
|
||||
pstring del_script;
|
||||
int ret;
|
||||
|
||||
pstrcpy(del_script, lp_deluserfromgroup_script());
|
||||
if (! *del_script) return -1;
|
||||
pstring_sub(del_script, "%g", unix_group);
|
||||
pstring_sub(del_script, "%u", unix_user);
|
||||
ret = smbrun(del_script,NULL);
|
||||
DEBUG(3,("smb_delete_user_group: Running the command `%s' gave %d\n",del_script,ret));
|
||||
return ret;
|
||||
/* defer to scripts */
|
||||
|
||||
if ( *lp_deluserfromgroup_script() ) {
|
||||
pstrcpy(del_script, lp_deluserfromgroup_script());
|
||||
pstring_sub(del_script, "%g", unix_group);
|
||||
pstring_sub(del_script, "%u", unix_user);
|
||||
ret = smbrun(del_script,NULL);
|
||||
DEBUG(3,("smb_delete_user_group: Running the command `%s' gave %d\n",del_script,ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Try winbindd */
|
||||
|
||||
if ( winbind_remove_user_from_group( unix_user, unix_group ) ) {
|
||||
DEBUG(3,("smb_delete_group: winbindd removed user (%s) from the group (%s)\n",
|
||||
unix_user, unix_group));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
@ -24,7 +24,7 @@
|
||||
Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#define SMB_IDMAP_INTERFACE_VERSION 1
|
||||
#define SMB_IDMAP_INTERFACE_VERSION 2
|
||||
|
||||
|
||||
#define ID_EMPTY 0x00
|
||||
@ -42,6 +42,7 @@ struct idmap_methods {
|
||||
/* Called when backend is first loaded */
|
||||
NTSTATUS (*init)( char *params );
|
||||
|
||||
NTSTATUS (*allocate_id)(unid_t *id, int id_type);
|
||||
NTSTATUS (*get_sid_from_id)(DOM_SID *sid, unid_t id, int id_type);
|
||||
NTSTATUS (*get_id_from_sid)(unid_t *id, int *id_type, const DOM_SID *sid);
|
||||
NTSTATUS (*set_mapping)(const DOM_SID *sid, unid_t id, int id_type);
|
||||
|
@ -367,3 +367,147 @@ BOOL winbind_ping( void )
|
||||
return result == NSS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
Ask winbindd to create a local user
|
||||
**********************************************************************/
|
||||
|
||||
BOOL winbind_create_user( const char *name )
|
||||
{
|
||||
struct winbindd_request request;
|
||||
struct winbindd_response response;
|
||||
NSS_STATUS result;
|
||||
|
||||
if ( !lp_winbind_enable_local_accounts() )
|
||||
return False;
|
||||
|
||||
if ( !name )
|
||||
return False;
|
||||
|
||||
DEBUG(10,("winbind_create_user: %s\n", name));
|
||||
|
||||
fstrcpy( request.data.acct_mgt.username, name );
|
||||
fstrcpy( request.data.acct_mgt.groupname, "" );
|
||||
|
||||
ZERO_STRUCT(response);
|
||||
|
||||
result = winbindd_request( WINBINDD_CREATE_USER, &request, &response);
|
||||
|
||||
return result == NSS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
Ask winbindd to create a local group
|
||||
**********************************************************************/
|
||||
|
||||
BOOL winbind_create_group( const char *name )
|
||||
{
|
||||
struct winbindd_request request;
|
||||
struct winbindd_response response;
|
||||
NSS_STATUS result;
|
||||
|
||||
if ( !lp_winbind_enable_local_accounts() )
|
||||
return False;
|
||||
|
||||
if ( !name )
|
||||
return False;
|
||||
|
||||
DEBUG(10,("winbind_create_group: %s\n", name));
|
||||
|
||||
fstrcpy( request.data.acct_mgt.groupname, name );
|
||||
|
||||
ZERO_STRUCT(response);
|
||||
|
||||
result = winbindd_request( WINBINDD_CREATE_GROUP, &request, &response);
|
||||
|
||||
return result == NSS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
Ask winbindd to add a user to a local group
|
||||
**********************************************************************/
|
||||
|
||||
BOOL winbind_add_user_to_group( const char *user, const char *group )
|
||||
{
|
||||
struct winbindd_request request;
|
||||
struct winbindd_response response;
|
||||
NSS_STATUS result;
|
||||
|
||||
if ( !lp_winbind_enable_local_accounts() )
|
||||
return False;
|
||||
|
||||
if ( !user || !group )
|
||||
return False;
|
||||
|
||||
DEBUG(10,("winbind_add_user_to_group: user(%s), group(%s) \n",
|
||||
user, group));
|
||||
|
||||
fstrcpy( request.data.acct_mgt.username, user );
|
||||
fstrcpy( request.data.acct_mgt.groupname, group );
|
||||
|
||||
ZERO_STRUCT(response);
|
||||
|
||||
result = winbindd_request( WINBINDD_ADD_USER_TO_GROUP, &request, &response);
|
||||
|
||||
return result == NSS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
Ask winbindd to remove a user to a local group
|
||||
**********************************************************************/
|
||||
|
||||
BOOL winbind_remove_user_from_group( const char *user, const char *group )
|
||||
{
|
||||
struct winbindd_request request;
|
||||
struct winbindd_response response;
|
||||
NSS_STATUS result;
|
||||
|
||||
if ( !lp_winbind_enable_local_accounts() )
|
||||
return False;
|
||||
|
||||
if ( !user || !group )
|
||||
return False;
|
||||
|
||||
DEBUG(10,("winbind_remove_user_from_group: user(%s), group(%s) \n",
|
||||
user, group));
|
||||
|
||||
fstrcpy( request.data.acct_mgt.username, user );
|
||||
fstrcpy( request.data.acct_mgt.groupname, group );
|
||||
|
||||
ZERO_STRUCT(response);
|
||||
|
||||
result = winbindd_request( WINBINDD_REMOVE_USER_FROM_GROUP, &request, &response);
|
||||
|
||||
return result == NSS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
Ask winbindd to set the primary group for a user local user
|
||||
**********************************************************************/
|
||||
|
||||
BOOL winbind_set_user_primary_group( const char *user, const char *group )
|
||||
{
|
||||
struct winbindd_request request;
|
||||
struct winbindd_response response;
|
||||
NSS_STATUS result;
|
||||
|
||||
if ( !lp_winbind_enable_local_accounts() )
|
||||
return False;
|
||||
|
||||
if ( !user || !group )
|
||||
return False;
|
||||
|
||||
DEBUG(10,("winbind_set_user_primary_group: user(%s), group(%s) \n",
|
||||
user, group));
|
||||
|
||||
fstrcpy( request.data.acct_mgt.username, user );
|
||||
fstrcpy( request.data.acct_mgt.groupname, group );
|
||||
|
||||
ZERO_STRUCT(response);
|
||||
|
||||
result = winbindd_request( WINBINDD_SET_USER_PRIMARY_GROUP, &request, &response);
|
||||
|
||||
return result == NSS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -511,6 +511,151 @@ static BOOL wbinfo_auth_crap(char *username)
|
||||
return result == NSS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
create a winbindd user
|
||||
******************************************************************/
|
||||
|
||||
static BOOL wbinfo_create_user(char *username)
|
||||
{
|
||||
struct winbindd_request request;
|
||||
struct winbindd_response response;
|
||||
NSS_STATUS result;
|
||||
|
||||
/* Send off request */
|
||||
|
||||
ZERO_STRUCT(request);
|
||||
ZERO_STRUCT(response);
|
||||
|
||||
fstrcpy(request.data.acct_mgt.username, username);
|
||||
|
||||
result = winbindd_request(WINBINDD_CREATE_USER, &request, &response);
|
||||
|
||||
if (response.data.auth.nt_status)
|
||||
d_printf("error code was %s (0x%x)\nerror messsage was: %s\n",
|
||||
response.data.auth.nt_status_string,
|
||||
response.data.auth.nt_status,
|
||||
response.data.auth.error_string);
|
||||
|
||||
return result == NSS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
create a winbindd group
|
||||
******************************************************************/
|
||||
|
||||
static BOOL wbinfo_create_group(char *groupname)
|
||||
{
|
||||
struct winbindd_request request;
|
||||
struct winbindd_response response;
|
||||
NSS_STATUS result;
|
||||
|
||||
/* Send off request */
|
||||
|
||||
ZERO_STRUCT(request);
|
||||
ZERO_STRUCT(response);
|
||||
|
||||
fstrcpy(request.data.acct_mgt.groupname, groupname);
|
||||
|
||||
result = winbindd_request(WINBINDD_CREATE_GROUP, &request, &response);
|
||||
|
||||
if (response.data.auth.nt_status)
|
||||
d_printf("error code was %s (0x%x)\nerror messsage was: %s\n",
|
||||
response.data.auth.nt_status_string,
|
||||
response.data.auth.nt_status,
|
||||
response.data.auth.error_string);
|
||||
|
||||
return result == NSS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
parse a string in the form user:group
|
||||
******************************************************************/
|
||||
|
||||
static BOOL parse_user_group( const char *string, fstring user, fstring group )
|
||||
{
|
||||
char *p;
|
||||
|
||||
if ( !string )
|
||||
return False;
|
||||
|
||||
if ( !(p = strchr( string, ':' )) )
|
||||
return False;
|
||||
|
||||
*p = '\0';
|
||||
p++;
|
||||
|
||||
fstrcpy( user, string );
|
||||
fstrcpy( group, p );
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
add a user to a winbindd group
|
||||
******************************************************************/
|
||||
|
||||
static BOOL wbinfo_add_user_to_group(char *string)
|
||||
{
|
||||
struct winbindd_request request;
|
||||
struct winbindd_response response;
|
||||
NSS_STATUS result;
|
||||
|
||||
/* Send off request */
|
||||
|
||||
ZERO_STRUCT(request);
|
||||
ZERO_STRUCT(response);
|
||||
|
||||
if ( !parse_user_group( string, request.data.acct_mgt.username,
|
||||
request.data.acct_mgt.groupname))
|
||||
{
|
||||
d_printf("Can't parse user:group from %s\n", string);
|
||||
return False;
|
||||
}
|
||||
|
||||
result = winbindd_request(WINBINDD_ADD_USER_TO_GROUP, &request, &response);
|
||||
|
||||
if (response.data.auth.nt_status)
|
||||
d_printf("error code was %s (0x%x)\nerror messsage was: %s\n",
|
||||
response.data.auth.nt_status_string,
|
||||
response.data.auth.nt_status,
|
||||
response.data.auth.error_string);
|
||||
|
||||
return result == NSS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
remove a user from a winbindd group
|
||||
******************************************************************/
|
||||
|
||||
static BOOL wbinfo_remove_user_from_group(char *string)
|
||||
{
|
||||
struct winbindd_request request;
|
||||
struct winbindd_response response;
|
||||
NSS_STATUS result;
|
||||
|
||||
/* Send off request */
|
||||
|
||||
ZERO_STRUCT(request);
|
||||
ZERO_STRUCT(response);
|
||||
|
||||
if ( !parse_user_group( string, request.data.acct_mgt.username,
|
||||
request.data.acct_mgt.groupname))
|
||||
{
|
||||
d_printf("Can't parse user:group from %s\n", string);
|
||||
return False;
|
||||
}
|
||||
|
||||
result = winbindd_request(WINBINDD_REMOVE_USER_FROM_GROUP, &request, &response);
|
||||
|
||||
if (response.data.auth.nt_status)
|
||||
d_printf("error code was %s (0x%x)\nerror messsage was: %s\n",
|
||||
response.data.auth.nt_status_string,
|
||||
response.data.auth.nt_status,
|
||||
response.data.auth.error_string);
|
||||
|
||||
return result == NSS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* Print domain users */
|
||||
|
||||
static BOOL print_domain_users(void)
|
||||
@ -705,6 +850,10 @@ int main(int argc, char **argv)
|
||||
{ "gid-to-sid", 'G', POPT_ARG_INT, &int_arg, 'G', "Converts gid to sid", "GID" },
|
||||
{ "sid-to-uid", 'S', POPT_ARG_STRING, &string_arg, 'S', "Converts sid to uid", "SID" },
|
||||
{ "sid-to-gid", 'Y', POPT_ARG_STRING, &string_arg, 'Y', "Converts sid to gid", "SID" },
|
||||
{ "create-user", 'c', POPT_ARG_STRING, &string_arg, 'c', "Create a local user account", "name" },
|
||||
{ "create-group", 'C', POPT_ARG_STRING, &string_arg, 'C', "Create a local group", "name" },
|
||||
{ "add-to-group", 'o', POPT_ARG_STRING, &string_arg, 'o', "Add user to group", "user:group" },
|
||||
{ "del-from-group", 'O', POPT_ARG_STRING, &string_arg, 'O', "Remove user from group", "user:group" },
|
||||
{ "check-secret", 't', POPT_ARG_NONE, 0, 't', "Check shared secret" },
|
||||
{ "trusted-domains", 'm', POPT_ARG_NONE, 0, 'm', "List trusted domains" },
|
||||
{ "sequence", 0, POPT_ARG_NONE, 0, OPT_SEQUENCE, "Show sequence numbers of all domains" },
|
||||
@ -863,7 +1012,31 @@ int main(int argc, char **argv)
|
||||
goto done;
|
||||
break;
|
||||
}
|
||||
case 'p':
|
||||
case 'c':
|
||||
if ( !wbinfo_create_user(string_arg) ) {
|
||||
d_printf("Could not create user account\n");
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
case 'C':
|
||||
if ( !wbinfo_create_group(string_arg) ) {
|
||||
d_printf("Could not create group\n");
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
case 'o':
|
||||
if ( !wbinfo_add_user_to_group(string_arg) ) {
|
||||
d_printf("Could not add user to group\n");
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
case 'O':
|
||||
if ( !wbinfo_remove_user_from_group(string_arg) ) {
|
||||
d_printf("Could not remove user kfrom group\n");
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
case 'P':
|
||||
if (!wbinfo_ping()) {
|
||||
d_printf("could not ping winbindd!\n");
|
||||
goto done;
|
||||
|
@ -268,7 +268,16 @@ static struct dispatch_table dispatch_table[] = {
|
||||
|
||||
{ WINBINDD_WINS_BYNAME, winbindd_wins_byname, "WINS_BYNAME" },
|
||||
{ WINBINDD_WINS_BYIP, winbindd_wins_byip, "WINS_BYIP" },
|
||||
|
||||
|
||||
/* UNIX account management functions */
|
||||
{ WINBINDD_CREATE_USER, winbindd_create_user, "CREATE_USER" },
|
||||
{ WINBINDD_CREATE_GROUP, winbindd_create_group, "CREATE_GROUP" },
|
||||
{ WINBINDD_ADD_USER_TO_GROUP, winbindd_add_user_to_group, "ADD_USER_TO_GROUP" },
|
||||
{ WINBINDD_REMOVE_USER_FROM_GROUP, winbindd_remove_user_from_group,"REMOVE_USER_FROM_GROUP"},
|
||||
{ WINBINDD_SET_USER_PRIMARY_GROUP, winbindd_set_user_primary_group,"SET_USER_PRIMARY_GROUP"},
|
||||
{ WINBINDD_DELETE_USER, winbindd_delete_user, "DELETE_USER" },
|
||||
{ WINBINDD_DELETE_GROUP, winbindd_delete_group, "DELETE_GROUP" },
|
||||
|
||||
/* End of list */
|
||||
|
||||
{ WINBINDD_NUM_CMDS, NULL, "NONE" }
|
||||
|
946
source3/nsswitch/winbindd_acct.c
Normal file
946
source3/nsswitch/winbindd_acct.c
Normal file
@ -0,0 +1,946 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
Winbind account management functions
|
||||
|
||||
Copyright (C) by Gerald (Jerry) Carter 2003
|
||||
|
||||
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 "winbindd.h"
|
||||
|
||||
#undef DBGC_CLASS
|
||||
#define DBGC_CLASS DBGC_WINBIND
|
||||
|
||||
#define WBKEY_PASSWD "WBA_PASSWD"
|
||||
#define WBKEY_GROUP "WBA_GROUP"
|
||||
|
||||
#define NUM_PW_FIELDS 7
|
||||
#define NUM_GRP_FIELDS 4
|
||||
|
||||
/* Globals */
|
||||
|
||||
static TDB_CONTEXT *account_tdb;
|
||||
|
||||
extern userdom_struct current_user_info;
|
||||
|
||||
/*****************************************************************************
|
||||
Initialise auto-account database.
|
||||
*****************************************************************************/
|
||||
|
||||
static BOOL winbindd_accountdb_init(void)
|
||||
{
|
||||
/* see if we've already opened the tdb */
|
||||
|
||||
if ( account_tdb )
|
||||
return True;
|
||||
|
||||
/* Nope. Try to open it */
|
||||
|
||||
if (!(account_tdb = tdb_open_log(lock_path("winbindd_idmap.tdb"), 0,
|
||||
TDB_DEFAULT, O_RDWR | O_CREAT, 0600)))
|
||||
{
|
||||
/* last chance -- maybe idmap has already opened it */
|
||||
if ( !(account_tdb = idmap_tdb_handle()) ) {
|
||||
|
||||
DEBUG(0, ("winbindd_idmap_init: Unable to open idmap database\n"));
|
||||
return False;
|
||||
}
|
||||
}
|
||||
|
||||
/* yeah! */
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
Convert a string in /etc/passwd format to a struct passwd* entry
|
||||
**********************************************************************/
|
||||
|
||||
static WINBINDD_PW* string2passwd( char *string )
|
||||
{
|
||||
static WINBINDD_PW pw;
|
||||
char *p, *str;
|
||||
char *fields[NUM_PW_FIELDS];
|
||||
int i;
|
||||
|
||||
if ( !string )
|
||||
return NULL;
|
||||
|
||||
ZERO_STRUCTP( &pw );
|
||||
|
||||
DEBUG(10,("string2passwd: converting \"%s\"\n", string));
|
||||
|
||||
ZERO_STRUCT( fields );
|
||||
|
||||
for ( i=0, str=string; i<NUM_PW_FIELDS-1; i++ ) {
|
||||
if ( !(p = strchr( str, ':' )) ) {
|
||||
DEBUG(0,("string2passwd: parsing failure\n"));
|
||||
return NULL;
|
||||
}
|
||||
*p = '\0';
|
||||
if ( str )
|
||||
fields[i] = str;
|
||||
str = p + 1;
|
||||
}
|
||||
if ( str )
|
||||
fields[i] = str;
|
||||
|
||||
/* copy fields */
|
||||
|
||||
fstrcpy( pw.pw_name, fields[0] );
|
||||
fstrcpy( pw.pw_passwd, fields[1] );
|
||||
pw.pw_uid = atoi( fields[2] );
|
||||
pw.pw_gid = atoi( fields[3] );
|
||||
fstrcpy( pw.pw_gecos, fields[4] );
|
||||
fstrcpy( pw.pw_dir, fields[5] );
|
||||
fstrcpy( pw.pw_shell, fields[6] );
|
||||
|
||||
|
||||
/* last minute sanity checks */
|
||||
|
||||
if ( pw.pw_uid==0 || pw.pw_gid==0 ) {
|
||||
DEBUG(0,("string2passwd: Failure! uid==%d, gid==%d\n",
|
||||
pw.pw_uid, pw.pw_gid));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DEBUG(10,("string2passwd: Success\n"));
|
||||
|
||||
return &pw;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
Convert a struct passwd* to a string formatted for /etc/passwd
|
||||
**********************************************************************/
|
||||
|
||||
static char* passwd2string( const WINBINDD_PW *pw )
|
||||
{
|
||||
static pstring string;
|
||||
int ret;
|
||||
|
||||
if ( !pw || !pw->pw_name )
|
||||
return NULL;
|
||||
|
||||
DEBUG(10,("passwd2string: converting passwd struct for %s\n",
|
||||
pw->pw_name));
|
||||
|
||||
ret = snprintf( string, sizeof(string), "%s:%s:%d:%d:%s:%s:%s",
|
||||
pw->pw_name,
|
||||
pw->pw_passwd ? pw->pw_passwd : "x",
|
||||
pw->pw_uid,
|
||||
pw->pw_gid,
|
||||
pw->pw_gecos,
|
||||
pw->pw_dir,
|
||||
pw->pw_shell );
|
||||
|
||||
if ( ret < 0 ) {
|
||||
DEBUG(0,("passwd2string: snprintf() failed!\n"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
Convert a string in /etc/group format to a struct group* entry
|
||||
**********************************************************************/
|
||||
|
||||
static WINBINDD_GR* string2group( char *string )
|
||||
{
|
||||
static WINBINDD_GR grp;
|
||||
char *p, *str;
|
||||
char *fields[NUM_GRP_FIELDS];
|
||||
int i;
|
||||
char **gr_members = NULL;
|
||||
int num_gr_members = 0;
|
||||
|
||||
if ( !string )
|
||||
return NULL;
|
||||
|
||||
ZERO_STRUCTP( &grp );
|
||||
|
||||
DEBUG(10,("string2group: converting \"%s\"\n", string));
|
||||
|
||||
ZERO_STRUCT( fields );
|
||||
|
||||
for ( i=0, str=string; i<NUM_GRP_FIELDS-1; i++ ) {
|
||||
if ( !(p = strchr( str, ':' )) ) {
|
||||
DEBUG(0,("string2group: parsing failure\n"));
|
||||
return NULL;
|
||||
}
|
||||
*p = '\0';
|
||||
if ( str )
|
||||
fields[i] = str;
|
||||
str = p + 1;
|
||||
}
|
||||
|
||||
/* group members */
|
||||
|
||||
if ( *str ) {
|
||||
/* we already know we have a non-empty string */
|
||||
|
||||
num_gr_members = count_chars(str, ',') + 1;
|
||||
|
||||
/* if there was at least one comma, then there
|
||||
are n+1 members */
|
||||
if ( num_gr_members ) {
|
||||
fstring buffer;
|
||||
|
||||
gr_members = (char**)smb_xmalloc(sizeof(char*)*num_gr_members+1);
|
||||
|
||||
i = 0;
|
||||
while ( next_token(&str, buffer, ",", sizeof(buffer)) && i<num_gr_members ) {
|
||||
gr_members[i++] = smb_xstrdup(buffer);
|
||||
}
|
||||
|
||||
gr_members[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* copy fields */
|
||||
|
||||
fstrcpy( grp.gr_name, fields[0] );
|
||||
fstrcpy( grp.gr_passwd, fields[1] );
|
||||
grp.gr_gid = atoi( fields[2] );
|
||||
|
||||
grp.num_gr_mem = num_gr_members;
|
||||
grp.gr_mem = gr_members;
|
||||
|
||||
/* last minute sanity checks */
|
||||
|
||||
if ( grp.gr_gid == 0 ) {
|
||||
DEBUG(0,("string2group: Failure! gid==%d\n", grp.gr_gid));
|
||||
SAFE_FREE( gr_members );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DEBUG(10,("string2group: Success\n"));
|
||||
|
||||
return &grp;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
Convert a struct group* to a string formatted for /etc/group
|
||||
**********************************************************************/
|
||||
|
||||
static char* group2string( const WINBINDD_GR *grp )
|
||||
{
|
||||
static pstring string;
|
||||
int ret;
|
||||
char *member, *gr_mem_str;
|
||||
int num_members;
|
||||
int i, size;
|
||||
|
||||
if ( !grp || !grp->gr_name )
|
||||
return NULL;
|
||||
|
||||
DEBUG(10,("group2string: converting passwd struct for %s\n",
|
||||
grp->gr_name));
|
||||
|
||||
if ( grp->num_gr_mem ) {
|
||||
int idx = 0;
|
||||
|
||||
member = grp->gr_mem[0];
|
||||
size = 0;
|
||||
num_members = 0;
|
||||
|
||||
while ( member ) {
|
||||
size += strlen(member) + 1;
|
||||
num_members++;
|
||||
member = grp->gr_mem[num_members];
|
||||
}
|
||||
|
||||
gr_mem_str = smb_xmalloc(size);
|
||||
|
||||
for ( i=0; i<num_members; i++ ) {
|
||||
snprintf( &gr_mem_str[idx], size-idx, "%s,", grp->gr_mem[i] );
|
||||
idx += strlen(grp->gr_mem[i]) + 1;
|
||||
}
|
||||
/* add trailing NULL (also removes trailing ',' */
|
||||
gr_mem_str[size-1] = '\0';
|
||||
}
|
||||
else {
|
||||
/* no members */
|
||||
gr_mem_str = smb_xmalloc(sizeof(fstring));
|
||||
fstrcpy( gr_mem_str, "" );
|
||||
}
|
||||
|
||||
ret = snprintf( string, sizeof(string)-1, "%s:%s:%d:%s",
|
||||
grp->gr_name,
|
||||
grp->gr_passwd ? grp->gr_passwd : "*",
|
||||
grp->gr_gid,
|
||||
gr_mem_str );
|
||||
|
||||
SAFE_FREE( gr_mem_str );
|
||||
|
||||
if ( ret < 0 ) {
|
||||
DEBUG(0,("group2string: snprintf() failed!\n"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
**********************************************************************/
|
||||
|
||||
static char* acct_userkey_byname( const char *name )
|
||||
{
|
||||
static fstring key;
|
||||
|
||||
snprintf( key, sizeof(key), "%s/NAME/%s", WBKEY_PASSWD, name );
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
**********************************************************************/
|
||||
|
||||
static char* acct_userkey_byuid( uid_t uid )
|
||||
{
|
||||
static fstring key;
|
||||
|
||||
snprintf( key, sizeof(key), "%s/UID/%d", WBKEY_PASSWD, uid );
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
**********************************************************************/
|
||||
|
||||
static char* acct_groupkey_byname( const char *name )
|
||||
{
|
||||
static fstring key;
|
||||
|
||||
snprintf( key, sizeof(key), "%s/NAME/%s", WBKEY_GROUP, name );
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
**********************************************************************/
|
||||
|
||||
static char* acct_groupkey_bygid( gid_t gid )
|
||||
{
|
||||
static fstring key;
|
||||
|
||||
snprintf( key, sizeof(key), "%s/GID/%d", WBKEY_GROUP, gid );
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
**********************************************************************/
|
||||
|
||||
WINBINDD_PW* wb_getpwnam( const char * name )
|
||||
{
|
||||
char *keystr;
|
||||
TDB_DATA data;
|
||||
static WINBINDD_PW *pw;
|
||||
|
||||
if ( !account_tdb && !winbindd_accountdb_init() ) {
|
||||
DEBUG(0,("wb_getpwnam: Failed to open winbindd account db\n"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
keystr = acct_userkey_byname( name );
|
||||
|
||||
data = tdb_fetch_by_string( account_tdb, keystr );
|
||||
|
||||
pw = NULL;
|
||||
|
||||
if ( data.dptr ) {
|
||||
pw = string2passwd( data.dptr );
|
||||
SAFE_FREE( data.dptr );
|
||||
}
|
||||
|
||||
DEBUG(5,("wb_getpwnam: %s user (%s)\n",
|
||||
(pw ? "Found" : "Did not find"), name ));
|
||||
|
||||
return pw;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
**********************************************************************/
|
||||
|
||||
WINBINDD_PW* wb_getpwuid( const uid_t uid )
|
||||
{
|
||||
char *keystr;
|
||||
TDB_DATA data;
|
||||
static WINBINDD_PW *pw;
|
||||
|
||||
if ( !account_tdb && !winbindd_accountdb_init() ) {
|
||||
DEBUG(0,("wb_getpwuid: Failed to open winbindd account db\n"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
data = tdb_fetch_by_string( account_tdb, acct_userkey_byuid(uid) );
|
||||
if ( !data.dptr ) {
|
||||
DEBUG(4,("wb_getpwuid: failed to locate uid == %d\n", uid));
|
||||
return NULL;
|
||||
}
|
||||
keystr = acct_userkey_byname( data.dptr );
|
||||
|
||||
SAFE_FREE( data.dptr );
|
||||
|
||||
data = tdb_fetch_by_string( account_tdb, keystr );
|
||||
|
||||
pw = NULL;
|
||||
|
||||
if ( data.dptr ) {
|
||||
pw = string2passwd( data.dptr );
|
||||
SAFE_FREE( data.dptr );
|
||||
}
|
||||
|
||||
DEBUG(5,("wb_getpwuid: %s user (uid == %d)\n",
|
||||
(pw ? "Found" : "Did not find"), uid ));
|
||||
|
||||
return pw;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
**********************************************************************/
|
||||
|
||||
BOOL wb_storepwnam( const WINBINDD_PW *pw )
|
||||
{
|
||||
char *namekey, *uidkey;
|
||||
TDB_DATA data;
|
||||
char *str;
|
||||
int ret = 0;
|
||||
fstring username;
|
||||
|
||||
if ( !account_tdb && !winbindd_accountdb_init() ) {
|
||||
DEBUG(0,("wb_storepwnam: Failed to open winbindd account db\n"));
|
||||
return False;
|
||||
}
|
||||
|
||||
namekey = acct_userkey_byname( pw->pw_name );
|
||||
|
||||
/* lock the main entry first */
|
||||
|
||||
if ( tdb_lock_bystring(account_tdb, namekey, 0) == -1 ) {
|
||||
DEBUG(0,("wb_storepwnam: Failed to lock %s\n", namekey));
|
||||
return False;
|
||||
}
|
||||
|
||||
str = passwd2string( pw );
|
||||
|
||||
data.dptr = str;
|
||||
data.dsize = strlen(str) + 1;
|
||||
|
||||
if ( (tdb_store_by_string(account_tdb, namekey, data, TDB_REPLACE)) == -1 ) {
|
||||
DEBUG(0,("wb_storepwnam: Failed to store \"%s\"\n", str));
|
||||
ret = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* store the uid index */
|
||||
|
||||
uidkey = acct_userkey_byuid(pw->pw_uid);
|
||||
|
||||
fstrcpy( username, pw->pw_name );
|
||||
data.dptr = username;
|
||||
data.dsize = strlen(username) + 1;
|
||||
|
||||
if ( (tdb_store_by_string(account_tdb, uidkey, data, TDB_REPLACE)) == -1 ) {
|
||||
DEBUG(0,("wb_storepwnam: Failed to store uid key \"%s\"\n", str));
|
||||
tdb_delete_by_string(account_tdb, namekey);
|
||||
ret = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
DEBUG(10,("wb_storepwnam: Success -> \"%s\"\n", str));
|
||||
|
||||
done:
|
||||
tdb_unlock_bystring( account_tdb, namekey );
|
||||
|
||||
return ( ret == 0 );
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
**********************************************************************/
|
||||
|
||||
WINBINDD_GR* wb_getgrnam( const char * name )
|
||||
{
|
||||
char *keystr;
|
||||
TDB_DATA data;
|
||||
static WINBINDD_GR *grp;
|
||||
|
||||
if ( !account_tdb && !winbindd_accountdb_init() ) {
|
||||
DEBUG(0,("wb_getgrnam: Failed to open winbindd account db\n"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
keystr = acct_groupkey_byname( name );
|
||||
|
||||
data = tdb_fetch_by_string( account_tdb, keystr );
|
||||
|
||||
grp = NULL;
|
||||
|
||||
if ( data.dptr ) {
|
||||
grp = string2group( data.dptr );
|
||||
SAFE_FREE( data.dptr );
|
||||
}
|
||||
|
||||
DEBUG(5,("wb_getgrnam: %s group (%s)\n",
|
||||
(grp ? "Found" : "Did not find"), name ));
|
||||
|
||||
return grp;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
**********************************************************************/
|
||||
|
||||
WINBINDD_GR* wb_getgrgid( gid_t gid )
|
||||
{
|
||||
char *keystr;
|
||||
TDB_DATA data;
|
||||
static WINBINDD_GR *grp;
|
||||
|
||||
if ( !account_tdb && !winbindd_accountdb_init() ) {
|
||||
DEBUG(0,("wb_getgrgid: Failed to open winbindd account db\n"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
data = tdb_fetch_by_string( account_tdb, acct_groupkey_bygid(gid) );
|
||||
if ( !data.dptr ) {
|
||||
DEBUG(4,("wb_getgrgid: failed to locate gid == %d\n", gid));
|
||||
return NULL;
|
||||
}
|
||||
keystr = acct_groupkey_byname( data.dptr );
|
||||
|
||||
SAFE_FREE( data.dptr );
|
||||
|
||||
data = tdb_fetch_by_string( account_tdb, keystr );
|
||||
|
||||
grp = NULL;
|
||||
|
||||
if ( data.dptr ) {
|
||||
grp = string2group( data.dptr );
|
||||
SAFE_FREE( data.dptr );
|
||||
}
|
||||
|
||||
DEBUG(5,("wb_getgrgid: %s group (gid == %d)\n",
|
||||
(grp ? "Found" : "Did not find"), gid ));
|
||||
|
||||
return grp;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
**********************************************************************/
|
||||
|
||||
BOOL wb_storegrnam( const WINBINDD_GR *grp )
|
||||
{
|
||||
char *namekey, *gidkey;
|
||||
TDB_DATA data;
|
||||
char *str;
|
||||
int ret = 0;
|
||||
fstring groupname;
|
||||
|
||||
if ( !account_tdb && !winbindd_accountdb_init() ) {
|
||||
DEBUG(0,("wb_storepwnam: Failed to open winbindd account db\n"));
|
||||
return False;
|
||||
}
|
||||
|
||||
namekey = acct_groupkey_byname( grp->gr_name );
|
||||
|
||||
/* lock the main entry first */
|
||||
|
||||
if ( tdb_lock_bystring(account_tdb, namekey, 0) == -1 ) {
|
||||
DEBUG(0,("wb_storegrnam: Failed to lock %s\n", namekey));
|
||||
return False;
|
||||
}
|
||||
|
||||
str = group2string( grp );
|
||||
|
||||
data.dptr = str;
|
||||
data.dsize = strlen(str) + 1;
|
||||
|
||||
if ( (tdb_store_by_string(account_tdb, namekey, data, TDB_REPLACE)) == -1 ) {
|
||||
DEBUG(0,("wb_storegrnam: Failed to store \"%s\"\n", str));
|
||||
ret = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* store the gid index */
|
||||
|
||||
gidkey = acct_groupkey_bygid(grp->gr_gid);
|
||||
|
||||
fstrcpy( groupname, grp->gr_name );
|
||||
data.dptr = groupname;
|
||||
data.dsize = strlen(groupname) + 1;
|
||||
|
||||
if ( (tdb_store_by_string(account_tdb, gidkey, data, TDB_REPLACE)) == -1 ) {
|
||||
DEBUG(0,("wb_storegrnam: Failed to store gid key \"%s\"\n", str));
|
||||
tdb_delete_by_string(account_tdb, namekey);
|
||||
ret = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
DEBUG(10,("wb_storegrnam: Success -> \"%s\"\n", str));
|
||||
|
||||
done:
|
||||
tdb_unlock_bystring( account_tdb, namekey );
|
||||
|
||||
return ( ret == 0 );
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
**********************************************************************/
|
||||
|
||||
static BOOL wb_addgrpmember( WINBINDD_GR *grp, const char *user )
|
||||
{
|
||||
int i;
|
||||
char **members;
|
||||
|
||||
if ( !grp || !user )
|
||||
return False;
|
||||
|
||||
for ( i=0; i<grp->num_gr_mem; i++ ) {
|
||||
if ( StrCaseCmp( grp->gr_mem[i], user ) == 0 )
|
||||
return True;
|
||||
}
|
||||
|
||||
/* add one new slot and keep an extra for the terminating NULL */
|
||||
members = Realloc( grp->gr_mem, (grp->num_gr_mem+2)*sizeof(char*) );
|
||||
if ( !members )
|
||||
return False;
|
||||
|
||||
grp->gr_mem = members;
|
||||
grp->gr_mem[grp->num_gr_mem++] = smb_xstrdup(user);
|
||||
grp->gr_mem[grp->num_gr_mem] = NULL;
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
**********************************************************************/
|
||||
|
||||
static BOOL wb_delgrpmember( WINBINDD_GR *grp, const char *user )
|
||||
{
|
||||
int i;
|
||||
BOOL found = False;
|
||||
|
||||
if ( !grp || !user )
|
||||
return False;
|
||||
|
||||
for ( i=0; i<grp->num_gr_mem && !found; i++ ) {
|
||||
if ( StrCaseCmp( grp->gr_mem[i], user ) == 0 )
|
||||
found = True;
|
||||
}
|
||||
|
||||
if ( !found )
|
||||
return False;
|
||||
|
||||
memmove( grp->gr_mem[i], grp->gr_mem[i+1], sizeof(char*)*(grp->num_gr_mem-(i+1)) );
|
||||
grp->num_gr_mem--;
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
**********************************************************************/
|
||||
|
||||
static void free_winbindd_gr( WINBINDD_GR *grp )
|
||||
{
|
||||
int i;
|
||||
|
||||
if ( !grp )
|
||||
return;
|
||||
|
||||
for ( i=0; i<grp->num_gr_mem; i++ )
|
||||
SAFE_FREE( grp->gr_mem[i] );
|
||||
|
||||
SAFE_FREE( grp->gr_mem );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
Create a new "UNIX" user for the system given a username
|
||||
**********************************************************************/
|
||||
|
||||
enum winbindd_result winbindd_create_user(struct winbindd_cli_state *state)
|
||||
{
|
||||
char *user, *group;
|
||||
unid_t id;
|
||||
WINBINDD_PW pw;
|
||||
WINBINDD_GR *wb_grp;
|
||||
struct group *unix_grp;
|
||||
gid_t primary_gid;
|
||||
|
||||
if ( !state->privileged ) {
|
||||
DEBUG(2, ("winbindd_create_user: non-privileged access denied!\n"));
|
||||
return WINBINDD_ERROR;
|
||||
}
|
||||
|
||||
/* Ensure null termination */
|
||||
state->request.data.acct_mgt.username[sizeof(state->request.data.acct_mgt.username)-1]='\0';
|
||||
state->request.data.acct_mgt.groupname[sizeof(state->request.data.acct_mgt.groupname)-1]='\0';
|
||||
|
||||
user = state->request.data.acct_mgt.username;
|
||||
group = state->request.data.acct_mgt.groupname;
|
||||
|
||||
DEBUG(3, ("[%5d]: create_user user=>(%s), group=>(%s)\n",
|
||||
state->pid, user, group));
|
||||
|
||||
if ( !*group )
|
||||
group = lp_template_primary_group();
|
||||
|
||||
/* validate the primary group
|
||||
1) lookup in local tdb first
|
||||
2) call getgrnam() as a last resort */
|
||||
|
||||
if ( (wb_grp=wb_getgrnam(group)) != NULL ) {
|
||||
primary_gid = wb_grp->gr_gid;
|
||||
free_winbindd_gr( wb_grp );
|
||||
}
|
||||
else if ( (unix_grp=sys_getgrnam(group)) != NULL ) {
|
||||
primary_gid = unix_grp->gr_gid;
|
||||
}
|
||||
else {
|
||||
DEBUG(2,("winbindd_create_user: Cannot validate gid for group (%s)\n", group));
|
||||
return WINBINDD_ERROR;
|
||||
}
|
||||
|
||||
/* get a new uid */
|
||||
|
||||
if ( !NT_STATUS_IS_OK(idmap_allocate_id( &id, ID_USERID)) ) {
|
||||
DEBUG(0,("winbindd_create_user: idmap_allocate_id() failed!\n"));
|
||||
return WINBINDD_ERROR;
|
||||
}
|
||||
|
||||
/* The substitution of %U and %D in the 'template homedir' is done
|
||||
by lp_string() calling standard_sub_basic(). */
|
||||
|
||||
fstrcpy( current_user_info.smb_name, user );
|
||||
sub_set_smb_name( user );
|
||||
fstrcpy( current_user_info.domain, get_global_sam_name() );
|
||||
|
||||
/* fill in the passwd struct */
|
||||
|
||||
fstrcpy( pw.pw_name, user );
|
||||
fstrcpy( pw.pw_passwd, "x" );
|
||||
fstrcpy( pw.pw_gecos, user);
|
||||
fstrcpy( pw.pw_dir, lp_template_homedir() );
|
||||
fstrcpy( pw.pw_shell, lp_template_shell() );
|
||||
|
||||
pw.pw_uid = id.uid;
|
||||
pw.pw_gid = primary_gid;
|
||||
|
||||
return ( wb_storepwnam(&pw) ? WINBINDD_OK : WINBINDD_ERROR );
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
Create a new "UNIX" group for the system given a username
|
||||
**********************************************************************/
|
||||
|
||||
enum winbindd_result winbindd_create_group(struct winbindd_cli_state *state)
|
||||
{
|
||||
char *group;
|
||||
unid_t id;
|
||||
WINBINDD_GR grp;
|
||||
|
||||
if ( !state->privileged ) {
|
||||
DEBUG(2, ("winbindd_create_group: non-privileged access denied!\n"));
|
||||
return WINBINDD_ERROR;
|
||||
}
|
||||
|
||||
/* Ensure null termination */
|
||||
state->request.data.acct_mgt.groupname[sizeof(state->request.data.acct_mgt.groupname)-1]='\0';
|
||||
group = state->request.data.acct_mgt.groupname;
|
||||
|
||||
DEBUG(3, ("[%5d]: create_group (%s)\n", state->pid, group));
|
||||
|
||||
/* get a new uid */
|
||||
|
||||
if ( !NT_STATUS_IS_OK(idmap_allocate_id( &id, ID_GROUPID)) ) {
|
||||
DEBUG(0,("winbindd_create_group: idmap_allocate_id() failed!\n"));
|
||||
return WINBINDD_ERROR;
|
||||
}
|
||||
|
||||
/* fill in the group struct */
|
||||
|
||||
fstrcpy( grp.gr_name, group );
|
||||
fstrcpy( grp.gr_passwd, "*" );
|
||||
|
||||
grp.gr_gid = id.gid;
|
||||
grp.gr_mem = NULL; /* start with no members */
|
||||
grp.num_gr_mem = 0;
|
||||
|
||||
return ( wb_storegrnam(&grp) ? WINBINDD_OK : WINBINDD_ERROR );
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
Add a user to the membership for a group.
|
||||
**********************************************************************/
|
||||
|
||||
enum winbindd_result winbindd_add_user_to_group(struct winbindd_cli_state *state)
|
||||
{
|
||||
WINBINDD_PW *pw;
|
||||
WINBINDD_GR *grp;
|
||||
char *user, *group;
|
||||
BOOL ret;
|
||||
|
||||
if ( !state->privileged ) {
|
||||
DEBUG(2, ("winbindd_add_user_to_group: non-privileged access denied!\n"));
|
||||
return WINBINDD_ERROR;
|
||||
}
|
||||
|
||||
/* Ensure null termination */
|
||||
state->request.data.acct_mgt.groupname[sizeof(state->request.data.acct_mgt.groupname)-1]='\0';
|
||||
state->request.data.acct_mgt.username[sizeof(state->request.data.acct_mgt.username)-1]='\0';
|
||||
group = state->request.data.acct_mgt.groupname;
|
||||
user = state->request.data.acct_mgt.username;
|
||||
|
||||
DEBUG(3, ("[%5d]: add_user_to_group add %s to %s\n", state->pid,
|
||||
user, group));
|
||||
|
||||
/* make sure it is a valid user */
|
||||
|
||||
if ( !(pw = wb_getpwnam( user )) ) {
|
||||
DEBUG(4,("winbindd_add_user_to_group: Cannot add a non-existent user\n"));
|
||||
return WINBINDD_ERROR;
|
||||
}
|
||||
|
||||
/* make sure it is a valid group */
|
||||
|
||||
if ( !(grp = wb_getgrnam( group )) ) {
|
||||
DEBUG(4,("winbindd_add_user_to_group: Cannot add a user to a non-extistent group\n"));
|
||||
return WINBINDD_ERROR;
|
||||
}
|
||||
|
||||
if ( !wb_addgrpmember( grp, user ) )
|
||||
return WINBINDD_ERROR;
|
||||
|
||||
ret = wb_storegrnam(grp);
|
||||
|
||||
free_winbindd_gr( grp );
|
||||
|
||||
return ( ret ? WINBINDD_OK : WINBINDD_ERROR );
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
Remove a user from the membership of a group
|
||||
**********************************************************************/
|
||||
|
||||
enum winbindd_result winbindd_remove_user_from_group(struct winbindd_cli_state *state)
|
||||
{
|
||||
WINBINDD_GR *grp;
|
||||
char *user, *group;
|
||||
BOOL ret;
|
||||
|
||||
if ( !state->privileged ) {
|
||||
DEBUG(2, ("winbindd_remove_user_from_group: non-privileged access denied!\n"));
|
||||
return WINBINDD_ERROR;
|
||||
}
|
||||
|
||||
/* Ensure null termination */
|
||||
state->request.data.acct_mgt.groupname[sizeof(state->request.data.acct_mgt.groupname)-1]='\0';
|
||||
state->request.data.acct_mgt.username[sizeof(state->request.data.acct_mgt.username)-1]='\0';
|
||||
group = state->request.data.acct_mgt.groupname;
|
||||
user = state->request.data.acct_mgt.username;
|
||||
|
||||
DEBUG(3, ("[%5d]: remove_user_to_group delete %s from %s\n", state->pid,
|
||||
user, group));
|
||||
|
||||
/* don't worry about checking the username since we're removing it anyways */
|
||||
|
||||
/* make sure it is a valid group */
|
||||
|
||||
if ( !(grp = wb_getgrnam( group )) ) {
|
||||
DEBUG(4,("winbindd_remove_user_to_group: Cannot remove a user to a non-extistent group\n"));
|
||||
return WINBINDD_ERROR;
|
||||
}
|
||||
|
||||
if ( !wb_delgrpmember( grp, user ) )
|
||||
return WINBINDD_ERROR;
|
||||
|
||||
ret = wb_storegrnam(grp);
|
||||
|
||||
free_winbindd_gr( grp );
|
||||
|
||||
return ( ret ? WINBINDD_OK : WINBINDD_ERROR );
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
Set the primary group membership of a user
|
||||
**********************************************************************/
|
||||
|
||||
enum winbindd_result winbindd_set_user_primary_group(struct winbindd_cli_state *state)
|
||||
{
|
||||
WINBINDD_PW *pw;
|
||||
WINBINDD_GR *grp;
|
||||
char *user, *group;
|
||||
|
||||
if ( !state->privileged ) {
|
||||
DEBUG(2, ("winbindd_set_user_primary_group: non-privileged access denied!\n"));
|
||||
return WINBINDD_ERROR;
|
||||
}
|
||||
|
||||
/* Ensure null termination */
|
||||
state->request.data.acct_mgt.groupname[sizeof(state->request.data.acct_mgt.groupname)-1]='\0';
|
||||
state->request.data.acct_mgt.username[sizeof(state->request.data.acct_mgt.username)-1]='\0';
|
||||
group = state->request.data.acct_mgt.groupname;
|
||||
user = state->request.data.acct_mgt.username;
|
||||
|
||||
DEBUG(3, ("[%5d]: set_user_primary_group group %s for user %s\n", state->pid,
|
||||
group, user));
|
||||
|
||||
/* make sure it is a valid user */
|
||||
|
||||
if ( !(pw = wb_getpwnam( user )) ) {
|
||||
DEBUG(4,("winbindd_add_user_to_group: Cannot add a non-existent user\n"));
|
||||
return WINBINDD_ERROR;
|
||||
}
|
||||
|
||||
/* make sure it is a valid group */
|
||||
|
||||
if ( !(grp = wb_getgrnam( group )) ) {
|
||||
DEBUG(4,("winbindd_add_user_to_group: Cannot add a user to a non-extistent group\n"));
|
||||
return WINBINDD_ERROR;
|
||||
}
|
||||
|
||||
pw->pw_gid = grp->gr_gid;
|
||||
|
||||
free_winbindd_gr( grp );
|
||||
|
||||
return ( wb_storepwnam(pw) ? WINBINDD_OK : WINBINDD_ERROR );
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
Set the primary group membership of a user
|
||||
**********************************************************************/
|
||||
|
||||
enum winbindd_result winbindd_delete_user(struct winbindd_cli_state *state)
|
||||
{
|
||||
return WINBINDD_ERROR;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
Set the primary group membership of a user
|
||||
**********************************************************************/
|
||||
|
||||
enum winbindd_result winbindd_delete_group(struct winbindd_cli_state *state)
|
||||
{
|
||||
return WINBINDD_ERROR;
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,34 @@
|
||||
#undef DBGC_CLASS
|
||||
#define DBGC_CLASS DBGC_WINBIND
|
||||
|
||||
/*********************************************************************
|
||||
*********************************************************************/
|
||||
|
||||
static int gr_mem_buffer( char **buffer, char **members, int num_members )
|
||||
{
|
||||
int i;
|
||||
int len = 0;
|
||||
int idx = 0;
|
||||
|
||||
if ( num_members == 0 ) {
|
||||
*buffer = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for ( i=0; i<num_members; i++ )
|
||||
len += strlen(members[i])+1;
|
||||
|
||||
*buffer = (char*)smb_xmalloc(len);
|
||||
for ( i=0; i<num_members; i++ ) {
|
||||
snprintf( &(*buffer)[idx], len-idx, "%s,", members[i]);
|
||||
idx += strlen(members[i])+1;
|
||||
}
|
||||
/* terminate with NULL */
|
||||
(*buffer)[len-1] = '\0';
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
Empty static struct for negative caching.
|
||||
****************************************************************/
|
||||
@ -193,6 +221,7 @@ done:
|
||||
enum winbindd_result winbindd_getgrnam(struct winbindd_cli_state *state)
|
||||
{
|
||||
DOM_SID group_sid;
|
||||
WINBINDD_GR *grp;
|
||||
struct winbindd_domain *domain;
|
||||
enum SID_NAME_USE name_type;
|
||||
fstring name_domain, name_group;
|
||||
@ -211,18 +240,38 @@ enum winbindd_result winbindd_getgrnam(struct winbindd_cli_state *state)
|
||||
memset(name_group, 0, sizeof(fstring));
|
||||
|
||||
tmp = state->request.data.groupname;
|
||||
if (!parse_domain_user(tmp, name_domain, name_group))
|
||||
return WINBINDD_ERROR;
|
||||
|
||||
parse_domain_user(tmp, name_domain, name_group);
|
||||
|
||||
/* don't handle our own domain if we are a DC ( or a member of a Samba domain
|
||||
that shares UNIX accounts). This code handles cases where
|
||||
the account doesn't exist anywhere and gets passed on down the NSS layer */
|
||||
/* if no domain or our local domain, then do a local tdb search */
|
||||
|
||||
if ( !*name_domain || strequal(name_domain, get_global_sam_name()) ) {
|
||||
char *buffer = NULL;
|
||||
|
||||
if ( !(grp=wb_getgrnam(name_group)) ) {
|
||||
DEBUG(5,("winbindd_getgrnam: lookup for %s\\%s failed\n",
|
||||
name_domain, name_group));
|
||||
return WINBINDD_ERROR;
|
||||
}
|
||||
memcpy( &state->response.data.gr, grp, sizeof(WINBINDD_GR) );
|
||||
|
||||
if ( (IS_DC || lp_winbind_trusted_domains_only()) && strequal(name_domain, lp_workgroup()) ) {
|
||||
DEBUG(7,("winbindd_getgrnam: rejecting getpwnam() for %s\\%s since I am on the PDC for this domain\n",
|
||||
gr_mem_len = gr_mem_buffer( &buffer, grp->gr_mem, grp->num_gr_mem );
|
||||
|
||||
state->response.data.gr.gr_mem_ofs = 0;
|
||||
state->response.length += gr_mem_len;
|
||||
state->response.extra_data = buffer; /* give the memory away */
|
||||
|
||||
return WINBINDD_OK;
|
||||
}
|
||||
|
||||
/* should we deal with users for our domain? */
|
||||
|
||||
if ( lp_winbind_trusted_domains_only() && strequal(name_domain, lp_workgroup())) {
|
||||
DEBUG(7,("winbindd_getgrnam: My domain -- rejecting getgrnam() for %s\\%s.\n",
|
||||
name_domain, name_group));
|
||||
return WINBINDD_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/* Get info for the domain */
|
||||
|
||||
@ -277,6 +326,7 @@ enum winbindd_result winbindd_getgrnam(struct winbindd_cli_state *state)
|
||||
enum winbindd_result winbindd_getgrgid(struct winbindd_cli_state *state)
|
||||
{
|
||||
struct winbindd_domain *domain;
|
||||
WINBINDD_GR *grp;
|
||||
DOM_SID group_sid;
|
||||
enum SID_NAME_USE name_type;
|
||||
fstring dom_name;
|
||||
@ -293,6 +343,21 @@ enum winbindd_result winbindd_getgrgid(struct winbindd_cli_state *state)
|
||||
(state->request.data.gid > server_state.gid_high))
|
||||
return WINBINDD_ERROR;
|
||||
|
||||
/* alway try local tdb lookup first */
|
||||
if ( ( grp=wb_getgrgid(state->request.data.gid)) != NULL ) {
|
||||
char *buffer = NULL;
|
||||
|
||||
memcpy( &state->response.data.gr, grp, sizeof(WINBINDD_GR) );
|
||||
|
||||
gr_mem_len = gr_mem_buffer( &buffer, grp->gr_mem, grp->num_gr_mem );
|
||||
|
||||
state->response.data.gr.gr_mem_ofs = 0;
|
||||
state->response.length += gr_mem_len;
|
||||
state->response.extra_data = buffer; /* give away the memory */
|
||||
|
||||
return WINBINDD_OK;
|
||||
}
|
||||
|
||||
/* Get rid from gid */
|
||||
if (!NT_STATUS_IS_OK(idmap_gid_to_sid(&group_sid, state->request.data.gid))) {
|
||||
DEBUG(1, ("could not convert gid %d to rid\n",
|
||||
@ -859,8 +924,12 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state)
|
||||
|
||||
/* Parse domain and username */
|
||||
|
||||
if (!parse_domain_user(state->request.data.username, name_domain,
|
||||
name_user))
|
||||
parse_domain_user(state->request.data.username,
|
||||
name_domain, name_user);
|
||||
|
||||
/* bail if there is no domain */
|
||||
|
||||
if ( !*name_domain )
|
||||
goto done;
|
||||
|
||||
/* Get info for the domain */
|
||||
|
@ -1,194 +0,0 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
Winbind ID Mapping
|
||||
Copyright (C) Tim Potter 2000
|
||||
Copyright (C) Anthony Liguori <aliguor@us.ibm.com> 2003
|
||||
|
||||
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 "winbindd.h"
|
||||
|
||||
static struct {
|
||||
const char *name;
|
||||
/* Function to create a member of the idmap_methods list */
|
||||
BOOL (*reg_meth)(struct winbindd_idmap_methods **methods);
|
||||
struct winbindd_idmap_methods *methods;
|
||||
} builtin_winbindd_idmap_functions[] = {
|
||||
{ "tdb", winbind_idmap_reg_tdb, NULL },
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
/* singleton pattern: uberlazy evaluation */
|
||||
static struct winbindd_idmap_methods *impl;
|
||||
|
||||
static struct winbindd_idmap_methods *get_impl(const char *name)
|
||||
{
|
||||
int i = 0;
|
||||
struct winbindd_idmap_methods *ret = NULL;
|
||||
|
||||
while (builtin_winbindd_idmap_functions[i].name &&
|
||||
strcmp(builtin_winbindd_idmap_functions[i].name, name)) {
|
||||
i++;
|
||||
}
|
||||
|
||||
if (builtin_winbindd_idmap_functions[i].name) {
|
||||
if (!builtin_winbindd_idmap_functions[i].methods) {
|
||||
builtin_winbindd_idmap_functions[i].reg_meth(&builtin_winbindd_idmap_functions[i].methods);
|
||||
}
|
||||
|
||||
ret = builtin_winbindd_idmap_functions[i].methods;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Initialize backend */
|
||||
BOOL winbindd_idmap_init(void)
|
||||
{
|
||||
BOOL ret = False;
|
||||
|
||||
DEBUG(3, ("winbindd_idmap_init: using '%s' as backend\n",
|
||||
lp_winbind_backend()));
|
||||
|
||||
if (!impl) {
|
||||
impl = get_impl(lp_winbind_backend());
|
||||
if (!impl) {
|
||||
DEBUG(0, ("winbindd_idmap_init: could not load backend '%s'\n",
|
||||
lp_winbind_backend()));
|
||||
}
|
||||
}
|
||||
|
||||
if (impl) {
|
||||
ret = impl->init();
|
||||
}
|
||||
|
||||
DEBUG(3, ("winbind_idmap_init: returning %s\n", ret ? "true" : "false"));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Get UID from SID */
|
||||
BOOL winbindd_idmap_get_uid_from_sid(DOM_SID *sid, uid_t *uid)
|
||||
{
|
||||
BOOL ret = False;
|
||||
|
||||
if (!impl) {
|
||||
impl = get_impl(lp_winbind_backend());
|
||||
if (!impl) {
|
||||
DEBUG(0, ("winbindd_idmap_init: could not load backend '%s'\n",
|
||||
lp_winbind_backend()));
|
||||
}
|
||||
}
|
||||
|
||||
if (impl) {
|
||||
ret = impl->get_uid_from_sid(sid, uid);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Get GID from SID */
|
||||
BOOL winbindd_idmap_get_gid_from_sid(DOM_SID *sid, gid_t *gid)
|
||||
{
|
||||
BOOL ret = False;
|
||||
|
||||
if (!impl) {
|
||||
impl = get_impl(lp_winbind_backend());
|
||||
if (!impl) {
|
||||
DEBUG(0, ("winbindd_idmap_init: could not load backend '%s'\n",
|
||||
lp_winbind_backend()));
|
||||
}
|
||||
}
|
||||
|
||||
if (impl) {
|
||||
ret = impl->get_gid_from_sid(sid, gid);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Get SID from UID */
|
||||
BOOL winbindd_idmap_get_sid_from_uid(uid_t uid, DOM_SID *sid)
|
||||
{
|
||||
BOOL ret = False;
|
||||
|
||||
if (!impl) {
|
||||
impl = get_impl(lp_winbind_backend());
|
||||
if (!impl) {
|
||||
DEBUG(0, ("winbindd_idmap_init: could not load backend '%s'\n",
|
||||
lp_winbind_backend()));
|
||||
}
|
||||
}
|
||||
|
||||
if (impl) {
|
||||
ret = impl->get_sid_from_uid(uid, sid);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Get SID from GID */
|
||||
BOOL winbindd_idmap_get_sid_from_gid(gid_t gid, DOM_SID *sid)
|
||||
{
|
||||
BOOL ret = False;
|
||||
|
||||
if (!impl) {
|
||||
impl = get_impl(lp_winbind_backend());
|
||||
}
|
||||
|
||||
if (impl) {
|
||||
ret = impl->get_sid_from_gid(gid, sid);
|
||||
} else {
|
||||
DEBUG(0, ("winbindd_idmap_init: could not load backend '%s'\n",
|
||||
lp_winbind_backend()));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Close backend */
|
||||
BOOL winbindd_idmap_close(void)
|
||||
{
|
||||
BOOL ret = False;
|
||||
|
||||
if (!impl) {
|
||||
impl = get_impl(lp_winbind_backend());
|
||||
}
|
||||
|
||||
if (impl) {
|
||||
ret = impl->close();
|
||||
} else {
|
||||
DEBUG(0, ("winbindd_idmap_init: could not load backend '%s'\n",
|
||||
lp_winbind_backend()));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Dump backend status */
|
||||
void winbindd_idmap_status(void)
|
||||
{
|
||||
if (!impl) {
|
||||
impl = get_impl(lp_winbind_backend());
|
||||
}
|
||||
|
||||
if (impl) {
|
||||
impl->status();
|
||||
} else {
|
||||
DEBUG(0, ("winbindd_idmap_init: could not load backend '%s'\n",
|
||||
lp_winbind_backend()));
|
||||
}
|
||||
}
|
@ -1,459 +0,0 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
Winbind daemon - user related function
|
||||
|
||||
Copyright (C) Tim Potter 2000
|
||||
Copyright (C) Anthony Liguori 2003
|
||||
|
||||
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 "winbindd.h"
|
||||
|
||||
#undef DBGC_CLASS
|
||||
#define DBGC_CLASS DBGC_WINBIND
|
||||
|
||||
/* High water mark keys */
|
||||
#define HWM_GROUP "GROUP HWM"
|
||||
#define HWM_USER "USER HWM"
|
||||
|
||||
/* idmap version determines auto-conversion */
|
||||
#define IDMAP_VERSION 2
|
||||
|
||||
/* Globals */
|
||||
static TDB_CONTEXT *idmap_tdb;
|
||||
|
||||
/* convert one record to the new format */
|
||||
static int tdb_convert_fn(TDB_CONTEXT * tdb, TDB_DATA key, TDB_DATA data,
|
||||
void *ignored)
|
||||
{
|
||||
struct winbindd_domain *domain;
|
||||
char *p;
|
||||
DOM_SID sid;
|
||||
uint32 rid;
|
||||
fstring keystr;
|
||||
fstring dom_name;
|
||||
TDB_DATA key2;
|
||||
|
||||
p = strchr(key.dptr, '/');
|
||||
if (!p)
|
||||
return 0;
|
||||
|
||||
*p = 0;
|
||||
fstrcpy(dom_name, key.dptr);
|
||||
*p++ = '/';
|
||||
|
||||
domain = find_domain_from_name(dom_name);
|
||||
if (!domain) {
|
||||
/* We must delete the old record. */
|
||||
DEBUG(0,
|
||||
("winbindd: tdb_convert_fn : Unable to find domain %s\n",
|
||||
dom_name));
|
||||
DEBUG(0,
|
||||
("winbindd: tdb_convert_fn : deleting record %s\n",
|
||||
key.dptr));
|
||||
tdb_delete(idmap_tdb, key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
rid = atoi(p);
|
||||
|
||||
sid_copy(&sid, &domain->sid);
|
||||
sid_append_rid(&sid, rid);
|
||||
|
||||
sid_to_string(keystr, &sid);
|
||||
key2.dptr = keystr;
|
||||
key2.dsize = strlen(keystr) + 1;
|
||||
|
||||
if (tdb_store(idmap_tdb, key2, data, TDB_INSERT) != 0) {
|
||||
/* not good! */
|
||||
DEBUG(0,
|
||||
("winbindd: tdb_convert_fn : Unable to update record %s\n",
|
||||
key2.dptr));
|
||||
DEBUG(0,
|
||||
("winbindd: tdb_convert_fn : conversion failed - idmap corrupt ?\n"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tdb_store(idmap_tdb, data, key2, TDB_REPLACE) != 0) {
|
||||
/* not good! */
|
||||
DEBUG(0,
|
||||
("winbindd: tdb_convert_fn : Unable to update record %s\n",
|
||||
data.dptr));
|
||||
DEBUG(0,
|
||||
("winbindd: tdb_convert_fn : conversion failed - idmap corrupt ?\n"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
tdb_delete(idmap_tdb, key);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
Convert the idmap database from an older version.
|
||||
*****************************************************************************/
|
||||
static BOOL tdb_idmap_convert(void)
|
||||
{
|
||||
int32 vers = tdb_fetch_int32(idmap_tdb, "IDMAP_VERSION");
|
||||
BOOL bigendianheader =
|
||||
(idmap_tdb->flags & TDB_BIGENDIAN) ? True : False;
|
||||
|
||||
if (vers == IDMAP_VERSION)
|
||||
return True;
|
||||
|
||||
if (((vers == -1) && bigendianheader)
|
||||
|| (IREV(vers) == IDMAP_VERSION)) {
|
||||
/* Arrggghh ! Bytereversed or old big-endian - make order independent ! */
|
||||
/*
|
||||
* high and low records were created on a
|
||||
* big endian machine and will need byte-reversing.
|
||||
*/
|
||||
|
||||
int32 wm;
|
||||
|
||||
wm = tdb_fetch_int32(idmap_tdb, HWM_USER);
|
||||
|
||||
if (wm != -1) {
|
||||
wm = IREV(wm);
|
||||
} else
|
||||
wm = server_state.uid_low;
|
||||
|
||||
if (tdb_store_int32(idmap_tdb, HWM_USER, wm) == -1) {
|
||||
DEBUG(0,
|
||||
("tdb_idmap_convert: Unable to byteswap user hwm in idmap database\n"));
|
||||
return False;
|
||||
}
|
||||
|
||||
wm = tdb_fetch_int32(idmap_tdb, HWM_GROUP);
|
||||
if (wm != -1) {
|
||||
wm = IREV(wm);
|
||||
} else
|
||||
wm = server_state.gid_low;
|
||||
|
||||
if (tdb_store_int32(idmap_tdb, HWM_GROUP, wm) == -1) {
|
||||
DEBUG(0,
|
||||
("tdb_idmap_convert: Unable to byteswap group hwm in idmap database\n"));
|
||||
return False;
|
||||
}
|
||||
}
|
||||
|
||||
/* the old format stored as DOMAIN/rid - now we store the SID direct */
|
||||
tdb_traverse(idmap_tdb, tdb_convert_fn, NULL);
|
||||
|
||||
if (tdb_store_int32(idmap_tdb, "IDMAP_VERSION", IDMAP_VERSION) ==
|
||||
-1) {
|
||||
DEBUG(0,
|
||||
("tdb_idmap_convert: Unable to byteswap group hwm in idmap database\n"));
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
/* Allocate either a user or group id from the pool */
|
||||
static BOOL tdb_allocate_id(uid_t * id, BOOL isgroup)
|
||||
{
|
||||
int hwm;
|
||||
|
||||
/* Get current high water mark */
|
||||
if ((hwm = tdb_fetch_int32(idmap_tdb,
|
||||
isgroup ? HWM_GROUP : HWM_USER)) ==
|
||||
-1) {
|
||||
return False;
|
||||
}
|
||||
|
||||
/* Return next available uid in list */
|
||||
if ((isgroup && (hwm > server_state.gid_high)) ||
|
||||
(!isgroup && (hwm > server_state.uid_high))) {
|
||||
DEBUG(0,
|
||||
("winbind %sid range full!\n", isgroup ? "g" : "u"));
|
||||
return False;
|
||||
}
|
||||
|
||||
if (id) {
|
||||
*id = hwm;
|
||||
}
|
||||
|
||||
hwm++;
|
||||
|
||||
/* Store new high water mark */
|
||||
tdb_store_int32(idmap_tdb, isgroup ? HWM_GROUP : HWM_USER, hwm);
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
/* Get a sid from an id */
|
||||
static BOOL tdb_get_sid_from_id(int id, DOM_SID * sid, BOOL isgroup)
|
||||
{
|
||||
TDB_DATA key, data;
|
||||
fstring keystr;
|
||||
BOOL result = False;
|
||||
|
||||
slprintf(keystr, sizeof(keystr), "%s %d", isgroup ? "GID" : "UID",
|
||||
id);
|
||||
|
||||
key.dptr = keystr;
|
||||
key.dsize = strlen(keystr) + 1;
|
||||
|
||||
data = tdb_fetch(idmap_tdb, key);
|
||||
|
||||
if (data.dptr) {
|
||||
result = string_to_sid(sid, data.dptr);
|
||||
SAFE_FREE(data.dptr);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Get an id from a sid */
|
||||
static BOOL tdb_get_id_from_sid(DOM_SID * sid, uid_t * id, BOOL isgroup)
|
||||
{
|
||||
TDB_DATA data, key;
|
||||
fstring keystr;
|
||||
BOOL result = False;
|
||||
|
||||
/* Check if sid is present in database */
|
||||
sid_to_string(keystr, sid);
|
||||
|
||||
key.dptr = keystr;
|
||||
key.dsize = strlen(keystr) + 1;
|
||||
|
||||
data = tdb_fetch(idmap_tdb, key);
|
||||
|
||||
if (data.dptr) {
|
||||
fstring scanstr;
|
||||
int the_id;
|
||||
|
||||
/* Parse and return existing uid */
|
||||
fstrcpy(scanstr, isgroup ? "GID" : "UID");
|
||||
fstrcat(scanstr, " %d");
|
||||
|
||||
if (sscanf(data.dptr, scanstr, &the_id) == 1) {
|
||||
/* Store uid */
|
||||
if (id) {
|
||||
*id = the_id;
|
||||
}
|
||||
|
||||
result = True;
|
||||
}
|
||||
|
||||
SAFE_FREE(data.dptr);
|
||||
} else {
|
||||
|
||||
/* Allocate a new id for this sid */
|
||||
if (id && tdb_allocate_id(id, isgroup)) {
|
||||
fstring keystr2;
|
||||
|
||||
/* Store new id */
|
||||
slprintf(keystr2, sizeof(keystr2), "%s %d",
|
||||
isgroup ? "GID" : "UID", *id);
|
||||
|
||||
data.dptr = keystr2;
|
||||
data.dsize = strlen(keystr2) + 1;
|
||||
|
||||
tdb_store(idmap_tdb, key, data, TDB_REPLACE);
|
||||
tdb_store(idmap_tdb, data, key, TDB_REPLACE);
|
||||
|
||||
result = True;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
Initialise idmap database.
|
||||
*****************************************************************************/
|
||||
static BOOL tdb_idmap_init(void)
|
||||
{
|
||||
SMB_STRUCT_STAT stbuf;
|
||||
|
||||
/* move to the new database on first startup */
|
||||
if (!file_exist(lock_path("idmap.tdb"), &stbuf)) {
|
||||
if (file_exist(lock_path("winbindd_idmap.tdb"), &stbuf)) {
|
||||
char *cmd = NULL;
|
||||
|
||||
/* lazy file copy */
|
||||
if (asprintf(&cmd, "cp -p %s/winbindd_idmap.tdb %s/idmap.tdb", lp_lockdir(), lp_lockdir()) != -1) {
|
||||
system(cmd);
|
||||
free(cmd);
|
||||
}
|
||||
if (!file_exist(lock_path("idmap.tdb"), &stbuf)) {
|
||||
DEBUG(0, ("idmap_init: Unable to make a new database copy\n"));
|
||||
return False;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Open tdb cache */
|
||||
if (!(idmap_tdb = tdb_open_log(lock_path("idmap.tdb"), 0,
|
||||
TDB_DEFAULT, O_RDWR | O_CREAT,
|
||||
0600))) {
|
||||
DEBUG(0,
|
||||
("winbindd_idmap_init: Unable to open idmap database\n"));
|
||||
return False;
|
||||
}
|
||||
|
||||
/* possibly convert from an earlier version */
|
||||
if (!tdb_idmap_convert()) {
|
||||
DEBUG(0, ("winbindd_idmap_init: Unable to open idmap database\n"));
|
||||
return False;
|
||||
}
|
||||
|
||||
/* Create high water marks for group and user id */
|
||||
if (tdb_fetch_int32(idmap_tdb, HWM_USER) == -1) {
|
||||
if (tdb_store_int32
|
||||
(idmap_tdb, HWM_USER, server_state.uid_low) == -1) {
|
||||
DEBUG(0,
|
||||
("winbindd_idmap_init: Unable to initialise user hwm in idmap database\n"));
|
||||
return False;
|
||||
}
|
||||
}
|
||||
|
||||
if (tdb_fetch_int32(idmap_tdb, HWM_GROUP) == -1) {
|
||||
if (tdb_store_int32
|
||||
(idmap_tdb, HWM_GROUP, server_state.gid_low) == -1) {
|
||||
DEBUG(0,
|
||||
("winbindd_idmap_init: Unable to initialise group hwm in idmap database\n"));
|
||||
return False;
|
||||
}
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
/* Get a sid from a uid */
|
||||
static BOOL tdb_get_sid_from_uid(uid_t uid, DOM_SID * sid)
|
||||
{
|
||||
return tdb_get_sid_from_id((int) uid, sid, False);
|
||||
}
|
||||
|
||||
/* Get a sid from a gid */
|
||||
static BOOL tdb_get_sid_from_gid(gid_t gid, DOM_SID * sid)
|
||||
{
|
||||
return tdb_get_sid_from_id((int) gid, sid, True);
|
||||
}
|
||||
|
||||
/* Get a uid from a sid */
|
||||
static BOOL tdb_get_uid_from_sid(DOM_SID * sid, uid_t * uid)
|
||||
{
|
||||
return tdb_get_id_from_sid(sid, uid, False);
|
||||
}
|
||||
|
||||
/* Get a gid from a group sid */
|
||||
static BOOL tdb_get_gid_from_sid(DOM_SID * sid, gid_t * gid)
|
||||
{
|
||||
return tdb_get_id_from_sid(sid, gid, True);
|
||||
}
|
||||
|
||||
/* Close the tdb */
|
||||
static BOOL tdb_idmap_close(void)
|
||||
{
|
||||
if (idmap_tdb)
|
||||
return (tdb_close(idmap_tdb) == 0);
|
||||
return True;
|
||||
}
|
||||
|
||||
|
||||
/* Dump status information to log file. Display different stuff based on
|
||||
the debug level:
|
||||
|
||||
Debug Level Information Displayed
|
||||
=================================================================
|
||||
0 Percentage of [ug]id range allocated
|
||||
0 High water marks (next allocated ids)
|
||||
*/
|
||||
|
||||
#define DUMP_INFO 0
|
||||
|
||||
static void tdb_idmap_status(void)
|
||||
{
|
||||
int user_hwm, group_hwm;
|
||||
|
||||
DEBUG(0, ("winbindd idmap status:\n"));
|
||||
|
||||
/* Get current high water marks */
|
||||
|
||||
if ((user_hwm = tdb_fetch_int32(idmap_tdb, HWM_USER)) == -1) {
|
||||
DEBUG(DUMP_INFO,
|
||||
("\tCould not get userid high water mark!\n"));
|
||||
}
|
||||
|
||||
if ((group_hwm = tdb_fetch_int32(idmap_tdb, HWM_GROUP)) == -1) {
|
||||
DEBUG(DUMP_INFO,
|
||||
("\tCould not get groupid high water mark!\n"));
|
||||
}
|
||||
|
||||
/* Display next ids to allocate */
|
||||
|
||||
if (user_hwm != -1) {
|
||||
DEBUG(DUMP_INFO,
|
||||
("\tNext userid to allocate is %d\n", user_hwm));
|
||||
}
|
||||
|
||||
if (group_hwm != -1) {
|
||||
DEBUG(DUMP_INFO,
|
||||
("\tNext groupid to allocate is %d\n", group_hwm));
|
||||
}
|
||||
|
||||
/* Display percentage of id range already allocated. */
|
||||
|
||||
if (user_hwm != -1) {
|
||||
int num_users = user_hwm - server_state.uid_low;
|
||||
int total_users =
|
||||
server_state.uid_high - server_state.uid_low;
|
||||
|
||||
DEBUG(DUMP_INFO,
|
||||
("\tUser id range is %d%% full (%d of %d)\n",
|
||||
num_users * 100 / total_users, num_users,
|
||||
total_users));
|
||||
}
|
||||
|
||||
if (group_hwm != -1) {
|
||||
int num_groups = group_hwm - server_state.gid_low;
|
||||
int total_groups =
|
||||
server_state.gid_high - server_state.gid_low;
|
||||
|
||||
DEBUG(DUMP_INFO,
|
||||
("\tGroup id range is %d%% full (%d of %d)\n",
|
||||
num_groups * 100 / total_groups, num_groups,
|
||||
total_groups));
|
||||
}
|
||||
|
||||
/* Display complete mapping of users and groups to rids */
|
||||
}
|
||||
|
||||
struct winbindd_idmap_methods tdb_idmap_methods = {
|
||||
tdb_idmap_init,
|
||||
|
||||
tdb_get_sid_from_uid,
|
||||
tdb_get_sid_from_gid,
|
||||
|
||||
tdb_get_uid_from_sid,
|
||||
tdb_get_gid_from_sid,
|
||||
|
||||
tdb_idmap_close,
|
||||
|
||||
tdb_idmap_status
|
||||
};
|
||||
|
||||
BOOL winbind_idmap_reg_tdb(struct winbindd_idmap_methods **meth)
|
||||
{
|
||||
*meth = &tdb_idmap_methods;
|
||||
|
||||
return True;
|
||||
}
|
@ -36,7 +36,7 @@
|
||||
|
||||
/* Update this when you change the interface. */
|
||||
|
||||
#define WINBIND_INTERFACE_VERSION 7
|
||||
#define WINBIND_INTERFACE_VERSION 8
|
||||
|
||||
/* Socket commands */
|
||||
|
||||
@ -99,6 +99,16 @@ enum winbindd_cmd {
|
||||
WINBINDD_WINS_BYIP,
|
||||
WINBINDD_WINS_BYNAME,
|
||||
|
||||
/* account management commands */
|
||||
|
||||
WINBINDD_CREATE_USER,
|
||||
WINBINDD_CREATE_GROUP,
|
||||
WINBINDD_ADD_USER_TO_GROUP,
|
||||
WINBINDD_REMOVE_USER_FROM_GROUP,
|
||||
WINBINDD_SET_USER_PRIMARY_GROUP,
|
||||
WINBINDD_DELETE_USER,
|
||||
WINBINDD_DELETE_GROUP,
|
||||
|
||||
/* this is like GETGRENT but gives an empty group list */
|
||||
WINBINDD_GETGRLST,
|
||||
|
||||
@ -111,6 +121,27 @@ enum winbindd_cmd {
|
||||
WINBINDD_NUM_CMDS
|
||||
};
|
||||
|
||||
typedef struct winbindd_pw {
|
||||
fstring pw_name;
|
||||
fstring pw_passwd;
|
||||
uid_t pw_uid;
|
||||
gid_t pw_gid;
|
||||
fstring pw_gecos;
|
||||
fstring pw_dir;
|
||||
fstring pw_shell;
|
||||
} WINBINDD_PW;
|
||||
|
||||
|
||||
typedef struct winbindd_gr {
|
||||
fstring gr_name;
|
||||
fstring gr_passwd;
|
||||
gid_t gr_gid;
|
||||
int num_gr_mem;
|
||||
int gr_mem_ofs; /* offset to group membership */
|
||||
char **gr_mem;
|
||||
} WINBINDD_GR;
|
||||
|
||||
|
||||
#define WBFLAG_PAM_INFO3_NDR 0x0001
|
||||
#define WBFLAG_PAM_INFO3_TEXT 0x0002
|
||||
#define WBFLAG_PAM_NTKEY 0x0004
|
||||
@ -160,6 +191,10 @@ struct winbindd_request {
|
||||
fstring name;
|
||||
} name;
|
||||
uint32 num_entries; /* getpwent, getgrent */
|
||||
struct {
|
||||
fstring username;
|
||||
fstring groupname;
|
||||
} acct_mgt;
|
||||
} data;
|
||||
char null_term;
|
||||
};
|
||||
@ -189,25 +224,11 @@ struct winbindd_response {
|
||||
|
||||
/* getpwnam, getpwuid */
|
||||
|
||||
struct winbindd_pw {
|
||||
fstring pw_name;
|
||||
fstring pw_passwd;
|
||||
uid_t pw_uid;
|
||||
gid_t pw_gid;
|
||||
fstring pw_gecos;
|
||||
fstring pw_dir;
|
||||
fstring pw_shell;
|
||||
} pw;
|
||||
struct winbindd_pw pw;
|
||||
|
||||
/* getgrnam, getgrgid */
|
||||
|
||||
struct winbindd_gr {
|
||||
fstring gr_name;
|
||||
fstring gr_passwd;
|
||||
gid_t gr_gid;
|
||||
int num_gr_mem;
|
||||
int gr_mem_ofs; /* offset to group membership */
|
||||
} gr;
|
||||
struct winbindd_gr gr;
|
||||
|
||||
uint32 num_entries; /* getpwent, getgrent */
|
||||
struct winbindd_sid {
|
||||
|
@ -142,8 +142,8 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state)
|
||||
|
||||
/* Parse domain and username */
|
||||
|
||||
if (!parse_domain_user(state->request.data.auth.user, name_domain,
|
||||
name_user)) {
|
||||
parse_domain_user(state->request.data.auth.user, name_domain, name_user);
|
||||
if ( !name_domain ) {
|
||||
DEBUG(5,("no domain separator (%s) in username (%s) - failing auth\n", lp_winbind_separator(), state->request.data.auth.user));
|
||||
result = NT_STATUS_INVALID_PARAMETER;
|
||||
goto done;
|
||||
@ -444,8 +444,8 @@ enum winbindd_result winbindd_pam_chauthtok(struct winbindd_cli_state *state)
|
||||
if (state == NULL)
|
||||
return WINBINDD_ERROR;
|
||||
|
||||
if (!parse_domain_user(state->request.data.chauthtok.user, domain,
|
||||
user)) {
|
||||
parse_domain_user(state->request.data.chauthtok.user, domain, user);
|
||||
if ( !*domain ) {
|
||||
result = NT_STATUS_INVALID_PARAMETER;
|
||||
goto done;
|
||||
}
|
||||
|
@ -1,360 +0,0 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
Winbind rpc backend functions
|
||||
|
||||
Copyright (C) Tim Potter 2000-2001,2003
|
||||
Copyright (C) Simo Sorce 2003
|
||||
|
||||
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 "winbindd.h"
|
||||
|
||||
#undef DBGC_CLASS
|
||||
#define DBGC_CLASS DBGC_WINBIND
|
||||
|
||||
|
||||
/* Query display info for a domain. This returns enough information plus a
|
||||
bit extra to give an overview of domain users for the User Manager
|
||||
application. */
|
||||
static NTSTATUS query_user_list(struct winbindd_domain *domain,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
uint32 *num_entries,
|
||||
WINBIND_USERINFO **info)
|
||||
{
|
||||
SAM_ACCOUNT *sam_account = NULL;
|
||||
NTSTATUS result;
|
||||
uint32 i;
|
||||
|
||||
DEBUG(3,("pdb: query_user_list\n"));
|
||||
|
||||
if (!NT_STATUS_IS_OK(result = pdb_init_sam(&sam_account))) {
|
||||
return result;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
*info = NULL;
|
||||
|
||||
if (pdb_setsampwent(False)) {
|
||||
|
||||
while (pdb_getsampwent(sam_account)) {
|
||||
|
||||
/* we return only nua accounts, or we will have duplicates */
|
||||
if (!idmap_check_sid_is_in_free_range(pdb_get_user_sid(sam_account))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
*info = talloc_realloc(mem_ctx, *info, (i + 1) * sizeof(WINBIND_USERINFO));
|
||||
if (!(*info)) {
|
||||
DEBUG(0,("query_user_list: out of memory!\n"));
|
||||
result = NT_STATUS_NO_MEMORY;
|
||||
break;
|
||||
}
|
||||
|
||||
(*info)[i].user_sid = talloc(mem_ctx, sizeof(DOM_SID));
|
||||
(*info)[i].group_sid = talloc(mem_ctx, sizeof(DOM_SID));
|
||||
if (!((*info)[i].user_sid) || !((*info)[i].group_sid)) {
|
||||
DEBUG(0,("query_user_list: out of memory!\n"));
|
||||
result = NT_STATUS_NO_MEMORY;
|
||||
break;
|
||||
}
|
||||
sid_copy((*info)[i].user_sid, pdb_get_user_sid(sam_account));
|
||||
sid_copy((*info)[i].group_sid, pdb_get_group_sid(sam_account));
|
||||
|
||||
(*info)[i].acct_name = talloc_strdup(mem_ctx, pdb_get_username(sam_account));
|
||||
(*info)[i].full_name = talloc_strdup(mem_ctx, pdb_get_fullname(sam_account));
|
||||
if (!((*info)[i].acct_name) || !((*info)[i].full_name)) {
|
||||
DEBUG(0,("query_user_list: out of memory!\n"));
|
||||
result = NT_STATUS_NO_MEMORY;
|
||||
break;
|
||||
}
|
||||
|
||||
i++;
|
||||
|
||||
if (!NT_STATUS_IS_OK(pdb_reset_sam(sam_account))) {
|
||||
result = NT_STATUS_UNSUCCESSFUL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*num_entries = i;
|
||||
result = NT_STATUS_OK;
|
||||
|
||||
} else {
|
||||
result = NT_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
pdb_free_sam(&sam_account);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* list all domain groups */
|
||||
static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
uint32 *num_entries,
|
||||
struct acct_info **info)
|
||||
{
|
||||
NTSTATUS result = NT_STATUS_OK;
|
||||
|
||||
DEBUG(3,("pdb: enum_dom_groups (group support not implemented)\n"));
|
||||
|
||||
*num_entries = 0;
|
||||
*info = 0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* List all domain groups */
|
||||
|
||||
static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
uint32 *num_entries,
|
||||
struct acct_info **info)
|
||||
{
|
||||
NTSTATUS result = NT_STATUS_OK;
|
||||
|
||||
DEBUG(3,("pdb: enum_local_groups (group support not implemented)\n"));
|
||||
|
||||
*num_entries = 0;
|
||||
*info = 0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* convert a single name to a sid in a domain */
|
||||
static NTSTATUS name_to_sid(struct winbindd_domain *domain,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
const char *name,
|
||||
DOM_SID *sid,
|
||||
enum SID_NAME_USE *type)
|
||||
{
|
||||
SAM_ACCOUNT *sam_account = NULL;
|
||||
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
|
||||
|
||||
DEBUG(3,("pdb: name_to_sid name=%s (group support not implemented)\n", name));
|
||||
|
||||
if (NT_STATUS_IS_OK(pdb_init_sam(&sam_account))) {
|
||||
if (!pdb_getsampwnam(sam_account, name)) {
|
||||
result = NT_STATUS_UNSUCCESSFUL;
|
||||
} else { /* it is a sam user */
|
||||
sid_copy(sid, pdb_get_user_sid(sam_account));
|
||||
*type = SID_NAME_USER;
|
||||
result = NT_STATUS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
pdb_free_sam(&sam_account);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
convert a domain SID to a user or group name
|
||||
*/
|
||||
static NTSTATUS sid_to_name(struct winbindd_domain *domain,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
DOM_SID *sid,
|
||||
char **name,
|
||||
enum SID_NAME_USE *type)
|
||||
{
|
||||
SAM_ACCOUNT *sam_account = NULL;
|
||||
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
|
||||
uint32 id;
|
||||
|
||||
DEBUG(3,("pdb: sid_to_name sid=%s\n", sid_string_static(sid)));
|
||||
|
||||
if (NT_STATUS_IS_OK(idmap_sid_to_uid(sid, &id, 0))) { /* this is a user */
|
||||
|
||||
if (!NT_STATUS_IS_OK(result = pdb_init_sam(&sam_account))) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!pdb_getsampwsid(sam_account, sid)) {
|
||||
pdb_free_sam(&sam_account);
|
||||
return NT_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
*name = talloc_strdup(mem_ctx, pdb_get_username(sam_account));
|
||||
if (!(*name)) {
|
||||
DEBUG(0,("query_user: out of memory!\n"));
|
||||
pdb_free_sam(&sam_account);
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
pdb_free_sam(&sam_account);
|
||||
*type = SID_NAME_USER;
|
||||
result = NT_STATUS_OK;
|
||||
|
||||
} else if (NT_STATUS_IS_OK(idmap_sid_to_gid(sid, &id, 0))) { /* this is a group */
|
||||
|
||||
DEBUG(3,("pdb: sid_to_name: group support not implemented\n"));
|
||||
result = NT_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Lookup user information from a rid or username. */
|
||||
static NTSTATUS query_user(struct winbindd_domain *domain,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
DOM_SID *user_sid,
|
||||
WINBIND_USERINFO *user_info)
|
||||
{
|
||||
SAM_ACCOUNT *sam_account = NULL;
|
||||
NTSTATUS result;
|
||||
|
||||
DEBUG(3,("pdb: query_user sid=%s\n", sid_string_static(user_sid)));
|
||||
|
||||
if (!NT_STATUS_IS_OK(result = pdb_init_sam(&sam_account))) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!pdb_getsampwsid(sam_account, user_sid)) {
|
||||
pdb_free_sam(&sam_account);
|
||||
return NT_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/* we return only nua accounts, or we will have duplicates */
|
||||
if (!idmap_check_sid_is_in_free_range(user_sid)) {
|
||||
pdb_free_sam(&sam_account);
|
||||
return NT_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
user_info->user_sid = talloc(mem_ctx, sizeof(DOM_SID));
|
||||
user_info->group_sid = talloc(mem_ctx, sizeof(DOM_SID));
|
||||
if (!(user_info->user_sid) || !(user_info->group_sid)) {
|
||||
DEBUG(0,("query_user: out of memory!\n"));
|
||||
pdb_free_sam(&sam_account);
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
sid_copy(user_info->user_sid, pdb_get_user_sid(sam_account));
|
||||
sid_copy(user_info->group_sid, pdb_get_group_sid(sam_account));
|
||||
|
||||
user_info->acct_name = talloc_strdup(mem_ctx, pdb_get_username(sam_account));
|
||||
user_info->full_name = talloc_strdup(mem_ctx, pdb_get_fullname(sam_account));
|
||||
if (!(user_info->acct_name) || !(user_info->full_name)) {
|
||||
DEBUG(0,("query_user: out of memory!\n"));
|
||||
pdb_free_sam(&sam_account);
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
pdb_free_sam(&sam_account);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/* Lookup groups a user is a member of. I wish Unix had a call like this! */
|
||||
static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
DOM_SID *user_sid,
|
||||
uint32 *num_groups, DOM_SID ***user_gids)
|
||||
{
|
||||
NTSTATUS result = NT_STATUS_OK;
|
||||
|
||||
DEBUG(3,("pdb: lookup_usergroups (group support not implemented)\n"));
|
||||
|
||||
num_groups = 0;
|
||||
user_gids = 0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/* Lookup group membership given a rid. */
|
||||
static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
DOM_SID *group_sid, uint32 *num_names,
|
||||
DOM_SID ***sid_mem, char ***names,
|
||||
uint32 **name_types)
|
||||
{
|
||||
NTSTATUS result = NT_STATUS_NOT_IMPLEMENTED;
|
||||
|
||||
DEBUG(3,("pdb: lookup_groupmem (group support not implemented)\n"));
|
||||
|
||||
num_names = 0;
|
||||
sid_mem = 0;
|
||||
names = 0;
|
||||
name_types = 0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* find the sequence number for a domain */
|
||||
static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
|
||||
{
|
||||
/* FIXME: we fake up the seq_num untill our passdb support it */
|
||||
static uint32 seq_num;
|
||||
|
||||
DEBUG(3,("pdb: sequence_number\n"));
|
||||
|
||||
*seq = seq_num++;
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/* get a list of trusted domains */
|
||||
static NTSTATUS trusted_domains(struct winbindd_domain *domain,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
uint32 *num_domains,
|
||||
char ***names,
|
||||
char ***alt_names,
|
||||
DOM_SID **dom_sids)
|
||||
{
|
||||
NTSTATUS result = NT_STATUS_NOT_IMPLEMENTED;
|
||||
|
||||
DEBUG(3,("pdb: trusted_domains (todo!)\n"));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* find the domain sid for a domain */
|
||||
static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid)
|
||||
{
|
||||
DEBUG(3,("pdb: domain_sid\n"));
|
||||
|
||||
if (strcmp(domain->name, lp_workgroup())) {
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
} else {
|
||||
sid_copy(sid, get_global_sam_sid());
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/* find alternate names list for the domain
|
||||
* should we look for netbios aliases??
|
||||
SSS */
|
||||
static NTSTATUS alternate_name(struct winbindd_domain *domain)
|
||||
{
|
||||
DEBUG(3,("pdb: alternate_name\n"));
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
/* the rpc backend methods are exposed via this structure */
|
||||
struct winbindd_methods passdb_methods = {
|
||||
False,
|
||||
query_user_list,
|
||||
enum_dom_groups,
|
||||
enum_local_groups,
|
||||
name_to_sid,
|
||||
sid_to_name,
|
||||
query_user,
|
||||
lookup_usergroups,
|
||||
lookup_groupmem,
|
||||
sequence_number,
|
||||
trusted_domains,
|
||||
domain_sid,
|
||||
alternate_name
|
||||
};
|
@ -97,6 +97,7 @@ static BOOL winbindd_fill_pwent(char *dom_name, char *user_name,
|
||||
enum winbindd_result winbindd_getpwnam(struct winbindd_cli_state *state)
|
||||
{
|
||||
WINBIND_USERINFO user_info;
|
||||
WINBINDD_PW *pw;
|
||||
DOM_SID user_sid;
|
||||
NTSTATUS status;
|
||||
fstring name_domain, name_user;
|
||||
@ -112,16 +113,25 @@ enum winbindd_result winbindd_getpwnam(struct winbindd_cli_state *state)
|
||||
|
||||
/* Parse domain and username */
|
||||
|
||||
if (!parse_domain_user(state->request.data.username, name_domain,
|
||||
name_user))
|
||||
return WINBINDD_ERROR;
|
||||
parse_domain_user(state->request.data.username,
|
||||
name_domain, name_user);
|
||||
|
||||
/* don't handle our own domain if we are a DC ( or a member of a Samba domain
|
||||
that shares UNIX accounts). This code handles cases where
|
||||
the account doesn't exist anywhere and gets passed on down the NSS layer */
|
||||
/* if this is our local domain (or no domain), the do a local tdb search */
|
||||
|
||||
if ( !*name_domain || strequal(name_domain, get_global_sam_name()) ) {
|
||||
if ( !(pw = wb_getpwnam(name_user)) ) {
|
||||
DEBUG(5,("winbindd_getpwnam: lookup for %s\\%s failed\n",
|
||||
name_domain, name_user));
|
||||
return WINBINDD_ERROR;
|
||||
}
|
||||
memcpy( &state->response.data.pw, pw, sizeof(WINBINDD_PW) );
|
||||
return WINBINDD_OK;
|
||||
}
|
||||
|
||||
if ( (IS_DC || lp_winbind_trusted_domains_only()) && strequal(name_domain, lp_workgroup()) ) {
|
||||
DEBUG(7,("winbindd_getpwnam: rejecting getpwnam() for %s\\%s since I am on the PDC for this domain\n",
|
||||
/* should we deal with users for our domain? */
|
||||
|
||||
if ( lp_winbind_trusted_domains_only() && strequal(name_domain, lp_workgroup())) {
|
||||
DEBUG(7,("winbindd_getpenam: My domain -- rejecting getpwnam() for %s\\%s.\n",
|
||||
name_domain, name_user));
|
||||
return WINBINDD_ERROR;
|
||||
}
|
||||
@ -184,6 +194,7 @@ enum winbindd_result winbindd_getpwuid(struct winbindd_cli_state *state)
|
||||
{
|
||||
DOM_SID user_sid;
|
||||
struct winbindd_domain *domain;
|
||||
WINBINDD_PW *pw;
|
||||
fstring dom_name;
|
||||
fstring user_name;
|
||||
enum SID_NAME_USE name_type;
|
||||
@ -200,6 +211,13 @@ enum winbindd_result winbindd_getpwuid(struct winbindd_cli_state *state)
|
||||
|
||||
DEBUG(3, ("[%5d]: getpwuid %d\n", state->pid,
|
||||
state->request.data.uid));
|
||||
|
||||
/* always try local tdb first */
|
||||
|
||||
if ( (pw = wb_getpwuid(state->request.data.uid)) != NULL ) {
|
||||
memcpy( &state->response.data.pw, pw, sizeof(WINBINDD_PW) );
|
||||
return WINBINDD_OK;
|
||||
}
|
||||
|
||||
/* Get rid from uid */
|
||||
|
||||
|
@ -415,18 +415,22 @@ BOOL parse_domain_user(const char *domuser, fstring domain, fstring user)
|
||||
{
|
||||
char *p = strchr(domuser,*lp_winbind_separator());
|
||||
|
||||
if (!(p || lp_winbind_use_default_domain()))
|
||||
return False;
|
||||
|
||||
if(!p && lp_winbind_use_default_domain()) {
|
||||
if ( !p ) {
|
||||
fstrcpy(user, domuser);
|
||||
fstrcpy(domain, lp_workgroup());
|
||||
} else {
|
||||
|
||||
if ( lp_winbind_use_default_domain() )
|
||||
fstrcpy(domain, lp_workgroup());
|
||||
else
|
||||
fstrcpy( domain, "" );
|
||||
}
|
||||
else {
|
||||
fstrcpy(user, p+1);
|
||||
fstrcpy(domain, domuser);
|
||||
domain[PTR_DIFF(p, domuser)] = 0;
|
||||
}
|
||||
|
||||
strupper_m(domain);
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
|
@ -165,9 +165,11 @@ typedef struct
|
||||
char *szIdmapGID;
|
||||
BOOL bEnableRidAlgorithm;
|
||||
int AlgorithmicRidBase;
|
||||
char *szTemplatePrimaryGroup;
|
||||
char *szTemplateHomedir;
|
||||
char *szTemplateShell;
|
||||
char *szWinbindSeparator;
|
||||
BOOL bWinbindEnableLocalAccounts;
|
||||
BOOL bWinbindEnumUsers;
|
||||
BOOL bWinbindEnumGroups;
|
||||
BOOL bWinbindUseDefaultDomain;
|
||||
@ -1123,10 +1125,12 @@ static struct parm_struct parm_table[] = {
|
||||
{"winbind uid", P_STRING, P_GLOBAL, &Globals.szIdmapUID, handle_idmap_uid, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
|
||||
{"idmap gid", P_STRING, P_GLOBAL, &Globals.szIdmapGID, handle_idmap_gid, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
|
||||
{"winbind gid", P_STRING, P_GLOBAL, &Globals.szIdmapGID, handle_idmap_gid, NULL, FLAG_ADVANCED | FLAG_DEVELOPER },
|
||||
{"template primary group", P_STRING, P_GLOBAL, &Globals.szTemplatePrimaryGroup, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
|
||||
{"template homedir", P_STRING, P_GLOBAL, &Globals.szTemplateHomedir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
|
||||
{"template shell", P_STRING, P_GLOBAL, &Globals.szTemplateShell, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
|
||||
{"winbind separator", P_STRING, P_GLOBAL, &Globals.szWinbindSeparator, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
|
||||
{"winbind cache time", P_INTEGER, P_GLOBAL, &Globals.winbind_cache_time, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
|
||||
{"winbind enable local accounts", P_BOOL, P_GLOBAL, &Globals.bWinbindEnableLocalAccounts, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
|
||||
{"winbind enum users", P_BOOL, P_GLOBAL, &Globals.bWinbindEnumUsers, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
|
||||
{"winbind enum groups", P_BOOL, P_GLOBAL, &Globals.bWinbindEnumGroups, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
|
||||
{"winbind use default domain", P_BOOL, P_GLOBAL, &Globals.bWinbindUseDefaultDomain, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
|
||||
@ -1465,10 +1469,12 @@ static void init_globals(void)
|
||||
|
||||
string_set(&Globals.szTemplateShell, "/bin/false");
|
||||
string_set(&Globals.szTemplateHomedir, "/home/%D/%U");
|
||||
string_set(&Globals.szTemplatePrimaryGroup, "nobody");
|
||||
string_set(&Globals.szWinbindSeparator, "\\");
|
||||
string_set(&Globals.szAclCompat, "");
|
||||
|
||||
Globals.winbind_cache_time = 300; /* 5 minutes */
|
||||
Globals.bWinbindEnableLocalAccounts = True;
|
||||
Globals.bWinbindEnumUsers = True;
|
||||
Globals.bWinbindEnumGroups = True;
|
||||
Globals.bWinbindUseDefaultDomain = False;
|
||||
@ -1632,10 +1638,12 @@ FN_GLOBAL_STRING(lp_abort_shutdown_script, &Globals.szAbortShutdownScript)
|
||||
|
||||
FN_GLOBAL_STRING(lp_wins_hook, &Globals.szWINSHook)
|
||||
FN_GLOBAL_STRING(lp_wins_partners, &Globals.szWINSPartners)
|
||||
FN_GLOBAL_STRING(lp_template_primary_group, &Globals.szTemplatePrimaryGroup)
|
||||
FN_GLOBAL_STRING(lp_template_homedir, &Globals.szTemplateHomedir)
|
||||
FN_GLOBAL_STRING(lp_template_shell, &Globals.szTemplateShell)
|
||||
FN_GLOBAL_CONST_STRING(lp_winbind_separator, &Globals.szWinbindSeparator)
|
||||
FN_GLOBAL_STRING(lp_acl_compatibility, &Globals.szAclCompat)
|
||||
FN_GLOBAL_BOOL(lp_winbind_enable_local_accounts, &Globals.bWinbindEnableLocalAccounts)
|
||||
FN_GLOBAL_BOOL(lp_winbind_enum_users, &Globals.bWinbindEnumUsers)
|
||||
FN_GLOBAL_BOOL(lp_winbind_enum_groups, &Globals.bWinbindEnumGroups)
|
||||
FN_GLOBAL_BOOL(lp_winbind_use_default_domain, &Globals.bWinbindUseDefaultDomain)
|
||||
|
@ -2259,17 +2259,13 @@ NTSTATUS _api_samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_
|
||||
*/
|
||||
|
||||
DEBUG(10,("checking account %s at pos %d for $ termination\n",account, strlen(account)-1));
|
||||
#if 0
|
||||
if ((acb_info & ACB_WSTRUST) && (account[strlen(account)-1] == '$')) {
|
||||
pstrcpy(add_script, lp_addmachine_script());
|
||||
} else if ((!(acb_info & ACB_WSTRUST)) && (account[strlen(account)-1] != '$')) {
|
||||
pstrcpy(add_script, lp_adduser_script());
|
||||
} else {
|
||||
DEBUG(0, ("_api_samr_create_user: mismatch between trust flags and $ termination\n"));
|
||||
pdb_free_sam(&sam_pass);
|
||||
return NT_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* we used to have code here that made sure the acb_info flags
|
||||
* matched with the users named (e.g. an account flags as a machine
|
||||
* trust account ended in '$'). It has been ifdef'd out for a long
|
||||
* time, so I replaced it with this comment. --jerry
|
||||
*/
|
||||
|
||||
/* the passdb lookup has failed; check to see if we need to run the
|
||||
add user/machine script */
|
||||
@ -2295,11 +2291,17 @@ NTSTATUS _api_samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_
|
||||
add_ret = smbrun(add_script,NULL);
|
||||
DEBUG(3,("_api_samr_create_user: Running the command `%s' gave %d\n", add_script, add_ret));
|
||||
}
|
||||
else /* no add user script -- ask winbindd to do it */
|
||||
{
|
||||
if ( !winbind_create_user( account ) )
|
||||
DEBUG(3,("_api_samr_create_user: winbind_create_user(%s) failed\n", account));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
nt_status = pdb_init_sam_new(&sam_pass, account);
|
||||
if (!NT_STATUS_IS_OK(nt_status))
|
||||
/* implicit call to getpwnam() next */
|
||||
|
||||
if ( !NT_STATUS_IS_OK(nt_status = pdb_init_sam_new(&sam_pass, account)) )
|
||||
return nt_status;
|
||||
|
||||
pdb_set_acct_ctrl(sam_pass, acb_info, PDB_CHANGED);
|
||||
|
@ -251,6 +251,21 @@ NTSTATUS idmap_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Get ID from SID. This can create a mapping for a SID to a POSIX id.
|
||||
**************************************************************************/
|
||||
|
||||
NTSTATUS idmap_allocate_id(unid_t *id, int id_type)
|
||||
{
|
||||
/* we have to allocate from the authoritative backend */
|
||||
|
||||
if ( remote_map )
|
||||
return remote_map->allocate_id( id, id_type );
|
||||
|
||||
return cache_map->allocate_id( id, id_type );
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
Shutdown maps.
|
||||
**************************************************************************/
|
||||
|
@ -675,6 +675,7 @@ static void ldap_idmap_status(void)
|
||||
|
||||
static struct idmap_methods ldap_methods = {
|
||||
ldap_idmap_init,
|
||||
ldap_allocate_id,
|
||||
ldap_get_sid_from_id,
|
||||
ldap_get_id_from_sid,
|
||||
ldap_set_mapping,
|
||||
|
@ -45,6 +45,20 @@ static struct idmap_state {
|
||||
gid_t gid_low, gid_high; /* Range of gids to allocate */
|
||||
} idmap_state;
|
||||
|
||||
/**********************************************************************
|
||||
Return the TDB_CONTEXT* for winbindd_idmap. I **really** feel
|
||||
dirty doing this, but not so dirty that I want to create another
|
||||
tdb
|
||||
***********************************************************************/
|
||||
|
||||
TDB_CONTEXT *idmap_tdb_handle( void )
|
||||
{
|
||||
if ( idmap_tdb )
|
||||
return idmap_tdb;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Allocate either a user or group id from the pool */
|
||||
static NTSTATUS db_allocate_id(unid_t *id, int id_type)
|
||||
{
|
||||
@ -111,7 +125,7 @@ static NTSTATUS db_allocate_id(unid_t *id, int id_type)
|
||||
}
|
||||
|
||||
(*id).gid = hwm;
|
||||
DEBUG(10,("db_allocate_id: ID_GROUPID (*id).uid = %d\n", (unsigned int)hwm));
|
||||
DEBUG(10,("db_allocate_id: ID_GROUPID (*id).gid = %d\n", (unsigned int)hwm));
|
||||
|
||||
break;
|
||||
default:
|
||||
@ -595,6 +609,7 @@ static void db_idmap_status(void)
|
||||
static struct idmap_methods db_methods = {
|
||||
|
||||
db_idmap_init,
|
||||
db_allocate_id,
|
||||
db_get_sid_from_id,
|
||||
db_get_id_from_sid,
|
||||
db_set_mapping,
|
||||
|
@ -146,6 +146,10 @@ END {
|
||||
gotstart = 1;
|
||||
}
|
||||
|
||||
if( $0 ~ /^WINBINDD_PW|^WINBINDD_GR/ ) {
|
||||
gotstart = 1;
|
||||
}
|
||||
|
||||
if(!gotstart) {
|
||||
next;
|
||||
}
|
||||
|
@ -809,17 +809,28 @@ NTSTATUS sid_to_uid(const DOM_SID *psid, uid_t *puid)
|
||||
if (fetch_uid_from_cache(puid, psid))
|
||||
return NT_STATUS_OK;
|
||||
|
||||
/*
|
||||
* First we must look up the name and decide if this is a user sid.
|
||||
*/
|
||||
/* if this is our DIS then go straight to a local lookup */
|
||||
|
||||
if ( sid_compare_domain(get_global_sam_sid(), psid) == 0 ) {
|
||||
DEBUG(10,("sid_to_uid: my domain (%s) - trying local.\n",
|
||||
sid_string_static(psid) ));
|
||||
|
||||
if ( (ret = local_sid_to_uid(puid, psid, &name_type)) == True )
|
||||
store_uid_sid_cache(psid, *puid);
|
||||
|
||||
return (ret ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
|
||||
|
||||
/* look up the name and decide if this is a user sid */
|
||||
|
||||
if ( (!winbind_lookup_sid(psid, dom_name, name, &name_type)) || (name_type != SID_NAME_USER) ) {
|
||||
DEBUG(10,("sid_to_uid: winbind lookup for sid %s failed - trying local.\n",
|
||||
sid_to_string(sid_str, psid) ));
|
||||
sid_string_static(psid) ));
|
||||
|
||||
ret = local_sid_to_uid(puid, psid, &name_type);
|
||||
if (ret)
|
||||
if ( (ret = local_sid_to_uid(puid, psid, &name_type)) == True )
|
||||
store_uid_sid_cache(psid, *puid);
|
||||
|
||||
return (ret ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
|
||||
|
@ -441,10 +441,17 @@ fetch_account_info(uint32 rid, SAM_ACCOUNT_INFO *delta)
|
||||
add_ret = smbrun(add_script,NULL);
|
||||
DEBUG(1,("fetch_account: Running the command `%s' "
|
||||
"gave %d\n", add_script, add_ret));
|
||||
|
||||
/* try and find the possible unix account again */
|
||||
passwd = Get_Pwnam(account);
|
||||
}
|
||||
else {
|
||||
DEBUG(8,("fetch_account_info: no add user/machine script. Asking winbindd\n"));
|
||||
if ( !winbind_create_user( account ) )
|
||||
DEBUG(4,("fetch_account_info: winbind_create_user() failed\n"));
|
||||
}
|
||||
|
||||
/* try and find the possible unix account again */
|
||||
if ( !(passwd = Get_Pwnam(account)) )
|
||||
return NT_STATUS_NO_SUCH_USER;
|
||||
|
||||
}
|
||||
|
||||
sid_copy(&user_sid, get_global_sam_sid());
|
||||
@ -912,7 +919,7 @@ fetch_sam_entry(SAM_DELTA_HDR *hdr_delta, SAM_DELTA_CTR *delta,
|
||||
&delta->als_mem_info, dom_sid);
|
||||
break;
|
||||
case SAM_DELTA_DOMAIN_INFO:
|
||||
d_printf("SAMBA_DELTA_DOMAIN_INFO not handled\n");
|
||||
d_printf("SAM_DELTA_DOMAIN_INFO not handled\n");
|
||||
break;
|
||||
default:
|
||||
d_printf("Unknown delta record type %d\n", hdr_delta->type);
|
||||
|
Loading…
x
Reference in New Issue
Block a user