2 Unix SMB/CIFS implementation.
4 Winbind account management functions
6 Copyright (C) by Gerald (Jerry) Carter 2003
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #define DBGC_CLASS DBGC_WINBIND
28 #define WBKEY_PASSWD "WBA_PASSWD"
29 #define WBKEY_GROUP "WBA_GROUP"
31 #define NUM_PW_FIELDS 7
32 #define NUM_GRP_FIELDS 4
36 static TDB_CONTEXT *account_tdb;
38 extern userdom_struct current_user_info;
40 struct _check_primary_grp {
45 /**********************************************************************
46 **********************************************************************/
48 static void free_winbindd_gr( WINBINDD_GR *grp )
55 for ( i=0; i<grp->num_gr_mem; i++ )
56 SAFE_FREE( grp->gr_mem[i] );
58 SAFE_FREE( grp->gr_mem );
63 /*****************************************************************************
64 Initialise auto-account database.
65 *****************************************************************************/
67 static BOOL winbindd_accountdb_init(void)
69 /* see if we've already opened the tdb */
74 /* Nope. Try to open it */
76 if (!(account_tdb = tdb_open_log(lock_path("winbindd_idmap.tdb"), 0,
77 TDB_DEFAULT, O_RDWR | O_CREAT, 0600)))
79 /* last chance -- maybe idmap has already opened it */
80 if ( !(account_tdb = idmap_tdb_handle()) ) {
82 DEBUG(0, ("winbindd_idmap_init: Unable to open idmap database\n"));
92 /**********************************************************************
93 Convert a string in /etc/passwd format to a struct passwd* entry
94 **********************************************************************/
96 static WINBINDD_PW* string2passwd( char *string )
98 static WINBINDD_PW pw;
100 char *fields[NUM_PW_FIELDS];
108 DEBUG(10,("string2passwd: converting \"%s\"\n", string));
110 ZERO_STRUCT( fields );
112 for ( i=0, str=string; i<NUM_PW_FIELDS-1; i++ ) {
113 if ( !(p = strchr( str, ':' )) ) {
114 DEBUG(0,("string2passwd: parsing failure\n"));
127 fstrcpy( pw.pw_name, fields[0] );
128 fstrcpy( pw.pw_passwd, fields[1] );
129 pw.pw_uid = atoi( fields[2] );
130 pw.pw_gid = atoi( fields[3] );
131 fstrcpy( pw.pw_gecos, fields[4] );
132 fstrcpy( pw.pw_dir, fields[5] );
133 fstrcpy( pw.pw_shell, fields[6] );
136 /* last minute sanity checks */
138 if ( pw.pw_uid==0 || pw.pw_gid==0 ) {
139 DEBUG(0,("string2passwd: Failure! uid==%d, gid==%d\n",
140 pw.pw_uid, pw.pw_gid));
144 DEBUG(10,("string2passwd: Success\n"));
149 /**********************************************************************
150 Convert a struct passwd* to a string formatted for /etc/passwd
151 **********************************************************************/
153 static char* passwd2string( const WINBINDD_PW *pw )
155 static pstring string;
158 if ( !pw || !pw->pw_name )
161 DEBUG(10,("passwd2string: converting passwd struct for %s\n",
164 ret = snprintf( string, sizeof(string), "%s:%s:%d:%d:%s:%s:%s",
166 pw->pw_passwd ? pw->pw_passwd : "x",
174 DEBUG(0,("passwd2string: snprintf() failed!\n"));
181 /**********************************************************************
182 Convert a string in /etc/group format to a struct group* entry
183 **********************************************************************/
185 static WINBINDD_GR* string2group( char *string )
187 static WINBINDD_GR grp;
189 char *fields[NUM_GRP_FIELDS];
191 char **gr_members = NULL;
192 int num_gr_members = 0;
197 ZERO_STRUCTP( &grp );
199 DEBUG(10,("string2group: converting \"%s\"\n", string));
201 ZERO_STRUCT( fields );
203 for ( i=0, str=string; i<NUM_GRP_FIELDS-1; i++ ) {
204 if ( !(p = strchr( str, ':' )) ) {
205 DEBUG(0,("string2group: parsing failure\n"));
217 /* we already know we have a non-empty string */
219 num_gr_members = count_chars(str, ',') + 1;
221 /* if there was at least one comma, then there
223 if ( num_gr_members ) {
226 gr_members = (char**)smb_xmalloc(sizeof(char*)*num_gr_members+1);
229 while ( next_token(&str, buffer, ",", sizeof(buffer)) && i<num_gr_members ) {
230 gr_members[i++] = smb_xstrdup(buffer);
233 gr_members[i] = NULL;
240 fstrcpy( grp.gr_name, fields[0] );
241 fstrcpy( grp.gr_passwd, fields[1] );
242 grp.gr_gid = atoi( fields[2] );
244 grp.num_gr_mem = num_gr_members;
245 grp.gr_mem = gr_members;
247 /* last minute sanity checks */
249 if ( grp.gr_gid == 0 ) {
250 DEBUG(0,("string2group: Failure! gid==%d\n", grp.gr_gid));
251 SAFE_FREE( gr_members );
255 DEBUG(10,("string2group: Success\n"));
260 /**********************************************************************
261 Convert a struct group* to a string formatted for /etc/group
262 **********************************************************************/
264 static char* group2string( const WINBINDD_GR *grp )
266 static pstring string;
268 char *member, *gr_mem_str;
272 if ( !grp || !grp->gr_name )
275 DEBUG(10,("group2string: converting passwd struct for %s\n",
278 if ( grp->num_gr_mem ) {
281 member = grp->gr_mem[0];
286 size += strlen(member) + 1;
288 member = grp->gr_mem[num_members];
291 gr_mem_str = smb_xmalloc(size);
293 for ( i=0; i<num_members; i++ ) {
294 snprintf( &gr_mem_str[idx], size-idx, "%s,", grp->gr_mem[i] );
295 idx += strlen(grp->gr_mem[i]) + 1;
297 /* add trailing NULL (also removes trailing ',' */
298 gr_mem_str[size-1] = '\0';
302 gr_mem_str = smb_xmalloc(sizeof(fstring));
303 fstrcpy( gr_mem_str, "" );
306 ret = snprintf( string, sizeof(string)-1, "%s:%s:%d:%s",
308 grp->gr_passwd ? grp->gr_passwd : "*",
312 SAFE_FREE( gr_mem_str );
315 DEBUG(0,("group2string: snprintf() failed!\n"));
322 /**********************************************************************
323 **********************************************************************/
325 static char* acct_userkey_byname( const char *name )
329 snprintf( key, sizeof(key), "%s/NAME/%s", WBKEY_PASSWD, name );
334 /**********************************************************************
335 **********************************************************************/
337 static char* acct_userkey_byuid( uid_t uid )
341 snprintf( key, sizeof(key), "%s/UID/%d", WBKEY_PASSWD, uid );
346 /**********************************************************************
347 **********************************************************************/
349 static char* acct_groupkey_byname( const char *name )
353 snprintf( key, sizeof(key), "%s/NAME/%s", WBKEY_GROUP, name );
358 /**********************************************************************
359 **********************************************************************/
361 static char* acct_groupkey_bygid( gid_t gid )
365 snprintf( key, sizeof(key), "%s/GID/%d", WBKEY_GROUP, gid );
370 /**********************************************************************
371 **********************************************************************/
373 WINBINDD_PW* wb_getpwnam( const char * name )
377 static WINBINDD_PW *pw;
379 if ( !account_tdb && !winbindd_accountdb_init() ) {
380 DEBUG(0,("wb_getpwnam: Failed to open winbindd account db\n"));
385 keystr = acct_userkey_byname( name );
387 data = tdb_fetch_bystring( account_tdb, keystr );
392 pw = string2passwd( data.dptr );
393 SAFE_FREE( data.dptr );
396 DEBUG(5,("wb_getpwnam: %s user (%s)\n",
397 (pw ? "Found" : "Did not find"), name ));
402 /**********************************************************************
403 **********************************************************************/
405 WINBINDD_PW* wb_getpwuid( const uid_t uid )
409 static WINBINDD_PW *pw;
411 if ( !account_tdb && !winbindd_accountdb_init() ) {
412 DEBUG(0,("wb_getpwuid: Failed to open winbindd account db\n"));
416 data = tdb_fetch_bystring( account_tdb, acct_userkey_byuid(uid) );
418 DEBUG(4,("wb_getpwuid: failed to locate uid == %d\n", uid));
421 keystr = acct_userkey_byname( data.dptr );
423 SAFE_FREE( data.dptr );
425 data = tdb_fetch_bystring( account_tdb, keystr );
430 pw = string2passwd( data.dptr );
431 SAFE_FREE( data.dptr );
434 DEBUG(5,("wb_getpwuid: %s user (uid == %d)\n",
435 (pw ? "Found" : "Did not find"), uid ));
440 /**********************************************************************
441 **********************************************************************/
443 BOOL wb_storepwnam( const WINBINDD_PW *pw )
445 char *namekey, *uidkey;
451 if ( !account_tdb && !winbindd_accountdb_init() ) {
452 DEBUG(0,("wb_storepwnam: Failed to open winbindd account db\n"));
456 namekey = acct_userkey_byname( pw->pw_name );
458 /* lock the main entry first */
460 if ( tdb_lock_bystring(account_tdb, namekey, 0) == -1 ) {
461 DEBUG(0,("wb_storepwnam: Failed to lock %s\n", namekey));
465 str = passwd2string( pw );
468 data.dsize = strlen(str) + 1;
470 if ( (tdb_store_bystring(account_tdb, namekey, data, TDB_REPLACE)) == -1 ) {
471 DEBUG(0,("wb_storepwnam: Failed to store \"%s\"\n", str));
476 /* store the uid index */
478 uidkey = acct_userkey_byuid(pw->pw_uid);
480 fstrcpy( username, pw->pw_name );
481 data.dptr = username;
482 data.dsize = strlen(username) + 1;
484 if ( (tdb_store_bystring(account_tdb, uidkey, data, TDB_REPLACE)) == -1 ) {
485 DEBUG(0,("wb_storepwnam: Failed to store uid key \"%s\"\n", str));
486 tdb_delete_bystring(account_tdb, namekey);
491 DEBUG(10,("wb_storepwnam: Success -> \"%s\"\n", str));
494 tdb_unlock_bystring( account_tdb, namekey );
499 /**********************************************************************
500 **********************************************************************/
502 WINBINDD_GR* wb_getgrnam( const char * name )
506 static WINBINDD_GR *grp;
508 if ( !account_tdb && !winbindd_accountdb_init() ) {
509 DEBUG(0,("wb_getgrnam: Failed to open winbindd account db\n"));
514 keystr = acct_groupkey_byname( name );
516 data = tdb_fetch_bystring( account_tdb, keystr );
521 grp = string2group( data.dptr );
522 SAFE_FREE( data.dptr );
525 DEBUG(5,("wb_getgrnam: %s group (%s)\n",
526 (grp ? "Found" : "Did not find"), name ));
531 /**********************************************************************
532 **********************************************************************/
534 WINBINDD_GR* wb_getgrgid( gid_t gid )
538 static WINBINDD_GR *grp;
540 if ( !account_tdb && !winbindd_accountdb_init() ) {
541 DEBUG(0,("wb_getgrgid: Failed to open winbindd account db\n"));
545 data = tdb_fetch_bystring( account_tdb, acct_groupkey_bygid(gid) );
547 DEBUG(4,("wb_getgrgid: failed to locate gid == %d\n", gid));
550 keystr = acct_groupkey_byname( data.dptr );
552 SAFE_FREE( data.dptr );
554 data = tdb_fetch_bystring( account_tdb, keystr );
559 grp = string2group( data.dptr );
560 SAFE_FREE( data.dptr );
563 DEBUG(5,("wb_getgrgid: %s group (gid == %d)\n",
564 (grp ? "Found" : "Did not find"), gid ));
569 /**********************************************************************
570 **********************************************************************/
572 BOOL wb_storegrnam( const WINBINDD_GR *grp )
574 char *namekey, *gidkey;
580 if ( !account_tdb && !winbindd_accountdb_init() ) {
581 DEBUG(0,("wb_storepwnam: Failed to open winbindd account db\n"));
585 namekey = acct_groupkey_byname( grp->gr_name );
587 /* lock the main entry first */
589 if ( tdb_lock_bystring(account_tdb, namekey, 0) == -1 ) {
590 DEBUG(0,("wb_storegrnam: Failed to lock %s\n", namekey));
594 str = group2string( grp );
597 data.dsize = strlen(str) + 1;
599 if ( (tdb_store_bystring(account_tdb, namekey, data, TDB_REPLACE)) == -1 ) {
600 DEBUG(0,("wb_storegrnam: Failed to store \"%s\"\n", str));
605 /* store the gid index */
607 gidkey = acct_groupkey_bygid(grp->gr_gid);
609 fstrcpy( groupname, grp->gr_name );
610 data.dptr = groupname;
611 data.dsize = strlen(groupname) + 1;
613 if ( (tdb_store_bystring(account_tdb, gidkey, data, TDB_REPLACE)) == -1 ) {
614 DEBUG(0,("wb_storegrnam: Failed to store gid key \"%s\"\n", str));
615 tdb_delete_bystring(account_tdb, namekey);
620 DEBUG(10,("wb_storegrnam: Success -> \"%s\"\n", str));
623 tdb_unlock_bystring( account_tdb, namekey );
628 /**********************************************************************
629 **********************************************************************/
631 static BOOL wb_addgrpmember( WINBINDD_GR *grp, const char *user )
639 for ( i=0; i<grp->num_gr_mem; i++ ) {
640 if ( StrCaseCmp( grp->gr_mem[i], user ) == 0 )
644 /* add one new slot and keep an extra for the terminating NULL */
645 members = Realloc( grp->gr_mem, (grp->num_gr_mem+2)*sizeof(char*) );
649 grp->gr_mem = members;
650 grp->gr_mem[grp->num_gr_mem++] = smb_xstrdup(user);
651 grp->gr_mem[grp->num_gr_mem] = NULL;
656 /**********************************************************************
657 **********************************************************************/
659 static BOOL wb_delgrpmember( WINBINDD_GR *grp, const char *user )
667 for ( i=0; i<grp->num_gr_mem && !found; i++ ) {
668 if ( StrCaseCmp( grp->gr_mem[i], user ) == 0 )
675 /* still some remaining members */
677 if ( grp->num_gr_mem > 1 ) {
678 memmove( grp->gr_mem[i], grp->gr_mem[i+1], sizeof(char*)*(grp->num_gr_mem-(i+1)) );
681 else { /* last one */
682 free_winbindd_gr( grp );
690 /**********************************************************************
691 **********************************************************************/
693 static int cleangroups_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf,
698 char *name = (char*)state;
700 snprintf( key, sizeof(key), "%s/NAME", WBKEY_GROUP );
703 /* if this is a group entry then, check the members */
705 if ( (strncmp(kbuf.dptr, key, len) == 0) && dbuf.dptr ) {
708 if ( !(grp = string2group( dbuf.dptr )) ) {
709 DEBUG(0,("cleangroups_traverse_fn: Failure to parse [%s]\n",
714 /* just try to delete the user and rely on wb_delgrpmember()
715 to tell you whether or not the group changed. This is more
716 effecient than testing group membership first since the
717 checks for deleting a user from a group is essentially the
718 same as checking if he/she is a member */
720 if ( wb_delgrpmember( grp, name ) ) {
721 DEBUG(10,("cleanupgroups_traverse_fn: Removed user (%s) from group (%s)\n",
722 name, grp->gr_name));
723 wb_storegrnam( grp );
726 free_winbindd_gr( grp );
732 /**********************************************************************
733 **********************************************************************/
735 static BOOL wb_delete_user( WINBINDD_PW *pw)
740 if ( !account_tdb && !winbindd_accountdb_init() ) {
741 DEBUG(0,("wb_delete_user: Failed to open winbindd account db\n"));
745 namekey = acct_userkey_byname( pw->pw_name );
747 /* lock the main entry first */
749 if ( tdb_lock_bystring(account_tdb, namekey, 0) == -1 ) {
750 DEBUG(0,("wb_delete_user: Failed to lock %s\n", namekey));
754 /* remove user from all groups */
756 tdb_traverse(account_tdb, cleangroups_traverse_fn, (void *)pw->pw_name);
758 /* remove the user */
759 uidkey = acct_userkey_byuid( pw->pw_uid );
761 tdb_delete_bystring( account_tdb, namekey );
762 tdb_delete_bystring( account_tdb, uidkey );
764 tdb_unlock_bystring( account_tdb, namekey );
769 /**********************************************************************
770 **********************************************************************/
772 static int isprimarygroup_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf,
773 TDB_DATA dbuf, void *params)
777 struct _check_primary_grp *check = (struct _check_primary_grp*)params;
779 snprintf( key, sizeof(key), "%s/NAME", WBKEY_PASSWD );
782 /* if this is a group entry then, check the members */
784 if ( (strncmp(kbuf.dptr, key, len) == 0) && dbuf.dptr ) {
787 if ( !(pw = string2passwd( dbuf.dptr )) ) {
788 DEBUG(0,("isprimarygroup_traverse_fn: Failure to parse [%s]\n",
793 if ( check->gid == pw->pw_gid ) {
803 /**********************************************************************
804 **********************************************************************/
806 static BOOL wb_delete_group( WINBINDD_GR *grp )
808 struct _check_primary_grp check;
812 if ( !account_tdb && !winbindd_accountdb_init() ) {
813 DEBUG(0,("wb_delete_group: Failed to open winbindd account db\n"));
817 /* lock the main entry first */
819 namekey = acct_groupkey_byname( grp->gr_name );
820 if ( tdb_lock_bystring(account_tdb, namekey, 0) == -1 ) {
821 DEBUG(0,("wb_delete_group: Failed to lock %s\n", namekey));
825 /* is this group the primary group for any user? If
829 tdb_traverse(account_tdb, isprimarygroup_traverse_fn, (void *)&check);
832 DEBUG(4,("wb_delete_group: Cannot delete group (%s) since it "
833 "is the primary group for some users\n", grp->gr_name));
837 /* We're clear. Delete the group */
839 DEBUG(5,("wb_delete_group: Removing group (%s)\n", grp->gr_name));
841 gidkey = acct_groupkey_bygid( grp->gr_gid );
843 tdb_delete_bystring( account_tdb, namekey );
844 tdb_delete_bystring( account_tdb, gidkey );
846 tdb_unlock_bystring( account_tdb, namekey );
851 /**********************************************************************
852 Create a new "UNIX" user for the system given a username
853 **********************************************************************/
855 enum winbindd_result winbindd_create_user(struct winbindd_cli_state *state)
861 struct group *unix_grp;
863 uint32 flags = state->request.flags;
866 if ( !state->privileged ) {
867 DEBUG(2, ("winbindd_create_user: non-privileged access denied!\n"));
868 return WINBINDD_ERROR;
871 /* Ensure null termination */
872 state->request.data.acct_mgt.username[sizeof(state->request.data.acct_mgt.username)-1]='\0';
873 state->request.data.acct_mgt.groupname[sizeof(state->request.data.acct_mgt.groupname)-1]='\0';
875 user = state->request.data.acct_mgt.username;
876 group = state->request.data.acct_mgt.groupname;
878 DEBUG(3, ("[%5d]: create_user: user=>(%s), group=>(%s)\n",
879 state->pid, user, group));
882 group = lp_template_primary_group();
884 /* validate the primary group
885 1) lookup in local tdb first
886 2) call getgrnam() as a last resort */
888 if ( (wb_grp=wb_getgrnam(group)) != NULL ) {
889 primary_gid = wb_grp->gr_gid;
890 free_winbindd_gr( wb_grp );
892 else if ( (unix_grp=sys_getgrnam(group)) != NULL ) {
893 primary_gid = unix_grp->gr_gid;
896 DEBUG(2,("winbindd_create_user: Cannot validate gid for group (%s)\n", group));
897 return WINBINDD_ERROR;
902 if ( !NT_STATUS_IS_OK(idmap_allocate_id( &id, ID_USERID)) ) {
903 DEBUG(0,("winbindd_create_user: idmap_allocate_id() failed!\n"));
904 return WINBINDD_ERROR;
907 /* The substitution of %U and %D in the 'template homedir' is done
908 by lp_string() calling standard_sub_basic(). */
910 fstrcpy( current_user_info.smb_name, user );
911 sub_set_smb_name( user );
912 fstrcpy( current_user_info.domain, get_global_sam_name() );
914 /* fill in the passwd struct */
916 fstrcpy( pw.pw_name, user );
917 fstrcpy( pw.pw_passwd, "x" );
918 fstrcpy( pw.pw_gecos, user);
919 fstrcpy( pw.pw_dir, lp_template_homedir() );
920 fstrcpy( pw.pw_shell, lp_template_shell() );
923 pw.pw_gid = primary_gid;
925 /* store the new entry */
927 if ( !wb_storepwnam(&pw) )
928 return WINBINDD_ERROR;
930 /* do we need a new RID? */
932 if ( flags & WBFLAG_ALLOCATE_RID ) {
933 if ( !NT_STATUS_IS_OK(idmap_allocate_rid(&rid, USER_RID_TYPE)) ) {
934 DEBUG(0,("winbindd_create_user: RID allocation failure! Cannot create user (%s)\n",
936 wb_delete_user( &pw );
938 return WINBINDD_ERROR;
941 state->response.data.rid = rid;
947 /**********************************************************************
948 Create a new "UNIX" group for the system given a username
949 **********************************************************************/
951 enum winbindd_result winbindd_create_group(struct winbindd_cli_state *state)
956 uint32 flags = state->request.flags;
959 if ( !state->privileged ) {
960 DEBUG(2, ("winbindd_create_group: non-privileged access denied!\n"));
961 return WINBINDD_ERROR;
964 /* Ensure null termination */
965 state->request.data.acct_mgt.groupname[sizeof(state->request.data.acct_mgt.groupname)-1]='\0';
966 group = state->request.data.acct_mgt.groupname;
968 DEBUG(3, ("[%5d]: create_group: (%s)\n", state->pid, group));
972 if ( !NT_STATUS_IS_OK(idmap_allocate_id( &id, ID_GROUPID)) ) {
973 DEBUG(0,("winbindd_create_group: idmap_allocate_id() failed!\n"));
974 return WINBINDD_ERROR;
977 /* fill in the group struct */
979 fstrcpy( grp.gr_name, group );
980 fstrcpy( grp.gr_passwd, "*" );
983 grp.gr_mem = NULL; /* start with no members */
986 if ( !wb_storegrnam(&grp) )
987 return WINBINDD_ERROR;
989 /* do we need a new RID? */
991 if ( flags & WBFLAG_ALLOCATE_RID ) {
992 if ( !NT_STATUS_IS_OK(idmap_allocate_rid(&rid, GROUP_RID_TYPE)) ) {
993 DEBUG(0,("winbindd_create_group: RID allocation failure! Cannot create group (%s)\n",
995 wb_delete_group( &grp );
997 return WINBINDD_ERROR;
1000 state->response.data.rid = rid;
1006 /**********************************************************************
1007 Add a user to the membership for a group.
1008 **********************************************************************/
1010 enum winbindd_result winbindd_add_user_to_group(struct winbindd_cli_state *state)
1017 if ( !state->privileged ) {
1018 DEBUG(2, ("winbindd_add_user_to_group: non-privileged access denied!\n"));
1019 return WINBINDD_ERROR;
1022 /* Ensure null termination */
1023 state->request.data.acct_mgt.groupname[sizeof(state->request.data.acct_mgt.groupname)-1]='\0';
1024 state->request.data.acct_mgt.username[sizeof(state->request.data.acct_mgt.username)-1]='\0';
1025 group = state->request.data.acct_mgt.groupname;
1026 user = state->request.data.acct_mgt.username;
1028 DEBUG(3, ("[%5d]: add_user_to_group: add %s to %s\n", state->pid,
1031 /* make sure it is a valid user */
1033 if ( !(pw = wb_getpwnam( user )) ) {
1034 DEBUG(4,("winbindd_add_user_to_group: Cannot add a non-existent user\n"));
1035 return WINBINDD_ERROR;
1038 /* make sure it is a valid group */
1040 if ( !(grp = wb_getgrnam( group )) ) {
1041 DEBUG(4,("winbindd_add_user_to_group: Cannot add a user to a non-extistent group\n"));
1042 return WINBINDD_ERROR;
1045 if ( !wb_addgrpmember( grp, user ) )
1046 return WINBINDD_ERROR;
1048 ret = wb_storegrnam(grp);
1050 free_winbindd_gr( grp );
1052 return ( ret ? WINBINDD_OK : WINBINDD_ERROR );
1055 /**********************************************************************
1056 Remove a user from the membership of a group
1057 **********************************************************************/
1059 enum winbindd_result winbindd_remove_user_from_group(struct winbindd_cli_state *state)
1065 if ( !state->privileged ) {
1066 DEBUG(2, ("winbindd_remove_user_from_group: non-privileged access denied!\n"));
1067 return WINBINDD_ERROR;
1070 /* Ensure null termination */
1071 state->request.data.acct_mgt.groupname[sizeof(state->request.data.acct_mgt.groupname)-1]='\0';
1072 state->request.data.acct_mgt.username[sizeof(state->request.data.acct_mgt.username)-1]='\0';
1073 group = state->request.data.acct_mgt.groupname;
1074 user = state->request.data.acct_mgt.username;
1076 DEBUG(3, ("[%5d]: remove_user_to_group: delete %s from %s\n", state->pid,
1079 /* don't worry about checking the username since we're removing it anyways */
1081 /* make sure it is a valid group */
1083 if ( !(grp = wb_getgrnam( group )) ) {
1084 DEBUG(4,("winbindd_remove_user_to_group: Cannot remove a user to a non-extistent group\n"));
1085 return WINBINDD_ERROR;
1088 if ( !wb_delgrpmember( grp, user ) )
1089 return WINBINDD_ERROR;
1091 ret = wb_storegrnam(grp);
1093 free_winbindd_gr( grp );
1095 return ( ret ? WINBINDD_OK : WINBINDD_ERROR );
1098 /**********************************************************************
1099 Set the primary group membership of a user
1100 **********************************************************************/
1102 enum winbindd_result winbindd_set_user_primary_group(struct winbindd_cli_state *state)
1108 if ( !state->privileged ) {
1109 DEBUG(2, ("winbindd_set_user_primary_group: non-privileged access denied!\n"));
1110 return WINBINDD_ERROR;
1113 /* Ensure null termination */
1114 state->request.data.acct_mgt.groupname[sizeof(state->request.data.acct_mgt.groupname)-1]='\0';
1115 state->request.data.acct_mgt.username[sizeof(state->request.data.acct_mgt.username)-1]='\0';
1116 group = state->request.data.acct_mgt.groupname;
1117 user = state->request.data.acct_mgt.username;
1119 DEBUG(3, ("[%5d]: set_user_primary_grou:p group %s for user %s\n", state->pid,
1122 /* make sure it is a valid user */
1124 if ( !(pw = wb_getpwnam( user )) ) {
1125 DEBUG(4,("winbindd_add_user_to_group: Cannot add a non-existent user\n"));
1126 return WINBINDD_ERROR;
1129 /* make sure it is a valid group */
1131 if ( !(grp = wb_getgrnam( group )) ) {
1132 DEBUG(4,("winbindd_add_user_to_group: Cannot add a user to a non-extistent group\n"));
1133 return WINBINDD_ERROR;
1136 pw->pw_gid = grp->gr_gid;
1138 free_winbindd_gr( grp );
1140 return ( wb_storepwnam(pw) ? WINBINDD_OK : WINBINDD_ERROR );
1143 /**********************************************************************
1144 Delete a user from the winbindd account tdb.
1145 **********************************************************************/
1147 enum winbindd_result winbindd_delete_user(struct winbindd_cli_state *state)
1152 if ( !state->privileged ) {
1153 DEBUG(2, ("winbindd_delete_user: non-privileged access denied!\n"));
1154 return WINBINDD_ERROR;
1157 /* Ensure null termination */
1158 state->request.data.acct_mgt.username[sizeof(state->request.data.acct_mgt.username)-1]='\0';
1159 user = state->request.data.acct_mgt.username;
1161 DEBUG(3, ("[%5d]: delete_user: %s\n", state->pid, user));
1163 /* make sure it is a valid user */
1165 if ( !(pw = wb_getpwnam( user )) ) {
1166 DEBUG(4,("winbindd_delete_user: Cannot delete a non-existent user\n"));
1167 return WINBINDD_ERROR;
1170 return ( wb_delete_user(pw) ? WINBINDD_OK : WINBINDD_ERROR );
1173 /**********************************************************************
1174 Delete a group from winbindd's account tdb.
1175 **********************************************************************/
1177 enum winbindd_result winbindd_delete_group(struct winbindd_cli_state *state)
1183 if ( !state->privileged ) {
1184 DEBUG(2, ("winbindd_delete_group: non-privileged access denied!\n"));
1185 return WINBINDD_ERROR;
1188 /* Ensure null termination */
1189 state->request.data.acct_mgt.username[sizeof(state->request.data.acct_mgt.groupname)-1]='\0';
1190 group = state->request.data.acct_mgt.groupname;
1192 DEBUG(3, ("[%5d]: delete_group: %s\n", state->pid, group));
1194 /* make sure it is a valid group */
1196 if ( !(grp = wb_getgrnam( group )) ) {
1197 DEBUG(4,("winbindd_delete_group: Cannot delete a non-existent group\n"));
1198 return WINBINDD_ERROR;
1201 ret = wb_delete_group(grp);
1203 free_winbindd_gr( grp );
1205 return ( ret ? WINBINDD_OK : WINBINDD_ERROR );