summaryrefslogtreecommitdiff
path: root/source3/nsswitch
diff options
context:
space:
mode:
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 */