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"));
178 add_member(const char *domain, const char *user,
179 char ***members, int *num_members)
183 fill_domain_username(name, domain, user);
185 *members = Realloc(*members, (*num_members+1) * sizeof(char **));
187 if (members == NULL) {
188 DEBUG(10, ("Realloc failed\n"));
192 (*members)[*num_members] = strdup(name);
196 /**********************************************************************
197 Add member users resulting from sid. Expand if it is a domain group.
198 **********************************************************************/
201 add_expanded_sid(DOM_SID *sid, char ***members, int *num_members)
205 struct winbindd_domain *domain;
209 enum SID_NAME_USE type;
218 TALLOC_CTX *mem_ctx = talloc_init("add_expanded_sid");
220 if (mem_ctx == NULL) {
221 DEBUG(1, ("talloc_init failed\n"));
225 sid_copy(&dom_sid, sid);
226 sid_split_rid(&dom_sid, &rid);
228 domain = find_domain_from_sid(&dom_sid);
230 if (domain == NULL) {
231 DEBUG(3, ("Could not find domain for sid %s\n",
232 sid_string_static(sid)));
236 result = domain->methods->sid_to_name(domain, mem_ctx, sid,
239 if (!NT_STATUS_IS_OK(result)) {
240 DEBUG(3, ("sid_to_name failed for sid %s\n",
241 sid_string_static(sid)));
245 DEBUG(10, ("Found name %s, type %d\n", name, type));
247 if (type == SID_NAME_USER) {
248 add_member(domain->name, name, members, num_members);
252 if (type != SID_NAME_DOM_GRP) {
253 DEBUG(10, ("Alias member %s neither user nor group, ignore\n",
258 /* Expand the domain group */
260 result = domain->methods->lookup_groupmem(domain, mem_ctx,
265 if (!NT_STATUS_IS_OK(result)) {
266 DEBUG(10, ("Could not lookup group members for %s: %s\n",
267 name, nt_errstr(result)));
271 for (i=0; i<num_names; i++) {
272 DEBUG(10, ("Adding group member SID %s\n",
273 sid_string_static(sid_mem[i])));
275 if (types[i] != SID_NAME_USER) {
276 DEBUG(1, ("Hmmm. Member %s of group %s is no user. "
277 "Ignoring.\n", names[i], name));
281 add_member(domain->name, names[i], members, num_members);
285 talloc_destroy(mem_ctx);
289 /**********************************************************************
290 Add alias members. Expand them if they are domain groups.
291 **********************************************************************/
294 add_expanded_alias_members(gid_t gid, char ***members, int *num_members)
297 DOM_SID *sids = NULL;
300 if (!pdb_getgrgid(&map, gid)) {
301 DEBUG(10, ("No mapping for group %d\n", gid));
305 if ( (map.sid_name_use != SID_NAME_WKN_GRP) &&
306 (map.sid_name_use != SID_NAME_ALIAS) ) {
307 DEBUG(10, ("Group %d is no alias\n", gid));
311 if (!pdb_enum_aliasmem(&map.sid, &sids, &num_sids)) {
312 DEBUG(10, ("Could not enum aliases for group sid %s\n",
313 sid_string_static(&map.sid)));
317 for (i=0; i<num_sids; i++) {
318 DEBUG(10, ("additional SID: %s\n",
319 sid_string_static(&sids[i])));
321 add_expanded_sid(&sids[i], members, num_members);
329 /**********************************************************************
330 Convert a string in /etc/group format to a struct group* entry
331 **********************************************************************/
333 static WINBINDD_GR* string2group( char *string )
335 static WINBINDD_GR grp;
337 char *fields[NUM_GRP_FIELDS];
339 char **gr_members = NULL;
340 int num_gr_members = 0;
345 ZERO_STRUCTP( &grp );
347 DEBUG(10,("string2group: converting \"%s\"\n", string));
349 ZERO_STRUCT( fields );
351 for ( i=0, str=string; i<NUM_GRP_FIELDS-1; i++ ) {
352 if ( !(p = strchr( str, ':' )) ) {
353 DEBUG(0,("string2group: parsing failure\n"));
365 /* we already know we have a non-empty string */
367 num_gr_members = count_chars(str, ',') + 1;
369 /* if there was at least one comma, then there
371 if ( num_gr_members ) {
374 gr_members = (char**)smb_xmalloc(sizeof(char*)*(num_gr_members+1));
377 while ( next_token(&str, buffer, ",", sizeof(buffer)) && i<num_gr_members ) {
378 gr_members[i++] = smb_xstrdup(buffer);
381 gr_members[i] = NULL;
388 fstrcpy( grp.gr_name, fields[0] );
389 fstrcpy( grp.gr_passwd, fields[1] );
390 grp.gr_gid = atoi( fields[2] );
392 add_expanded_alias_members(grp.gr_gid, &gr_members, &num_gr_members);
394 grp.num_gr_mem = num_gr_members;
395 grp.gr_mem = gr_members;
397 /* last minute sanity checks */
399 if ( grp.gr_gid == 0 ) {
400 DEBUG(0,("string2group: Failure! gid==%lu\n", (unsigned long)grp.gr_gid));
401 SAFE_FREE( gr_members );
405 DEBUG(10,("string2group: Success\n"));
410 /**********************************************************************
411 Convert a struct group* to a string formatted for /etc/group
412 **********************************************************************/
414 static char* group2string( const WINBINDD_GR *grp )
416 static pstring string;
418 char *member, *gr_mem_str;
422 if ( !grp || !grp->gr_name )
425 DEBUG(10,("group2string: converting passwd struct for %s\n",
428 if ( grp->num_gr_mem ) {
431 member = grp->gr_mem[0];
436 size += strlen(member) + 1;
438 member = grp->gr_mem[num_members];
441 gr_mem_str = smb_xmalloc(size);
443 for ( i=0; i<num_members; i++ ) {
444 snprintf( &gr_mem_str[idx], size-idx, "%s,", grp->gr_mem[i] );
445 idx += strlen(grp->gr_mem[i]) + 1;
447 /* add trailing NULL (also removes trailing ',' */
448 gr_mem_str[size-1] = '\0';
452 gr_mem_str = smb_xmalloc(sizeof(fstring));
453 fstrcpy( gr_mem_str, "" );
456 ret = pstr_sprintf( string, "%s:%s:%lu:%s",
458 grp->gr_passwd ? grp->gr_passwd : "*",
459 (unsigned long)grp->gr_gid,
462 SAFE_FREE( gr_mem_str );
465 DEBUG(0,("group2string: pstr_sprintf() failed!\n"));
472 /**********************************************************************
473 **********************************************************************/
475 static char* acct_userkey_byname( const char *name )
479 fstr_sprintf( key, "%s/NAME/%s", WBKEY_PASSWD, name );
484 /**********************************************************************
485 **********************************************************************/
487 static char* acct_userkey_byuid( uid_t uid )
491 fstr_sprintf( key, "%s/UID/%lu", WBKEY_PASSWD, (unsigned long)uid );
496 /**********************************************************************
497 **********************************************************************/
499 static char* acct_groupkey_byname( const char *name )
503 fstr_sprintf( key, "%s/NAME/%s", WBKEY_GROUP, name );
508 /**********************************************************************
509 **********************************************************************/
511 static char* acct_groupkey_bygid( gid_t gid )
515 fstr_sprintf( key, "%s/GID/%lu", WBKEY_GROUP, (unsigned long)gid );
520 /**********************************************************************
521 **********************************************************************/
523 WINBINDD_PW* wb_getpwnam( const char * name )
527 static WINBINDD_PW *pw;
529 if ( !account_tdb && !winbindd_accountdb_init() ) {
530 DEBUG(0,("wb_getpwnam: Failed to open winbindd account db\n"));
535 keystr = acct_userkey_byname( name );
537 data = tdb_fetch_bystring( account_tdb, keystr );
542 pw = string2passwd( data.dptr );
543 SAFE_FREE( data.dptr );
546 DEBUG(5,("wb_getpwnam: %s user (%s)\n",
547 (pw ? "Found" : "Did not find"), name ));
552 /**********************************************************************
553 **********************************************************************/
555 WINBINDD_PW* wb_getpwuid( const uid_t uid )
559 static WINBINDD_PW *pw;
561 if ( !account_tdb && !winbindd_accountdb_init() ) {
562 DEBUG(0,("wb_getpwuid: Failed to open winbindd account db\n"));
566 data = tdb_fetch_bystring( account_tdb, acct_userkey_byuid(uid) );
568 DEBUG(4,("wb_getpwuid: failed to locate uid == %lu\n", (unsigned long)uid));
571 keystr = acct_userkey_byname( data.dptr );
573 SAFE_FREE( data.dptr );
575 data = tdb_fetch_bystring( account_tdb, keystr );
580 pw = string2passwd( data.dptr );
581 SAFE_FREE( data.dptr );
584 DEBUG(5,("wb_getpwuid: %s user (uid == %lu)\n",
585 (pw ? "Found" : "Did not find"), (unsigned long)uid ));
590 /**********************************************************************
591 **********************************************************************/
593 static BOOL wb_storepwnam( const WINBINDD_PW *pw )
595 char *namekey, *uidkey;
601 if ( !account_tdb && !winbindd_accountdb_init() ) {
602 DEBUG(0,("wb_storepwnam: Failed to open winbindd account db\n"));
606 namekey = acct_userkey_byname( pw->pw_name );
608 /* lock the main entry first */
610 if ( tdb_lock_bystring(account_tdb, namekey, 0) == -1 ) {
611 DEBUG(0,("wb_storepwnam: Failed to lock %s\n", namekey));
615 str = passwd2string( pw );
618 data.dsize = strlen(str) + 1;
620 if ( (tdb_store_bystring(account_tdb, namekey, data, TDB_REPLACE)) == -1 ) {
621 DEBUG(0,("wb_storepwnam: Failed to store \"%s\"\n", str));
626 /* store the uid index */
628 uidkey = acct_userkey_byuid(pw->pw_uid);
630 fstrcpy( username, pw->pw_name );
631 data.dptr = username;
632 data.dsize = strlen(username) + 1;
634 if ( (tdb_store_bystring(account_tdb, uidkey, data, TDB_REPLACE)) == -1 ) {
635 DEBUG(0,("wb_storepwnam: Failed to store uid key \"%s\"\n", str));
636 tdb_delete_bystring(account_tdb, namekey);
641 DEBUG(10,("wb_storepwnam: Success -> \"%s\"\n", str));
644 tdb_unlock_bystring( account_tdb, namekey );
649 /**********************************************************************
650 **********************************************************************/
652 WINBINDD_GR* wb_getgrnam( const char * name )
656 static WINBINDD_GR *grp;
658 if ( !account_tdb && !winbindd_accountdb_init() ) {
659 DEBUG(0,("wb_getgrnam: Failed to open winbindd account db\n"));
664 keystr = acct_groupkey_byname( name );
666 data = tdb_fetch_bystring( account_tdb, keystr );
671 grp = string2group( data.dptr );
672 SAFE_FREE( data.dptr );
675 DEBUG(5,("wb_getgrnam: %s group (%s)\n",
676 (grp ? "Found" : "Did not find"), name ));
681 /**********************************************************************
682 **********************************************************************/
684 WINBINDD_GR* wb_getgrgid( gid_t gid )
688 static WINBINDD_GR *grp;
690 if ( !account_tdb && !winbindd_accountdb_init() ) {
691 DEBUG(0,("wb_getgrgid: Failed to open winbindd account db\n"));
695 data = tdb_fetch_bystring( account_tdb, acct_groupkey_bygid(gid) );
697 DEBUG(4,("wb_getgrgid: failed to locate gid == %lu\n",
698 (unsigned long)gid));
701 keystr = acct_groupkey_byname( data.dptr );
703 SAFE_FREE( data.dptr );
705 data = tdb_fetch_bystring( account_tdb, keystr );
710 grp = string2group( data.dptr );
711 SAFE_FREE( data.dptr );
714 DEBUG(5,("wb_getgrgid: %s group (gid == %lu)\n",
715 (grp ? "Found" : "Did not find"), (unsigned long)gid ));
720 /**********************************************************************
721 **********************************************************************/
723 static BOOL wb_storegrnam( const WINBINDD_GR *grp )
725 char *namekey, *gidkey;
731 if ( !account_tdb && !winbindd_accountdb_init() ) {
732 DEBUG(0,("wb_storepwnam: Failed to open winbindd account db\n"));
736 namekey = acct_groupkey_byname( grp->gr_name );
738 /* lock the main entry first */
740 if ( tdb_lock_bystring(account_tdb, namekey, 0) == -1 ) {
741 DEBUG(0,("wb_storegrnam: Failed to lock %s\n", namekey));
745 str = group2string( grp );
748 data.dsize = strlen(str) + 1;
750 if ( (tdb_store_bystring(account_tdb, namekey, data, TDB_REPLACE)) == -1 ) {
751 DEBUG(0,("wb_storegrnam: Failed to store \"%s\"\n", str));
756 /* store the gid index */
758 gidkey = acct_groupkey_bygid(grp->gr_gid);
760 fstrcpy( groupname, grp->gr_name );
761 data.dptr = groupname;
762 data.dsize = strlen(groupname) + 1;
764 if ( (tdb_store_bystring(account_tdb, gidkey, data, TDB_REPLACE)) == -1 ) {
765 DEBUG(0,("wb_storegrnam: Failed to store gid key \"%s\"\n", str));
766 tdb_delete_bystring(account_tdb, namekey);
771 DEBUG(10,("wb_storegrnam: Success -> \"%s\"\n", str));
774 tdb_unlock_bystring( account_tdb, namekey );
779 /**********************************************************************
780 **********************************************************************/
782 static BOOL wb_addgrpmember( WINBINDD_GR *grp, const char *user )
790 for ( i=0; i<grp->num_gr_mem; i++ ) {
791 if ( StrCaseCmp( grp->gr_mem[i], user ) == 0 )
795 /* add one new slot and keep an extra for the terminating NULL */
796 members = Realloc( grp->gr_mem, (grp->num_gr_mem+2)*sizeof(char*) );
800 grp->gr_mem = members;
801 grp->gr_mem[grp->num_gr_mem++] = smb_xstrdup(user);
802 grp->gr_mem[grp->num_gr_mem] = NULL;
807 /**********************************************************************
808 **********************************************************************/
810 static BOOL wb_delgrpmember( WINBINDD_GR *grp, const char *user )
818 for ( i=0; i<grp->num_gr_mem; i++ ) {
819 if ( StrCaseCmp( grp->gr_mem[i], user ) == 0 ) {
828 /* still some remaining members */
830 if ( grp->num_gr_mem > 1 ) {
831 SAFE_FREE(grp->gr_mem[i]);
833 grp->gr_mem[i] = grp->gr_mem[grp->num_gr_mem];
834 grp->gr_mem[grp->num_gr_mem] = NULL;
836 else { /* last one */
837 free_winbindd_gr( grp );
845 /**********************************************************************
846 **********************************************************************/
848 static int cleangroups_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf,
853 char *name = (char*)state;
855 fstr_sprintf( key, "%s/NAME", WBKEY_GROUP );
858 /* if this is a group entry then, check the members */
860 if ( (strncmp(kbuf.dptr, key, len) == 0) && dbuf.dptr ) {
863 if ( !(grp = string2group( dbuf.dptr )) ) {
864 DEBUG(0,("cleangroups_traverse_fn: Failure to parse [%s]\n",
869 /* just try to delete the user and rely on wb_delgrpmember()
870 to tell you whether or not the group changed. This is more
871 effecient than testing group membership first since the
872 checks for deleting a user from a group is essentially the
873 same as checking if he/she is a member */
875 if ( wb_delgrpmember( grp, name ) ) {
876 DEBUG(10,("cleanupgroups_traverse_fn: Removed user (%s) from group (%s)\n",
877 name, grp->gr_name));
878 wb_storegrnam( grp );
881 free_winbindd_gr( grp );
887 /**********************************************************************
888 **********************************************************************/
890 static BOOL wb_delete_user( WINBINDD_PW *pw)
895 if ( !account_tdb && !winbindd_accountdb_init() ) {
896 DEBUG(0,("wb_delete_user: Failed to open winbindd account db\n"));
900 namekey = acct_userkey_byname( pw->pw_name );
902 /* lock the main entry first */
904 if ( tdb_lock_bystring(account_tdb, namekey, 0) == -1 ) {
905 DEBUG(0,("wb_delete_user: Failed to lock %s\n", namekey));
909 /* remove user from all groups */
911 tdb_traverse(account_tdb, cleangroups_traverse_fn, (void *)pw->pw_name);
913 /* remove the user */
914 uidkey = acct_userkey_byuid( pw->pw_uid );
916 tdb_delete_bystring( account_tdb, namekey );
917 tdb_delete_bystring( account_tdb, uidkey );
919 tdb_unlock_bystring( account_tdb, namekey );
924 /**********************************************************************
925 **********************************************************************/
927 static int isprimarygroup_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf,
928 TDB_DATA dbuf, void *params)
932 struct _check_primary_grp *check = (struct _check_primary_grp*)params;
934 fstr_sprintf( key, "%s/NAME", WBKEY_PASSWD );
937 /* if this is a group entry then, check the members */
939 if ( (strncmp(kbuf.dptr, key, len) == 0) && dbuf.dptr ) {
942 if ( !(pw = string2passwd( dbuf.dptr )) ) {
943 DEBUG(0,("isprimarygroup_traverse_fn: Failure to parse [%s]\n",
948 if ( check->gid == pw->pw_gid ) {
958 /**********************************************************************
959 **********************************************************************/
961 static BOOL wb_delete_group( WINBINDD_GR *grp )
963 struct _check_primary_grp check;
967 if ( !account_tdb && !winbindd_accountdb_init() ) {
968 DEBUG(0,("wb_delete_group: Failed to open winbindd account db\n"));
972 /* lock the main entry first */
974 namekey = acct_groupkey_byname( grp->gr_name );
975 if ( tdb_lock_bystring(account_tdb, namekey, 0) == -1 ) {
976 DEBUG(0,("wb_delete_group: Failed to lock %s\n", namekey));
980 /* is this group the primary group for any user? If
984 tdb_traverse(account_tdb, isprimarygroup_traverse_fn, (void *)&check);
987 DEBUG(4,("wb_delete_group: Cannot delete group (%s) since it "
988 "is the primary group for some users\n", grp->gr_name));
992 /* We're clear. Delete the group */
994 DEBUG(5,("wb_delete_group: Removing group (%s)\n", grp->gr_name));
996 gidkey = acct_groupkey_bygid( grp->gr_gid );
998 tdb_delete_bystring( account_tdb, namekey );
999 tdb_delete_bystring( account_tdb, gidkey );
1001 tdb_unlock_bystring( account_tdb, namekey );
1006 /**********************************************************************
1007 Create a new "UNIX" user for the system given a username
1008 **********************************************************************/
1010 enum winbindd_result winbindd_create_user(struct winbindd_cli_state *state)
1014 WINBINDD_PW pw, *pw_check;
1015 WINBINDD_GR *wb_grp;
1016 struct group *unix_grp;
1018 uint32 flags = state->request.flags;
1021 if ( !state->privileged ) {
1022 DEBUG(2, ("winbindd_create_user: non-privileged access denied!\n"));
1023 return WINBINDD_ERROR;
1026 /* Ensure null termination */
1027 state->request.data.acct_mgt.username[sizeof(state->request.data.acct_mgt.username)-1]='\0';
1028 state->request.data.acct_mgt.groupname[sizeof(state->request.data.acct_mgt.groupname)-1]='\0';
1030 user = state->request.data.acct_mgt.username;
1031 group = state->request.data.acct_mgt.groupname;
1033 DEBUG(3, ("[%5lu]: create_user: user=>(%s), group=>(%s)\n",
1034 (unsigned long)state->pid, user, group));
1036 if ( (pw_check=wb_getpwnam(user)) != NULL ) {
1037 DEBUG(0,("winbindd_create_user: Refusing to create user that already exists (%s)\n",
1039 return WINBINDD_ERROR;
1044 group = lp_template_primary_group();
1046 /* validate the primary group
1047 1) lookup in local tdb first
1048 2) call getgrnam() as a last resort */
1050 if ( (wb_grp=wb_getgrnam(group)) != NULL ) {
1051 primary_gid = wb_grp->gr_gid;
1052 free_winbindd_gr( wb_grp );
1054 else if ( (unix_grp=sys_getgrnam(group)) != NULL ) {
1055 primary_gid = unix_grp->gr_gid;
1058 DEBUG(2,("winbindd_create_user: Cannot validate gid for group (%s)\n", group));
1059 return WINBINDD_ERROR;
1064 if ( !NT_STATUS_IS_OK(idmap_allocate_id( &id, ID_USERID)) ) {
1065 DEBUG(0,("winbindd_create_user: idmap_allocate_id() failed!\n"));
1066 return WINBINDD_ERROR;
1069 /* The substitution of %U and %D in the 'template homedir' is done
1070 by lp_string() calling standard_sub_basic(). */
1072 fstrcpy( current_user_info.smb_name, user );
1073 sub_set_smb_name( user );
1074 fstrcpy( current_user_info.domain, get_global_sam_name() );
1076 /* fill in the passwd struct */
1078 fstrcpy( pw.pw_name, user );
1079 fstrcpy( pw.pw_passwd, "x" );
1080 fstrcpy( pw.pw_gecos, user);
1081 fstrcpy( pw.pw_dir, lp_template_homedir() );
1082 fstrcpy( pw.pw_shell, lp_template_shell() );
1085 pw.pw_gid = primary_gid;
1087 /* store the new entry */
1089 if ( !wb_storepwnam(&pw) )
1090 return WINBINDD_ERROR;
1092 /* do we need a new RID? */
1094 if ( flags & WBFLAG_ALLOCATE_RID ) {
1095 if ( !NT_STATUS_IS_OK(idmap_allocate_rid(&rid, USER_RID_TYPE)) ) {
1096 DEBUG(0,("winbindd_create_user: RID allocation failure! Cannot create user (%s)\n",
1098 wb_delete_user( &pw );
1100 return WINBINDD_ERROR;
1103 state->response.data.rid = rid;
1109 /**********************************************************************
1110 Create a new "UNIX" group for the system given a username
1111 **********************************************************************/
1113 enum winbindd_result winbindd_create_group(struct winbindd_cli_state *state)
1117 WINBINDD_GR grp, *grp_check;
1118 uint32 flags = state->request.flags;
1121 if ( !state->privileged ) {
1122 DEBUG(2, ("winbindd_create_group: non-privileged access denied!\n"));
1123 return WINBINDD_ERROR;
1126 /* Ensure null termination */
1127 state->request.data.acct_mgt.groupname[sizeof(state->request.data.acct_mgt.groupname)-1]='\0';
1128 group = state->request.data.acct_mgt.groupname;
1130 DEBUG(3, ("[%5lu]: create_group: (%s)\n", (unsigned long)state->pid, group));
1132 if ( (grp_check=wb_getgrnam(group)) != NULL ) {
1133 DEBUG(0,("winbindd_create_group: Refusing to create group that already exists (%s)\n",
1135 return WINBINDD_ERROR;
1140 if ( !NT_STATUS_IS_OK(idmap_allocate_id( &id, ID_GROUPID)) ) {
1141 DEBUG(0,("winbindd_create_group: idmap_allocate_id() failed!\n"));
1142 return WINBINDD_ERROR;
1145 /* fill in the group struct */
1147 fstrcpy( grp.gr_name, group );
1148 fstrcpy( grp.gr_passwd, "*" );
1150 grp.gr_gid = id.gid;
1151 grp.gr_mem = NULL; /* start with no members */
1154 if ( !wb_storegrnam(&grp) )
1155 return WINBINDD_ERROR;
1157 /* do we need a new RID? */
1159 if ( flags & WBFLAG_ALLOCATE_RID ) {
1160 if ( !NT_STATUS_IS_OK(idmap_allocate_rid(&rid, GROUP_RID_TYPE)) ) {
1161 DEBUG(0,("winbindd_create_group: RID allocation failure! Cannot create group (%s)\n",
1163 wb_delete_group( &grp );
1165 return WINBINDD_ERROR;
1168 state->response.data.rid = rid;
1174 /**********************************************************************
1175 Add a user to the membership for a group.
1176 **********************************************************************/
1178 enum winbindd_result winbindd_add_user_to_group(struct winbindd_cli_state *state)
1185 if ( !state->privileged ) {
1186 DEBUG(2, ("winbindd_add_user_to_group: non-privileged access denied!\n"));
1187 return WINBINDD_ERROR;
1190 /* Ensure null termination */
1191 state->request.data.acct_mgt.groupname[sizeof(state->request.data.acct_mgt.groupname)-1]='\0';
1192 state->request.data.acct_mgt.username[sizeof(state->request.data.acct_mgt.username)-1]='\0';
1193 group = state->request.data.acct_mgt.groupname;
1194 user = state->request.data.acct_mgt.username;
1196 DEBUG(3, ("[%5lu]: add_user_to_group: add %s to %s\n", (unsigned long)state->pid,
1199 /* make sure it is a valid user */
1201 if ( !(pw = wb_getpwnam( user )) ) {
1202 DEBUG(4,("winbindd_add_user_to_group: Cannot add a non-existent user\n"));
1203 return WINBINDD_ERROR;
1206 /* make sure it is a valid group */
1208 if ( !(grp = wb_getgrnam( group )) ) {
1209 DEBUG(4,("winbindd_add_user_to_group: Cannot add a user to a non-extistent group\n"));
1210 return WINBINDD_ERROR;
1213 if ( !wb_addgrpmember( grp, user ) )
1214 return WINBINDD_ERROR;
1216 ret = wb_storegrnam(grp);
1218 free_winbindd_gr( grp );
1220 return ( ret ? WINBINDD_OK : WINBINDD_ERROR );
1223 /**********************************************************************
1224 Remove a user from the membership of a group
1225 **********************************************************************/
1227 enum winbindd_result winbindd_remove_user_from_group(struct winbindd_cli_state *state)
1233 if ( !state->privileged ) {
1234 DEBUG(2, ("winbindd_remove_user_from_group: non-privileged access denied!\n"));
1235 return WINBINDD_ERROR;
1238 /* Ensure null termination */
1239 state->request.data.acct_mgt.groupname[sizeof(state->request.data.acct_mgt.groupname)-1]='\0';
1240 state->request.data.acct_mgt.username[sizeof(state->request.data.acct_mgt.username)-1]='\0';
1241 group = state->request.data.acct_mgt.groupname;
1242 user = state->request.data.acct_mgt.username;
1244 DEBUG(3, ("[%5lu]: remove_user_from_group: delete %s from %s\n", (unsigned long)state->pid,
1247 /* don't worry about checking the username since we're removing it anyways */
1249 /* make sure it is a valid group */
1251 if ( !(grp = wb_getgrnam( group )) ) {
1252 DEBUG(4,("winbindd_remove_user_from_group: Cannot remove a user from a non-extistent group\n"));
1253 return WINBINDD_ERROR;
1256 if ( !wb_delgrpmember( grp, user ) )
1257 return WINBINDD_ERROR;
1259 ret = wb_storegrnam(grp);
1261 free_winbindd_gr( grp );
1263 return ( ret ? WINBINDD_OK : WINBINDD_ERROR );
1266 /**********************************************************************
1267 Set the primary group membership of a user
1268 **********************************************************************/
1270 enum winbindd_result winbindd_set_user_primary_group(struct winbindd_cli_state *state)
1276 if ( !state->privileged ) {
1277 DEBUG(2, ("winbindd_set_user_primary_group: non-privileged access denied!\n"));
1278 return WINBINDD_ERROR;
1281 /* Ensure null termination */
1282 state->request.data.acct_mgt.groupname[sizeof(state->request.data.acct_mgt.groupname)-1]='\0';
1283 state->request.data.acct_mgt.username[sizeof(state->request.data.acct_mgt.username)-1]='\0';
1284 group = state->request.data.acct_mgt.groupname;
1285 user = state->request.data.acct_mgt.username;
1287 DEBUG(3, ("[%5lu]: set_user_primary_group: group %s for user %s\n",
1288 (unsigned long)state->pid, group, user));
1290 /* make sure it is a valid user */
1292 if ( !(pw = wb_getpwnam( user )) ) {
1293 DEBUG(4,("winbindd_add_user_to_group: Cannot add a non-existent user\n"));
1294 return WINBINDD_ERROR;
1297 /* make sure it is a valid group */
1299 if ( !(grp = wb_getgrnam( group )) ) {
1300 DEBUG(4,("winbindd_add_user_to_group: Cannot add a user to a non-extistent group\n"));
1301 return WINBINDD_ERROR;
1304 pw->pw_gid = grp->gr_gid;
1306 free_winbindd_gr( grp );
1308 return ( wb_storepwnam(pw) ? WINBINDD_OK : WINBINDD_ERROR );
1311 /**********************************************************************
1312 Delete a user from the winbindd account tdb.
1313 **********************************************************************/
1315 enum winbindd_result winbindd_delete_user(struct winbindd_cli_state *state)
1320 if ( !state->privileged ) {
1321 DEBUG(2, ("winbindd_delete_user: non-privileged access denied!\n"));
1322 return WINBINDD_ERROR;
1325 /* Ensure null termination */
1326 state->request.data.acct_mgt.username[sizeof(state->request.data.acct_mgt.username)-1]='\0';
1327 user = state->request.data.acct_mgt.username;
1329 DEBUG(3, ("[%5lu]: delete_user: %s\n", (unsigned long)state->pid, user));
1331 /* make sure it is a valid user */
1333 if ( !(pw = wb_getpwnam( user )) ) {
1334 DEBUG(4,("winbindd_delete_user: Cannot delete a non-existent user\n"));
1335 return WINBINDD_ERROR;
1338 return ( wb_delete_user(pw) ? WINBINDD_OK : WINBINDD_ERROR );
1341 /**********************************************************************
1342 Delete a group from winbindd's account tdb.
1343 **********************************************************************/
1345 enum winbindd_result winbindd_delete_group(struct winbindd_cli_state *state)
1351 if ( !state->privileged ) {
1352 DEBUG(2, ("winbindd_delete_group: non-privileged access denied!\n"));
1353 return WINBINDD_ERROR;
1356 /* Ensure null termination */
1357 state->request.data.acct_mgt.username[sizeof(state->request.data.acct_mgt.groupname)-1]='\0';
1358 group = state->request.data.acct_mgt.groupname;
1360 DEBUG(3, ("[%5lu]: delete_group: %s\n", (unsigned long)state->pid, group));
1362 /* make sure it is a valid group */
1364 if ( !(grp = wb_getgrnam( group )) ) {
1365 DEBUG(4,("winbindd_delete_group: Cannot delete a non-existent group\n"));
1366 return WINBINDD_ERROR;
1369 ret = wb_delete_group(grp);
1371 free_winbindd_gr( grp );
1373 return ( ret ? WINBINDD_OK : WINBINDD_ERROR );
1376 static void add_string_to_array(char *name, char ***names, int *num_names)
1378 *names = Realloc(*names, (*num_names + 1) * sizeof(char **));
1383 (*names)[*num_names] = name;
1387 /**********************************************************************
1388 List all group names locally defined
1389 **********************************************************************/
1391 void wb_list_group_names(char ***names, int *num_names)
1393 TDB_LIST_NODE *nodes, *node;
1395 if (!winbindd_accountdb_init())
1398 nodes = tdb_search_keys(account_tdb, acct_groupkey_byname("*"));
1402 while (node != NULL) {
1403 char *name = (char *)node->node_key.dptr;
1405 DEBUG(10, ("Found key %s\n", name));
1409 /* Skip WBA_GROUP */
1410 name = strchr(name, '/');
1416 name = strchr(name, '/');
1421 DEBUG(10, ("adding %s\n", name));
1423 add_string_to_array(strdup(name), names, num_names);
1426 tdb_search_list_free(nodes);