summaryrefslogtreecommitdiff
path: root/source3/nsswitch/winbindd_acct.c
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2003-07-11 05:33:40 +0000
committerGerald Carter <jerry@samba.org>2003-07-11 05:33:40 +0000
commit03d5867d529f126da368ebda70bf2d997aa602e0 (patch)
tree6bed479ab42b3bcbd5ac6b70157c16232ff69869 /source3/nsswitch/winbindd_acct.c
parentd117c83ca9fc1b598d09f5d24805560e9c49f65c (diff)
downloadsamba-03d5867d529f126da368ebda70bf2d997aa602e0.tar.gz
samba-03d5867d529f126da368ebda70bf2d997aa602e0.tar.bz2
samba-03d5867d529f126da368ebda70bf2d997aa602e0.zip
moving more code around.
* move rid allocation into IDMAP. See comments in _api_samr_create_user() * add winbind delete user/group functions I'm checking this in to sync up with everyone. But I'm going to split the add a separate winbindd_allocate_rid() function for systems that have an 'add user script' but need idmap to give them a RID. Life would be so much simplier without 'enable rid algorithm'. The current RID allocation is horrible due to this one fact. Tested idmap_tdb but not idmap_ldap yet. Will do that tomorrow. Nothing has changed in the way a samba domain is represented, stored, or search in the directory so things should be ok with previous installations. going to bed now. (This used to be commit 0463045cc7ff177fab44b25faffad5bf7140244d)
Diffstat (limited to 'source3/nsswitch/winbindd_acct.c')
-rw-r--r--source3/nsswitch/winbindd_acct.c226
1 files changed, 203 insertions, 23 deletions
diff --git a/source3/nsswitch/winbindd_acct.c b/source3/nsswitch/winbindd_acct.c
index 2a3a6eb2bb..a1cd1d5f19 100644
--- a/source3/nsswitch/winbindd_acct.c
+++ b/source3/nsswitch/winbindd_acct.c
@@ -37,6 +37,29 @@ static TDB_CONTEXT *account_tdb;
extern userdom_struct current_user_info;
+struct _check_primary_grp {
+ gid_t gid;
+ BOOL found;
+};
+
+/**********************************************************************
+**********************************************************************/
+
+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;
+}
+
/*****************************************************************************
Initialise auto-account database.
*****************************************************************************/
@@ -649,8 +672,17 @@ static BOOL wb_delgrpmember( WINBINDD_GR *grp, const char *user )
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--;
+ /* still some remaining members */
+
+ if ( grp->num_gr_mem > 1 ) {
+ memmove( grp->gr_mem[i], grp->gr_mem[i+1], sizeof(char*)*(grp->num_gr_mem-(i+1)) );
+ grp->num_gr_mem--;
+ }
+ else { /* last one */
+ free_winbindd_gr( grp );
+ grp->gr_mem = NULL;
+ grp->num_gr_mem = 0;
+ }
return True;
}
@@ -658,34 +690,59 @@ static BOOL wb_delgrpmember( WINBINDD_GR *grp, const char *user )
/**********************************************************************
**********************************************************************/
-static void free_winbindd_gr( WINBINDD_GR *grp )
+static int cleangroups_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf,
+ void *state)
{
- int i;
-
- if ( !grp )
- return;
+ int len;
+ fstring key;
+ char *name = (char*)state;
+
+ snprintf( key, sizeof(key), "%s/NAME", WBKEY_GROUP );
+ len = strlen(key);
+
+ /* if this is a group entry then, check the members */
+
+ if ( (strncmp(kbuf.dptr, key, len) == 0) && dbuf.dptr ) {
+ WINBINDD_GR *grp;
- for ( i=0; i<grp->num_gr_mem; i++ )
- SAFE_FREE( grp->gr_mem[i] );
+ if ( !(grp = string2group( dbuf.dptr )) ) {
+ DEBUG(0,("cleangroups_traverse_fn: Failure to parse [%s]\n",
+ dbuf.dptr));
+ return 0;
+ }
+
+ /* just try to delete the user and rely on wb_delgrpmember()
+ to tell you whether or not the group changed. This is more
+ effecient than testing group membership first since the
+ checks for deleting a user from a group is essentially the
+ same as checking if he/she is a member */
+
+ if ( wb_delgrpmember( grp, name ) ) {
+ DEBUG(10,("cleanupgroups_traverse_fn: Removed user (%s) from group (%s)\n",
+ name, grp->gr_name));
+ wb_storegrnam( grp );
+ }
+
+ free_winbindd_gr( grp );
+ }
- SAFE_FREE( grp->gr_mem );
-
- return;
+ return 0;
}
/**********************************************************************
**********************************************************************/
-static BOOL wb_delete_user( const char *name)
+static BOOL wb_delete_user( WINBINDD_PW *pw)
{
char *namekey;
+ char *uidkey;
if ( !account_tdb && !winbindd_accountdb_init() ) {
- DEBUG(0,("wb_storepwnam: Failed to open winbindd account db\n"));
+ DEBUG(0,("wb_delete_user: Failed to open winbindd account db\n"));
return False;
}
- namekey = acct_userkey_byname( name );
+ namekey = acct_userkey_byname( pw->pw_name );
/* lock the main entry first */
@@ -694,20 +751,101 @@ static BOOL wb_delete_user( const char *name)
return False;
}
+ /* remove user from all groups */
+
+ tdb_traverse(account_tdb, cleangroups_traverse_fn, (void *)pw->pw_name);
+
+ /* remove the user */
+ uidkey = acct_userkey_byuid( pw->pw_uid );
tdb_delete_bystring( account_tdb, namekey );
+ tdb_delete_bystring( account_tdb, uidkey );
+
tdb_unlock_bystring( account_tdb, namekey );
return True;
}
+/**********************************************************************
+**********************************************************************/
+
+static int isprimarygroup_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf,
+ TDB_DATA dbuf, void *params)
+{
+ int len;
+ fstring key;
+ struct _check_primary_grp *check = (struct _check_primary_grp*)params;
+
+ snprintf( key, sizeof(key), "%s/NAME", WBKEY_PASSWD );
+ len = strlen(key);
+
+ /* if this is a group entry then, check the members */
+
+ if ( (strncmp(kbuf.dptr, key, len) == 0) && dbuf.dptr ) {
+ WINBINDD_PW *pw;;
+
+ if ( !(pw = string2passwd( dbuf.dptr )) ) {
+ DEBUG(0,("isprimarygroup_traverse_fn: Failure to parse [%s]\n",
+ dbuf.dptr));
+ return 0;
+ }
+
+ if ( check->gid == pw->pw_gid ) {
+ check->found = True;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
/**********************************************************************
**********************************************************************/
-static BOOL wb_delete_group( const char *name)
+static BOOL wb_delete_group( WINBINDD_GR *grp )
{
- return False;
+ struct _check_primary_grp check;
+ char *namekey;
+ char *gidkey;
+
+ if ( !account_tdb && !winbindd_accountdb_init() ) {
+ DEBUG(0,("wb_delete_group: Failed to open winbindd account db\n"));
+ return False;
+ }
+
+ /* lock the main entry first */
+
+ namekey = acct_groupkey_byname( grp->gr_name );
+ if ( tdb_lock_bystring(account_tdb, namekey, 0) == -1 ) {
+ DEBUG(0,("wb_delete_group: Failed to lock %s\n", namekey));
+ return False;
+ }
+
+ /* is this group the primary group for any user? If
+ so deny delete */
+
+ check.found = False;
+ tdb_traverse(account_tdb, isprimarygroup_traverse_fn, (void *)&check);
+
+ if ( check.found ) {
+ DEBUG(4,("wb_delete_group: Cannot delete group (%s) since it "
+ "is the primary group for some users\n", grp->gr_name));
+ return False;
+ }
+
+ /* We're clear. Delete the group */
+
+ DEBUG(5,("wb_delete_group: Removing group (%s)\n", grp->gr_name));
+
+ gidkey = acct_groupkey_bygid( grp->gr_gid );
+
+ tdb_delete_bystring( account_tdb, namekey );
+ tdb_delete_bystring( account_tdb, gidkey );
+
+ tdb_unlock_bystring( account_tdb, namekey );
+
+ return True;
}
/**********************************************************************
@@ -722,6 +860,8 @@ enum winbindd_result winbindd_create_user(struct winbindd_cli_state *state)
WINBINDD_GR *wb_grp;
struct group *unix_grp;
gid_t primary_gid;
+ uint32 flags = state->request.flags;
+ uint32 rid;
if ( !state->privileged ) {
DEBUG(2, ("winbindd_create_user: non-privileged access denied!\n"));
@@ -781,8 +921,27 @@ enum winbindd_result winbindd_create_user(struct winbindd_cli_state *state)
pw.pw_uid = id.uid;
pw.pw_gid = primary_gid;
+
+ /* store the new entry */
+
+ if ( !wb_storepwnam(&pw) )
+ return WINBINDD_ERROR;
+
+ /* do we need a new RID? */
+
+ if ( flags & WBFLAG_ALLOCATE_RID ) {
+ if ( !NT_STATUS_IS_OK(idmap_allocate_rid(&rid, USER_RID_TYPE)) ) {
+ DEBUG(0,("winbindd_create_user: RID allocation failure! Cannot create user (%s)\n",
+ user));
+ wb_delete_user( &pw );
+
+ return WINBINDD_ERROR;
+ }
+
+ state->response.data.rid = rid;
+ }
- return ( wb_storepwnam(&pw) ? WINBINDD_OK : WINBINDD_ERROR );
+ return WINBINDD_OK;
}
/**********************************************************************
@@ -794,6 +953,8 @@ enum winbindd_result winbindd_create_group(struct winbindd_cli_state *state)
char *group;
unid_t id;
WINBINDD_GR grp;
+ uint32 flags = state->request.flags;
+ uint32 rid;
if ( !state->privileged ) {
DEBUG(2, ("winbindd_create_group: non-privileged access denied!\n"));
@@ -821,8 +982,25 @@ enum winbindd_result winbindd_create_group(struct winbindd_cli_state *state)
grp.gr_gid = id.gid;
grp.gr_mem = NULL; /* start with no members */
grp.num_gr_mem = 0;
+
+ if ( !wb_storegrnam(&grp) )
+ return WINBINDD_ERROR;
+
+ /* do we need a new RID? */
+
+ if ( flags & WBFLAG_ALLOCATE_RID ) {
+ if ( !NT_STATUS_IS_OK(idmap_allocate_rid(&rid, GROUP_RID_TYPE)) ) {
+ DEBUG(0,("winbindd_create_group: RID allocation failure! Cannot create group (%s)\n",
+ group));
+ wb_delete_group( &grp );
+
+ return WINBINDD_ERROR;
+ }
+
+ state->response.data.rid = rid;
+ }
- return ( wb_storegrnam(&grp) ? WINBINDD_OK : WINBINDD_ERROR );
+ return WINBINDD_OK;
}
/**********************************************************************
@@ -989,8 +1167,7 @@ enum winbindd_result winbindd_delete_user(struct winbindd_cli_state *state)
return WINBINDD_ERROR;
}
-
- return ( wb_delete_user(user) ? WINBINDD_OK : WINBINDD_ERROR );
+ return ( wb_delete_user(pw) ? WINBINDD_OK : WINBINDD_ERROR );
}
/**********************************************************************
@@ -1001,6 +1178,7 @@ enum winbindd_result winbindd_delete_group(struct winbindd_cli_state *state)
{
WINBINDD_GR *grp;
char *group;
+ BOOL ret;
if ( !state->privileged ) {
DEBUG(2, ("winbindd_delete_group: non-privileged access denied!\n"));
@@ -1016,13 +1194,15 @@ enum winbindd_result winbindd_delete_group(struct winbindd_cli_state *state)
/* make sure it is a valid group */
if ( !(grp = wb_getgrnam( group )) ) {
- DEBUG(4,("winbindd_delete_user: Cannot delete a non-existent group\n"));
+ DEBUG(4,("winbindd_delete_group: Cannot delete a non-existent group\n"));
return WINBINDD_ERROR;
}
+ ret = wb_delete_group(grp);
+
free_winbindd_gr( grp );
- return ( wb_delete_group(group) ? WINBINDD_OK : WINBINDD_ERROR );
+ return ( ret ? WINBINDD_OK : WINBINDD_ERROR );
}