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==%lu, gid==%lu\n",
140 (unsigned long)pw
.pw_uid
, (unsigned long)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
= pstr_sprintf( string
, "%s:%s:%lu:%lu:%s:%s:%s",
166 pw
->pw_passwd
? pw
->pw_passwd
: "x",
167 (unsigned long)pw
->pw_uid
,
168 (unsigned long)pw
->pw_gid
,
174 DEBUG(0,("passwd2string: pstr_sprintf() 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==%lu\n", (unsigned long)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
= pstr_sprintf( string
, "%s:%s:%lu:%s",
308 grp
->gr_passwd
? grp
->gr_passwd
: "*",
309 (unsigned long)grp
->gr_gid
,
312 SAFE_FREE( gr_mem_str
);
315 DEBUG(0,("group2string: pstr_sprintf() failed!\n"));
322 /**********************************************************************
323 **********************************************************************/
325 static char* acct_userkey_byname( const char *name
)
329 fstr_sprintf( key
, "%s/NAME/%s", WBKEY_PASSWD
, name
);
334 /**********************************************************************
335 **********************************************************************/
337 static char* acct_userkey_byuid( uid_t uid
)
341 fstr_sprintf( key
, "%s/UID/%lu", WBKEY_PASSWD
, (unsigned long)uid
);
346 /**********************************************************************
347 **********************************************************************/
349 static char* acct_groupkey_byname( const char *name
)
353 fstr_sprintf( key
, "%s/NAME/%s", WBKEY_GROUP
, name
);
358 /**********************************************************************
359 **********************************************************************/
361 static char* acct_groupkey_bygid( gid_t gid
)
365 fstr_sprintf( key
, "%s/GID/%lu", WBKEY_GROUP
, (unsigned long)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 == %lu\n", (unsigned long)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 == %lu)\n",
435 (pw
? "Found" : "Did not find"), (unsigned long)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 == %lu\n",
548 (unsigned long)gid
));
551 keystr
= acct_groupkey_byname( data
.dptr
);
553 SAFE_FREE( data
.dptr
);
555 data
= tdb_fetch_bystring( account_tdb
, keystr
);
560 grp
= string2group( data
.dptr
);
561 SAFE_FREE( data
.dptr
);
564 DEBUG(5,("wb_getgrgid: %s group (gid == %lu)\n",
565 (grp
? "Found" : "Did not find"), (unsigned long)gid
));
570 /**********************************************************************
571 **********************************************************************/
573 BOOL
wb_storegrnam( const WINBINDD_GR
*grp
)
575 char *namekey
, *gidkey
;
581 if ( !account_tdb
&& !winbindd_accountdb_init() ) {
582 DEBUG(0,("wb_storepwnam: Failed to open winbindd account db\n"));
586 namekey
= acct_groupkey_byname( grp
->gr_name
);
588 /* lock the main entry first */
590 if ( tdb_lock_bystring(account_tdb
, namekey
, 0) == -1 ) {
591 DEBUG(0,("wb_storegrnam: Failed to lock %s\n", namekey
));
595 str
= group2string( grp
);
598 data
.dsize
= strlen(str
) + 1;
600 if ( (tdb_store_bystring(account_tdb
, namekey
, data
, TDB_REPLACE
)) == -1 ) {
601 DEBUG(0,("wb_storegrnam: Failed to store \"%s\"\n", str
));
606 /* store the gid index */
608 gidkey
= acct_groupkey_bygid(grp
->gr_gid
);
610 fstrcpy( groupname
, grp
->gr_name
);
611 data
.dptr
= groupname
;
612 data
.dsize
= strlen(groupname
) + 1;
614 if ( (tdb_store_bystring(account_tdb
, gidkey
, data
, TDB_REPLACE
)) == -1 ) {
615 DEBUG(0,("wb_storegrnam: Failed to store gid key \"%s\"\n", str
));
616 tdb_delete_bystring(account_tdb
, namekey
);
621 DEBUG(10,("wb_storegrnam: Success -> \"%s\"\n", str
));
624 tdb_unlock_bystring( account_tdb
, namekey
);
629 /**********************************************************************
630 **********************************************************************/
632 static BOOL
wb_addgrpmember( WINBINDD_GR
*grp
, const char *user
)
640 for ( i
=0; i
<grp
->num_gr_mem
; i
++ ) {
641 if ( StrCaseCmp( grp
->gr_mem
[i
], user
) == 0 )
645 /* add one new slot and keep an extra for the terminating NULL */
646 members
= Realloc( grp
->gr_mem
, (grp
->num_gr_mem
+2)*sizeof(char*) );
650 grp
->gr_mem
= members
;
651 grp
->gr_mem
[grp
->num_gr_mem
++] = smb_xstrdup(user
);
652 grp
->gr_mem
[grp
->num_gr_mem
] = NULL
;
657 /**********************************************************************
658 **********************************************************************/
660 static BOOL
wb_delgrpmember( WINBINDD_GR
*grp
, const char *user
)
668 for ( i
=0; i
<grp
->num_gr_mem
&& !found
; i
++ ) {
669 if ( StrCaseCmp( grp
->gr_mem
[i
], user
) == 0 )
676 /* still some remaining members */
678 if ( grp
->num_gr_mem
> 1 ) {
679 memmove( grp
->gr_mem
[i
], grp
->gr_mem
[i
+1], sizeof(char*)*(grp
->num_gr_mem
-(i
+1)) );
682 else { /* last one */
683 free_winbindd_gr( grp
);
691 /**********************************************************************
692 **********************************************************************/
694 static int cleangroups_traverse_fn(TDB_CONTEXT
*the_tdb
, TDB_DATA kbuf
, TDB_DATA dbuf
,
699 char *name
= (char*)state
;
701 fstr_sprintf( key
, "%s/NAME", WBKEY_GROUP
);
704 /* if this is a group entry then, check the members */
706 if ( (strncmp(kbuf
.dptr
, key
, len
) == 0) && dbuf
.dptr
) {
709 if ( !(grp
= string2group( dbuf
.dptr
)) ) {
710 DEBUG(0,("cleangroups_traverse_fn: Failure to parse [%s]\n",
715 /* just try to delete the user and rely on wb_delgrpmember()
716 to tell you whether or not the group changed. This is more
717 effecient than testing group membership first since the
718 checks for deleting a user from a group is essentially the
719 same as checking if he/she is a member */
721 if ( wb_delgrpmember( grp
, name
) ) {
722 DEBUG(10,("cleanupgroups_traverse_fn: Removed user (%s) from group (%s)\n",
723 name
, grp
->gr_name
));
724 wb_storegrnam( grp
);
727 free_winbindd_gr( grp
);
733 /**********************************************************************
734 **********************************************************************/
736 static BOOL
wb_delete_user( WINBINDD_PW
*pw
)
741 if ( !account_tdb
&& !winbindd_accountdb_init() ) {
742 DEBUG(0,("wb_delete_user: Failed to open winbindd account db\n"));
746 namekey
= acct_userkey_byname( pw
->pw_name
);
748 /* lock the main entry first */
750 if ( tdb_lock_bystring(account_tdb
, namekey
, 0) == -1 ) {
751 DEBUG(0,("wb_delete_user: Failed to lock %s\n", namekey
));
755 /* remove user from all groups */
757 tdb_traverse(account_tdb
, cleangroups_traverse_fn
, (void *)pw
->pw_name
);
759 /* remove the user */
760 uidkey
= acct_userkey_byuid( pw
->pw_uid
);
762 tdb_delete_bystring( account_tdb
, namekey
);
763 tdb_delete_bystring( account_tdb
, uidkey
);
765 tdb_unlock_bystring( account_tdb
, namekey
);
770 /**********************************************************************
771 **********************************************************************/
773 static int isprimarygroup_traverse_fn(TDB_CONTEXT
*the_tdb
, TDB_DATA kbuf
,
774 TDB_DATA dbuf
, void *params
)
778 struct _check_primary_grp
*check
= (struct _check_primary_grp
*)params
;
780 fstr_sprintf( key
, "%s/NAME", WBKEY_PASSWD
);
783 /* if this is a group entry then, check the members */
785 if ( (strncmp(kbuf
.dptr
, key
, len
) == 0) && dbuf
.dptr
) {
788 if ( !(pw
= string2passwd( dbuf
.dptr
)) ) {
789 DEBUG(0,("isprimarygroup_traverse_fn: Failure to parse [%s]\n",
794 if ( check
->gid
== pw
->pw_gid
) {
804 /**********************************************************************
805 **********************************************************************/
807 static BOOL
wb_delete_group( WINBINDD_GR
*grp
)
809 struct _check_primary_grp check
;
813 if ( !account_tdb
&& !winbindd_accountdb_init() ) {
814 DEBUG(0,("wb_delete_group: Failed to open winbindd account db\n"));
818 /* lock the main entry first */
820 namekey
= acct_groupkey_byname( grp
->gr_name
);
821 if ( tdb_lock_bystring(account_tdb
, namekey
, 0) == -1 ) {
822 DEBUG(0,("wb_delete_group: Failed to lock %s\n", namekey
));
826 /* is this group the primary group for any user? If
830 tdb_traverse(account_tdb
, isprimarygroup_traverse_fn
, (void *)&check
);
833 DEBUG(4,("wb_delete_group: Cannot delete group (%s) since it "
834 "is the primary group for some users\n", grp
->gr_name
));
838 /* We're clear. Delete the group */
840 DEBUG(5,("wb_delete_group: Removing group (%s)\n", grp
->gr_name
));
842 gidkey
= acct_groupkey_bygid( grp
->gr_gid
);
844 tdb_delete_bystring( account_tdb
, namekey
);
845 tdb_delete_bystring( account_tdb
, gidkey
);
847 tdb_unlock_bystring( account_tdb
, namekey
);
852 /**********************************************************************
853 Create a new "UNIX" user for the system given a username
854 **********************************************************************/
856 enum winbindd_result
winbindd_create_user(struct winbindd_cli_state
*state
)
862 struct group
*unix_grp
;
864 uint32 flags
= state
->request
.flags
;
867 if ( !state
->privileged
) {
868 DEBUG(2, ("winbindd_create_user: non-privileged access denied!\n"));
869 return WINBINDD_ERROR
;
872 /* Ensure null termination */
873 state
->request
.data
.acct_mgt
.username
[sizeof(state
->request
.data
.acct_mgt
.username
)-1]='\0';
874 state
->request
.data
.acct_mgt
.groupname
[sizeof(state
->request
.data
.acct_mgt
.groupname
)-1]='\0';
876 user
= state
->request
.data
.acct_mgt
.username
;
877 group
= state
->request
.data
.acct_mgt
.groupname
;
879 DEBUG(3, ("[%5lu]: create_user: user=>(%s), group=>(%s)\n",
880 (unsigned long)state
->pid
, user
, group
));
883 group
= lp_template_primary_group();
885 /* validate the primary group
886 1) lookup in local tdb first
887 2) call getgrnam() as a last resort */
889 if ( (wb_grp
=wb_getgrnam(group
)) != NULL
) {
890 primary_gid
= wb_grp
->gr_gid
;
891 free_winbindd_gr( wb_grp
);
893 else if ( (unix_grp
=sys_getgrnam(group
)) != NULL
) {
894 primary_gid
= unix_grp
->gr_gid
;
897 DEBUG(2,("winbindd_create_user: Cannot validate gid for group (%s)\n", group
));
898 return WINBINDD_ERROR
;
903 if ( !NT_STATUS_IS_OK(idmap_allocate_id( &id
, ID_USERID
)) ) {
904 DEBUG(0,("winbindd_create_user: idmap_allocate_id() failed!\n"));
905 return WINBINDD_ERROR
;
908 /* The substitution of %U and %D in the 'template homedir' is done
909 by lp_string() calling standard_sub_basic(). */
911 fstrcpy( current_user_info
.smb_name
, user
);
912 sub_set_smb_name( user
);
913 fstrcpy( current_user_info
.domain
, get_global_sam_name() );
915 /* fill in the passwd struct */
917 fstrcpy( pw
.pw_name
, user
);
918 fstrcpy( pw
.pw_passwd
, "x" );
919 fstrcpy( pw
.pw_gecos
, user
);
920 fstrcpy( pw
.pw_dir
, lp_template_homedir() );
921 fstrcpy( pw
.pw_shell
, lp_template_shell() );
924 pw
.pw_gid
= primary_gid
;
926 /* store the new entry */
928 if ( !wb_storepwnam(&pw
) )
929 return WINBINDD_ERROR
;
931 /* do we need a new RID? */
933 if ( flags
& WBFLAG_ALLOCATE_RID
) {
934 if ( !NT_STATUS_IS_OK(idmap_allocate_rid(&rid
, USER_RID_TYPE
)) ) {
935 DEBUG(0,("winbindd_create_user: RID allocation failure! Cannot create user (%s)\n",
937 wb_delete_user( &pw
);
939 return WINBINDD_ERROR
;
942 state
->response
.data
.rid
= rid
;
948 /**********************************************************************
949 Create a new "UNIX" group for the system given a username
950 **********************************************************************/
952 enum winbindd_result
winbindd_create_group(struct winbindd_cli_state
*state
)
957 uint32 flags
= state
->request
.flags
;
960 if ( !state
->privileged
) {
961 DEBUG(2, ("winbindd_create_group: non-privileged access denied!\n"));
962 return WINBINDD_ERROR
;
965 /* Ensure null termination */
966 state
->request
.data
.acct_mgt
.groupname
[sizeof(state
->request
.data
.acct_mgt
.groupname
)-1]='\0';
967 group
= state
->request
.data
.acct_mgt
.groupname
;
969 DEBUG(3, ("[%5lu]: create_group: (%s)\n", (unsigned long)state
->pid
, group
));
973 if ( !NT_STATUS_IS_OK(idmap_allocate_id( &id
, ID_GROUPID
)) ) {
974 DEBUG(0,("winbindd_create_group: idmap_allocate_id() failed!\n"));
975 return WINBINDD_ERROR
;
978 /* fill in the group struct */
980 fstrcpy( grp
.gr_name
, group
);
981 fstrcpy( grp
.gr_passwd
, "*" );
984 grp
.gr_mem
= NULL
; /* start with no members */
987 if ( !wb_storegrnam(&grp
) )
988 return WINBINDD_ERROR
;
990 /* do we need a new RID? */
992 if ( flags
& WBFLAG_ALLOCATE_RID
) {
993 if ( !NT_STATUS_IS_OK(idmap_allocate_rid(&rid
, GROUP_RID_TYPE
)) ) {
994 DEBUG(0,("winbindd_create_group: RID allocation failure! Cannot create group (%s)\n",
996 wb_delete_group( &grp
);
998 return WINBINDD_ERROR
;
1001 state
->response
.data
.rid
= rid
;
1007 /**********************************************************************
1008 Add a user to the membership for a group.
1009 **********************************************************************/
1011 enum winbindd_result
winbindd_add_user_to_group(struct winbindd_cli_state
*state
)
1018 if ( !state
->privileged
) {
1019 DEBUG(2, ("winbindd_add_user_to_group: non-privileged access denied!\n"));
1020 return WINBINDD_ERROR
;
1023 /* Ensure null termination */
1024 state
->request
.data
.acct_mgt
.groupname
[sizeof(state
->request
.data
.acct_mgt
.groupname
)-1]='\0';
1025 state
->request
.data
.acct_mgt
.username
[sizeof(state
->request
.data
.acct_mgt
.username
)-1]='\0';
1026 group
= state
->request
.data
.acct_mgt
.groupname
;
1027 user
= state
->request
.data
.acct_mgt
.username
;
1029 DEBUG(3, ("[%5lu]: add_user_to_group: add %s to %s\n", (unsigned long)state
->pid
,
1032 /* make sure it is a valid user */
1034 if ( !(pw
= wb_getpwnam( user
)) ) {
1035 DEBUG(4,("winbindd_add_user_to_group: Cannot add a non-existent user\n"));
1036 return WINBINDD_ERROR
;
1039 /* make sure it is a valid group */
1041 if ( !(grp
= wb_getgrnam( group
)) ) {
1042 DEBUG(4,("winbindd_add_user_to_group: Cannot add a user to a non-extistent group\n"));
1043 return WINBINDD_ERROR
;
1046 if ( !wb_addgrpmember( grp
, user
) )
1047 return WINBINDD_ERROR
;
1049 ret
= wb_storegrnam(grp
);
1051 free_winbindd_gr( grp
);
1053 return ( ret
? WINBINDD_OK
: WINBINDD_ERROR
);
1056 /**********************************************************************
1057 Remove a user from the membership of a group
1058 **********************************************************************/
1060 enum winbindd_result
winbindd_remove_user_from_group(struct winbindd_cli_state
*state
)
1066 if ( !state
->privileged
) {
1067 DEBUG(2, ("winbindd_remove_user_from_group: non-privileged access denied!\n"));
1068 return WINBINDD_ERROR
;
1071 /* Ensure null termination */
1072 state
->request
.data
.acct_mgt
.groupname
[sizeof(state
->request
.data
.acct_mgt
.groupname
)-1]='\0';
1073 state
->request
.data
.acct_mgt
.username
[sizeof(state
->request
.data
.acct_mgt
.username
)-1]='\0';
1074 group
= state
->request
.data
.acct_mgt
.groupname
;
1075 user
= state
->request
.data
.acct_mgt
.username
;
1077 DEBUG(3, ("[%5lu]: remove_user_to_group: delete %s from %s\n", (unsigned long)state
->pid
,
1080 /* don't worry about checking the username since we're removing it anyways */
1082 /* make sure it is a valid group */
1084 if ( !(grp
= wb_getgrnam( group
)) ) {
1085 DEBUG(4,("winbindd_remove_user_to_group: Cannot remove a user to a non-extistent group\n"));
1086 return WINBINDD_ERROR
;
1089 if ( !wb_delgrpmember( grp
, user
) )
1090 return WINBINDD_ERROR
;
1092 ret
= wb_storegrnam(grp
);
1094 free_winbindd_gr( grp
);
1096 return ( ret
? WINBINDD_OK
: WINBINDD_ERROR
);
1099 /**********************************************************************
1100 Set the primary group membership of a user
1101 **********************************************************************/
1103 enum winbindd_result
winbindd_set_user_primary_group(struct winbindd_cli_state
*state
)
1109 if ( !state
->privileged
) {
1110 DEBUG(2, ("winbindd_set_user_primary_group: non-privileged access denied!\n"));
1111 return WINBINDD_ERROR
;
1114 /* Ensure null termination */
1115 state
->request
.data
.acct_mgt
.groupname
[sizeof(state
->request
.data
.acct_mgt
.groupname
)-1]='\0';
1116 state
->request
.data
.acct_mgt
.username
[sizeof(state
->request
.data
.acct_mgt
.username
)-1]='\0';
1117 group
= state
->request
.data
.acct_mgt
.groupname
;
1118 user
= state
->request
.data
.acct_mgt
.username
;
1120 DEBUG(3, ("[%5lu]: set_user_primary_group: group %s for user %s\n",
1121 (unsigned long)state
->pid
, group
, user
));
1123 /* make sure it is a valid user */
1125 if ( !(pw
= wb_getpwnam( user
)) ) {
1126 DEBUG(4,("winbindd_add_user_to_group: Cannot add a non-existent user\n"));
1127 return WINBINDD_ERROR
;
1130 /* make sure it is a valid group */
1132 if ( !(grp
= wb_getgrnam( group
)) ) {
1133 DEBUG(4,("winbindd_add_user_to_group: Cannot add a user to a non-extistent group\n"));
1134 return WINBINDD_ERROR
;
1137 pw
->pw_gid
= grp
->gr_gid
;
1139 free_winbindd_gr( grp
);
1141 return ( wb_storepwnam(pw
) ? WINBINDD_OK
: WINBINDD_ERROR
);
1144 /**********************************************************************
1145 Delete a user from the winbindd account tdb.
1146 **********************************************************************/
1148 enum winbindd_result
winbindd_delete_user(struct winbindd_cli_state
*state
)
1153 if ( !state
->privileged
) {
1154 DEBUG(2, ("winbindd_delete_user: non-privileged access denied!\n"));
1155 return WINBINDD_ERROR
;
1158 /* Ensure null termination */
1159 state
->request
.data
.acct_mgt
.username
[sizeof(state
->request
.data
.acct_mgt
.username
)-1]='\0';
1160 user
= state
->request
.data
.acct_mgt
.username
;
1162 DEBUG(3, ("[%5lu]: delete_user: %s\n", (unsigned long)state
->pid
, user
));
1164 /* make sure it is a valid user */
1166 if ( !(pw
= wb_getpwnam( user
)) ) {
1167 DEBUG(4,("winbindd_delete_user: Cannot delete a non-existent user\n"));
1168 return WINBINDD_ERROR
;
1171 return ( wb_delete_user(pw
) ? WINBINDD_OK
: WINBINDD_ERROR
);
1174 /**********************************************************************
1175 Delete a group from winbindd's account tdb.
1176 **********************************************************************/
1178 enum winbindd_result
winbindd_delete_group(struct winbindd_cli_state
*state
)
1184 if ( !state
->privileged
) {
1185 DEBUG(2, ("winbindd_delete_group: non-privileged access denied!\n"));
1186 return WINBINDD_ERROR
;
1189 /* Ensure null termination */
1190 state
->request
.data
.acct_mgt
.username
[sizeof(state
->request
.data
.acct_mgt
.groupname
)-1]='\0';
1191 group
= state
->request
.data
.acct_mgt
.groupname
;
1193 DEBUG(3, ("[%5lu]: delete_group: %s\n", (unsigned long)state
->pid
, group
));
1195 /* make sure it is a valid group */
1197 if ( !(grp
= wb_getgrnam( group
)) ) {
1198 DEBUG(4,("winbindd_delete_group: Cannot delete a non-existent group\n"));
1199 return WINBINDD_ERROR
;
1202 ret
= wb_delete_group(grp
);
1204 free_winbindd_gr( grp
);
1206 return ( ret
? WINBINDD_OK
: WINBINDD_ERROR
);