port latest changes from SAMBA_3_0 tree
[Samba/bb.git] / source / nsswitch / winbindd_acct.c
blob8abfd17110804a3ac024747227df214f4037669d
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 /* 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"));
83 return False;
87 /* yeah! */
89 return True;
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;
99 char *p, *str;
100 char *fields[NUM_PW_FIELDS];
101 int i;
103 if ( !string )
104 return NULL;
106 ZERO_STRUCTP( &pw );
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"));
115 return NULL;
117 *p = '\0';
118 if ( str )
119 fields[i] = str;
120 str = p + 1;
122 if ( str )
123 fields[i] = str;
125 /* copy fields */
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));
141 return NULL;
144 DEBUG(10,("string2passwd: Success\n"));
146 return &pw;
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;
156 int ret;
158 if ( !pw || !pw->pw_name )
159 return NULL;
161 DEBUG(10,("passwd2string: converting passwd struct for %s\n",
162 pw->pw_name));
164 ret = pstr_sprintf( string, "%s:%s:%lu:%lu:%s:%s:%s",
165 pw->pw_name,
166 pw->pw_passwd ? pw->pw_passwd : "x",
167 (unsigned long)pw->pw_uid,
168 (unsigned long)pw->pw_gid,
169 pw->pw_gecos,
170 pw->pw_dir,
171 pw->pw_shell );
173 if ( ret < 0 ) {
174 DEBUG(0,("passwd2string: pstr_sprintf() failed!\n"));
175 return NULL;
178 return string;
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;
188 char *p, *str;
189 char *fields[NUM_GRP_FIELDS];
190 int i;
191 char **gr_members = NULL;
192 int num_gr_members = 0;
194 if ( !string )
195 return NULL;
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"));
206 return NULL;
208 *p = '\0';
209 if ( str )
210 fields[i] = str;
211 str = p + 1;
214 /* group members */
216 if ( *str ) {
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
222 are n+1 members */
223 if ( num_gr_members ) {
224 fstring buffer;
226 gr_members = (char**)smb_xmalloc(sizeof(char*)*num_gr_members+1);
228 i = 0;
229 while ( next_token(&str, buffer, ",", sizeof(buffer)) && i<num_gr_members ) {
230 gr_members[i++] = smb_xstrdup(buffer);
233 gr_members[i] = NULL;
238 /* copy fields */
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 );
252 return NULL;
255 DEBUG(10,("string2group: Success\n"));
257 return &grp;
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;
267 int ret;
268 char *member, *gr_mem_str;
269 int num_members;
270 int i, size;
272 if ( !grp || !grp->gr_name )
273 return NULL;
275 DEBUG(10,("group2string: converting passwd struct for %s\n",
276 grp->gr_name));
278 if ( grp->num_gr_mem ) {
279 int idx = 0;
281 member = grp->gr_mem[0];
282 size = 0;
283 num_members = 0;
285 while ( member ) {
286 size += strlen(member) + 1;
287 num_members++;
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';
300 else {
301 /* no members */
302 gr_mem_str = smb_xmalloc(sizeof(fstring));
303 fstrcpy( gr_mem_str, "" );
306 ret = pstr_sprintf( string, "%s:%s:%lu:%s",
307 grp->gr_name,
308 grp->gr_passwd ? grp->gr_passwd : "*",
309 (unsigned long)grp->gr_gid,
310 gr_mem_str );
312 SAFE_FREE( gr_mem_str );
314 if ( ret < 0 ) {
315 DEBUG(0,("group2string: pstr_sprintf() failed!\n"));
316 return NULL;
319 return string;
322 /**********************************************************************
323 **********************************************************************/
325 static char* acct_userkey_byname( const char *name )
327 static fstring key;
329 fstr_sprintf( key, "%s/NAME/%s", WBKEY_PASSWD, name );
331 return key;
334 /**********************************************************************
335 **********************************************************************/
337 static char* acct_userkey_byuid( uid_t uid )
339 static fstring key;
341 fstr_sprintf( key, "%s/UID/%lu", WBKEY_PASSWD, (unsigned long)uid );
343 return key;
346 /**********************************************************************
347 **********************************************************************/
349 static char* acct_groupkey_byname( const char *name )
351 static fstring key;
353 fstr_sprintf( key, "%s/NAME/%s", WBKEY_GROUP, name );
355 return key;
358 /**********************************************************************
359 **********************************************************************/
361 static char* acct_groupkey_bygid( gid_t gid )
363 static fstring key;
365 fstr_sprintf( key, "%s/GID/%lu", WBKEY_GROUP, (unsigned long)gid );
367 return key;
370 /**********************************************************************
371 **********************************************************************/
373 WINBINDD_PW* wb_getpwnam( const char * name )
375 char *keystr;
376 TDB_DATA data;
377 static WINBINDD_PW *pw;
379 if ( !account_tdb && !winbindd_accountdb_init() ) {
380 DEBUG(0,("wb_getpwnam: Failed to open winbindd account db\n"));
381 return NULL;
385 keystr = acct_userkey_byname( name );
387 data = tdb_fetch_bystring( account_tdb, keystr );
389 pw = NULL;
391 if ( data.dptr ) {
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 ));
399 return pw;
402 /**********************************************************************
403 **********************************************************************/
405 WINBINDD_PW* wb_getpwuid( const uid_t uid )
407 char *keystr;
408 TDB_DATA data;
409 static WINBINDD_PW *pw;
411 if ( !account_tdb && !winbindd_accountdb_init() ) {
412 DEBUG(0,("wb_getpwuid: Failed to open winbindd account db\n"));
413 return NULL;
416 data = tdb_fetch_bystring( account_tdb, acct_userkey_byuid(uid) );
417 if ( !data.dptr ) {
418 DEBUG(4,("wb_getpwuid: failed to locate uid == %lu\n", (unsigned long)uid));
419 return NULL;
421 keystr = acct_userkey_byname( data.dptr );
423 SAFE_FREE( data.dptr );
425 data = tdb_fetch_bystring( account_tdb, keystr );
427 pw = NULL;
429 if ( data.dptr ) {
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 ));
437 return pw;
440 /**********************************************************************
441 **********************************************************************/
443 BOOL wb_storepwnam( const WINBINDD_PW *pw )
445 char *namekey, *uidkey;
446 TDB_DATA data;
447 char *str;
448 int ret = 0;
449 fstring username;
451 if ( !account_tdb && !winbindd_accountdb_init() ) {
452 DEBUG(0,("wb_storepwnam: Failed to open winbindd account db\n"));
453 return False;
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));
462 return False;
465 str = passwd2string( pw );
467 data.dptr = str;
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));
472 ret = -1;
473 goto done;
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);
487 ret = -1;
488 goto done;
491 DEBUG(10,("wb_storepwnam: Success -> \"%s\"\n", str));
493 done:
494 tdb_unlock_bystring( account_tdb, namekey );
496 return ( ret == 0 );
499 /**********************************************************************
500 **********************************************************************/
502 WINBINDD_GR* wb_getgrnam( const char * name )
504 char *keystr;
505 TDB_DATA data;
506 static WINBINDD_GR *grp;
508 if ( !account_tdb && !winbindd_accountdb_init() ) {
509 DEBUG(0,("wb_getgrnam: Failed to open winbindd account db\n"));
510 return NULL;
514 keystr = acct_groupkey_byname( name );
516 data = tdb_fetch_bystring( account_tdb, keystr );
518 grp = NULL;
520 if ( data.dptr ) {
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 ));
528 return grp;
531 /**********************************************************************
532 **********************************************************************/
534 WINBINDD_GR* wb_getgrgid( gid_t gid )
536 char *keystr;
537 TDB_DATA data;
538 static WINBINDD_GR *grp;
540 if ( !account_tdb && !winbindd_accountdb_init() ) {
541 DEBUG(0,("wb_getgrgid: Failed to open winbindd account db\n"));
542 return NULL;
545 data = tdb_fetch_bystring( account_tdb, acct_groupkey_bygid(gid) );
546 if ( !data.dptr ) {
547 DEBUG(4,("wb_getgrgid: failed to locate gid == %lu\n",
548 (unsigned long)gid));
549 return NULL;
551 keystr = acct_groupkey_byname( data.dptr );
553 SAFE_FREE( data.dptr );
555 data = tdb_fetch_bystring( account_tdb, keystr );
557 grp = NULL;
559 if ( data.dptr ) {
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 ));
567 return grp;
570 /**********************************************************************
571 **********************************************************************/
573 BOOL wb_storegrnam( const WINBINDD_GR *grp )
575 char *namekey, *gidkey;
576 TDB_DATA data;
577 char *str;
578 int ret = 0;
579 fstring groupname;
581 if ( !account_tdb && !winbindd_accountdb_init() ) {
582 DEBUG(0,("wb_storepwnam: Failed to open winbindd account db\n"));
583 return False;
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));
592 return False;
595 str = group2string( grp );
597 data.dptr = str;
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));
602 ret = -1;
603 goto done;
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);
617 ret = -1;
618 goto done;
621 DEBUG(10,("wb_storegrnam: Success -> \"%s\"\n", str));
623 done:
624 tdb_unlock_bystring( account_tdb, namekey );
626 return ( ret == 0 );
629 /**********************************************************************
630 **********************************************************************/
632 static BOOL wb_addgrpmember( WINBINDD_GR *grp, const char *user )
634 int i;
635 char **members;
637 if ( !grp || !user )
638 return False;
640 for ( i=0; i<grp->num_gr_mem; i++ ) {
641 if ( StrCaseCmp( grp->gr_mem[i], user ) == 0 )
642 return True;
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*) );
647 if ( !members )
648 return False;
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;
654 return True;
657 /**********************************************************************
658 **********************************************************************/
660 static BOOL wb_delgrpmember( WINBINDD_GR *grp, const char *user )
662 int i;
663 BOOL found = False;
665 if ( !grp || !user )
666 return False;
668 for ( i=0; i<grp->num_gr_mem && !found; i++ ) {
669 if ( StrCaseCmp( grp->gr_mem[i], user ) == 0 )
670 found = True;
673 if ( !found )
674 return False;
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)) );
680 grp->num_gr_mem--;
682 else { /* last one */
683 free_winbindd_gr( grp );
684 grp->gr_mem = NULL;
685 grp->num_gr_mem = 0;
688 return True;
691 /**********************************************************************
692 **********************************************************************/
694 static int cleangroups_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf,
695 void *state)
697 int len;
698 fstring key;
699 char *name = (char*)state;
701 fstr_sprintf( key, "%s/NAME", WBKEY_GROUP );
702 len = strlen(key);
704 /* if this is a group entry then, check the members */
706 if ( (strncmp(kbuf.dptr, key, len) == 0) && dbuf.dptr ) {
707 WINBINDD_GR *grp;
709 if ( !(grp = string2group( dbuf.dptr )) ) {
710 DEBUG(0,("cleangroups_traverse_fn: Failure to parse [%s]\n",
711 dbuf.dptr));
712 return 0;
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 );
730 return 0;
733 /**********************************************************************
734 **********************************************************************/
736 static BOOL wb_delete_user( WINBINDD_PW *pw)
738 char *namekey;
739 char *uidkey;
741 if ( !account_tdb && !winbindd_accountdb_init() ) {
742 DEBUG(0,("wb_delete_user: Failed to open winbindd account db\n"));
743 return False;
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));
752 return False;
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 );
767 return True;
770 /**********************************************************************
771 **********************************************************************/
773 static int isprimarygroup_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf,
774 TDB_DATA dbuf, void *params)
776 int len;
777 fstring key;
778 struct _check_primary_grp *check = (struct _check_primary_grp*)params;
780 fstr_sprintf( key, "%s/NAME", WBKEY_PASSWD );
781 len = strlen(key);
783 /* if this is a group entry then, check the members */
785 if ( (strncmp(kbuf.dptr, key, len) == 0) && dbuf.dptr ) {
786 WINBINDD_PW *pw;;
788 if ( !(pw = string2passwd( dbuf.dptr )) ) {
789 DEBUG(0,("isprimarygroup_traverse_fn: Failure to parse [%s]\n",
790 dbuf.dptr));
791 return 0;
794 if ( check->gid == pw->pw_gid ) {
795 check->found = True;
796 return 1;
800 return 0;
804 /**********************************************************************
805 **********************************************************************/
807 static BOOL wb_delete_group( WINBINDD_GR *grp )
809 struct _check_primary_grp check;
810 char *namekey;
811 char *gidkey;
813 if ( !account_tdb && !winbindd_accountdb_init() ) {
814 DEBUG(0,("wb_delete_group: Failed to open winbindd account db\n"));
815 return False;
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));
823 return False;
826 /* is this group the primary group for any user? If
827 so deny delete */
829 check.found = False;
830 tdb_traverse(account_tdb, isprimarygroup_traverse_fn, (void *)&check);
832 if ( check.found ) {
833 DEBUG(4,("wb_delete_group: Cannot delete group (%s) since it "
834 "is the primary group for some users\n", grp->gr_name));
835 return False;
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 );
849 return True;
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)
858 char *user, *group;
859 unid_t id;
860 WINBINDD_PW pw;
861 WINBINDD_GR *wb_grp;
862 struct group *unix_grp;
863 gid_t primary_gid;
864 uint32 flags = state->request.flags;
865 uint32 rid;
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));
882 if ( !*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;
896 else {
897 DEBUG(2,("winbindd_create_user: Cannot validate gid for group (%s)\n", group));
898 return WINBINDD_ERROR;
901 /* get a new uid */
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() );
923 pw.pw_uid = id.uid;
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",
936 user));
937 wb_delete_user( &pw );
939 return WINBINDD_ERROR;
942 state->response.data.rid = rid;
945 return WINBINDD_OK;
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)
954 char *group;
955 unid_t id;
956 WINBINDD_GR grp;
957 uint32 flags = state->request.flags;
958 uint32 rid;
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));
971 /* get a new uid */
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, "*" );
983 grp.gr_gid = id.gid;
984 grp.gr_mem = NULL; /* start with no members */
985 grp.num_gr_mem = 0;
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",
995 group));
996 wb_delete_group( &grp );
998 return WINBINDD_ERROR;
1001 state->response.data.rid = rid;
1004 return WINBINDD_OK;
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)
1013 WINBINDD_PW *pw;
1014 WINBINDD_GR *grp;
1015 char *user, *group;
1016 BOOL ret;
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,
1030 user, group));
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)
1062 WINBINDD_GR *grp;
1063 char *user, *group;
1064 BOOL ret;
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,
1078 user, group));
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)
1105 WINBINDD_PW *pw;
1106 WINBINDD_GR *grp;
1107 char *user, *group;
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)
1150 WINBINDD_PW *pw;
1151 char *user;
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)
1180 WINBINDD_GR *grp;
1181 char *group;
1182 BOOL ret;
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 );