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.
27 #define DBGC_CLASS DBGC_WINBIND
29 #define WBKEY_PASSWD "WBA_PASSWD"
30 #define WBKEY_GROUP "WBA_GROUP"
32 #define NUM_PW_FIELDS 7
33 #define NUM_GRP_FIELDS 4
37 static TDB_CONTEXT
*account_tdb
;
39 extern userdom_struct current_user_info
;
41 struct _check_primary_grp
{
46 /**********************************************************************
47 **********************************************************************/
49 static void free_winbindd_gr( WINBINDD_GR
*grp
)
56 for ( i
=0; i
<grp
->num_gr_mem
; i
++ )
57 SAFE_FREE( grp
->gr_mem
[i
] );
59 SAFE_FREE( grp
->gr_mem
);
64 /*****************************************************************************
65 Initialise auto-account database.
66 *****************************************************************************/
68 static BOOL
winbindd_accountdb_init(void)
70 /* see if we've already opened the tdb */
75 /* winbindd_idmap.tdb should always be opened by the idmap_init()
78 if ( !(account_tdb
= idmap_tdb_handle()) ) {
79 DEBUG(0, ("winbindd_accountdb_init: Unable to retreive handle for database\n"));
88 /**********************************************************************
89 Convert a string in /etc/passwd format to a struct passwd* entry
90 **********************************************************************/
92 static WINBINDD_PW
* string2passwd( char *string
)
94 static WINBINDD_PW pw
;
96 char *fields
[NUM_PW_FIELDS
];
104 DEBUG(10,("string2passwd: converting \"%s\"\n", string
));
106 ZERO_STRUCT( fields
);
108 for ( i
=0, str
=string
; i
<NUM_PW_FIELDS
-1; i
++ ) {
109 if ( !(p
= strchr( str
, ':' )) ) {
110 DEBUG(0,("string2passwd: parsing failure\n"));
123 fstrcpy( pw
.pw_name
, fields
[0] );
124 fstrcpy( pw
.pw_passwd
, fields
[1] );
125 pw
.pw_uid
= atoi( fields
[2] );
126 pw
.pw_gid
= atoi( fields
[3] );
127 fstrcpy( pw
.pw_gecos
, fields
[4] );
128 fstrcpy( pw
.pw_dir
, fields
[5] );
129 fstrcpy( pw
.pw_shell
, fields
[6] );
132 /* last minute sanity checks */
134 if ( pw
.pw_uid
==0 || pw
.pw_gid
==0 ) {
135 DEBUG(0,("string2passwd: Failure! uid==%lu, gid==%lu\n",
136 (unsigned long)pw
.pw_uid
, (unsigned long)pw
.pw_gid
));
140 DEBUG(10,("string2passwd: Success\n"));
145 /**********************************************************************
146 Convert a struct passwd* to a string formatted for /etc/passwd
147 **********************************************************************/
149 static char* passwd2string( const WINBINDD_PW
*pw
)
151 static pstring string
;
154 if ( !pw
|| !pw
->pw_name
)
157 DEBUG(10,("passwd2string: converting passwd struct for %s\n",
160 ret
= pstr_sprintf( string
, "%s:%s:%lu:%lu:%s:%s:%s",
162 pw
->pw_passwd
? pw
->pw_passwd
: "x",
163 (unsigned long)pw
->pw_uid
,
164 (unsigned long)pw
->pw_gid
,
170 DEBUG(0,("passwd2string: pstr_sprintf() failed!\n"));
177 /**********************************************************************
178 Convert a string in /etc/group format to a struct group* entry
179 **********************************************************************/
181 static WINBINDD_GR
* string2group( char *string
)
183 static WINBINDD_GR grp
;
185 char *fields
[NUM_GRP_FIELDS
];
187 char **gr_members
= NULL
;
188 int num_gr_members
= 0;
193 ZERO_STRUCTP( &grp
);
195 DEBUG(10,("string2group: converting \"%s\"\n", string
));
197 ZERO_STRUCT( fields
);
199 for ( i
=0, str
=string
; i
<NUM_GRP_FIELDS
-1; i
++ ) {
200 if ( !(p
= strchr( str
, ':' )) ) {
201 DEBUG(0,("string2group: parsing failure\n"));
213 /* we already know we have a non-empty string */
215 num_gr_members
= count_chars(str
, ',') + 1;
217 /* if there was at least one comma, then there
219 if ( num_gr_members
) {
222 gr_members
= (char**)smb_xmalloc(sizeof(char*)*num_gr_members
+1);
225 while ( next_token(&str
, buffer
, ",", sizeof(buffer
)) && i
<num_gr_members
) {
226 gr_members
[i
++] = smb_xstrdup(buffer
);
229 gr_members
[i
] = NULL
;
236 fstrcpy( grp
.gr_name
, fields
[0] );
237 fstrcpy( grp
.gr_passwd
, fields
[1] );
238 grp
.gr_gid
= atoi( fields
[2] );
240 grp
.num_gr_mem
= num_gr_members
;
241 grp
.gr_mem
= gr_members
;
243 /* last minute sanity checks */
245 if ( grp
.gr_gid
== 0 ) {
246 DEBUG(0,("string2group: Failure! gid==%lu\n", (unsigned long)grp
.gr_gid
));
247 SAFE_FREE( gr_members
);
251 DEBUG(10,("string2group: Success\n"));
256 /**********************************************************************
257 Convert a struct group* to a string formatted for /etc/group
258 **********************************************************************/
260 static char* group2string( const WINBINDD_GR
*grp
)
262 static pstring string
;
264 char *member
, *gr_mem_str
;
268 if ( !grp
|| !grp
->gr_name
)
271 DEBUG(10,("group2string: converting passwd struct for %s\n",
274 if ( grp
->num_gr_mem
) {
277 member
= grp
->gr_mem
[0];
282 size
+= strlen(member
) + 1;
284 member
= grp
->gr_mem
[num_members
];
287 gr_mem_str
= smb_xmalloc(size
);
289 for ( i
=0; i
<num_members
; i
++ ) {
290 snprintf( &gr_mem_str
[idx
], size
-idx
, "%s,", grp
->gr_mem
[i
] );
291 idx
+= strlen(grp
->gr_mem
[i
]) + 1;
293 /* add trailing NULL (also removes trailing ',' */
294 gr_mem_str
[size
-1] = '\0';
298 gr_mem_str
= smb_xmalloc(sizeof(fstring
));
299 fstrcpy( gr_mem_str
, "" );
302 ret
= pstr_sprintf( string
, "%s:%s:%lu:%s",
304 grp
->gr_passwd
? grp
->gr_passwd
: "*",
305 (unsigned long)grp
->gr_gid
,
308 SAFE_FREE( gr_mem_str
);
311 DEBUG(0,("group2string: pstr_sprintf() failed!\n"));
318 /**********************************************************************
319 **********************************************************************/
321 static char* acct_userkey_byname( const char *name
)
325 fstr_sprintf( key
, "%s/NAME/%s", WBKEY_PASSWD
, name
);
330 /**********************************************************************
331 **********************************************************************/
333 static char* acct_userkey_byuid( uid_t uid
)
337 fstr_sprintf( key
, "%s/UID/%lu", WBKEY_PASSWD
, (unsigned long)uid
);
342 /**********************************************************************
343 **********************************************************************/
345 static char* acct_groupkey_byname( const char *name
)
349 fstr_sprintf( key
, "%s/NAME/%s", WBKEY_GROUP
, name
);
354 /**********************************************************************
355 **********************************************************************/
357 static char* acct_groupkey_bygid( gid_t gid
)
361 fstr_sprintf( key
, "%s/GID/%lu", WBKEY_GROUP
, (unsigned long)gid
);
366 /**********************************************************************
367 **********************************************************************/
369 WINBINDD_PW
* wb_getpwnam( const char * name
)
373 static WINBINDD_PW
*pw
;
375 if ( !account_tdb
&& !winbindd_accountdb_init() ) {
376 DEBUG(0,("wb_getpwnam: Failed to open winbindd account db\n"));
381 keystr
= acct_userkey_byname( name
);
383 data
= tdb_fetch_bystring( account_tdb
, keystr
);
388 pw
= string2passwd( data
.dptr
);
389 SAFE_FREE( data
.dptr
);
392 DEBUG(5,("wb_getpwnam: %s user (%s)\n",
393 (pw
? "Found" : "Did not find"), name
));
398 /**********************************************************************
399 **********************************************************************/
401 WINBINDD_PW
* wb_getpwuid( const uid_t uid
)
405 static WINBINDD_PW
*pw
;
407 if ( !account_tdb
&& !winbindd_accountdb_init() ) {
408 DEBUG(0,("wb_getpwuid: Failed to open winbindd account db\n"));
412 data
= tdb_fetch_bystring( account_tdb
, acct_userkey_byuid(uid
) );
414 DEBUG(4,("wb_getpwuid: failed to locate uid == %lu\n", (unsigned long)uid
));
417 keystr
= acct_userkey_byname( data
.dptr
);
419 SAFE_FREE( data
.dptr
);
421 data
= tdb_fetch_bystring( account_tdb
, keystr
);
426 pw
= string2passwd( data
.dptr
);
427 SAFE_FREE( data
.dptr
);
430 DEBUG(5,("wb_getpwuid: %s user (uid == %lu)\n",
431 (pw
? "Found" : "Did not find"), (unsigned long)uid
));
436 /**********************************************************************
437 **********************************************************************/
439 BOOL
wb_storepwnam( const WINBINDD_PW
*pw
)
441 char *namekey
, *uidkey
;
447 if ( !account_tdb
&& !winbindd_accountdb_init() ) {
448 DEBUG(0,("wb_storepwnam: Failed to open winbindd account db\n"));
452 namekey
= acct_userkey_byname( pw
->pw_name
);
454 /* lock the main entry first */
456 if ( tdb_lock_bystring(account_tdb
, namekey
, 0) == -1 ) {
457 DEBUG(0,("wb_storepwnam: Failed to lock %s\n", namekey
));
461 str
= passwd2string( pw
);
464 data
.dsize
= strlen(str
) + 1;
466 if ( (tdb_store_bystring(account_tdb
, namekey
, data
, TDB_REPLACE
)) == -1 ) {
467 DEBUG(0,("wb_storepwnam: Failed to store \"%s\"\n", str
));
472 /* store the uid index */
474 uidkey
= acct_userkey_byuid(pw
->pw_uid
);
476 fstrcpy( username
, pw
->pw_name
);
477 data
.dptr
= username
;
478 data
.dsize
= strlen(username
) + 1;
480 if ( (tdb_store_bystring(account_tdb
, uidkey
, data
, TDB_REPLACE
)) == -1 ) {
481 DEBUG(0,("wb_storepwnam: Failed to store uid key \"%s\"\n", str
));
482 tdb_delete_bystring(account_tdb
, namekey
);
487 DEBUG(10,("wb_storepwnam: Success -> \"%s\"\n", str
));
490 tdb_unlock_bystring( account_tdb
, namekey
);
495 /**********************************************************************
496 **********************************************************************/
498 WINBINDD_GR
* wb_getgrnam( const char * name
)
502 static WINBINDD_GR
*grp
;
504 if ( !account_tdb
&& !winbindd_accountdb_init() ) {
505 DEBUG(0,("wb_getgrnam: Failed to open winbindd account db\n"));
510 keystr
= acct_groupkey_byname( name
);
512 data
= tdb_fetch_bystring( account_tdb
, keystr
);
517 grp
= string2group( data
.dptr
);
518 SAFE_FREE( data
.dptr
);
521 DEBUG(5,("wb_getgrnam: %s group (%s)\n",
522 (grp
? "Found" : "Did not find"), name
));
527 /**********************************************************************
528 **********************************************************************/
530 WINBINDD_GR
* wb_getgrgid( gid_t gid
)
534 static WINBINDD_GR
*grp
;
536 if ( !account_tdb
&& !winbindd_accountdb_init() ) {
537 DEBUG(0,("wb_getgrgid: Failed to open winbindd account db\n"));
541 data
= tdb_fetch_bystring( account_tdb
, acct_groupkey_bygid(gid
) );
543 DEBUG(4,("wb_getgrgid: failed to locate gid == %lu\n",
544 (unsigned long)gid
));
547 keystr
= acct_groupkey_byname( data
.dptr
);
549 SAFE_FREE( data
.dptr
);
551 data
= tdb_fetch_bystring( account_tdb
, keystr
);
556 grp
= string2group( data
.dptr
);
557 SAFE_FREE( data
.dptr
);
560 DEBUG(5,("wb_getgrgid: %s group (gid == %lu)\n",
561 (grp
? "Found" : "Did not find"), (unsigned long)gid
));
566 /**********************************************************************
567 **********************************************************************/
569 BOOL
wb_storegrnam( const WINBINDD_GR
*grp
)
571 char *namekey
, *gidkey
;
577 if ( !account_tdb
&& !winbindd_accountdb_init() ) {
578 DEBUG(0,("wb_storepwnam: Failed to open winbindd account db\n"));
582 namekey
= acct_groupkey_byname( grp
->gr_name
);
584 /* lock the main entry first */
586 if ( tdb_lock_bystring(account_tdb
, namekey
, 0) == -1 ) {
587 DEBUG(0,("wb_storegrnam: Failed to lock %s\n", namekey
));
591 str
= group2string( grp
);
594 data
.dsize
= strlen(str
) + 1;
596 if ( (tdb_store_bystring(account_tdb
, namekey
, data
, TDB_REPLACE
)) == -1 ) {
597 DEBUG(0,("wb_storegrnam: Failed to store \"%s\"\n", str
));
602 /* store the gid index */
604 gidkey
= acct_groupkey_bygid(grp
->gr_gid
);
606 fstrcpy( groupname
, grp
->gr_name
);
607 data
.dptr
= groupname
;
608 data
.dsize
= strlen(groupname
) + 1;
610 if ( (tdb_store_bystring(account_tdb
, gidkey
, data
, TDB_REPLACE
)) == -1 ) {
611 DEBUG(0,("wb_storegrnam: Failed to store gid key \"%s\"\n", str
));
612 tdb_delete_bystring(account_tdb
, namekey
);
617 DEBUG(10,("wb_storegrnam: Success -> \"%s\"\n", str
));
620 tdb_unlock_bystring( account_tdb
, namekey
);
625 /**********************************************************************
626 **********************************************************************/
628 static BOOL
wb_addgrpmember( WINBINDD_GR
*grp
, const char *user
)
636 for ( i
=0; i
<grp
->num_gr_mem
; i
++ ) {
637 if ( StrCaseCmp( grp
->gr_mem
[i
], user
) == 0 )
641 /* add one new slot and keep an extra for the terminating NULL */
642 members
= Realloc( grp
->gr_mem
, (grp
->num_gr_mem
+2)*sizeof(char*) );
646 grp
->gr_mem
= members
;
647 grp
->gr_mem
[grp
->num_gr_mem
++] = smb_xstrdup(user
);
648 grp
->gr_mem
[grp
->num_gr_mem
] = NULL
;
653 /**********************************************************************
654 **********************************************************************/
656 static BOOL
wb_delgrpmember( WINBINDD_GR
*grp
, const char *user
)
664 for ( i
=0; i
<grp
->num_gr_mem
&& !found
; i
++ ) {
665 if ( StrCaseCmp( grp
->gr_mem
[i
], user
) == 0 )
672 /* still some remaining members */
674 if ( grp
->num_gr_mem
> 1 ) {
675 memmove( grp
->gr_mem
[i
], grp
->gr_mem
[i
+1], sizeof(char*)*(grp
->num_gr_mem
-(i
+1)) );
678 else { /* last one */
679 free_winbindd_gr( grp
);
687 /**********************************************************************
688 **********************************************************************/
690 static int cleangroups_traverse_fn(TDB_CONTEXT
*the_tdb
, TDB_DATA kbuf
, TDB_DATA dbuf
,
695 char *name
= (char*)state
;
697 fstr_sprintf( key
, "%s/NAME", WBKEY_GROUP
);
700 /* if this is a group entry then, check the members */
702 if ( (strncmp(kbuf
.dptr
, key
, len
) == 0) && dbuf
.dptr
) {
705 if ( !(grp
= string2group( dbuf
.dptr
)) ) {
706 DEBUG(0,("cleangroups_traverse_fn: Failure to parse [%s]\n",
711 /* just try to delete the user and rely on wb_delgrpmember()
712 to tell you whether or not the group changed. This is more
713 effecient than testing group membership first since the
714 checks for deleting a user from a group is essentially the
715 same as checking if he/she is a member */
717 if ( wb_delgrpmember( grp
, name
) ) {
718 DEBUG(10,("cleanupgroups_traverse_fn: Removed user (%s) from group (%s)\n",
719 name
, grp
->gr_name
));
720 wb_storegrnam( grp
);
723 free_winbindd_gr( grp
);
729 /**********************************************************************
730 **********************************************************************/
732 static BOOL
wb_delete_user( WINBINDD_PW
*pw
)
737 if ( !account_tdb
&& !winbindd_accountdb_init() ) {
738 DEBUG(0,("wb_delete_user: Failed to open winbindd account db\n"));
742 namekey
= acct_userkey_byname( pw
->pw_name
);
744 /* lock the main entry first */
746 if ( tdb_lock_bystring(account_tdb
, namekey
, 0) == -1 ) {
747 DEBUG(0,("wb_delete_user: Failed to lock %s\n", namekey
));
751 /* remove user from all groups */
753 tdb_traverse(account_tdb
, cleangroups_traverse_fn
, (void *)pw
->pw_name
);
755 /* remove the user */
756 uidkey
= acct_userkey_byuid( pw
->pw_uid
);
758 tdb_delete_bystring( account_tdb
, namekey
);
759 tdb_delete_bystring( account_tdb
, uidkey
);
761 tdb_unlock_bystring( account_tdb
, namekey
);
766 /**********************************************************************
767 **********************************************************************/
769 static int isprimarygroup_traverse_fn(TDB_CONTEXT
*the_tdb
, TDB_DATA kbuf
,
770 TDB_DATA dbuf
, void *params
)
774 struct _check_primary_grp
*check
= (struct _check_primary_grp
*)params
;
776 fstr_sprintf( key
, "%s/NAME", WBKEY_PASSWD
);
779 /* if this is a group entry then, check the members */
781 if ( (strncmp(kbuf
.dptr
, key
, len
) == 0) && dbuf
.dptr
) {
784 if ( !(pw
= string2passwd( dbuf
.dptr
)) ) {
785 DEBUG(0,("isprimarygroup_traverse_fn: Failure to parse [%s]\n",
790 if ( check
->gid
== pw
->pw_gid
) {
800 /**********************************************************************
801 **********************************************************************/
803 static BOOL
wb_delete_group( WINBINDD_GR
*grp
)
805 struct _check_primary_grp check
;
809 if ( !account_tdb
&& !winbindd_accountdb_init() ) {
810 DEBUG(0,("wb_delete_group: Failed to open winbindd account db\n"));
814 /* lock the main entry first */
816 namekey
= acct_groupkey_byname( grp
->gr_name
);
817 if ( tdb_lock_bystring(account_tdb
, namekey
, 0) == -1 ) {
818 DEBUG(0,("wb_delete_group: Failed to lock %s\n", namekey
));
822 /* is this group the primary group for any user? If
826 tdb_traverse(account_tdb
, isprimarygroup_traverse_fn
, (void *)&check
);
829 DEBUG(4,("wb_delete_group: Cannot delete group (%s) since it "
830 "is the primary group for some users\n", grp
->gr_name
));
834 /* We're clear. Delete the group */
836 DEBUG(5,("wb_delete_group: Removing group (%s)\n", grp
->gr_name
));
838 gidkey
= acct_groupkey_bygid( grp
->gr_gid
);
840 tdb_delete_bystring( account_tdb
, namekey
);
841 tdb_delete_bystring( account_tdb
, gidkey
);
843 tdb_unlock_bystring( account_tdb
, namekey
);
848 /**********************************************************************
849 Create a new "UNIX" user for the system given a username
850 **********************************************************************/
852 enum winbindd_result
winbindd_create_user(struct winbindd_cli_state
*state
)
858 struct group
*unix_grp
;
860 uint32 flags
= state
->request
.flags
;
863 if ( !state
->privileged
) {
864 DEBUG(2, ("winbindd_create_user: non-privileged access denied!\n"));
865 return WINBINDD_ERROR
;
868 /* Ensure null termination */
869 state
->request
.data
.acct_mgt
.username
[sizeof(state
->request
.data
.acct_mgt
.username
)-1]='\0';
870 state
->request
.data
.acct_mgt
.groupname
[sizeof(state
->request
.data
.acct_mgt
.groupname
)-1]='\0';
872 user
= state
->request
.data
.acct_mgt
.username
;
873 group
= state
->request
.data
.acct_mgt
.groupname
;
875 DEBUG(3, ("[%5lu]: create_user: user=>(%s), group=>(%s)\n",
876 (unsigned long)state
->pid
, user
, group
));
879 group
= lp_template_primary_group();
881 /* validate the primary group
882 1) lookup in local tdb first
883 2) call getgrnam() as a last resort */
885 if ( (wb_grp
=wb_getgrnam(group
)) != NULL
) {
886 primary_gid
= wb_grp
->gr_gid
;
887 free_winbindd_gr( wb_grp
);
889 else if ( (unix_grp
=sys_getgrnam(group
)) != NULL
) {
890 primary_gid
= unix_grp
->gr_gid
;
893 DEBUG(2,("winbindd_create_user: Cannot validate gid for group (%s)\n", group
));
894 return WINBINDD_ERROR
;
899 if ( !NT_STATUS_IS_OK(idmap_allocate_id( &id
, ID_USERID
)) ) {
900 DEBUG(0,("winbindd_create_user: idmap_allocate_id() failed!\n"));
901 return WINBINDD_ERROR
;
904 /* The substitution of %U and %D in the 'template homedir' is done
905 by lp_string() calling standard_sub_basic(). */
907 fstrcpy( current_user_info
.smb_name
, user
);
908 sub_set_smb_name( user
);
909 fstrcpy( current_user_info
.domain
, get_global_sam_name() );
911 /* fill in the passwd struct */
913 fstrcpy( pw
.pw_name
, user
);
914 fstrcpy( pw
.pw_passwd
, "x" );
915 fstrcpy( pw
.pw_gecos
, user
);
916 fstrcpy( pw
.pw_dir
, lp_template_homedir() );
917 fstrcpy( pw
.pw_shell
, lp_template_shell() );
920 pw
.pw_gid
= primary_gid
;
922 /* store the new entry */
924 if ( !wb_storepwnam(&pw
) )
925 return WINBINDD_ERROR
;
927 /* do we need a new RID? */
929 if ( flags
& WBFLAG_ALLOCATE_RID
) {
930 if ( !NT_STATUS_IS_OK(idmap_allocate_rid(&rid
, USER_RID_TYPE
)) ) {
931 DEBUG(0,("winbindd_create_user: RID allocation failure! Cannot create user (%s)\n",
933 wb_delete_user( &pw
);
935 return WINBINDD_ERROR
;
938 state
->response
.data
.rid
= rid
;
944 /**********************************************************************
945 Create a new "UNIX" group for the system given a username
946 **********************************************************************/
948 enum winbindd_result
winbindd_create_group(struct winbindd_cli_state
*state
)
953 uint32 flags
= state
->request
.flags
;
956 if ( !state
->privileged
) {
957 DEBUG(2, ("winbindd_create_group: non-privileged access denied!\n"));
958 return WINBINDD_ERROR
;
961 /* Ensure null termination */
962 state
->request
.data
.acct_mgt
.groupname
[sizeof(state
->request
.data
.acct_mgt
.groupname
)-1]='\0';
963 group
= state
->request
.data
.acct_mgt
.groupname
;
965 DEBUG(3, ("[%5lu]: create_group: (%s)\n", (unsigned long)state
->pid
, group
));
969 if ( !NT_STATUS_IS_OK(idmap_allocate_id( &id
, ID_GROUPID
)) ) {
970 DEBUG(0,("winbindd_create_group: idmap_allocate_id() failed!\n"));
971 return WINBINDD_ERROR
;
974 /* fill in the group struct */
976 fstrcpy( grp
.gr_name
, group
);
977 fstrcpy( grp
.gr_passwd
, "*" );
980 grp
.gr_mem
= NULL
; /* start with no members */
983 if ( !wb_storegrnam(&grp
) )
984 return WINBINDD_ERROR
;
986 /* do we need a new RID? */
988 if ( flags
& WBFLAG_ALLOCATE_RID
) {
989 if ( !NT_STATUS_IS_OK(idmap_allocate_rid(&rid
, GROUP_RID_TYPE
)) ) {
990 DEBUG(0,("winbindd_create_group: RID allocation failure! Cannot create group (%s)\n",
992 wb_delete_group( &grp
);
994 return WINBINDD_ERROR
;
997 state
->response
.data
.rid
= rid
;
1003 /**********************************************************************
1004 Add a user to the membership for a group.
1005 **********************************************************************/
1007 enum winbindd_result
winbindd_add_user_to_group(struct winbindd_cli_state
*state
)
1014 if ( !state
->privileged
) {
1015 DEBUG(2, ("winbindd_add_user_to_group: non-privileged access denied!\n"));
1016 return WINBINDD_ERROR
;
1019 /* Ensure null termination */
1020 state
->request
.data
.acct_mgt
.groupname
[sizeof(state
->request
.data
.acct_mgt
.groupname
)-1]='\0';
1021 state
->request
.data
.acct_mgt
.username
[sizeof(state
->request
.data
.acct_mgt
.username
)-1]='\0';
1022 group
= state
->request
.data
.acct_mgt
.groupname
;
1023 user
= state
->request
.data
.acct_mgt
.username
;
1025 DEBUG(3, ("[%5lu]: add_user_to_group: add %s to %s\n", (unsigned long)state
->pid
,
1028 /* make sure it is a valid user */
1030 if ( !(pw
= wb_getpwnam( user
)) ) {
1031 DEBUG(4,("winbindd_add_user_to_group: Cannot add a non-existent user\n"));
1032 return WINBINDD_ERROR
;
1035 /* make sure it is a valid group */
1037 if ( !(grp
= wb_getgrnam( group
)) ) {
1038 DEBUG(4,("winbindd_add_user_to_group: Cannot add a user to a non-extistent group\n"));
1039 return WINBINDD_ERROR
;
1042 if ( !wb_addgrpmember( grp
, user
) )
1043 return WINBINDD_ERROR
;
1045 ret
= wb_storegrnam(grp
);
1047 free_winbindd_gr( grp
);
1049 return ( ret
? WINBINDD_OK
: WINBINDD_ERROR
);
1052 /**********************************************************************
1053 Remove a user from the membership of a group
1054 **********************************************************************/
1056 enum winbindd_result
winbindd_remove_user_from_group(struct winbindd_cli_state
*state
)
1062 if ( !state
->privileged
) {
1063 DEBUG(2, ("winbindd_remove_user_from_group: non-privileged access denied!\n"));
1064 return WINBINDD_ERROR
;
1067 /* Ensure null termination */
1068 state
->request
.data
.acct_mgt
.groupname
[sizeof(state
->request
.data
.acct_mgt
.groupname
)-1]='\0';
1069 state
->request
.data
.acct_mgt
.username
[sizeof(state
->request
.data
.acct_mgt
.username
)-1]='\0';
1070 group
= state
->request
.data
.acct_mgt
.groupname
;
1071 user
= state
->request
.data
.acct_mgt
.username
;
1073 DEBUG(3, ("[%5lu]: remove_user_to_group: delete %s from %s\n", (unsigned long)state
->pid
,
1076 /* don't worry about checking the username since we're removing it anyways */
1078 /* make sure it is a valid group */
1080 if ( !(grp
= wb_getgrnam( group
)) ) {
1081 DEBUG(4,("winbindd_remove_user_to_group: Cannot remove a user to a non-extistent group\n"));
1082 return WINBINDD_ERROR
;
1085 if ( !wb_delgrpmember( grp
, user
) )
1086 return WINBINDD_ERROR
;
1088 ret
= wb_storegrnam(grp
);
1090 free_winbindd_gr( grp
);
1092 return ( ret
? WINBINDD_OK
: WINBINDD_ERROR
);
1095 /**********************************************************************
1096 Set the primary group membership of a user
1097 **********************************************************************/
1099 enum winbindd_result
winbindd_set_user_primary_group(struct winbindd_cli_state
*state
)
1105 if ( !state
->privileged
) {
1106 DEBUG(2, ("winbindd_set_user_primary_group: non-privileged access denied!\n"));
1107 return WINBINDD_ERROR
;
1110 /* Ensure null termination */
1111 state
->request
.data
.acct_mgt
.groupname
[sizeof(state
->request
.data
.acct_mgt
.groupname
)-1]='\0';
1112 state
->request
.data
.acct_mgt
.username
[sizeof(state
->request
.data
.acct_mgt
.username
)-1]='\0';
1113 group
= state
->request
.data
.acct_mgt
.groupname
;
1114 user
= state
->request
.data
.acct_mgt
.username
;
1116 DEBUG(3, ("[%5lu]: set_user_primary_group: group %s for user %s\n",
1117 (unsigned long)state
->pid
, group
, user
));
1119 /* make sure it is a valid user */
1121 if ( !(pw
= wb_getpwnam( user
)) ) {
1122 DEBUG(4,("winbindd_add_user_to_group: Cannot add a non-existent user\n"));
1123 return WINBINDD_ERROR
;
1126 /* make sure it is a valid group */
1128 if ( !(grp
= wb_getgrnam( group
)) ) {
1129 DEBUG(4,("winbindd_add_user_to_group: Cannot add a user to a non-extistent group\n"));
1130 return WINBINDD_ERROR
;
1133 pw
->pw_gid
= grp
->gr_gid
;
1135 free_winbindd_gr( grp
);
1137 return ( wb_storepwnam(pw
) ? WINBINDD_OK
: WINBINDD_ERROR
);
1140 /**********************************************************************
1141 Delete a user from the winbindd account tdb.
1142 **********************************************************************/
1144 enum winbindd_result
winbindd_delete_user(struct winbindd_cli_state
*state
)
1149 if ( !state
->privileged
) {
1150 DEBUG(2, ("winbindd_delete_user: non-privileged access denied!\n"));
1151 return WINBINDD_ERROR
;
1154 /* Ensure null termination */
1155 state
->request
.data
.acct_mgt
.username
[sizeof(state
->request
.data
.acct_mgt
.username
)-1]='\0';
1156 user
= state
->request
.data
.acct_mgt
.username
;
1158 DEBUG(3, ("[%5lu]: delete_user: %s\n", (unsigned long)state
->pid
, user
));
1160 /* make sure it is a valid user */
1162 if ( !(pw
= wb_getpwnam( user
)) ) {
1163 DEBUG(4,("winbindd_delete_user: Cannot delete a non-existent user\n"));
1164 return WINBINDD_ERROR
;
1167 return ( wb_delete_user(pw
) ? WINBINDD_OK
: WINBINDD_ERROR
);
1170 /**********************************************************************
1171 Delete a group from winbindd's account tdb.
1172 **********************************************************************/
1174 enum winbindd_result
winbindd_delete_group(struct winbindd_cli_state
*state
)
1180 if ( !state
->privileged
) {
1181 DEBUG(2, ("winbindd_delete_group: non-privileged access denied!\n"));
1182 return WINBINDD_ERROR
;
1185 /* Ensure null termination */
1186 state
->request
.data
.acct_mgt
.username
[sizeof(state
->request
.data
.acct_mgt
.groupname
)-1]='\0';
1187 group
= state
->request
.data
.acct_mgt
.groupname
;
1189 DEBUG(3, ("[%5lu]: delete_group: %s\n", (unsigned long)state
->pid
, group
));
1191 /* make sure it is a valid group */
1193 if ( !(grp
= wb_getgrnam( group
)) ) {
1194 DEBUG(4,("winbindd_delete_group: Cannot delete a non-existent group\n"));
1195 return WINBINDD_ERROR
;
1198 ret
= wb_delete_group(grp
);
1200 free_winbindd_gr( grp
);
1202 return ( ret
? WINBINDD_OK
: WINBINDD_ERROR
);