summaryrefslogtreecommitdiff
path: root/source3/nsswitch
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
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')
-rw-r--r--source3/nsswitch/wb_client.c74
-rw-r--r--source3/nsswitch/wbinfo.c82
-rw-r--r--source3/nsswitch/winbindd_acct.c226
-rw-r--r--source3/nsswitch/winbindd_nss.h2
-rw-r--r--source3/nsswitch/winbindd_user.c13
5 files changed, 350 insertions, 47 deletions
diff --git a/source3/nsswitch/wb_client.c b/source3/nsswitch/wb_client.c
index 26a0e58191..eb9a7e9995 100644
--- a/source3/nsswitch/wb_client.c
+++ b/source3/nsswitch/wb_client.c
@@ -371,7 +371,7 @@ BOOL winbind_ping( void )
Ask winbindd to create a local user
**********************************************************************/
-BOOL winbind_create_user( const char *name )
+BOOL winbind_create_user( const char *name, uint32 *rid )
{
struct winbindd_request request;
struct winbindd_response response;
@@ -384,6 +384,11 @@ BOOL winbind_create_user( const char *name )
return False;
DEBUG(10,("winbind_create_user: %s\n", name));
+
+ /* see if the caller wants a new RID returned */
+
+ if ( rid )
+ request.flags = WBFLAG_ALLOCATE_RID;
fstrcpy( request.data.acct_mgt.username, name );
fstrcpy( request.data.acct_mgt.groupname, "" );
@@ -392,6 +397,9 @@ BOOL winbind_create_user( const char *name )
result = winbindd_request( WINBINDD_CREATE_USER, &request, &response);
+ if ( rid )
+ *rid = response.data.rid;
+
return result == NSS_STATUS_SUCCESS;
}
@@ -399,7 +407,7 @@ BOOL winbind_create_user( const char *name )
Ask winbindd to create a local group
**********************************************************************/
-BOOL winbind_create_group( const char *name )
+BOOL winbind_create_group( const char *name, uint32 *rid )
{
struct winbindd_request request;
struct winbindd_response response;
@@ -413,12 +421,20 @@ BOOL winbind_create_group( const char *name )
DEBUG(10,("winbind_create_group: %s\n", name));
+ /* see if the caller wants a new RID returned */
+
+ if ( rid )
+ request.flags = WBFLAG_ALLOCATE_RID;
+
fstrcpy( request.data.acct_mgt.groupname, name );
ZERO_STRUCT(response);
result = winbindd_request( WINBINDD_CREATE_GROUP, &request, &response);
+ if ( rid )
+ *rid = response.data.rid;
+
return result == NSS_STATUS_SUCCESS;
}
@@ -510,4 +526,58 @@ BOOL winbind_set_user_primary_group( const char *user, const char *group )
}
+/**********************************************************************
+ Ask winbindd to remove a user from its lists of accounts
+**********************************************************************/
+
+BOOL winbind_delete_user( const char *user )
+{
+ struct winbindd_request request;
+ struct winbindd_response response;
+ NSS_STATUS result;
+
+ if ( !lp_winbind_enable_local_accounts() )
+ return False;
+
+ if ( !user )
+ return False;
+
+ DEBUG(10,("winbind_delete_user: user (%s)\n", user));
+
+ fstrcpy( request.data.acct_mgt.username, user );
+
+ ZERO_STRUCT(response);
+
+ result = winbindd_request( WINBINDD_DELETE_USER, &request, &response);
+
+ return result == NSS_STATUS_SUCCESS;
+}
+
+/**********************************************************************
+ Ask winbindd to remove a group from its lists of accounts
+**********************************************************************/
+
+BOOL winbind_delete_group( const char *group )
+{
+ struct winbindd_request request;
+ struct winbindd_response response;
+ NSS_STATUS result;
+
+ if ( !lp_winbind_enable_local_accounts() )
+ return False;
+
+ if ( !group )
+ return False;
+
+ DEBUG(10,("winbind_delete_group: group (%s)\n", group));
+
+ fstrcpy( request.data.acct_mgt.groupname, group );
+
+ ZERO_STRUCT(response);
+
+ result = winbindd_request( WINBINDD_DELETE_GROUP, &request, &response);
+
+ return result == NSS_STATUS_SUCCESS;
+}
+
diff --git a/source3/nsswitch/wbinfo.c b/source3/nsswitch/wbinfo.c
index 6ebf6effa7..f533799370 100644
--- a/source3/nsswitch/wbinfo.c
+++ b/source3/nsswitch/wbinfo.c
@@ -526,16 +526,36 @@ static BOOL wbinfo_create_user(char *username)
ZERO_STRUCT(request);
ZERO_STRUCT(response);
+ request.flags = WBFLAG_ALLOCATE_RID;
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);
+ if ( result == NSS_STATUS_SUCCESS )
+ d_printf("New RID is %d\n", response.data.rid);
+
+ return result == NSS_STATUS_SUCCESS;
+}
+/******************************************************************
+ remove a winbindd user
+******************************************************************/
+
+static BOOL wbinfo_delete_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_DELETE_USER, &request, &response);
+
return result == NSS_STATUS_SUCCESS;
}
@@ -558,12 +578,28 @@ static BOOL wbinfo_create_group(char *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;
+}
+/******************************************************************
+ remove a winbindd group
+******************************************************************/
+
+static BOOL wbinfo_delete_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_DELETE_GROUP, &request, &response);
+
return result == NSS_STATUS_SUCCESS;
}
@@ -614,12 +650,6 @@ static BOOL wbinfo_add_user_to_group(char *string)
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;
}
@@ -647,12 +677,6 @@ static BOOL wbinfo_remove_user_from_group(char *string)
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;
}
@@ -851,7 +875,9 @@ int main(int argc, char **argv)
{ "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" },
+ { "delete-user", 'x', POPT_ARG_STRING, &string_arg, 'x', "Delete a local user account", "name" },
{ "create-group", 'C', POPT_ARG_STRING, &string_arg, 'C', "Create a local group", "name" },
+ { "delete-group", 'X', POPT_ARG_STRING, &string_arg, 'X', "Delete 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" },
@@ -1036,6 +1062,18 @@ int main(int argc, char **argv)
goto done;
}
break;
+ case 'x':
+ if ( !wbinfo_delete_user(string_arg) ) {
+ d_printf("Could not delete user account\n");
+ goto done;
+ }
+ break;
+ case 'X':
+ if ( !wbinfo_delete_group(string_arg) ) {
+ d_printf("Could not delete group\n");
+ goto done;
+ }
+ break;
case 'P':
if (!wbinfo_ping()) {
d_printf("could not ping winbindd!\n");
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 );
}
diff --git a/source3/nsswitch/winbindd_nss.h b/source3/nsswitch/winbindd_nss.h
index a2d9e82c7c..c4407bbe31 100644
--- a/source3/nsswitch/winbindd_nss.h
+++ b/source3/nsswitch/winbindd_nss.h
@@ -148,6 +148,7 @@ typedef struct winbindd_gr {
#define WBFLAG_PAM_LMKEY 0x0008
#define WBFLAG_PAM_CONTACT_TRUSTDOM 0x0010
#define WBFLAG_QUERY_ONLY 0x0020
+#define WBFLAG_ALLOCATE_RID 0x0040
/* Winbind request structure */
@@ -257,6 +258,7 @@ struct winbindd_response {
char nt_session_key[16];
char first_8_lm_hash[8];
} auth;
+ uint32 rid; /* create user or group */
} data;
/* Variable length return data */
diff --git a/source3/nsswitch/winbindd_user.c b/source3/nsswitch/winbindd_user.c
index 7c95ba8470..c49c41687b 100644
--- a/source3/nsswitch/winbindd_user.c
+++ b/source3/nsswitch/winbindd_user.c
@@ -308,6 +308,19 @@ enum winbindd_result winbindd_setpwent(struct winbindd_cli_state *state)
free_getent_state(state->getpwent_state);
state->getpwent_state = NULL;
}
+
+#if 0 /* JERRY */
+ /* add any local users we have */
+
+ if ( (domain_state = (struct getent_state *)malloc(sizeof(struct getent_state))) == NULL )
+ return WINBINDD_ERROR;
+
+ ZERO_STRUCTP(domain_state);
+
+ /* Add to list of open domains */
+
+ DLIST_ADD(state->getpwent_state, domain_state);
+#endif
/* Create sam pipes for each domain we know about */