r3780: final release notes
[Samba.git] / source / nsswitch / winbindd_acct.c
blobe6496695cb6aff283d87df22ee36aade7381f54e
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 "includes.h"
24 #include "winbindd.h"
26 #undef DBGC_CLASS
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
35 /* Globals */
37 static TDB_CONTEXT *account_tdb;
39 extern userdom_struct current_user_info;
41 struct _check_primary_grp {
42 gid_t gid;
43 BOOL found;
46 /**********************************************************************
47 **********************************************************************/
49 static void free_winbindd_gr( WINBINDD_GR *grp )
51 int i;
53 if ( !grp )
54 return;
56 for ( i=0; i<grp->num_gr_mem; i++ )
57 SAFE_FREE( grp->gr_mem[i] );
59 SAFE_FREE( grp->gr_mem );
61 return;
64 /*****************************************************************************
65 Initialise auto-account database.
66 *****************************************************************************/
68 static BOOL winbindd_accountdb_init(void)
70 /* see if we've already opened the tdb */
72 if ( account_tdb )
73 return True;
75 /* winbindd_idmap.tdb should always be opened by the idmap_init()
76 code first */
78 if ( !(account_tdb = idmap_tdb_handle()) ) {
79 DEBUG(0, ("winbindd_accountdb_init: Unable to retreive handle for database\n"));
80 return False;
83 /* yeah! */
85 return True;
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;
95 char *p, *str;
96 char *fields[NUM_PW_FIELDS];
97 int i;
99 if ( !string )
100 return NULL;
102 ZERO_STRUCTP( &pw );
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"));
111 return NULL;
113 *p = '\0';
114 if ( str )
115 fields[i] = str;
116 str = p + 1;
118 if ( str )
119 fields[i] = str;
121 /* copy fields */
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));
137 return NULL;
140 DEBUG(10,("string2passwd: Success\n"));
142 return &pw;
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;
152 int ret;
154 if ( !pw || !pw->pw_name )
155 return NULL;
157 DEBUG(10,("passwd2string: converting passwd struct for %s\n",
158 pw->pw_name));
160 ret = pstr_sprintf( string, "%s:%s:%lu:%lu:%s:%s:%s",
161 pw->pw_name,
162 pw->pw_passwd ? pw->pw_passwd : "x",
163 (unsigned long)pw->pw_uid,
164 (unsigned long)pw->pw_gid,
165 pw->pw_gecos,
166 pw->pw_dir,
167 pw->pw_shell );
169 if ( ret < 0 ) {
170 DEBUG(0,("passwd2string: pstr_sprintf() failed!\n"));
171 return NULL;
174 return string;
177 /**********************************************************************
178 Convert a string in /etc/group format to a struct group* entry
179 **********************************************************************/
181 static WINBINDD_GR* string2group( char *string )
183 static WINBINDD_GR grp;
184 char *p, *str;
185 char *fields[NUM_GRP_FIELDS];
186 int i;
187 char **gr_members = NULL;
188 int num_gr_members = 0;
190 if ( !string )
191 return NULL;
193 ZERO_STRUCTP( &grp );
195 DEBUG(10,("string2group: converting \"%s\"\n", string));
197 ZERO_STRUCT( fields );
199 for ( i=0, str=string; i<NUM_GRP_FIELDS-1; i++ ) {
200 if ( !(p = strchr( str, ':' )) ) {
201 DEBUG(0,("string2group: parsing failure\n"));
202 return NULL;
204 *p = '\0';
205 if ( str )
206 fields[i] = str;
207 str = p + 1;
210 /* group members */
212 if ( *str ) {
213 /* we already know we have a non-empty string */
215 num_gr_members = count_chars(str, ',') + 1;
217 /* if there was at least one comma, then there
218 are n+1 members */
219 if ( num_gr_members ) {
220 fstring buffer;
222 gr_members = (char**)smb_xmalloc(sizeof(char*)*(num_gr_members+1));
224 i = 0;
225 while ( next_token(&str, buffer, ",", sizeof(buffer)) && i<num_gr_members ) {
226 gr_members[i++] = smb_xstrdup(buffer);
229 gr_members[i] = NULL;
234 /* copy fields */
236 fstrcpy( grp.gr_name, fields[0] );
237 fstrcpy( grp.gr_passwd, fields[1] );
238 grp.gr_gid = atoi( fields[2] );
240 grp.num_gr_mem = num_gr_members;
241 grp.gr_mem = gr_members;
243 /* last minute sanity checks */
245 if ( grp.gr_gid == 0 ) {
246 DEBUG(0,("string2group: Failure! gid==%lu\n", (unsigned long)grp.gr_gid));
247 SAFE_FREE( gr_members );
248 return NULL;
251 DEBUG(10,("string2group: Success\n"));
253 return &grp;
256 /**********************************************************************
257 Convert a struct group* to a string formatted for /etc/group
258 **********************************************************************/
260 static char* group2string( const WINBINDD_GR *grp )
262 static pstring string;
263 int ret;
264 char *member, *gr_mem_str;
265 int num_members;
266 int i, size;
268 if ( !grp || !grp->gr_name )
269 return NULL;
271 DEBUG(10,("group2string: converting passwd struct for %s\n",
272 grp->gr_name));
274 if ( grp->num_gr_mem ) {
275 int idx = 0;
277 member = grp->gr_mem[0];
278 size = 0;
279 num_members = 0;
281 while ( member ) {
282 size += strlen(member) + 1;
283 num_members++;
284 member = grp->gr_mem[num_members];
287 gr_mem_str = smb_xmalloc(size);
289 for ( i=0; i<num_members; i++ ) {
290 snprintf( &gr_mem_str[idx], size-idx, "%s,", grp->gr_mem[i] );
291 idx += strlen(grp->gr_mem[i]) + 1;
293 /* add trailing NULL (also removes trailing ',' */
294 gr_mem_str[size-1] = '\0';
296 else {
297 /* no members */
298 gr_mem_str = smb_xmalloc(sizeof(fstring));
299 fstrcpy( gr_mem_str, "" );
302 ret = pstr_sprintf( string, "%s:%s:%lu:%s",
303 grp->gr_name,
304 grp->gr_passwd ? grp->gr_passwd : "*",
305 (unsigned long)grp->gr_gid,
306 gr_mem_str );
308 SAFE_FREE( gr_mem_str );
310 if ( ret < 0 ) {
311 DEBUG(0,("group2string: pstr_sprintf() failed!\n"));
312 return NULL;
315 return string;
318 /**********************************************************************
319 **********************************************************************/
321 static char* acct_userkey_byname( const char *name )
323 static fstring key;
325 fstr_sprintf( key, "%s/NAME/%s", WBKEY_PASSWD, name );
327 return key;
330 /**********************************************************************
331 **********************************************************************/
333 static char* acct_userkey_byuid( uid_t uid )
335 static fstring key;
337 fstr_sprintf( key, "%s/UID/%lu", WBKEY_PASSWD, (unsigned long)uid );
339 return key;
342 /**********************************************************************
343 **********************************************************************/
345 static char* acct_groupkey_byname( const char *name )
347 static fstring key;
349 fstr_sprintf( key, "%s/NAME/%s", WBKEY_GROUP, name );
351 return key;
354 /**********************************************************************
355 **********************************************************************/
357 static char* acct_groupkey_bygid( gid_t gid )
359 static fstring key;
361 fstr_sprintf( key, "%s/GID/%lu", WBKEY_GROUP, (unsigned long)gid );
363 return key;
366 /**********************************************************************
367 **********************************************************************/
369 WINBINDD_PW* wb_getpwnam( const char * name )
371 char *keystr;
372 TDB_DATA data;
373 static WINBINDD_PW *pw;
375 if ( !account_tdb && !winbindd_accountdb_init() ) {
376 DEBUG(0,("wb_getpwnam: Failed to open winbindd account db\n"));
377 return NULL;
381 keystr = acct_userkey_byname( name );
383 data = tdb_fetch_bystring( account_tdb, keystr );
385 pw = NULL;
387 if ( data.dptr ) {
388 pw = string2passwd( data.dptr );
389 SAFE_FREE( data.dptr );
392 DEBUG(5,("wb_getpwnam: %s user (%s)\n",
393 (pw ? "Found" : "Did not find"), name ));
395 return pw;
398 /**********************************************************************
399 **********************************************************************/
401 WINBINDD_PW* wb_getpwuid( const uid_t uid )
403 char *keystr;
404 TDB_DATA data;
405 static WINBINDD_PW *pw;
407 if ( !account_tdb && !winbindd_accountdb_init() ) {
408 DEBUG(0,("wb_getpwuid: Failed to open winbindd account db\n"));
409 return NULL;
412 data = tdb_fetch_bystring( account_tdb, acct_userkey_byuid(uid) );
413 if ( !data.dptr ) {
414 DEBUG(4,("wb_getpwuid: failed to locate uid == %lu\n", (unsigned long)uid));
415 return NULL;
417 keystr = acct_userkey_byname( data.dptr );
419 SAFE_FREE( data.dptr );
421 data = tdb_fetch_bystring( account_tdb, keystr );
423 pw = NULL;
425 if ( data.dptr ) {
426 pw = string2passwd( data.dptr );
427 SAFE_FREE( data.dptr );
430 DEBUG(5,("wb_getpwuid: %s user (uid == %lu)\n",
431 (pw ? "Found" : "Did not find"), (unsigned long)uid ));
433 return pw;
436 /**********************************************************************
437 **********************************************************************/
439 static BOOL wb_storepwnam( const WINBINDD_PW *pw )
441 char *namekey, *uidkey;
442 TDB_DATA data;
443 char *str;
444 int ret = 0;
445 fstring username;
447 if ( !account_tdb && !winbindd_accountdb_init() ) {
448 DEBUG(0,("wb_storepwnam: Failed to open winbindd account db\n"));
449 return False;
452 namekey = acct_userkey_byname( pw->pw_name );
454 /* lock the main entry first */
456 if ( tdb_lock_bystring(account_tdb, namekey, 0) == -1 ) {
457 DEBUG(0,("wb_storepwnam: Failed to lock %s\n", namekey));
458 return False;
461 str = passwd2string( pw );
463 data.dptr = str;
464 data.dsize = strlen(str) + 1;
466 if ( (tdb_store_bystring(account_tdb, namekey, data, TDB_REPLACE)) == -1 ) {
467 DEBUG(0,("wb_storepwnam: Failed to store \"%s\"\n", str));
468 ret = -1;
469 goto done;
472 /* store the uid index */
474 uidkey = acct_userkey_byuid(pw->pw_uid);
476 fstrcpy( username, pw->pw_name );
477 data.dptr = username;
478 data.dsize = strlen(username) + 1;
480 if ( (tdb_store_bystring(account_tdb, uidkey, data, TDB_REPLACE)) == -1 ) {
481 DEBUG(0,("wb_storepwnam: Failed to store uid key \"%s\"\n", str));
482 tdb_delete_bystring(account_tdb, namekey);
483 ret = -1;
484 goto done;
487 DEBUG(10,("wb_storepwnam: Success -> \"%s\"\n", str));
489 done:
490 tdb_unlock_bystring( account_tdb, namekey );
492 return ( ret == 0 );
495 /**********************************************************************
496 **********************************************************************/
498 WINBINDD_GR* wb_getgrnam( const char * name )
500 char *keystr;
501 TDB_DATA data;
502 static WINBINDD_GR *grp;
504 if ( !account_tdb && !winbindd_accountdb_init() ) {
505 DEBUG(0,("wb_getgrnam: Failed to open winbindd account db\n"));
506 return NULL;
510 keystr = acct_groupkey_byname( name );
512 data = tdb_fetch_bystring( account_tdb, keystr );
514 grp = NULL;
516 if ( data.dptr ) {
517 grp = string2group( data.dptr );
518 SAFE_FREE( data.dptr );
521 DEBUG(5,("wb_getgrnam: %s group (%s)\n",
522 (grp ? "Found" : "Did not find"), name ));
524 return grp;
527 /**********************************************************************
528 **********************************************************************/
530 WINBINDD_GR* wb_getgrgid( gid_t gid )
532 char *keystr;
533 TDB_DATA data;
534 static WINBINDD_GR *grp;
536 if ( !account_tdb && !winbindd_accountdb_init() ) {
537 DEBUG(0,("wb_getgrgid: Failed to open winbindd account db\n"));
538 return NULL;
541 data = tdb_fetch_bystring( account_tdb, acct_groupkey_bygid(gid) );
542 if ( !data.dptr ) {
543 DEBUG(4,("wb_getgrgid: failed to locate gid == %lu\n",
544 (unsigned long)gid));
545 return NULL;
547 keystr = acct_groupkey_byname( data.dptr );
549 SAFE_FREE( data.dptr );
551 data = tdb_fetch_bystring( account_tdb, keystr );
553 grp = NULL;
555 if ( data.dptr ) {
556 grp = string2group( data.dptr );
557 SAFE_FREE( data.dptr );
560 DEBUG(5,("wb_getgrgid: %s group (gid == %lu)\n",
561 (grp ? "Found" : "Did not find"), (unsigned long)gid ));
563 return grp;
566 /**********************************************************************
567 **********************************************************************/
569 static BOOL wb_storegrnam( const WINBINDD_GR *grp )
571 char *namekey, *gidkey;
572 TDB_DATA data;
573 char *str;
574 int ret = 0;
575 fstring groupname;
577 if ( !account_tdb && !winbindd_accountdb_init() ) {
578 DEBUG(0,("wb_storepwnam: Failed to open winbindd account db\n"));
579 return False;
582 namekey = acct_groupkey_byname( grp->gr_name );
584 /* lock the main entry first */
586 if ( tdb_lock_bystring(account_tdb, namekey, 0) == -1 ) {
587 DEBUG(0,("wb_storegrnam: Failed to lock %s\n", namekey));
588 return False;
591 str = group2string( grp );
593 data.dptr = str;
594 data.dsize = strlen(str) + 1;
596 if ( (tdb_store_bystring(account_tdb, namekey, data, TDB_REPLACE)) == -1 ) {
597 DEBUG(0,("wb_storegrnam: Failed to store \"%s\"\n", str));
598 ret = -1;
599 goto done;
602 /* store the gid index */
604 gidkey = acct_groupkey_bygid(grp->gr_gid);
606 fstrcpy( groupname, grp->gr_name );
607 data.dptr = groupname;
608 data.dsize = strlen(groupname) + 1;
610 if ( (tdb_store_bystring(account_tdb, gidkey, data, TDB_REPLACE)) == -1 ) {
611 DEBUG(0,("wb_storegrnam: Failed to store gid key \"%s\"\n", str));
612 tdb_delete_bystring(account_tdb, namekey);
613 ret = -1;
614 goto done;
617 DEBUG(10,("wb_storegrnam: Success -> \"%s\"\n", str));
619 done:
620 tdb_unlock_bystring( account_tdb, namekey );
622 return ( ret == 0 );
625 /**********************************************************************
626 **********************************************************************/
628 static BOOL wb_addgrpmember( WINBINDD_GR *grp, const char *user )
630 int i;
631 char **members;
633 if ( !grp || !user )
634 return False;
636 for ( i=0; i<grp->num_gr_mem; i++ ) {
637 if ( StrCaseCmp( grp->gr_mem[i], user ) == 0 )
638 return True;
641 /* add one new slot and keep an extra for the terminating NULL */
642 members = Realloc( grp->gr_mem, (grp->num_gr_mem+2)*sizeof(char*) );
643 if ( !members )
644 return False;
646 grp->gr_mem = members;
647 grp->gr_mem[grp->num_gr_mem++] = smb_xstrdup(user);
648 grp->gr_mem[grp->num_gr_mem] = NULL;
650 return True;
653 /**********************************************************************
654 **********************************************************************/
656 static BOOL wb_delgrpmember( WINBINDD_GR *grp, const char *user )
658 int i;
659 BOOL found = False;
661 if ( !grp || !user )
662 return False;
664 for ( i=0; i<grp->num_gr_mem; i++ ) {
665 if ( StrCaseCmp( grp->gr_mem[i], user ) == 0 ) {
666 found = True;
667 break;
671 if ( !found )
672 return False;
674 /* still some remaining members */
676 if ( grp->num_gr_mem > 1 ) {
677 SAFE_FREE(grp->gr_mem[i]);
678 grp->num_gr_mem--;
679 grp->gr_mem[i] = grp->gr_mem[grp->num_gr_mem];
680 grp->gr_mem[grp->num_gr_mem] = NULL;
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, *pw_check;
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 ( (pw_check=wb_getpwnam(user)) != NULL ) {
883 DEBUG(0,("winbindd_create_user: Refusing to create user that already exists (%s)\n",
884 user));
885 return WINBINDD_ERROR;
889 if ( !*group )
890 group = lp_template_primary_group();
892 /* validate the primary group
893 1) lookup in local tdb first
894 2) call getgrnam() as a last resort */
896 if ( (wb_grp=wb_getgrnam(group)) != NULL ) {
897 primary_gid = wb_grp->gr_gid;
898 free_winbindd_gr( wb_grp );
900 else if ( (unix_grp=sys_getgrnam(group)) != NULL ) {
901 primary_gid = unix_grp->gr_gid;
903 else {
904 DEBUG(2,("winbindd_create_user: Cannot validate gid for group (%s)\n", group));
905 return WINBINDD_ERROR;
908 /* get a new uid */
910 if ( !NT_STATUS_IS_OK(idmap_allocate_id( &id, ID_USERID)) ) {
911 DEBUG(0,("winbindd_create_user: idmap_allocate_id() failed!\n"));
912 return WINBINDD_ERROR;
915 /* The substitution of %U and %D in the 'template homedir' is done
916 by lp_string() calling standard_sub_basic(). */
918 fstrcpy( current_user_info.smb_name, user );
919 sub_set_smb_name( user );
920 fstrcpy( current_user_info.domain, get_global_sam_name() );
922 /* fill in the passwd struct */
924 fstrcpy( pw.pw_name, user );
925 fstrcpy( pw.pw_passwd, "x" );
926 fstrcpy( pw.pw_gecos, user);
927 fstrcpy( pw.pw_dir, lp_template_homedir() );
928 fstrcpy( pw.pw_shell, lp_template_shell() );
930 pw.pw_uid = id.uid;
931 pw.pw_gid = primary_gid;
933 /* store the new entry */
935 if ( !wb_storepwnam(&pw) )
936 return WINBINDD_ERROR;
938 /* do we need a new RID? */
940 if ( flags & WBFLAG_ALLOCATE_RID ) {
941 if ( !NT_STATUS_IS_OK(idmap_allocate_rid(&rid, USER_RID_TYPE)) ) {
942 DEBUG(0,("winbindd_create_user: RID allocation failure! Cannot create user (%s)\n",
943 user));
944 wb_delete_user( &pw );
946 return WINBINDD_ERROR;
949 state->response.data.rid = rid;
952 return WINBINDD_OK;
955 /**********************************************************************
956 Create a new "UNIX" group for the system given a username
957 **********************************************************************/
959 enum winbindd_result winbindd_create_group(struct winbindd_cli_state *state)
961 char *group;
962 unid_t id;
963 WINBINDD_GR grp, *grp_check;
964 uint32 flags = state->request.flags;
965 uint32 rid;
967 if ( !state->privileged ) {
968 DEBUG(2, ("winbindd_create_group: non-privileged access denied!\n"));
969 return WINBINDD_ERROR;
972 /* Ensure null termination */
973 state->request.data.acct_mgt.groupname[sizeof(state->request.data.acct_mgt.groupname)-1]='\0';
974 group = state->request.data.acct_mgt.groupname;
976 DEBUG(3, ("[%5lu]: create_group: (%s)\n", (unsigned long)state->pid, group));
978 if ( (grp_check=wb_getgrnam(group)) != NULL ) {
979 DEBUG(0,("winbindd_create_group: Refusing to create group that already exists (%s)\n",
980 group));
981 return WINBINDD_ERROR;
984 /* get a new gid */
986 if ( !NT_STATUS_IS_OK(idmap_allocate_id( &id, ID_GROUPID)) ) {
987 DEBUG(0,("winbindd_create_group: idmap_allocate_id() failed!\n"));
988 return WINBINDD_ERROR;
991 /* fill in the group struct */
993 fstrcpy( grp.gr_name, group );
994 fstrcpy( grp.gr_passwd, "*" );
996 grp.gr_gid = id.gid;
997 grp.gr_mem = NULL; /* start with no members */
998 grp.num_gr_mem = 0;
1000 if ( !wb_storegrnam(&grp) )
1001 return WINBINDD_ERROR;
1003 /* do we need a new RID? */
1005 if ( flags & WBFLAG_ALLOCATE_RID ) {
1006 if ( !NT_STATUS_IS_OK(idmap_allocate_rid(&rid, GROUP_RID_TYPE)) ) {
1007 DEBUG(0,("winbindd_create_group: RID allocation failure! Cannot create group (%s)\n",
1008 group));
1009 wb_delete_group( &grp );
1011 return WINBINDD_ERROR;
1014 state->response.data.rid = rid;
1017 return WINBINDD_OK;
1020 /**********************************************************************
1021 Add a user to the membership for a group.
1022 **********************************************************************/
1024 enum winbindd_result winbindd_add_user_to_group(struct winbindd_cli_state *state)
1026 WINBINDD_PW *pw;
1027 WINBINDD_GR *grp;
1028 char *user, *group;
1029 BOOL ret;
1031 if ( !state->privileged ) {
1032 DEBUG(2, ("winbindd_add_user_to_group: non-privileged access denied!\n"));
1033 return WINBINDD_ERROR;
1036 /* Ensure null termination */
1037 state->request.data.acct_mgt.groupname[sizeof(state->request.data.acct_mgt.groupname)-1]='\0';
1038 state->request.data.acct_mgt.username[sizeof(state->request.data.acct_mgt.username)-1]='\0';
1039 group = state->request.data.acct_mgt.groupname;
1040 user = state->request.data.acct_mgt.username;
1042 DEBUG(3, ("[%5lu]: add_user_to_group: add %s to %s\n", (unsigned long)state->pid,
1043 user, group));
1045 /* make sure it is a valid user */
1047 if ( !(pw = wb_getpwnam( user )) ) {
1048 DEBUG(4,("winbindd_add_user_to_group: Cannot add a non-existent user\n"));
1049 return WINBINDD_ERROR;
1052 /* make sure it is a valid group */
1054 if ( !(grp = wb_getgrnam( group )) ) {
1055 DEBUG(4,("winbindd_add_user_to_group: Cannot add a user to a non-extistent group\n"));
1056 return WINBINDD_ERROR;
1059 if ( !wb_addgrpmember( grp, user ) )
1060 return WINBINDD_ERROR;
1062 ret = wb_storegrnam(grp);
1064 free_winbindd_gr( grp );
1066 return ( ret ? WINBINDD_OK : WINBINDD_ERROR );
1069 /**********************************************************************
1070 Remove a user from the membership of a group
1071 **********************************************************************/
1073 enum winbindd_result winbindd_remove_user_from_group(struct winbindd_cli_state *state)
1075 WINBINDD_GR *grp;
1076 char *user, *group;
1077 BOOL ret;
1079 if ( !state->privileged ) {
1080 DEBUG(2, ("winbindd_remove_user_from_group: non-privileged access denied!\n"));
1081 return WINBINDD_ERROR;
1084 /* Ensure null termination */
1085 state->request.data.acct_mgt.groupname[sizeof(state->request.data.acct_mgt.groupname)-1]='\0';
1086 state->request.data.acct_mgt.username[sizeof(state->request.data.acct_mgt.username)-1]='\0';
1087 group = state->request.data.acct_mgt.groupname;
1088 user = state->request.data.acct_mgt.username;
1090 DEBUG(3, ("[%5lu]: remove_user_from_group: delete %s from %s\n", (unsigned long)state->pid,
1091 user, group));
1093 /* don't worry about checking the username since we're removing it anyways */
1095 /* make sure it is a valid group */
1097 if ( !(grp = wb_getgrnam( group )) ) {
1098 DEBUG(4,("winbindd_remove_user_from_group: Cannot remove a user from a non-extistent group\n"));
1099 return WINBINDD_ERROR;
1102 if ( !wb_delgrpmember( grp, user ) )
1103 return WINBINDD_ERROR;
1105 ret = wb_storegrnam(grp);
1107 free_winbindd_gr( grp );
1109 return ( ret ? WINBINDD_OK : WINBINDD_ERROR );
1112 /**********************************************************************
1113 Set the primary group membership of a user
1114 **********************************************************************/
1116 enum winbindd_result winbindd_set_user_primary_group(struct winbindd_cli_state *state)
1118 WINBINDD_PW *pw;
1119 WINBINDD_GR *grp;
1120 char *user, *group;
1122 if ( !state->privileged ) {
1123 DEBUG(2, ("winbindd_set_user_primary_group: non-privileged access denied!\n"));
1124 return WINBINDD_ERROR;
1127 /* Ensure null termination */
1128 state->request.data.acct_mgt.groupname[sizeof(state->request.data.acct_mgt.groupname)-1]='\0';
1129 state->request.data.acct_mgt.username[sizeof(state->request.data.acct_mgt.username)-1]='\0';
1130 group = state->request.data.acct_mgt.groupname;
1131 user = state->request.data.acct_mgt.username;
1133 DEBUG(3, ("[%5lu]: set_user_primary_group: group %s for user %s\n",
1134 (unsigned long)state->pid, group, user));
1136 /* make sure it is a valid user */
1138 if ( !(pw = wb_getpwnam( user )) ) {
1139 DEBUG(4,("winbindd_add_user_to_group: Cannot add a non-existent user\n"));
1140 return WINBINDD_ERROR;
1143 /* make sure it is a valid group */
1145 if ( !(grp = wb_getgrnam( group )) ) {
1146 DEBUG(4,("winbindd_add_user_to_group: Cannot add a user to a non-extistent group\n"));
1147 return WINBINDD_ERROR;
1150 pw->pw_gid = grp->gr_gid;
1152 free_winbindd_gr( grp );
1154 return ( wb_storepwnam(pw) ? WINBINDD_OK : WINBINDD_ERROR );
1157 /**********************************************************************
1158 Delete a user from the winbindd account tdb.
1159 **********************************************************************/
1161 enum winbindd_result winbindd_delete_user(struct winbindd_cli_state *state)
1163 WINBINDD_PW *pw;
1164 char *user;
1166 if ( !state->privileged ) {
1167 DEBUG(2, ("winbindd_delete_user: non-privileged access denied!\n"));
1168 return WINBINDD_ERROR;
1171 /* Ensure null termination */
1172 state->request.data.acct_mgt.username[sizeof(state->request.data.acct_mgt.username)-1]='\0';
1173 user = state->request.data.acct_mgt.username;
1175 DEBUG(3, ("[%5lu]: delete_user: %s\n", (unsigned long)state->pid, user));
1177 /* make sure it is a valid user */
1179 if ( !(pw = wb_getpwnam( user )) ) {
1180 DEBUG(4,("winbindd_delete_user: Cannot delete a non-existent user\n"));
1181 return WINBINDD_ERROR;
1184 return ( wb_delete_user(pw) ? WINBINDD_OK : WINBINDD_ERROR );
1187 /**********************************************************************
1188 Delete a group from winbindd's account tdb.
1189 **********************************************************************/
1191 enum winbindd_result winbindd_delete_group(struct winbindd_cli_state *state)
1193 WINBINDD_GR *grp;
1194 char *group;
1195 BOOL ret;
1197 if ( !state->privileged ) {
1198 DEBUG(2, ("winbindd_delete_group: non-privileged access denied!\n"));
1199 return WINBINDD_ERROR;
1202 /* Ensure null termination */
1203 state->request.data.acct_mgt.username[sizeof(state->request.data.acct_mgt.groupname)-1]='\0';
1204 group = state->request.data.acct_mgt.groupname;
1206 DEBUG(3, ("[%5lu]: delete_group: %s\n", (unsigned long)state->pid, group));
1208 /* make sure it is a valid group */
1210 if ( !(grp = wb_getgrnam( group )) ) {
1211 DEBUG(4,("winbindd_delete_group: Cannot delete a non-existent group\n"));
1212 return WINBINDD_ERROR;
1215 ret = wb_delete_group(grp);
1217 free_winbindd_gr( grp );
1219 return ( ret ? WINBINDD_OK : WINBINDD_ERROR );