import HEAD into svn+ssh://svn.samba.org/home/svn/samba/trunk
[metze/old/v3-2-winbind-ndr.git] / source / groupdb / mapping.c
1 /* 
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Jean François Micouleau      1998-2001.
6  *  
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2 of the License, or
10  *  (at your option) any later version.
11  *  
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *  
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, write to the Free Software
19  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21
22 #include "includes.h"
23
24 static TDB_CONTEXT *tdb; /* used for driver files */
25
26 #define DATABASE_VERSION_V1 1 /* native byte format. */
27 #define DATABASE_VERSION_V2 2 /* le format. */
28
29 #define GROUP_PREFIX "UNIXGROUP/"
30
31 /* Alias memberships are stored reverse, as memberships. The performance
32  * critical operation is to determine the aliases a SID is member of, not
33  * listing alias members. So we store a list of alias SIDs a SID is member of
34  * hanging of the member as key.
35  */
36 #define MEMBEROF_PREFIX "MEMBEROF/"
37
38 /****************************************************************************
39 dump the mapping group mapping to a text file
40 ****************************************************************************/
41 char *decode_sid_name_use(fstring group, enum SID_NAME_USE name_use)
42 {       
43         static fstring group_type;
44
45         switch(name_use) {
46                 case SID_NAME_USER:
47                         fstrcpy(group_type,"User");
48                         break;
49                 case SID_NAME_DOM_GRP:
50                         fstrcpy(group_type,"Domain group");
51                         break;
52                 case SID_NAME_DOMAIN:
53                         fstrcpy(group_type,"Domain");
54                         break;
55                 case SID_NAME_ALIAS:
56                         fstrcpy(group_type,"Local group");
57                         break;
58                 case SID_NAME_WKN_GRP:
59                         fstrcpy(group_type,"Builtin group");
60                         break;
61                 case SID_NAME_DELETED:
62                         fstrcpy(group_type,"Deleted");
63                         break;
64                 case SID_NAME_INVALID:
65                         fstrcpy(group_type,"Invalid");
66                         break;
67                 case SID_NAME_UNKNOWN:
68                 default:
69                         fstrcpy(group_type,"Unknown type");
70                         break;
71         }
72         
73         fstrcpy(group, group_type);
74         return group_type;
75 }
76
77 /****************************************************************************
78 initialise first time the mapping list - called from init_group_mapping()
79 ****************************************************************************/
80 static BOOL default_group_mapping(void)
81 {
82         DOM_SID sid_admins;
83         DOM_SID sid_users;
84         DOM_SID sid_guests;
85         fstring str_admins;
86         fstring str_users;
87         fstring str_guests;
88
89         /* Add the Wellknown groups */
90
91         add_initial_entry(-1, "S-1-5-32-544", SID_NAME_WKN_GRP, "Administrators", "");
92         add_initial_entry(-1, "S-1-5-32-545", SID_NAME_WKN_GRP, "Users", "");
93         add_initial_entry(-1, "S-1-5-32-546", SID_NAME_WKN_GRP, "Guests", "");
94         add_initial_entry(-1, "S-1-5-32-547", SID_NAME_WKN_GRP, "Power Users", "");
95         add_initial_entry(-1, "S-1-5-32-548", SID_NAME_WKN_GRP, "Account Operators", "");
96         add_initial_entry(-1, "S-1-5-32-549", SID_NAME_WKN_GRP, "System Operators", "");
97         add_initial_entry(-1, "S-1-5-32-550", SID_NAME_WKN_GRP, "Print Operators", "");
98         add_initial_entry(-1, "S-1-5-32-551", SID_NAME_WKN_GRP, "Backup Operators", "");
99         add_initial_entry(-1, "S-1-5-32-552", SID_NAME_WKN_GRP, "Replicators", "");
100
101         /* Add the defaults domain groups */
102
103         sid_copy(&sid_admins, get_global_sam_sid());
104         sid_append_rid(&sid_admins, DOMAIN_GROUP_RID_ADMINS);
105         sid_to_string(str_admins, &sid_admins);
106         add_initial_entry(-1, str_admins, SID_NAME_DOM_GRP, "Domain Admins", "");
107
108         sid_copy(&sid_users,  get_global_sam_sid());
109         sid_append_rid(&sid_users,  DOMAIN_GROUP_RID_USERS);
110         sid_to_string(str_users, &sid_users);
111         add_initial_entry(-1, str_users,  SID_NAME_DOM_GRP, "Domain Users",  "");
112
113         sid_copy(&sid_guests, get_global_sam_sid());
114         sid_append_rid(&sid_guests, DOMAIN_GROUP_RID_GUESTS);
115         sid_to_string(str_guests, &sid_guests);
116         add_initial_entry(-1, str_guests, SID_NAME_DOM_GRP, "Domain Guests", "");
117
118         return True;
119 }
120
121 /****************************************************************************
122  Open the group mapping tdb.
123 ****************************************************************************/
124
125 static BOOL init_group_mapping(void)
126 {
127         static pid_t local_pid;
128         const char *vstring = "INFO/version";
129         int32 vers_id;
130         
131         if (tdb && local_pid == sys_getpid())
132                 return True;
133         tdb = tdb_open_log(lock_path("group_mapping.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
134         if (!tdb) {
135                 DEBUG(0,("Failed to open group mapping database\n"));
136                 return False;
137         }
138
139         local_pid = sys_getpid();
140
141         /* handle a Samba upgrade */
142         tdb_lock_bystring(tdb, vstring, 0);
143
144         /* Cope with byte-reversed older versions of the db. */
145         vers_id = tdb_fetch_int32(tdb, vstring);
146         if ((vers_id == DATABASE_VERSION_V1) || (IREV(vers_id) == DATABASE_VERSION_V1)) {
147                 /* Written on a bigendian machine with old fetch_int code. Save as le. */
148                 tdb_store_int32(tdb, vstring, DATABASE_VERSION_V2);
149                 vers_id = DATABASE_VERSION_V2;
150         }
151
152         if (vers_id != DATABASE_VERSION_V2) {
153                 tdb_traverse(tdb, tdb_traverse_delete_fn, NULL);
154                 tdb_store_int32(tdb, vstring, DATABASE_VERSION_V2);
155         }
156
157         tdb_unlock_bystring(tdb, vstring);
158
159         /* write a list of default groups */
160         if(!default_group_mapping())
161                 return False;
162
163         return True;
164 }
165
166 /****************************************************************************
167 ****************************************************************************/
168 static BOOL add_mapping_entry(GROUP_MAP *map, int flag)
169 {
170         TDB_DATA kbuf, dbuf;
171         pstring key, buf;
172         fstring string_sid="";
173         int len;
174
175         if(!init_group_mapping()) {
176                 DEBUG(0,("failed to initialize group mapping\n"));
177                 return(False);
178         }
179         
180         sid_to_string(string_sid, &map->sid);
181
182         len = tdb_pack(buf, sizeof(buf), "ddff",
183                         map->gid, map->sid_name_use, map->nt_name, map->comment);
184
185         if (len > sizeof(buf))
186                 return False;
187
188         slprintf(key, sizeof(key), "%s%s", GROUP_PREFIX, string_sid);
189
190         kbuf.dsize = strlen(key)+1;
191         kbuf.dptr = key;
192         dbuf.dsize = len;
193         dbuf.dptr = buf;
194         if (tdb_store(tdb, kbuf, dbuf, flag) != 0) return False;
195
196         return True;
197 }
198
199 /****************************************************************************
200 initialise first time the mapping list
201 ****************************************************************************/
202 BOOL add_initial_entry(gid_t gid, const char *sid, enum SID_NAME_USE sid_name_use, const char *nt_name, const char *comment)
203 {
204         GROUP_MAP map;
205
206         if(!init_group_mapping()) {
207                 DEBUG(0,("failed to initialize group mapping\n"));
208                 return(False);
209         }
210         
211         map.gid=gid;
212         if (!string_to_sid(&map.sid, sid)) {
213                 DEBUG(0, ("string_to_sid failed: %s", sid));
214                 return False;
215         }
216         
217         map.sid_name_use=sid_name_use;
218         fstrcpy(map.nt_name, nt_name);
219         fstrcpy(map.comment, comment);
220
221         return pdb_add_group_mapping_entry(&map);
222 }
223
224 /****************************************************************************
225  Return the sid and the type of the unix group.
226 ****************************************************************************/
227
228 static BOOL get_group_map_from_sid(DOM_SID sid, GROUP_MAP *map)
229 {
230         TDB_DATA kbuf, dbuf;
231         pstring key;
232         fstring string_sid;
233         int ret = 0;
234         
235         if(!init_group_mapping()) {
236                 DEBUG(0,("failed to initialize group mapping\n"));
237                 return(False);
238         }
239
240         /* the key is the SID, retrieving is direct */
241
242         sid_to_string(string_sid, &sid);
243         slprintf(key, sizeof(key), "%s%s", GROUP_PREFIX, string_sid);
244
245         kbuf.dptr = key;
246         kbuf.dsize = strlen(key)+1;
247                 
248         dbuf = tdb_fetch(tdb, kbuf);
249         if (!dbuf.dptr)
250                 return False;
251
252         ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddff",
253                                 &map->gid, &map->sid_name_use, &map->nt_name, &map->comment);
254
255         SAFE_FREE(dbuf.dptr);
256         
257         if ( ret == -1 ) {
258                 DEBUG(3,("get_group_map_from_sid: tdb_unpack failure\n"));
259                 return False;
260         }
261
262         sid_copy(&map->sid, &sid);
263         
264         return True;
265 }
266
267 /****************************************************************************
268  Return the sid and the type of the unix group.
269 ****************************************************************************/
270
271 static BOOL get_group_map_from_gid(gid_t gid, GROUP_MAP *map)
272 {
273         TDB_DATA kbuf, dbuf, newkey;
274         fstring string_sid;
275         int ret;
276
277         if(!init_group_mapping()) {
278                 DEBUG(0,("failed to initialize group mapping\n"));
279                 return(False);
280         }
281
282         /* we need to enumerate the TDB to find the GID */
283
284         for (kbuf = tdb_firstkey(tdb); 
285              kbuf.dptr; 
286              newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
287
288                 if (strncmp(kbuf.dptr, GROUP_PREFIX, strlen(GROUP_PREFIX)) != 0) continue;
289                 
290                 dbuf = tdb_fetch(tdb, kbuf);
291                 if (!dbuf.dptr)
292                         continue;
293
294                 fstrcpy(string_sid, kbuf.dptr+strlen(GROUP_PREFIX));
295
296                 string_to_sid(&map->sid, string_sid);
297                 
298                 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddff",
299                                  &map->gid, &map->sid_name_use, &map->nt_name, &map->comment);
300
301                 SAFE_FREE(dbuf.dptr);
302
303                 if ( ret == -1 ) {
304                         DEBUG(3,("get_group_map_from_gid: tdb_unpack failure\n"));
305                         return False;
306                 }
307         
308                 if (gid==map->gid) {
309                         SAFE_FREE(kbuf.dptr);
310                         return True;
311                 }
312         }
313
314         return False;
315 }
316
317 /****************************************************************************
318  Return the sid and the type of the unix group.
319 ****************************************************************************/
320
321 static BOOL get_group_map_from_ntname(const char *name, GROUP_MAP *map)
322 {
323         TDB_DATA kbuf, dbuf, newkey;
324         fstring string_sid;
325         int ret;
326
327         if(!init_group_mapping()) {
328                 DEBUG(0,("get_group_map_from_ntname:failed to initialize group mapping\n"));
329                 return(False);
330         }
331
332         /* we need to enumerate the TDB to find the name */
333
334         for (kbuf = tdb_firstkey(tdb); 
335              kbuf.dptr; 
336              newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
337
338                 if (strncmp(kbuf.dptr, GROUP_PREFIX, strlen(GROUP_PREFIX)) != 0) continue;
339                 
340                 dbuf = tdb_fetch(tdb, kbuf);
341                 if (!dbuf.dptr)
342                         continue;
343
344                 fstrcpy(string_sid, kbuf.dptr+strlen(GROUP_PREFIX));
345
346                 string_to_sid(&map->sid, string_sid);
347                 
348                 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddff",
349                                  &map->gid, &map->sid_name_use, &map->nt_name, &map->comment);
350
351                 SAFE_FREE(dbuf.dptr);
352                 
353                 if ( ret == -1 ) {
354                         DEBUG(3,("get_group_map_from_ntname: tdb_unpack failure\n"));
355                         return False;
356                 }
357
358                 if (StrCaseCmp(name, map->nt_name)==0) {
359                         SAFE_FREE(kbuf.dptr);
360                         return True;
361                 }
362         }
363
364         return False;
365 }
366
367 /****************************************************************************
368  Remove a group mapping entry.
369 ****************************************************************************/
370
371 static BOOL group_map_remove(const DOM_SID *sid)
372 {
373         TDB_DATA kbuf, dbuf;
374         pstring key;
375         fstring string_sid;
376         
377         if(!init_group_mapping()) {
378                 DEBUG(0,("failed to initialize group mapping\n"));
379                 return(False);
380         }
381
382         /* the key is the SID, retrieving is direct */
383
384         sid_to_string(string_sid, sid);
385         slprintf(key, sizeof(key), "%s%s", GROUP_PREFIX, string_sid);
386
387         kbuf.dptr = key;
388         kbuf.dsize = strlen(key)+1;
389                 
390         dbuf = tdb_fetch(tdb, kbuf);
391         if (!dbuf.dptr)
392                 return False;
393         
394         SAFE_FREE(dbuf.dptr);
395
396         if(tdb_delete(tdb, kbuf) != TDB_SUCCESS)
397                 return False;
398
399         return True;
400 }
401
402 /****************************************************************************
403  Enumerate the group mapping.
404 ****************************************************************************/
405
406 static BOOL enum_group_mapping(enum SID_NAME_USE sid_name_use, GROUP_MAP **rmap,
407                         int *num_entries, BOOL unix_only)
408 {
409         TDB_DATA kbuf, dbuf, newkey;
410         fstring string_sid;
411         fstring group_type;
412         GROUP_MAP map;
413         GROUP_MAP *mapt;
414         int ret;
415         int entries=0;
416
417         if(!init_group_mapping()) {
418                 DEBUG(0,("failed to initialize group mapping\n"));
419                 return(False);
420         }
421
422         *num_entries=0;
423         *rmap=NULL;
424
425         for (kbuf = tdb_firstkey(tdb); 
426              kbuf.dptr; 
427              newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
428
429                 if (strncmp(kbuf.dptr, GROUP_PREFIX, strlen(GROUP_PREFIX)) != 0)
430                         continue;
431
432                 dbuf = tdb_fetch(tdb, kbuf);
433                 if (!dbuf.dptr)
434                         continue;
435
436                 fstrcpy(string_sid, kbuf.dptr+strlen(GROUP_PREFIX));
437                                 
438                 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddff",
439                                  &map.gid, &map.sid_name_use, &map.nt_name, &map.comment);
440
441                 SAFE_FREE(dbuf.dptr);
442
443                 if ( ret == -1 ) {
444                         DEBUG(3,("enum_group_mapping: tdb_unpack failure\n"));
445                         continue;
446                 }
447         
448                 /* list only the type or everything if UNKNOWN */
449                 if (sid_name_use!=SID_NAME_UNKNOWN  && sid_name_use!=map.sid_name_use) {
450                         DEBUG(11,("enum_group_mapping: group %s is not of the requested type\n", map.nt_name));
451                         continue;
452                 }
453
454                 if (unix_only==ENUM_ONLY_MAPPED && map.gid==-1) {
455                         DEBUG(11,("enum_group_mapping: group %s is non mapped\n", map.nt_name));
456                         continue;
457                 }
458
459                 string_to_sid(&map.sid, string_sid);
460                 
461                 decode_sid_name_use(group_type, map.sid_name_use);
462                 DEBUG(11,("enum_group_mapping: returning group %s of type %s\n", map.nt_name ,group_type));
463
464                 mapt=(GROUP_MAP *)Realloc((*rmap), (entries+1)*sizeof(GROUP_MAP));
465                 if (!mapt) {
466                         DEBUG(0,("enum_group_mapping: Unable to enlarge group map!\n"));
467                         SAFE_FREE(*rmap);
468                         return False;
469                 }
470                 else
471                         (*rmap) = mapt;
472
473                 mapt[entries].gid = map.gid;
474                 sid_copy( &mapt[entries].sid, &map.sid);
475                 mapt[entries].sid_name_use = map.sid_name_use;
476                 fstrcpy(mapt[entries].nt_name, map.nt_name);
477                 fstrcpy(mapt[entries].comment, map.comment);
478
479                 entries++;
480
481         }
482
483         *num_entries=entries;
484
485         return True;
486 }
487
488 /* This operation happens on session setup, so it should better be fast. We
489  * store a list of aliases a SID is member of hanging off MEMBEROF/SID. */
490
491 static NTSTATUS alias_memberships(const DOM_SID *sid, DOM_SID **sids, int *num)
492 {
493         fstring key, string_sid;
494         TDB_DATA kbuf, dbuf;
495         const char *p;
496
497         *num = 0;
498         *sids = NULL;
499
500         if (!init_group_mapping()) {
501                 DEBUG(0,("failed to initialize group mapping\n"));
502                 return NT_STATUS_ACCESS_DENIED;
503         }
504
505         sid_to_string(string_sid, sid);
506         slprintf(key, sizeof(key), "%s%s", MEMBEROF_PREFIX, string_sid);
507
508         kbuf.dsize = strlen(key)+1;
509         kbuf.dptr = key;
510
511         dbuf = tdb_fetch(tdb, kbuf);
512
513         if (dbuf.dptr == NULL) {
514                 return NT_STATUS_OK;
515         }
516
517         p = dbuf.dptr;
518
519         while (next_token(&p, string_sid, " ", sizeof(string_sid))) {
520
521                 DOM_SID alias;
522
523                 if (!string_to_sid(&alias, string_sid))
524                         continue;
525
526                 add_sid_to_array(&alias, sids, num);
527
528                 if (sids == NULL)
529                         return NT_STATUS_NO_MEMORY;
530         }
531
532         SAFE_FREE(dbuf.dptr);
533         return NT_STATUS_OK;
534 }
535
536 static BOOL is_aliasmem(const DOM_SID *alias, const DOM_SID *member)
537 {
538         DOM_SID *sids;
539         int i, num;
540
541         /* This feels the wrong way round, but the on-disk data structure
542          * dictates it this way. */
543         if (!NT_STATUS_IS_OK(alias_memberships(member, &sids, &num)))
544                 return False;
545
546         for (i=0; i<num; i++) {
547                 if (sid_compare(alias, &sids[i]) == 0) {
548                         SAFE_FREE(sids);
549                         return True;
550                 }
551         }
552         SAFE_FREE(sids);
553         return False;
554 }
555
556 static NTSTATUS add_aliasmem(const DOM_SID *alias, const DOM_SID *member)
557 {
558         GROUP_MAP map;
559         TDB_DATA kbuf, dbuf;
560         pstring key;
561         fstring string_sid;
562         char *new_memberstring;
563         int result;
564
565         if(!init_group_mapping()) {
566                 DEBUG(0,("failed to initialize group mapping\n"));
567                 return NT_STATUS_ACCESS_DENIED;
568         }
569
570         if (!get_group_map_from_sid(*alias, &map))
571                 return NT_STATUS_NO_SUCH_ALIAS;
572
573         if ( (map.sid_name_use != SID_NAME_ALIAS) &&
574              (map.sid_name_use != SID_NAME_WKN_GRP) )
575                 return NT_STATUS_NO_SUCH_ALIAS;
576
577         if (is_aliasmem(alias, member))
578                 return NT_STATUS_MEMBER_IN_ALIAS;
579
580         sid_to_string(string_sid, member);
581         slprintf(key, sizeof(key), "%s%s", MEMBEROF_PREFIX, string_sid);
582
583         kbuf.dsize = strlen(key)+1;
584         kbuf.dptr = key;
585
586         dbuf = tdb_fetch(tdb, kbuf);
587
588         sid_to_string(string_sid, alias);
589
590         if (dbuf.dptr != NULL) {
591                 asprintf(&new_memberstring, "%s %s", (char *)(dbuf.dptr),
592                          string_sid);
593         } else {
594                 new_memberstring = strdup(string_sid);
595         }
596
597         if (new_memberstring == NULL)
598                 return NT_STATUS_NO_MEMORY;
599
600         SAFE_FREE(dbuf.dptr);
601         dbuf.dsize = strlen(new_memberstring)+1;
602         dbuf.dptr = new_memberstring;
603
604         result = tdb_store(tdb, kbuf, dbuf, 0);
605
606         SAFE_FREE(new_memberstring);
607
608         return (result == 0 ? NT_STATUS_OK : NT_STATUS_ACCESS_DENIED);
609 }
610
611 struct aliasmem_closure {
612         const DOM_SID *alias;
613         DOM_SID **sids;
614         int *num;
615 };
616
617 static int collect_aliasmem(TDB_CONTEXT *tdb_ctx, TDB_DATA key, TDB_DATA data,
618                             void *state)
619 {
620         struct aliasmem_closure *closure = (struct aliasmem_closure *)state;
621         const char *p;
622         fstring alias_string;
623
624         if (strncmp(key.dptr, MEMBEROF_PREFIX,
625                     strlen(MEMBEROF_PREFIX)) != 0)
626                 return 0;
627
628         p = data.dptr;
629
630         while (next_token(&p, alias_string, " ", sizeof(alias_string))) {
631
632                 DOM_SID alias, member;
633                 const char *member_string;
634                 
635
636                 if (!string_to_sid(&alias, alias_string))
637                         continue;
638
639                 if (sid_compare(closure->alias, &alias) != 0)
640                         continue;
641
642                 /* Ok, we found the alias we're looking for in the membership
643                  * list currently scanned. The key represents the alias
644                  * member. Add that. */
645
646                 member_string = strchr(key.dptr, '/');
647
648                 /* Above we tested for MEMBEROF_PREFIX which includes the
649                  * slash. */
650
651                 SMB_ASSERT(member_string != NULL);
652                 member_string += 1;
653
654                 if (!string_to_sid(&member, member_string))
655                         continue;
656                 
657                 add_sid_to_array(&member, closure->sids, closure->num);
658         }
659
660         return 0;
661 }
662
663 static NTSTATUS enum_aliasmem(const DOM_SID *alias, DOM_SID **sids, int *num)
664 {
665         GROUP_MAP map;
666         struct aliasmem_closure closure;
667
668         if(!init_group_mapping()) {
669                 DEBUG(0,("failed to initialize group mapping\n"));
670                 return NT_STATUS_ACCESS_DENIED;
671         }
672
673         if (!get_group_map_from_sid(*alias, &map))
674                 return NT_STATUS_NO_SUCH_ALIAS;
675
676         if ( (map.sid_name_use != SID_NAME_ALIAS) &&
677              (map.sid_name_use != SID_NAME_WKN_GRP) )
678                 return NT_STATUS_NO_SUCH_ALIAS;
679
680         *sids = NULL;
681         *num = 0;
682
683         closure.alias = alias;
684         closure.sids = sids;
685         closure.num = num;
686
687         tdb_traverse(tdb, collect_aliasmem, &closure);
688         return NT_STATUS_OK;
689 }
690
691 static NTSTATUS del_aliasmem(const DOM_SID *alias, const DOM_SID *member)
692 {
693         NTSTATUS result;
694         DOM_SID *sids;
695         int i, num;
696         BOOL found = False;
697         char *member_string;
698         TDB_DATA kbuf, dbuf;
699         pstring key;
700         fstring sid_string;
701
702         result = alias_memberships(member, &sids, &num);
703
704         if (!NT_STATUS_IS_OK(result))
705                 return result;
706
707         for (i=0; i<num; i++) {
708                 if (sid_compare(&sids[i], alias) == 0) {
709                         found = True;
710                         break;
711                 }
712         }
713
714         if (!found) {
715                 SAFE_FREE(sids);
716                 return NT_STATUS_MEMBER_NOT_IN_ALIAS;
717         }
718
719         if (i < num)
720                 sids[i] = sids[num-1];
721
722         num -= 1;
723
724         sid_to_string(sid_string, member);
725         slprintf(key, sizeof(key), "%s%s", MEMBEROF_PREFIX, sid_string);
726
727         kbuf.dsize = strlen(key)+1;
728         kbuf.dptr = key;
729
730         if (num == 0)
731                 return tdb_delete(tdb, kbuf) == 0 ?
732                         NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
733
734         member_string = strdup("");
735
736         if (member_string == NULL) {
737                 SAFE_FREE(sids);
738                 return NT_STATUS_NO_MEMORY;
739         }
740
741         for (i=0; i<num; i++) {
742                 char *s = member_string;
743
744                 sid_to_string(sid_string, &sids[i]);
745                 asprintf(&member_string, "%s %s", s, sid_string);
746
747                 SAFE_FREE(s);
748                 if (member_string == NULL) {
749                         SAFE_FREE(sids);
750                         return NT_STATUS_NO_MEMORY;
751                 }
752         }
753
754         dbuf.dsize = strlen(member_string)+1;
755         dbuf.dptr = member_string;
756
757         result = tdb_store(tdb, kbuf, dbuf, 0) == 0 ?
758                 NT_STATUS_OK : NT_STATUS_ACCESS_DENIED;
759
760         SAFE_FREE(sids);
761         SAFE_FREE(member_string);
762
763         return result;
764 }
765
766 /*
767  *
768  * High level functions
769  * better to use them than the lower ones.
770  *
771  * we are checking if the group is in the mapping file
772  * and if the group is an existing unix group
773  *
774  */
775
776 /* get a domain group from it's SID */
777
778 BOOL get_domain_group_from_sid(DOM_SID sid, GROUP_MAP *map)
779 {
780         struct group *grp;
781         BOOL ret;
782         
783         if(!init_group_mapping()) {
784                 DEBUG(0,("failed to initialize group mapping\n"));
785                 return(False);
786         }
787
788         DEBUG(10, ("get_domain_group_from_sid\n"));
789
790         /* if the group is NOT in the database, it CAN NOT be a domain group */
791         
792         become_root();
793         ret = pdb_getgrsid(map, sid);
794         unbecome_root();
795         
796         if ( !ret ) 
797                 return False;
798
799         DEBUG(10, ("get_domain_group_from_sid: SID found in the TDB\n"));
800
801         /* if it's not a domain group, continue */
802         if (map->sid_name_use!=SID_NAME_DOM_GRP) {
803                 return False;
804         }
805
806         DEBUG(10, ("get_domain_group_from_sid: SID is a domain group\n"));
807         
808         if (map->gid==-1) {
809                 return False;
810         }
811
812         DEBUG(10, ("get_domain_group_from_sid: SID is mapped to gid:%lu\n",(unsigned long)map->gid));
813         
814         grp = getgrgid(map->gid);
815         if ( !grp ) {
816                 DEBUG(10, ("get_domain_group_from_sid: gid DOESN'T exist in UNIX security\n"));
817                 return False;
818         }
819
820         DEBUG(10, ("get_domain_group_from_sid: gid exists in UNIX security\n"));
821
822         return True;
823 }
824
825
826 /* get a local (alias) group from it's SID */
827
828 BOOL get_local_group_from_sid(DOM_SID *sid, GROUP_MAP *map)
829 {
830         BOOL ret;
831         
832         if(!init_group_mapping()) {
833                 DEBUG(0,("failed to initialize group mapping\n"));
834                 return(False);
835         }
836
837         /* The group is in the mapping table */
838         become_root();
839         ret = pdb_getgrsid(map, *sid);
840         unbecome_root();
841         
842         if ( !ret )
843                 return False;
844                 
845         if ( ( (map->sid_name_use != SID_NAME_ALIAS) &&
846                (map->sid_name_use != SID_NAME_WKN_GRP) )
847                 || (map->gid == -1)
848                 || (getgrgid(map->gid) == NULL) ) 
849         {
850                 return False;
851         }               
852                         
853 #if 1   /* JERRY */
854         /* local groups only exist in the group mapping DB so this 
855            is not necessary */
856            
857         else {
858                 /* the group isn't in the mapping table.
859                  * make one based on the unix information */
860                 uint32 alias_rid;
861                 struct group *grp;
862
863                 sid_peek_rid(sid, &alias_rid);
864                 map->gid=pdb_group_rid_to_gid(alias_rid);
865                 
866                 grp = getgrgid(map->gid);
867                 if ( !grp ) {
868                         DEBUG(3,("get_local_group_from_sid: No unix group for [%ul]\n", map->gid));
869                         return False;
870                 }
871
872                 map->sid_name_use=SID_NAME_ALIAS;
873
874                 fstrcpy(map->nt_name, grp->gr_name);
875                 fstrcpy(map->comment, "Local Unix Group");
876
877                 sid_copy(&map->sid, sid);
878         }
879 #endif
880
881         return True;
882 }
883
884 /* get a builtin group from it's SID */
885
886 BOOL get_builtin_group_from_sid(DOM_SID *sid, GROUP_MAP *map)
887 {
888         struct group *grp;
889         BOOL ret;
890         
891
892         if(!init_group_mapping()) {
893                 DEBUG(0,("failed to initialize group mapping\n"));
894                 return(False);
895         }
896
897         become_root();
898         ret = pdb_getgrsid(map, *sid);
899         unbecome_root();
900         
901         if ( !ret )
902                 return False;
903
904         if (map->sid_name_use!=SID_NAME_WKN_GRP) {
905                 return False;
906         }
907
908         if (map->gid==-1) {
909                 return False;
910         }
911
912         if ( (grp=getgrgid(map->gid)) == NULL) {
913                 return False;
914         }
915
916         return True;
917 }
918
919
920
921 /****************************************************************************
922 Returns a GROUP_MAP struct based on the gid.
923 ****************************************************************************/
924 BOOL get_group_from_gid(gid_t gid, GROUP_MAP *map)
925 {
926         struct group *grp;
927         BOOL ret;
928
929         if(!init_group_mapping()) {
930                 DEBUG(0,("failed to initialize group mapping\n"));
931                 return(False);
932         }
933
934         if ( (grp=getgrgid(gid)) == NULL)
935                 return False;
936
937         /*
938          * make a group map from scratch if doesn't exist.
939          */
940         
941         become_root();
942         ret = pdb_getgrgid(map, gid);
943         unbecome_root();
944         
945         if ( !ret ) {
946                 map->gid=gid;
947                 map->sid_name_use=SID_NAME_ALIAS;
948
949                 /* interim solution until we have a last RID allocated */
950
951                 sid_copy(&map->sid, get_global_sam_sid());
952                 sid_append_rid(&map->sid, pdb_gid_to_group_rid(gid));
953
954                 fstrcpy(map->nt_name, grp->gr_name);
955                 fstrcpy(map->comment, "Local Unix Group");
956         }
957         
958         return True;
959 }
960
961 /****************************************************************************
962  Create a UNIX group on demand.
963 ****************************************************************************/
964
965 int smb_create_group(char *unix_group, gid_t *new_gid)
966 {
967         pstring add_script;
968         int     ret = -1;
969         int     fd = 0;
970         
971         *new_gid = 0;
972
973         /* defer to scripts */
974         
975         if ( *lp_addgroup_script() ) {
976                 pstrcpy(add_script, lp_addgroup_script());
977                 pstring_sub(add_script, "%g", unix_group);
978                 ret = smbrun(add_script, (new_gid!=NULL) ? &fd : NULL);
979                 DEBUG(3,("smb_create_group: Running the command `%s' gave %d\n",add_script,ret));
980                 if (ret != 0)
981                         return ret;
982                         
983                 if (fd != 0) {
984                         fstring output;
985
986                         *new_gid = 0;
987                         if (read(fd, output, sizeof(output)) > 0) {
988                                 *new_gid = (gid_t)strtoul(output, NULL, 10);
989                         }
990                         
991                         close(fd);
992                 }
993
994         } else if ( winbind_create_group( unix_group, NULL ) ) {
995
996                 DEBUG(3,("smb_create_group: winbindd created the group (%s)\n",
997                         unix_group));
998                 ret = 0;
999         }
1000         
1001         if (*new_gid == 0) {
1002                 struct group *grp = getgrnam(unix_group);
1003
1004                 if (grp != NULL)
1005                         *new_gid = grp->gr_gid;
1006         }
1007                         
1008         return ret;     
1009 }
1010
1011 /****************************************************************************
1012  Delete a UNIX group on demand.
1013 ****************************************************************************/
1014
1015 int smb_delete_group(char *unix_group)
1016 {
1017         pstring del_script;
1018         int ret;
1019
1020         /* defer to scripts */
1021         
1022         if ( *lp_delgroup_script() ) {
1023                 pstrcpy(del_script, lp_delgroup_script());
1024                 pstring_sub(del_script, "%g", unix_group);
1025                 ret = smbrun(del_script,NULL);
1026                 DEBUG(3,("smb_delete_group: Running the command `%s' gave %d\n",del_script,ret));
1027                 return ret;
1028         }
1029
1030         if ( winbind_delete_group( unix_group ) ) {
1031                 DEBUG(3,("smb_delete_group: winbindd deleted the group (%s)\n",
1032                         unix_group));
1033                 return 0;
1034         }
1035                 
1036         return -1;
1037 }
1038
1039 /****************************************************************************
1040  Set a user's primary UNIX group.
1041 ****************************************************************************/
1042 int smb_set_primary_group(const char *unix_group, const char* unix_user)
1043 {
1044         pstring add_script;
1045         int ret;
1046
1047         /* defer to scripts */
1048         
1049         if ( *lp_setprimarygroup_script() ) {
1050                 pstrcpy(add_script, lp_setprimarygroup_script());
1051                 all_string_sub(add_script, "%g", unix_group, sizeof(add_script));
1052                 all_string_sub(add_script, "%u", unix_user, sizeof(add_script));
1053                 ret = smbrun(add_script,NULL);
1054                 DEBUG(3,("smb_set_primary_group: "
1055                          "Running the command `%s' gave %d\n",add_script,ret));
1056                 return ret;
1057         }
1058
1059         /* Try winbindd */
1060         
1061         if ( winbind_set_user_primary_group( unix_user, unix_group ) ) {
1062                 DEBUG(3,("smb_delete_group: winbindd set the group (%s) as the primary group for user (%s)\n",
1063                         unix_group, unix_user));
1064                 return 0;
1065         }               
1066         
1067         return -1;
1068 }
1069
1070 /****************************************************************************
1071  Add a user to a UNIX group.
1072 ****************************************************************************/
1073
1074 int smb_add_user_group(char *unix_group, char *unix_user)
1075 {
1076         pstring add_script;
1077         int ret;
1078
1079         /* defer to scripts */
1080         
1081         if ( *lp_addusertogroup_script() ) {
1082                 pstrcpy(add_script, lp_addusertogroup_script());
1083                 pstring_sub(add_script, "%g", unix_group);
1084                 pstring_sub(add_script, "%u", unix_user);
1085                 ret = smbrun(add_script,NULL);
1086                 DEBUG(3,("smb_add_user_group: Running the command `%s' gave %d\n",add_script,ret));
1087                 return ret;
1088         }
1089         
1090         /* Try winbindd */
1091
1092         if ( winbind_add_user_to_group( unix_user, unix_group ) ) {
1093                 DEBUG(3,("smb_delete_group: winbindd added user (%s) to the group (%s)\n",
1094                         unix_user, unix_group));
1095                 return -1;
1096         }       
1097         
1098         return -1;
1099 }
1100
1101 /****************************************************************************
1102  Delete a user from a UNIX group
1103 ****************************************************************************/
1104
1105 int smb_delete_user_group(const char *unix_group, const char *unix_user)
1106 {
1107         pstring del_script;
1108         int ret;
1109
1110         /* defer to scripts */
1111         
1112         if ( *lp_deluserfromgroup_script() ) {
1113                 pstrcpy(del_script, lp_deluserfromgroup_script());
1114                 pstring_sub(del_script, "%g", unix_group);
1115                 pstring_sub(del_script, "%u", unix_user);
1116                 ret = smbrun(del_script,NULL);
1117                 DEBUG(3,("smb_delete_user_group: Running the command `%s' gave %d\n",del_script,ret));
1118                 return ret;
1119         }
1120         
1121         /* Try winbindd */
1122
1123         if ( winbind_remove_user_from_group( unix_user, unix_group ) ) {
1124                 DEBUG(3,("smb_delete_group: winbindd removed user (%s) from the group (%s)\n",
1125                         unix_user, unix_group));
1126                 return 0;
1127         }
1128         
1129         return -1;
1130 }
1131
1132
1133 NTSTATUS pdb_default_getgrsid(struct pdb_methods *methods, GROUP_MAP *map,
1134                                  DOM_SID sid)
1135 {
1136         return get_group_map_from_sid(sid, map) ?
1137                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1138 }
1139
1140 NTSTATUS pdb_default_getgrgid(struct pdb_methods *methods, GROUP_MAP *map,
1141                                  gid_t gid)
1142 {
1143         return get_group_map_from_gid(gid, map) ?
1144                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1145 }
1146
1147 NTSTATUS pdb_default_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
1148                                  const char *name)
1149 {
1150         return get_group_map_from_ntname(name, map) ?
1151                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1152 }
1153
1154 NTSTATUS pdb_default_add_group_mapping_entry(struct pdb_methods *methods,
1155                                                 GROUP_MAP *map)
1156 {
1157         return add_mapping_entry(map, TDB_INSERT) ?
1158                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1159 }
1160
1161 NTSTATUS pdb_default_update_group_mapping_entry(struct pdb_methods *methods,
1162                                                    GROUP_MAP *map)
1163 {
1164         return add_mapping_entry(map, TDB_REPLACE) ?
1165                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1166 }
1167
1168 NTSTATUS pdb_default_delete_group_mapping_entry(struct pdb_methods *methods,
1169                                                    DOM_SID sid)
1170 {
1171         return group_map_remove(&sid) ?
1172                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1173 }
1174
1175 NTSTATUS pdb_default_enum_group_mapping(struct pdb_methods *methods,
1176                                            enum SID_NAME_USE sid_name_use,
1177                                            GROUP_MAP **rmap, int *num_entries,
1178                                            BOOL unix_only)
1179 {
1180         return enum_group_mapping(sid_name_use, rmap, num_entries, unix_only) ?
1181                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1182 }
1183
1184 NTSTATUS pdb_default_find_alias(struct pdb_methods *methods,
1185                                 const char *name, DOM_SID *sid)
1186 {
1187         GROUP_MAP map;
1188
1189         if (!pdb_getgrnam(&map, name))
1190                 return NT_STATUS_NO_SUCH_ALIAS;
1191
1192         if ((map.sid_name_use != SID_NAME_WKN_GRP) &&
1193             (map.sid_name_use != SID_NAME_ALIAS))
1194                 return NT_STATUS_OBJECT_TYPE_MISMATCH;
1195
1196         sid_copy(sid, &map.sid);
1197         return NT_STATUS_OK;
1198 }
1199
1200 NTSTATUS pdb_default_create_alias(struct pdb_methods *methods,
1201                                   const char *name, uint32 *rid)
1202 {
1203         DOM_SID sid;
1204         enum SID_NAME_USE type;
1205         uint32 new_rid;
1206         gid_t gid;
1207
1208         GROUP_MAP map;
1209
1210         if (lookup_name(get_global_sam_name(), name, &sid, &type))
1211                 return NT_STATUS_ALIAS_EXISTS;
1212
1213         if (!winbind_allocate_rid(&new_rid))
1214                 return NT_STATUS_ACCESS_DENIED;
1215
1216         sid_copy(&sid, get_global_sam_sid());
1217         sid_append_rid(&sid, new_rid);
1218
1219         /* Here we allocate the gid */
1220         if (!winbind_sid_to_gid(&gid, &sid)) {
1221                 DEBUG(0, ("Could not get gid for new RID\n"));
1222                 return NT_STATUS_ACCESS_DENIED;
1223         }
1224
1225         map.gid = gid;
1226         sid_copy(&map.sid, &sid);
1227         map.sid_name_use = SID_NAME_ALIAS;
1228         fstrcpy(map.nt_name, name);
1229         fstrcpy(map.comment, "");
1230
1231         if (!pdb_add_group_mapping_entry(&map)) {
1232                 DEBUG(0, ("Could not add group mapping entry for alias %s\n",
1233                           name));
1234                 return NT_STATUS_ACCESS_DENIED;
1235         }
1236
1237         *rid = new_rid;
1238
1239         return NT_STATUS_OK;
1240 }
1241
1242 NTSTATUS pdb_default_delete_alias(struct pdb_methods *methods,
1243                                   const DOM_SID *sid)
1244 {
1245         return pdb_delete_group_mapping_entry(*sid) ?
1246                 NT_STATUS_OK : NT_STATUS_ACCESS_DENIED;
1247 }
1248
1249 NTSTATUS pdb_default_enum_aliases(struct pdb_methods *methods,
1250                                   const DOM_SID *sid,
1251                                   uint32 start_idx, uint32 max_entries,
1252                                   uint32 *num_aliases,
1253                                   struct acct_info **info)
1254 {
1255         extern DOM_SID global_sid_Builtin;
1256
1257         GROUP_MAP *map;
1258         int i, num_maps;
1259         enum SID_NAME_USE type = SID_NAME_UNKNOWN;
1260
1261         if (sid_compare(sid, get_global_sam_sid()) == 0)
1262                 type = SID_NAME_ALIAS;
1263
1264         if (sid_compare(sid, &global_sid_Builtin) == 0)
1265                 type = SID_NAME_WKN_GRP;
1266
1267         if (!pdb_enum_group_mapping(type, &map, &num_maps, False) ||
1268             (num_maps == 0)) {
1269                 *num_aliases = 0;
1270                 *info = NULL;
1271                 goto done;
1272         }
1273
1274         if (start_idx > num_maps) {
1275                 *num_aliases = 0;
1276                 *info = NULL;
1277                 goto done;
1278         }
1279
1280         *num_aliases = num_maps - start_idx;
1281
1282         if (*num_aliases > max_entries)
1283                 *num_aliases = max_entries;
1284
1285         *info = malloc(sizeof(struct acct_info) * (*num_aliases));
1286
1287         for (i=0; i<*num_aliases; i++) {
1288                 fstrcpy((*info)[i].acct_name, map[i+start_idx].nt_name);
1289                 fstrcpy((*info)[i].acct_desc, map[i+start_idx].comment);
1290                 sid_peek_rid(&map[i].sid, &(*info)[i+start_idx].rid);
1291         }
1292
1293  done:
1294         SAFE_FREE(map);
1295         return NT_STATUS_OK;
1296 }
1297
1298 NTSTATUS pdb_default_get_aliasinfo(struct pdb_methods *methods,
1299                                    const DOM_SID *sid,
1300                                    struct acct_info *info)
1301 {
1302         GROUP_MAP map;
1303
1304         if (!pdb_getgrsid(&map, *sid))
1305                 return NT_STATUS_NO_SUCH_ALIAS;
1306
1307         fstrcpy(info->acct_name, map.nt_name);
1308         fstrcpy(info->acct_desc, map.comment);
1309         sid_peek_rid(&map.sid, &info->rid);
1310         return NT_STATUS_OK;
1311 }
1312
1313 NTSTATUS pdb_default_set_aliasinfo(struct pdb_methods *methods,
1314                                    const DOM_SID *sid,
1315                                    struct acct_info *info)
1316 {
1317         GROUP_MAP map;
1318
1319         if (!pdb_getgrsid(&map, *sid))
1320                 return NT_STATUS_NO_SUCH_ALIAS;
1321
1322         fstrcpy(map.comment, info->acct_desc);
1323
1324         if (!pdb_update_group_mapping_entry(&map))
1325                 return NT_STATUS_ACCESS_DENIED;
1326
1327         return NT_STATUS_OK;
1328 }
1329
1330 NTSTATUS pdb_default_add_aliasmem(struct pdb_methods *methods,
1331                                   const DOM_SID *alias, const DOM_SID *member)
1332 {
1333         return add_aliasmem(alias, member);
1334 }
1335
1336 NTSTATUS pdb_default_del_aliasmem(struct pdb_methods *methods,
1337                                   const DOM_SID *alias, const DOM_SID *member)
1338 {
1339         return del_aliasmem(alias, member);
1340 }
1341
1342 NTSTATUS pdb_default_enum_aliasmem(struct pdb_methods *methods,
1343                                    const DOM_SID *alias, DOM_SID **members,
1344                                    int *num_members)
1345 {
1346         return enum_aliasmem(alias, members, num_members);
1347 }
1348
1349 NTSTATUS pdb_default_alias_memberships(struct pdb_methods *methods,
1350                                        const DOM_SID *sid,
1351                                        DOM_SID **aliases, int *num)
1352 {
1353         return alias_memberships(sid, aliases, num);
1354 }
1355
1356 /**********************************************************************
1357  no ops for passdb backends that don't implement group mapping
1358  *********************************************************************/
1359
1360 NTSTATUS pdb_nop_getgrsid(struct pdb_methods *methods, GROUP_MAP *map,
1361                                  DOM_SID sid)
1362 {
1363         return NT_STATUS_UNSUCCESSFUL;
1364 }
1365
1366 NTSTATUS pdb_nop_getgrgid(struct pdb_methods *methods, GROUP_MAP *map,
1367                                  gid_t gid)
1368 {
1369         return NT_STATUS_UNSUCCESSFUL;
1370 }
1371
1372 NTSTATUS pdb_nop_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
1373                                  const char *name)
1374 {
1375         return NT_STATUS_UNSUCCESSFUL;
1376 }
1377
1378 NTSTATUS pdb_nop_add_group_mapping_entry(struct pdb_methods *methods,
1379                                                 GROUP_MAP *map)
1380 {
1381         return NT_STATUS_UNSUCCESSFUL;
1382 }
1383
1384 NTSTATUS pdb_nop_update_group_mapping_entry(struct pdb_methods *methods,
1385                                                    GROUP_MAP *map)
1386 {
1387         return NT_STATUS_UNSUCCESSFUL;
1388 }
1389
1390 NTSTATUS pdb_nop_delete_group_mapping_entry(struct pdb_methods *methods,
1391                                                    DOM_SID sid)
1392 {
1393         return NT_STATUS_UNSUCCESSFUL;
1394 }
1395
1396 NTSTATUS pdb_nop_enum_group_mapping(struct pdb_methods *methods,
1397                                            enum SID_NAME_USE sid_name_use,
1398                                            GROUP_MAP **rmap, int *num_entries,
1399                                            BOOL unix_only)
1400 {
1401         return NT_STATUS_UNSUCCESSFUL;
1402 }
1403
1404 /****************************************************************************
1405  These need to be redirected through pdb_interface.c
1406 ****************************************************************************/
1407 BOOL pdb_get_dom_grp_info(const DOM_SID *sid, struct acct_info *info)
1408 {
1409         GROUP_MAP map;
1410         BOOL res;
1411
1412         become_root();
1413         res = get_domain_group_from_sid(*sid, &map);
1414         unbecome_root();
1415
1416         if (!res)
1417                 return False;
1418
1419         fstrcpy(info->acct_name, map.nt_name);
1420         fstrcpy(info->acct_desc, map.comment);
1421         sid_peek_rid(sid, &info->rid);
1422         return True;
1423 }
1424
1425 BOOL pdb_set_dom_grp_info(const DOM_SID *sid, const struct acct_info *info)
1426 {
1427         GROUP_MAP map;
1428
1429         if (!get_domain_group_from_sid(*sid, &map))
1430                 return False;
1431
1432         fstrcpy(map.nt_name, info->acct_name);
1433         fstrcpy(map.comment, info->acct_desc);
1434
1435         return pdb_update_group_mapping_entry(&map);
1436 }
1437
1438