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 /* winbindd_idmap.tdb should always be opened by the idmap_init()
77 if ( !(account_tdb
= idmap_tdb_handle()) ) {
78 DEBUG(0, ("winbindd_accountdb_init: Unable to retreive handle for database\n"));
87 /**********************************************************************
88 Convert a string in /etc/passwd format to a struct passwd* entry
89 **********************************************************************/
91 static WINBINDD_PW
* string2passwd( char *string
)
93 static WINBINDD_PW pw
;
95 char *fields
[NUM_PW_FIELDS
];
103 DEBUG(10,("string2passwd: converting \"%s\"\n", string
));
105 ZERO_STRUCT( fields
);
107 for ( i
=0, str
=string
; i
<NUM_PW_FIELDS
-1; i
++ ) {
108 if ( !(p
= strchr( str
, ':' )) ) {
109 DEBUG(0,("string2passwd: parsing failure\n"));
122 fstrcpy( pw
.pw_name
, fields
[0] );
123 fstrcpy( pw
.pw_passwd
, fields
[1] );
124 pw
.pw_uid
= atoi( fields
[2] );
125 pw
.pw_gid
= atoi( fields
[3] );
126 fstrcpy( pw
.pw_gecos
, fields
[4] );
127 fstrcpy( pw
.pw_dir
, fields
[5] );
128 fstrcpy( pw
.pw_shell
, fields
[6] );
131 /* last minute sanity checks */
133 if ( pw
.pw_uid
==0 || pw
.pw_gid
==0 ) {
134 DEBUG(0,("string2passwd: Failure! uid==%lu, gid==%lu\n",
135 (unsigned long)pw
.pw_uid
, (unsigned long)pw
.pw_gid
));
139 DEBUG(10,("string2passwd: Success\n"));
144 /**********************************************************************
145 Convert a struct passwd* to a string formatted for /etc/passwd
146 **********************************************************************/
148 static char* passwd2string( const WINBINDD_PW
*pw
)
150 static pstring string
;
153 if ( !pw
|| !pw
->pw_name
)
156 DEBUG(10,("passwd2string: converting passwd struct for %s\n",
159 ret
= pstr_sprintf( string
, "%s:%s:%lu:%lu:%s:%s:%s",
161 pw
->pw_passwd
? pw
->pw_passwd
: "x",
162 (unsigned long)pw
->pw_uid
,
163 (unsigned long)pw
->pw_gid
,
169 DEBUG(0,("passwd2string: pstr_sprintf() failed!\n"));
176 /**********************************************************************
177 Convert a string in /etc/group format to a struct group* entry
178 **********************************************************************/
180 static WINBINDD_GR
* string2group( char *string
)
182 static WINBINDD_GR grp
;
184 char *fields
[NUM_GRP_FIELDS
];
186 char **gr_members
= NULL
;
187 int num_gr_members
= 0;
192 ZERO_STRUCTP( &grp
);
194 DEBUG(10,("string2group: converting \"%s\"\n", string
));
196 ZERO_STRUCT( fields
);
198 for ( i
=0, str
=string
; i
<NUM_GRP_FIELDS
-1; i
++ ) {
199 if ( !(p
= strchr( str
, ':' )) ) {
200 DEBUG(0,("string2group: parsing failure\n"));
212 /* we already know we have a non-empty string */
214 num_gr_members
= count_chars(str
, ',') + 1;
216 /* if there was at least one comma, then there
218 if ( num_gr_members
) {
221 gr_members
= (char**)smb_xmalloc(sizeof(char*)*num_gr_members
+1);
224 while ( next_token(&str
, buffer
, ",", sizeof(buffer
)) && i
<num_gr_members
) {
225 gr_members
[i
++] = smb_xstrdup(buffer
);
228 gr_members
[i
] = NULL
;
235 fstrcpy( grp
.gr_name
, fields
[0] );
236 fstrcpy( grp
.gr_passwd
, fields
[1] );
237 grp
.gr_gid
= atoi( fields
[2] );
239 grp
.num_gr_mem
= num_gr_members
;
240 grp
.gr_mem
= gr_members
;
242 /* last minute sanity checks */
244 if ( grp
.gr_gid
== 0 ) {
245 DEBUG(0,("string2group: Failure! gid==%lu\n", (unsigned long)grp
.gr_gid
));
246 SAFE_FREE( gr_members
);
250 DEBUG(10,("string2group: Success\n"));
255 /**********************************************************************
256 Convert a struct group* to a string formatted for /etc/group
257 **********************************************************************/
259 static char* group2string( const WINBINDD_GR
*grp
)
261 static pstring string
;
263 char *member
, *gr_mem_str
;
267 if ( !grp
|| !grp
->gr_name
)
270 DEBUG(10,("group2string: converting passwd struct for %s\n",
273 if ( grp
->num_gr_mem
) {
276 member
= grp
->gr_mem
[0];
281 size
+= strlen(member
) + 1;
283 member
= grp
->gr_mem
[num_members
];
286 gr_mem_str
= smb_xmalloc(size
);
288 for ( i
=0; i
<num_members
; i
++ ) {
289 snprintf( &gr_mem_str
[idx
], size
-idx
, "%s,", grp
->gr_mem
[i
] );
290 idx
+= strlen(grp
->gr_mem
[i
]) + 1;
292 /* add trailing NULL (also removes trailing ',' */
293 gr_mem_str
[size
-1] = '\0';
297 gr_mem_str
= smb_xmalloc(sizeof(fstring
));
298 fstrcpy( gr_mem_str
, "" );
301 ret
= pstr_sprintf( string
, "%s:%s:%lu:%s",
303 grp
->gr_passwd
? grp
->gr_passwd
: "*",
304 (unsigned long)grp
->gr_gid
,
307 SAFE_FREE( gr_mem_str
);
310 DEBUG(0,("group2string: pstr_sprintf() failed!\n"));
317 /**********************************************************************
318 **********************************************************************/
320 static char* acct_userkey_byname( const char *name
)
324 fstr_sprintf( key
, "%s/NAME/%s", WBKEY_PASSWD
, name
);
329 /**********************************************************************
330 **********************************************************************/
332 static char* acct_userkey_byuid( uid_t uid
)
336 fstr_sprintf( key
, "%s/UID/%lu", WBKEY_PASSWD
, (unsigned long)uid
);
341 /**********************************************************************
342 **********************************************************************/
344 static char* acct_groupkey_byname( const char *name
)
348 fstr_sprintf( key
, "%s/NAME/%s", WBKEY_GROUP
, name
);
353 /**********************************************************************
354 **********************************************************************/
356 static char* acct_groupkey_bygid( gid_t gid
)
360 fstr_sprintf( key
, "%s/GID/%lu", WBKEY_GROUP
, (unsigned long)gid
);
365 /**********************************************************************
366 **********************************************************************/
368 WINBINDD_PW
* wb_getpwnam( const char * name
)
372 static WINBINDD_PW
*pw
;
374 if ( !account_tdb
&& !winbindd_accountdb_init() ) {
375 DEBUG(0,("wb_getpwnam: Failed to open winbindd account db\n"));
380 keystr
= acct_userkey_byname( name
);
382 data
= tdb_fetch_bystring( account_tdb
, keystr
);
387 pw
= string2passwd( data
.dptr
);
388 SAFE_FREE( data
.dptr
);
391 DEBUG(5,("wb_getpwnam: %s user (%s)\n",
392 (pw
? "Found" : "Did not find"), name
));
397 /**********************************************************************
398 **********************************************************************/
400 WINBINDD_PW
* wb_getpwuid( const uid_t uid
)
404 static WINBINDD_PW
*pw
;
406 if ( !account_tdb
&& !winbindd_accountdb_init() ) {
407 DEBUG(0,("wb_getpwuid: Failed to open winbindd account db\n"));
411 data
= tdb_fetch_bystring( account_tdb
, acct_userkey_byuid(uid
) );
413 DEBUG(4,("wb_getpwuid: failed to locate uid == %lu\n", (unsigned long)uid
));
416 keystr
= acct_userkey_byname( data
.dptr
);
418 SAFE_FREE( data
.dptr
);
420 data
= tdb_fetch_bystring( account_tdb
, keystr
);
425 pw
= string2passwd( data
.dptr
);
426 SAFE_FREE( data
.dptr
);
429 DEBUG(5,("wb_getpwuid: %s user (uid == %lu)\n",
430 (pw
? "Found" : "Did not find"), (unsigned long)uid
));
435 /**********************************************************************
436 **********************************************************************/
438 BOOL
wb_storepwnam( const WINBINDD_PW
*pw
)
440 char *namekey
, *uidkey
;
446 if ( !account_tdb
&& !winbindd_accountdb_init() ) {
447 DEBUG(0,("wb_storepwnam: Failed to open winbindd account db\n"));
451 namekey
= acct_userkey_byname( pw
->pw_name
);
453 /* lock the main entry first */
455 if ( tdb_lock_bystring(account_tdb
, namekey
, 0) == -1 ) {
456 DEBUG(0,("wb_storepwnam: Failed to lock %s\n", namekey
));
460 str
= passwd2string( pw
);
463 data
.dsize
= strlen(str
) + 1;
465 if ( (tdb_store_bystring(account_tdb
, namekey
, data
, TDB_REPLACE
)) == -1 ) {
466 DEBUG(0,("wb_storepwnam: Failed to store \"%s\"\n", str
));
471 /* store the uid index */
473 uidkey
= acct_userkey_byuid(pw
->pw_uid
);
475 fstrcpy( username
, pw
->pw_name
);
476 data
.dptr
= username
;
477 data
.dsize
= strlen(username
) + 1;
479 if ( (tdb_store_bystring(account_tdb
, uidkey
, data
, TDB_REPLACE
)) == -1 ) {
480 DEBUG(0,("wb_storepwnam: Failed to store uid key \"%s\"\n", str
));
481 tdb_delete_bystring(account_tdb
, namekey
);
486 DEBUG(10,("wb_storepwnam: Success -> \"%s\"\n", str
));
489 tdb_unlock_bystring( account_tdb
, namekey
);
494 /**********************************************************************
495 **********************************************************************/
497 WINBINDD_GR
* wb_getgrnam( const char * name
)
501 static WINBINDD_GR
*grp
;
503 if ( !account_tdb
&& !winbindd_accountdb_init() ) {
504 DEBUG(0,("wb_getgrnam: Failed to open winbindd account db\n"));
509 keystr
= acct_groupkey_byname( name
);
511 data
= tdb_fetch_bystring( account_tdb
, keystr
);
516 grp
= string2group( data
.dptr
);
517 SAFE_FREE( data
.dptr
);
520 DEBUG(5,("wb_getgrnam: %s group (%s)\n",
521 (grp
? "Found" : "Did not find"), name
));
526 /**********************************************************************
527 **********************************************************************/
529 WINBINDD_GR
* wb_getgrgid( gid_t gid
)
533 static WINBINDD_GR
*grp
;
535 if ( !account_tdb
&& !winbindd_accountdb_init() ) {
536 DEBUG(0,("wb_getgrgid: Failed to open winbindd account db\n"));
540 data
= tdb_fetch_bystring( account_tdb
, acct_groupkey_bygid(gid
) );
542 DEBUG(4,("wb_getgrgid: failed to locate gid == %lu\n",
543 (unsigned long)gid
));
546 keystr
= acct_groupkey_byname( data
.dptr
);
548 SAFE_FREE( data
.dptr
);
550 data
= tdb_fetch_bystring( account_tdb
, keystr
);
555 grp
= string2group( data
.dptr
);
556 SAFE_FREE( data
.dptr
);
559 DEBUG(5,("wb_getgrgid: %s group (gid == %lu)\n",
560 (grp
? "Found" : "Did not find"), (unsigned long)gid
));
565 /**********************************************************************
566 **********************************************************************/
568 BOOL
wb_storegrnam( const WINBINDD_GR
*grp
)
570 char *namekey
, *gidkey
;
576 if ( !account_tdb
&& !winbindd_accountdb_init() ) {
577 DEBUG(0,("wb_storepwnam: Failed to open winbindd account db\n"));
581 namekey
= acct_groupkey_byname( grp
->gr_name
);
583 /* lock the main entry first */
585 if ( tdb_lock_bystring(account_tdb
, namekey
, 0) == -1 ) {
586 DEBUG(0,("wb_storegrnam: Failed to lock %s\n", namekey
));
590 str
= group2string( grp
);
593 data
.dsize
= strlen(str
) + 1;
595 if ( (tdb_store_bystring(account_tdb
, namekey
, data
, TDB_REPLACE
)) == -1 ) {
596 DEBUG(0,("wb_storegrnam: Failed to store \"%s\"\n", str
));
601 /* store the gid index */
603 gidkey
= acct_groupkey_bygid(grp
->gr_gid
);
605 fstrcpy( groupname
, grp
->gr_name
);
606 data
.dptr
= groupname
;
607 data
.dsize
= strlen(groupname
) + 1;
609 if ( (tdb_store_bystring(account_tdb
, gidkey
, data
, TDB_REPLACE
)) == -1 ) {
610 DEBUG(0,("wb_storegrnam: Failed to store gid key \"%s\"\n", str
));
611 tdb_delete_bystring(account_tdb
, namekey
);
616 DEBUG(10,("wb_storegrnam: Success -> \"%s\"\n", str
));
619 tdb_unlock_bystring( account_tdb
, namekey
);
624 /**********************************************************************
625 **********************************************************************/
627 static BOOL
wb_addgrpmember( WINBINDD_GR
*grp
, const char *user
)
635 for ( i
=0; i
<grp
->num_gr_mem
; i
++ ) {
636 if ( StrCaseCmp( grp
->gr_mem
[i
], user
) == 0 )
640 /* add one new slot and keep an extra for the terminating NULL */
641 members
= Realloc( grp
->gr_mem
, (grp
->num_gr_mem
+2)*sizeof(char*) );
645 grp
->gr_mem
= members
;
646 grp
->gr_mem
[grp
->num_gr_mem
++] = smb_xstrdup(user
);
647 grp
->gr_mem
[grp
->num_gr_mem
] = NULL
;
652 /**********************************************************************
653 **********************************************************************/
655 static BOOL
wb_delgrpmember( WINBINDD_GR
*grp
, const char *user
)
663 for ( i
=0; i
<grp
->num_gr_mem
&& !found
; i
++ ) {
664 if ( StrCaseCmp( grp
->gr_mem
[i
], user
) == 0 )
671 /* still some remaining members */
673 if ( grp
->num_gr_mem
> 1 ) {
674 memmove( grp
->gr_mem
[i
], grp
->gr_mem
[i
+1], sizeof(char*)*(grp
->num_gr_mem
-(i
+1)) );
677 else { /* last one */
678 free_winbindd_gr( grp
);
686 /**********************************************************************
687 **********************************************************************/
689 static int cleangroups_traverse_fn(TDB_CONTEXT
*the_tdb
, TDB_DATA kbuf
, TDB_DATA dbuf
,
694 char *name
= (char*)state
;
696 fstr_sprintf( key
, "%s/NAME", WBKEY_GROUP
);
699 /* if this is a group entry then, check the members */
701 if ( (strncmp(kbuf
.dptr
, key
, len
) == 0) && dbuf
.dptr
) {
704 if ( !(grp
= string2group( dbuf
.dptr
)) ) {
705 DEBUG(0,("cleangroups_traverse_fn: Failure to parse [%s]\n",
710 /* just try to delete the user and rely on wb_delgrpmember()
711 to tell you whether or not the group changed. This is more
712 effecient than testing group membership first since the
713 checks for deleting a user from a group is essentially the
714 same as checking if he/she is a member */
716 if ( wb_delgrpmember( grp
, name
) ) {
717 DEBUG(10,("cleanupgroups_traverse_fn: Removed user (%s) from group (%s)\n",
718 name
, grp
->gr_name
));
719 wb_storegrnam( grp
);
722 free_winbindd_gr( grp
);
728 /**********************************************************************
729 **********************************************************************/
731 static BOOL
wb_delete_user( WINBINDD_PW
*pw
)
736 if ( !account_tdb
&& !winbindd_accountdb_init() ) {
737 DEBUG(0,("wb_delete_user: Failed to open winbindd account db\n"));
741 namekey
= acct_userkey_byname( pw
->pw_name
);
743 /* lock the main entry first */
745 if ( tdb_lock_bystring(account_tdb
, namekey
, 0) == -1 ) {
746 DEBUG(0,("wb_delete_user: Failed to lock %s\n", namekey
));
750 /* remove user from all groups */
752 tdb_traverse(account_tdb
, cleangroups_traverse_fn
, (void *)pw
->pw_name
);
754 /* remove the user */
755 uidkey
= acct_userkey_byuid( pw
->pw_uid
);
757 tdb_delete_bystring( account_tdb
, namekey
);
758 tdb_delete_bystring( account_tdb
, uidkey
);
760 tdb_unlock_bystring( account_tdb
, namekey
);
765 /**********************************************************************
766 **********************************************************************/
768 static int isprimarygroup_traverse_fn(TDB_CONTEXT
*the_tdb
, TDB_DATA kbuf
,
769 TDB_DATA dbuf
, void *params
)
773 struct _check_primary_grp
*check
= (struct _check_primary_grp
*)params
;
775 fstr_sprintf( key
, "%s/NAME", WBKEY_PASSWD
);
778 /* if this is a group entry then, check the members */
780 if ( (strncmp(kbuf
.dptr
, key
, len
) == 0) && dbuf
.dptr
) {
783 if ( !(pw
= string2passwd( dbuf
.dptr
)) ) {
784 DEBUG(0,("isprimarygroup_traverse_fn: Failure to parse [%s]\n",
789 if ( check
->gid
== pw
->pw_gid
) {
799 /**********************************************************************
800 **********************************************************************/
802 static BOOL
wb_delete_group( WINBINDD_GR
*grp
)
804 struct _check_primary_grp check
;
808 if ( !account_tdb
&& !winbindd_accountdb_init() ) {
809 DEBUG(0,("wb_delete_group: Failed to open winbindd account db\n"));
813 /* lock the main entry first */
815 namekey
= acct_groupkey_byname( grp
->gr_name
);
816 if ( tdb_lock_bystring(account_tdb
, namekey
, 0) == -1 ) {
817 DEBUG(0,("wb_delete_group: Failed to lock %s\n", namekey
));
821 /* is this group the primary group for any user? If
825 tdb_traverse(account_tdb
, isprimarygroup_traverse_fn
, (void *)&check
);
828 DEBUG(4,("wb_delete_group: Cannot delete group (%s) since it "
829 "is the primary group for some users\n", grp
->gr_name
));
833 /* We're clear. Delete the group */
835 DEBUG(5,("wb_delete_group: Removing group (%s)\n", grp
->gr_name
));
837 gidkey
= acct_groupkey_bygid( grp
->gr_gid
);
839 tdb_delete_bystring( account_tdb
, namekey
);
840 tdb_delete_bystring( account_tdb
, gidkey
);
842 tdb_unlock_bystring( account_tdb
, namekey
);
847 /**********************************************************************
848 Create a new "UNIX" user for the system given a username
849 **********************************************************************/
851 enum winbindd_result
winbindd_create_user(struct winbindd_cli_state
*state
)
857 struct group
*unix_grp
;
859 uint32 flags
= state
->request
.flags
;
862 if ( !state
->privileged
) {
863 DEBUG(2, ("winbindd_create_user: non-privileged access denied!\n"));
864 return WINBINDD_ERROR
;
867 /* Ensure null termination */
868 state
->request
.data
.acct_mgt
.username
[sizeof(state
->request
.data
.acct_mgt
.username
)-1]='\0';
869 state
->request
.data
.acct_mgt
.groupname
[sizeof(state
->request
.data
.acct_mgt
.groupname
)-1]='\0';
871 user
= state
->request
.data
.acct_mgt
.username
;
872 group
= state
->request
.data
.acct_mgt
.groupname
;
874 DEBUG(3, ("[%5lu]: create_user: user=>(%s), group=>(%s)\n",
875 (unsigned long)state
->pid
, user
, group
));
878 group
= lp_template_primary_group();
880 /* validate the primary group
881 1) lookup in local tdb first
882 2) call getgrnam() as a last resort */
884 if ( (wb_grp
=wb_getgrnam(group
)) != NULL
) {
885 primary_gid
= wb_grp
->gr_gid
;
886 free_winbindd_gr( wb_grp
);
888 else if ( (unix_grp
=sys_getgrnam(group
)) != NULL
) {
889 primary_gid
= unix_grp
->gr_gid
;
892 DEBUG(2,("winbindd_create_user: Cannot validate gid for group (%s)\n", group
));
893 return WINBINDD_ERROR
;
898 if ( !NT_STATUS_IS_OK(idmap_allocate_id( &id
, ID_USERID
)) ) {
899 DEBUG(0,("winbindd_create_user: idmap_allocate_id() failed!\n"));
900 return WINBINDD_ERROR
;
903 /* The substitution of %U and %D in the 'template homedir' is done
904 by lp_string() calling standard_sub_basic(). */
906 fstrcpy( current_user_info
.smb_name
, user
);
907 sub_set_smb_name( user
);
908 fstrcpy( current_user_info
.domain
, get_global_sam_name() );
910 /* fill in the passwd struct */
912 fstrcpy( pw
.pw_name
, user
);
913 fstrcpy( pw
.pw_passwd
, "x" );
914 fstrcpy( pw
.pw_gecos
, user
);
915 fstrcpy( pw
.pw_dir
, lp_template_homedir() );
916 fstrcpy( pw
.pw_shell
, lp_template_shell() );
919 pw
.pw_gid
= primary_gid
;
921 /* store the new entry */
923 if ( !wb_storepwnam(&pw
) )
924 return WINBINDD_ERROR
;
926 /* do we need a new RID? */
928 if ( flags
& WBFLAG_ALLOCATE_RID
) {
929 if ( !NT_STATUS_IS_OK(idmap_allocate_rid(&rid
, USER_RID_TYPE
)) ) {
930 DEBUG(0,("winbindd_create_user: RID allocation failure! Cannot create user (%s)\n",
932 wb_delete_user( &pw
);
934 return WINBINDD_ERROR
;
937 state
->response
.data
.rid
= rid
;
943 /**********************************************************************
944 Create a new "UNIX" group for the system given a username
945 **********************************************************************/
947 enum winbindd_result
winbindd_create_group(struct winbindd_cli_state
*state
)
952 uint32 flags
= state
->request
.flags
;
955 if ( !state
->privileged
) {
956 DEBUG(2, ("winbindd_create_group: non-privileged access denied!\n"));
957 return WINBINDD_ERROR
;
960 /* Ensure null termination */
961 state
->request
.data
.acct_mgt
.groupname
[sizeof(state
->request
.data
.acct_mgt
.groupname
)-1]='\0';
962 group
= state
->request
.data
.acct_mgt
.groupname
;
964 DEBUG(3, ("[%5lu]: create_group: (%s)\n", (unsigned long)state
->pid
, group
));
968 if ( !NT_STATUS_IS_OK(idmap_allocate_id( &id
, ID_GROUPID
)) ) {
969 DEBUG(0,("winbindd_create_group: idmap_allocate_id() failed!\n"));
970 return WINBINDD_ERROR
;
973 /* fill in the group struct */
975 fstrcpy( grp
.gr_name
, group
);
976 fstrcpy( grp
.gr_passwd
, "*" );
979 grp
.gr_mem
= NULL
; /* start with no members */
982 if ( !wb_storegrnam(&grp
) )
983 return WINBINDD_ERROR
;
985 /* do we need a new RID? */
987 if ( flags
& WBFLAG_ALLOCATE_RID
) {
988 if ( !NT_STATUS_IS_OK(idmap_allocate_rid(&rid
, GROUP_RID_TYPE
)) ) {
989 DEBUG(0,("winbindd_create_group: RID allocation failure! Cannot create group (%s)\n",
991 wb_delete_group( &grp
);
993 return WINBINDD_ERROR
;
996 state
->response
.data
.rid
= rid
;
1002 /**********************************************************************
1003 Add a user to the membership for a group.
1004 **********************************************************************/
1006 enum winbindd_result
winbindd_add_user_to_group(struct winbindd_cli_state
*state
)
1013 if ( !state
->privileged
) {
1014 DEBUG(2, ("winbindd_add_user_to_group: non-privileged access denied!\n"));
1015 return WINBINDD_ERROR
;
1018 /* Ensure null termination */
1019 state
->request
.data
.acct_mgt
.groupname
[sizeof(state
->request
.data
.acct_mgt
.groupname
)-1]='\0';
1020 state
->request
.data
.acct_mgt
.username
[sizeof(state
->request
.data
.acct_mgt
.username
)-1]='\0';
1021 group
= state
->request
.data
.acct_mgt
.groupname
;
1022 user
= state
->request
.data
.acct_mgt
.username
;
1024 DEBUG(3, ("[%5lu]: add_user_to_group: add %s to %s\n", (unsigned long)state
->pid
,
1027 /* make sure it is a valid user */
1029 if ( !(pw
= wb_getpwnam( user
)) ) {
1030 DEBUG(4,("winbindd_add_user_to_group: Cannot add a non-existent user\n"));
1031 return WINBINDD_ERROR
;
1034 /* make sure it is a valid group */
1036 if ( !(grp
= wb_getgrnam( group
)) ) {
1037 DEBUG(4,("winbindd_add_user_to_group: Cannot add a user to a non-extistent group\n"));
1038 return WINBINDD_ERROR
;
1041 if ( !wb_addgrpmember( grp
, user
) )
1042 return WINBINDD_ERROR
;
1044 ret
= wb_storegrnam(grp
);
1046 free_winbindd_gr( grp
);
1048 return ( ret
? WINBINDD_OK
: WINBINDD_ERROR
);
1051 /**********************************************************************
1052 Remove a user from the membership of a group
1053 **********************************************************************/
1055 enum winbindd_result
winbindd_remove_user_from_group(struct winbindd_cli_state
*state
)
1061 if ( !state
->privileged
) {
1062 DEBUG(2, ("winbindd_remove_user_from_group: non-privileged access denied!\n"));
1063 return WINBINDD_ERROR
;
1066 /* Ensure null termination */
1067 state
->request
.data
.acct_mgt
.groupname
[sizeof(state
->request
.data
.acct_mgt
.groupname
)-1]='\0';
1068 state
->request
.data
.acct_mgt
.username
[sizeof(state
->request
.data
.acct_mgt
.username
)-1]='\0';
1069 group
= state
->request
.data
.acct_mgt
.groupname
;
1070 user
= state
->request
.data
.acct_mgt
.username
;
1072 DEBUG(3, ("[%5lu]: remove_user_to_group: delete %s from %s\n", (unsigned long)state
->pid
,
1075 /* don't worry about checking the username since we're removing it anyways */
1077 /* make sure it is a valid group */
1079 if ( !(grp
= wb_getgrnam( group
)) ) {
1080 DEBUG(4,("winbindd_remove_user_to_group: Cannot remove a user to a non-extistent group\n"));
1081 return WINBINDD_ERROR
;
1084 if ( !wb_delgrpmember( grp
, user
) )
1085 return WINBINDD_ERROR
;
1087 ret
= wb_storegrnam(grp
);
1089 free_winbindd_gr( grp
);
1091 return ( ret
? WINBINDD_OK
: WINBINDD_ERROR
);
1094 /**********************************************************************
1095 Set the primary group membership of a user
1096 **********************************************************************/
1098 enum winbindd_result
winbindd_set_user_primary_group(struct winbindd_cli_state
*state
)
1104 if ( !state
->privileged
) {
1105 DEBUG(2, ("winbindd_set_user_primary_group: non-privileged access denied!\n"));
1106 return WINBINDD_ERROR
;
1109 /* Ensure null termination */
1110 state
->request
.data
.acct_mgt
.groupname
[sizeof(state
->request
.data
.acct_mgt
.groupname
)-1]='\0';
1111 state
->request
.data
.acct_mgt
.username
[sizeof(state
->request
.data
.acct_mgt
.username
)-1]='\0';
1112 group
= state
->request
.data
.acct_mgt
.groupname
;
1113 user
= state
->request
.data
.acct_mgt
.username
;
1115 DEBUG(3, ("[%5lu]: set_user_primary_group: group %s for user %s\n",
1116 (unsigned long)state
->pid
, group
, user
));
1118 /* make sure it is a valid user */
1120 if ( !(pw
= wb_getpwnam( user
)) ) {
1121 DEBUG(4,("winbindd_add_user_to_group: Cannot add a non-existent user\n"));
1122 return WINBINDD_ERROR
;
1125 /* make sure it is a valid group */
1127 if ( !(grp
= wb_getgrnam( group
)) ) {
1128 DEBUG(4,("winbindd_add_user_to_group: Cannot add a user to a non-extistent group\n"));
1129 return WINBINDD_ERROR
;
1132 pw
->pw_gid
= grp
->gr_gid
;
1134 free_winbindd_gr( grp
);
1136 return ( wb_storepwnam(pw
) ? WINBINDD_OK
: WINBINDD_ERROR
);
1139 /**********************************************************************
1140 Delete a user from the winbindd account tdb.
1141 **********************************************************************/
1143 enum winbindd_result
winbindd_delete_user(struct winbindd_cli_state
*state
)
1148 if ( !state
->privileged
) {
1149 DEBUG(2, ("winbindd_delete_user: non-privileged access denied!\n"));
1150 return WINBINDD_ERROR
;
1153 /* Ensure null termination */
1154 state
->request
.data
.acct_mgt
.username
[sizeof(state
->request
.data
.acct_mgt
.username
)-1]='\0';
1155 user
= state
->request
.data
.acct_mgt
.username
;
1157 DEBUG(3, ("[%5lu]: delete_user: %s\n", (unsigned long)state
->pid
, user
));
1159 /* make sure it is a valid user */
1161 if ( !(pw
= wb_getpwnam( user
)) ) {
1162 DEBUG(4,("winbindd_delete_user: Cannot delete a non-existent user\n"));
1163 return WINBINDD_ERROR
;
1166 return ( wb_delete_user(pw
) ? WINBINDD_OK
: WINBINDD_ERROR
);
1169 /**********************************************************************
1170 Delete a group from winbindd's account tdb.
1171 **********************************************************************/
1173 enum winbindd_result
winbindd_delete_group(struct winbindd_cli_state
*state
)
1179 if ( !state
->privileged
) {
1180 DEBUG(2, ("winbindd_delete_group: non-privileged access denied!\n"));
1181 return WINBINDD_ERROR
;
1184 /* Ensure null termination */
1185 state
->request
.data
.acct_mgt
.username
[sizeof(state
->request
.data
.acct_mgt
.groupname
)-1]='\0';
1186 group
= state
->request
.data
.acct_mgt
.groupname
;
1188 DEBUG(3, ("[%5lu]: delete_group: %s\n", (unsigned long)state
->pid
, group
));
1190 /* make sure it is a valid group */
1192 if ( !(grp
= wb_getgrnam( group
)) ) {
1193 DEBUG(4,("winbindd_delete_group: Cannot delete a non-existent group\n"));
1194 return WINBINDD_ERROR
;
1197 ret
= wb_delete_group(grp
);
1199 free_winbindd_gr( grp
);
1201 return ( ret
? WINBINDD_OK
: WINBINDD_ERROR
);