Remove some unused variables uncovered by the build farm.
[Samba/gebeck_regimport.git] / source3 / nsswitch / winbindd_acct.c
blob0c06df7fdd4670a434ec835c939a2bbdea08554f
1 /*
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.
23 #include "winbindd.h"
25 #undef DBGC_CLASS
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
34 /* Globals */
36 static TDB_CONTEXT *account_tdb;
38 extern userdom_struct current_user_info;
40 struct _check_primary_grp {
41 gid_t gid;
42 BOOL found;
45 /**********************************************************************
46 **********************************************************************/
48 static void free_winbindd_gr( WINBINDD_GR *grp )
50 int i;
52 if ( !grp )
53 return;
55 for ( i=0; i<grp->num_gr_mem; i++ )
56 SAFE_FREE( grp->gr_mem[i] );
58 SAFE_FREE( grp->gr_mem );
60 return;
63 /*****************************************************************************
64 Initialise auto-account database.
65 *****************************************************************************/
67 static BOOL winbindd_accountdb_init(void)
69 /* see if we've already opened the tdb */
71 if ( account_tdb )
72 return True;
74 /* winbindd_idmap.tdb should always be opened by the idmap_init()
75 code first */
77 if ( !(account_tdb = idmap_tdb_handle()) ) {
78 DEBUG(0, ("winbindd_accountdb_init: Unable to retreive handle for database\n"));
79 return False;
82 /* yeah! */
84 return True;
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;
94 char *p, *str;
95 char *fields[NUM_PW_FIELDS];
96 int i;
98 if ( !string )
99 return NULL;
101 ZERO_STRUCTP( &pw );
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"));
110 return NULL;
112 *p = '\0';
113 if ( str )
114 fields[i] = str;
115 str = p + 1;
117 if ( str )
118 fields[i] = str;
120 /* copy fields */
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));
136 return NULL;
139 DEBUG(10,("string2passwd: Success\n"));
141 return &pw;
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;
151 int ret;
153 if ( !pw || !pw->pw_name )
154 return NULL;
156 DEBUG(10,("passwd2string: converting passwd struct for %s\n",
157 pw->pw_name));
159 ret = pstr_sprintf( string, "%s:%s:%lu:%lu:%s:%s:%s",
160 pw->pw_name,
161 pw->pw_passwd ? pw->pw_passwd : "x",
162 (unsigned long)pw->pw_uid,
163 (unsigned long)pw->pw_gid,
164 pw->pw_gecos,
165 pw->pw_dir,
166 pw->pw_shell );
168 if ( ret < 0 ) {
169 DEBUG(0,("passwd2string: pstr_sprintf() failed!\n"));
170 return NULL;
173 return string;
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;
183 char *p, *str;
184 char *fields[NUM_GRP_FIELDS];
185 int i;
186 char **gr_members = NULL;
187 int num_gr_members = 0;
189 if ( !string )
190 return NULL;
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"));
201 return NULL;
203 *p = '\0';
204 if ( str )
205 fields[i] = str;
206 str = p + 1;
209 /* group members */
211 if ( *str ) {
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
217 are n+1 members */
218 if ( num_gr_members ) {
219 fstring buffer;
221 gr_members = (char**)smb_xmalloc(sizeof(char*)*num_gr_members+1);
223 i = 0;
224 while ( next_token(&str, buffer, ",", sizeof(buffer)) && i<num_gr_members ) {
225 gr_members[i++] = smb_xstrdup(buffer);
228 gr_members[i] = NULL;
233 /* copy fields */
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 );
247 return NULL;
250 DEBUG(10,("string2group: Success\n"));
252 return &grp;
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;
262 int ret;
263 char *member, *gr_mem_str;
264 int num_members;
265 int i, size;
267 if ( !grp || !grp->gr_name )
268 return NULL;
270 DEBUG(10,("group2string: converting passwd struct for %s\n",
271 grp->gr_name));
273 if ( grp->num_gr_mem ) {
274 int idx = 0;
276 member = grp->gr_mem[0];
277 size = 0;
278 num_members = 0;
280 while ( member ) {
281 size += strlen(member) + 1;
282 num_members++;
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';
295 else {
296 /* no members */
297 gr_mem_str = smb_xmalloc(sizeof(fstring));
298 fstrcpy( gr_mem_str, "" );
301 ret = pstr_sprintf( string, "%s:%s:%lu:%s",
302 grp->gr_name,
303 grp->gr_passwd ? grp->gr_passwd : "*",
304 (unsigned long)grp->gr_gid,
305 gr_mem_str );
307 SAFE_FREE( gr_mem_str );
309 if ( ret < 0 ) {
310 DEBUG(0,("group2string: pstr_sprintf() failed!\n"));
311 return NULL;
314 return string;
317 /**********************************************************************
318 **********************************************************************/
320 static char* acct_userkey_byname( const char *name )
322 static fstring key;
324 fstr_sprintf( key, "%s/NAME/%s", WBKEY_PASSWD, name );
326 return key;
329 /**********************************************************************
330 **********************************************************************/
332 static char* acct_userkey_byuid( uid_t uid )
334 static fstring key;
336 fstr_sprintf( key, "%s/UID/%lu", WBKEY_PASSWD, (unsigned long)uid );
338 return key;
341 /**********************************************************************
342 **********************************************************************/
344 static char* acct_groupkey_byname( const char *name )
346 static fstring key;
348 fstr_sprintf( key, "%s/NAME/%s", WBKEY_GROUP, name );
350 return key;
353 /**********************************************************************
354 **********************************************************************/
356 static char* acct_groupkey_bygid( gid_t gid )
358 static fstring key;
360 fstr_sprintf( key, "%s/GID/%lu", WBKEY_GROUP, (unsigned long)gid );
362 return key;
365 /**********************************************************************
366 **********************************************************************/
368 WINBINDD_PW* wb_getpwnam( const char * name )
370 char *keystr;
371 TDB_DATA data;
372 static WINBINDD_PW *pw;
374 if ( !account_tdb && !winbindd_accountdb_init() ) {
375 DEBUG(0,("wb_getpwnam: Failed to open winbindd account db\n"));
376 return NULL;
380 keystr = acct_userkey_byname( name );
382 data = tdb_fetch_bystring( account_tdb, keystr );
384 pw = NULL;
386 if ( data.dptr ) {
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 ));
394 return pw;
397 /**********************************************************************
398 **********************************************************************/
400 WINBINDD_PW* wb_getpwuid( const uid_t uid )
402 char *keystr;
403 TDB_DATA data;
404 static WINBINDD_PW *pw;
406 if ( !account_tdb && !winbindd_accountdb_init() ) {
407 DEBUG(0,("wb_getpwuid: Failed to open winbindd account db\n"));
408 return NULL;
411 data = tdb_fetch_bystring( account_tdb, acct_userkey_byuid(uid) );
412 if ( !data.dptr ) {
413 DEBUG(4,("wb_getpwuid: failed to locate uid == %lu\n", (unsigned long)uid));
414 return NULL;
416 keystr = acct_userkey_byname( data.dptr );
418 SAFE_FREE( data.dptr );
420 data = tdb_fetch_bystring( account_tdb, keystr );
422 pw = NULL;
424 if ( data.dptr ) {
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 ));
432 return pw;
435 /**********************************************************************
436 **********************************************************************/
438 BOOL wb_storepwnam( const WINBINDD_PW *pw )
440 char *namekey, *uidkey;
441 TDB_DATA data;
442 char *str;
443 int ret = 0;
444 fstring username;
446 if ( !account_tdb && !winbindd_accountdb_init() ) {
447 DEBUG(0,("wb_storepwnam: Failed to open winbindd account db\n"));
448 return False;
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));
457 return False;
460 str = passwd2string( pw );
462 data.dptr = str;
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));
467 ret = -1;
468 goto done;
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);
482 ret = -1;
483 goto done;
486 DEBUG(10,("wb_storepwnam: Success -> \"%s\"\n", str));
488 done:
489 tdb_unlock_bystring( account_tdb, namekey );
491 return ( ret == 0 );
494 /**********************************************************************
495 **********************************************************************/
497 WINBINDD_GR* wb_getgrnam( const char * name )
499 char *keystr;
500 TDB_DATA data;
501 static WINBINDD_GR *grp;
503 if ( !account_tdb && !winbindd_accountdb_init() ) {
504 DEBUG(0,("wb_getgrnam: Failed to open winbindd account db\n"));
505 return NULL;
509 keystr = acct_groupkey_byname( name );
511 data = tdb_fetch_bystring( account_tdb, keystr );
513 grp = NULL;
515 if ( data.dptr ) {
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 ));
523 return grp;
526 /**********************************************************************
527 **********************************************************************/
529 WINBINDD_GR* wb_getgrgid( gid_t gid )
531 char *keystr;
532 TDB_DATA data;
533 static WINBINDD_GR *grp;
535 if ( !account_tdb && !winbindd_accountdb_init() ) {
536 DEBUG(0,("wb_getgrgid: Failed to open winbindd account db\n"));
537 return NULL;
540 data = tdb_fetch_bystring( account_tdb, acct_groupkey_bygid(gid) );
541 if ( !data.dptr ) {
542 DEBUG(4,("wb_getgrgid: failed to locate gid == %lu\n",
543 (unsigned long)gid));
544 return NULL;
546 keystr = acct_groupkey_byname( data.dptr );
548 SAFE_FREE( data.dptr );
550 data = tdb_fetch_bystring( account_tdb, keystr );
552 grp = NULL;
554 if ( data.dptr ) {
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 ));
562 return grp;
565 /**********************************************************************
566 **********************************************************************/
568 BOOL wb_storegrnam( const WINBINDD_GR *grp )
570 char *namekey, *gidkey;
571 TDB_DATA data;
572 char *str;
573 int ret = 0;
574 fstring groupname;
576 if ( !account_tdb && !winbindd_accountdb_init() ) {
577 DEBUG(0,("wb_storepwnam: Failed to open winbindd account db\n"));
578 return False;
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));
587 return False;
590 str = group2string( grp );
592 data.dptr = str;
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));
597 ret = -1;
598 goto done;
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);
612 ret = -1;
613 goto done;
616 DEBUG(10,("wb_storegrnam: Success -> \"%s\"\n", str));
618 done:
619 tdb_unlock_bystring( account_tdb, namekey );
621 return ( ret == 0 );
624 /**********************************************************************
625 **********************************************************************/
627 static BOOL wb_addgrpmember( WINBINDD_GR *grp, const char *user )
629 int i;
630 char **members;
632 if ( !grp || !user )
633 return False;
635 for ( i=0; i<grp->num_gr_mem; i++ ) {
636 if ( StrCaseCmp( grp->gr_mem[i], user ) == 0 )
637 return True;
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*) );
642 if ( !members )
643 return False;
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;
649 return True;
652 /**********************************************************************
653 **********************************************************************/
655 static BOOL wb_delgrpmember( WINBINDD_GR *grp, const char *user )
657 int i;
658 BOOL found = False;
660 if ( !grp || !user )
661 return False;
663 for ( i=0; i<grp->num_gr_mem && !found; i++ ) {
664 if ( StrCaseCmp( grp->gr_mem[i], user ) == 0 )
665 found = True;
668 if ( !found )
669 return False;
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)) );
675 grp->num_gr_mem--;
677 else { /* last one */
678 free_winbindd_gr( grp );
679 grp->gr_mem = NULL;
680 grp->num_gr_mem = 0;
683 return True;
686 /**********************************************************************
687 **********************************************************************/
689 static int cleangroups_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf,
690 void *state)
692 int len;
693 fstring key;
694 char *name = (char*)state;
696 fstr_sprintf( key, "%s/NAME", WBKEY_GROUP );
697 len = strlen(key);
699 /* if this is a group entry then, check the members */
701 if ( (strncmp(kbuf.dptr, key, len) == 0) && dbuf.dptr ) {
702 WINBINDD_GR *grp;
704 if ( !(grp = string2group( dbuf.dptr )) ) {
705 DEBUG(0,("cleangroups_traverse_fn: Failure to parse [%s]\n",
706 dbuf.dptr));
707 return 0;
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 );
725 return 0;
728 /**********************************************************************
729 **********************************************************************/
731 static BOOL wb_delete_user( WINBINDD_PW *pw)
733 char *namekey;
734 char *uidkey;
736 if ( !account_tdb && !winbindd_accountdb_init() ) {
737 DEBUG(0,("wb_delete_user: Failed to open winbindd account db\n"));
738 return False;
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));
747 return False;
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 );
762 return True;
765 /**********************************************************************
766 **********************************************************************/
768 static int isprimarygroup_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf,
769 TDB_DATA dbuf, void *params)
771 int len;
772 fstring key;
773 struct _check_primary_grp *check = (struct _check_primary_grp*)params;
775 fstr_sprintf( key, "%s/NAME", WBKEY_PASSWD );
776 len = strlen(key);
778 /* if this is a group entry then, check the members */
780 if ( (strncmp(kbuf.dptr, key, len) == 0) && dbuf.dptr ) {
781 WINBINDD_PW *pw;;
783 if ( !(pw = string2passwd( dbuf.dptr )) ) {
784 DEBUG(0,("isprimarygroup_traverse_fn: Failure to parse [%s]\n",
785 dbuf.dptr));
786 return 0;
789 if ( check->gid == pw->pw_gid ) {
790 check->found = True;
791 return 1;
795 return 0;
799 /**********************************************************************
800 **********************************************************************/
802 static BOOL wb_delete_group( WINBINDD_GR *grp )
804 struct _check_primary_grp check;
805 char *namekey;
806 char *gidkey;
808 if ( !account_tdb && !winbindd_accountdb_init() ) {
809 DEBUG(0,("wb_delete_group: Failed to open winbindd account db\n"));
810 return False;
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));
818 return False;
821 /* is this group the primary group for any user? If
822 so deny delete */
824 check.found = False;
825 tdb_traverse(account_tdb, isprimarygroup_traverse_fn, (void *)&check);
827 if ( check.found ) {
828 DEBUG(4,("wb_delete_group: Cannot delete group (%s) since it "
829 "is the primary group for some users\n", grp->gr_name));
830 return False;
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 );
844 return True;
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)
853 char *user, *group;
854 unid_t id;
855 WINBINDD_PW pw;
856 WINBINDD_GR *wb_grp;
857 struct group *unix_grp;
858 gid_t primary_gid;
859 uint32 flags = state->request.flags;
860 uint32 rid;
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));
877 if ( !*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;
891 else {
892 DEBUG(2,("winbindd_create_user: Cannot validate gid for group (%s)\n", group));
893 return WINBINDD_ERROR;
896 /* get a new uid */
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() );
918 pw.pw_uid = id.uid;
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",
931 user));
932 wb_delete_user( &pw );
934 return WINBINDD_ERROR;
937 state->response.data.rid = rid;
940 return WINBINDD_OK;
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)
949 char *group;
950 unid_t id;
951 WINBINDD_GR grp;
952 uint32 flags = state->request.flags;
953 uint32 rid;
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));
966 /* get a new uid */
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, "*" );
978 grp.gr_gid = id.gid;
979 grp.gr_mem = NULL; /* start with no members */
980 grp.num_gr_mem = 0;
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",
990 group));
991 wb_delete_group( &grp );
993 return WINBINDD_ERROR;
996 state->response.data.rid = rid;
999 return WINBINDD_OK;
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)
1008 WINBINDD_PW *pw;
1009 WINBINDD_GR *grp;
1010 char *user, *group;
1011 BOOL ret;
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,
1025 user, group));
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)
1057 WINBINDD_GR *grp;
1058 char *user, *group;
1059 BOOL ret;
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,
1073 user, group));
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)
1100 WINBINDD_PW *pw;
1101 WINBINDD_GR *grp;
1102 char *user, *group;
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)
1145 WINBINDD_PW *pw;
1146 char *user;
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)
1175 WINBINDD_GR *grp;
1176 char *group;
1177 BOOL ret;
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 );