And some more memory leaks in mapping.c and pdb_tdb.c. tdb_nextkey
[gd/samba-autobuild/.git] / source3 / 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 PRIVS privs[] = {
32         {SE_PRIV_NONE,           "no_privs",                  "No privilege"                    }, /* this one MUST be first */
33         {SE_PRIV_ADD_MACHINES,   "SeMachineAccountPrivilege", "Add workstations to the domain"  },
34         {SE_PRIV_SEC_PRIV,       "SeSecurityPrivilege",       "Manage the audit logs"           },
35         {SE_PRIV_TAKE_OWNER,     "SeTakeOwnershipPrivilege",  "Take ownership of file"          },
36         {SE_PRIV_ADD_USERS,      "SaAddUsers",                "Add users to the domain - Samba" },
37         {SE_PRIV_PRINT_OPERATOR, "SaPrintOp",                 "Add or remove printers - Samba"  },
38         {SE_PRIV_ALL,            "SaAllPrivs",                "all privileges"                  }
39 };
40 /*
41 PRIVS privs[] = {
42         {  2, "SeCreateTokenPrivilege" },
43         {  3, "SeAssignPrimaryTokenPrivilege" },
44         {  4, "SeLockMemoryPrivilege" },
45         {  5, "SeIncreaseQuotaPrivilege" },
46         {  6, "SeMachineAccountPrivilege" },
47         {  7, "SeTcbPrivilege" },
48         {  8, "SeSecurityPrivilege" },
49         {  9, "SeTakeOwnershipPrivilege" },
50         { 10, "SeLoadDriverPrivilege" },
51         { 11, "SeSystemProfilePrivilege" },
52         { 12, "SeSystemtimePrivilege" },
53         { 13, "SeProfileSingleProcessPrivilege" },
54         { 14, "SeIncreaseBasePriorityPrivilege" },
55         { 15, "SeCreatePagefilePrivilege" },
56         { 16, "SeCreatePermanentPrivilege" },
57         { 17, "SeBackupPrivilege" },
58         { 18, "SeRestorePrivilege" },
59         { 19, "SeShutdownPrivilege" },
60         { 20, "SeDebugPrivilege" },
61         { 21, "SeAuditPrivilege" },
62         { 22, "SeSystemEnvironmentPrivilege" },
63         { 23, "SeChangeNotifyPrivilege" },
64         { 24, "SeRemoteShutdownPrivilege" },
65         { 25, "SeUndockPrivilege" },
66         { 26, "SeSyncAgentPrivilege" },
67         { 27, "SeEnableDelegationPrivilege" },
68 };
69 */
70
71         /*
72          * Those are not really privileges like the other ones.
73          * They are handled in a special case and called
74          * system privileges.
75          *
76          * SeNetworkLogonRight
77          * SeUnsolicitedInputPrivilege
78          * SeBatchLogonRight
79          * SeServiceLogonRight
80          * SeInteractiveLogonRight
81          * SeDenyInteractiveLogonRight
82          * SeDenyNetworkLogonRight
83          * SeDenyBatchLogonRight
84          * SeDenyBatchLogonRight
85          */
86
87 #if 0
88 /****************************************************************************
89 check if the user has the required privilege.
90 ****************************************************************************/
91 static BOOL se_priv_access_check(NT_USER_TOKEN *token, uint32 privilege)
92 {
93         /* no token, no privilege */
94         if (token==NULL)
95                 return False;
96         
97         if ((token->privilege & privilege)==privilege)
98                 return True;
99         
100         return False;
101 }
102 #endif
103
104 /****************************************************************************
105 dump the mapping group mapping to a text file
106 ****************************************************************************/
107 char *decode_sid_name_use(fstring group, enum SID_NAME_USE name_use)
108 {       
109         static fstring group_type;
110
111         switch(name_use) {
112                 case SID_NAME_USER:
113                         fstrcpy(group_type,"User");
114                         break;
115                 case SID_NAME_DOM_GRP:
116                         fstrcpy(group_type,"Domain group");
117                         break;
118                 case SID_NAME_DOMAIN:
119                         fstrcpy(group_type,"Domain");
120                         break;
121                 case SID_NAME_ALIAS:
122                         fstrcpy(group_type,"Local group");
123                         break;
124                 case SID_NAME_WKN_GRP:
125                         fstrcpy(group_type,"Builtin group");
126                         break;
127                 case SID_NAME_DELETED:
128                         fstrcpy(group_type,"Deleted");
129                         break;
130                 case SID_NAME_INVALID:
131                         fstrcpy(group_type,"Invalid");
132                         break;
133                 case SID_NAME_UNKNOWN:
134                 default:
135                         fstrcpy(group_type,"Unknown type");
136                         break;
137         }
138         
139         fstrcpy(group, group_type);
140         return group_type;
141 }
142
143 /****************************************************************************
144 initialise first time the mapping list - called from init_group_mapping()
145 ****************************************************************************/
146 static BOOL default_group_mapping(void)
147 {
148         DOM_SID sid_admins;
149         DOM_SID sid_users;
150         DOM_SID sid_guests;
151         fstring str_admins;
152         fstring str_users;
153         fstring str_guests;
154         LUID_ATTR set;
155
156         PRIVILEGE_SET privilege_none;
157         PRIVILEGE_SET privilege_all;
158         PRIVILEGE_SET privilege_print_op;
159
160         init_privilege(&privilege_none);
161         init_privilege(&privilege_all);
162         init_privilege(&privilege_print_op);
163
164         set.attr=0;
165         set.luid.high=0;
166         set.luid.low=SE_PRIV_PRINT_OPERATOR;
167         add_privilege(&privilege_print_op, set);
168
169         add_all_privilege(&privilege_all);
170
171         /* Add the Wellknown groups */
172
173         add_initial_entry(-1, "S-1-5-32-544", SID_NAME_WKN_GRP, "Administrators", "", privilege_all, PR_ACCESS_FROM_NETWORK|PR_LOG_ON_LOCALLY);
174         add_initial_entry(-1, "S-1-5-32-545", SID_NAME_WKN_GRP, "Users", "", privilege_none, PR_ACCESS_FROM_NETWORK|PR_LOG_ON_LOCALLY);
175         add_initial_entry(-1, "S-1-5-32-546", SID_NAME_WKN_GRP, "Guests", "", privilege_none, PR_ACCESS_FROM_NETWORK);
176         add_initial_entry(-1, "S-1-5-32-547", SID_NAME_WKN_GRP, "Power Users", "", privilege_none, PR_ACCESS_FROM_NETWORK|PR_LOG_ON_LOCALLY);
177
178         add_initial_entry(-1, "S-1-5-32-548", SID_NAME_WKN_GRP, "Account Operators", "", privilege_none, PR_ACCESS_FROM_NETWORK|PR_LOG_ON_LOCALLY);
179         add_initial_entry(-1, "S-1-5-32-549", SID_NAME_WKN_GRP, "System Operators", "", privilege_none, PR_ACCESS_FROM_NETWORK|PR_LOG_ON_LOCALLY);
180         add_initial_entry(-1, "S-1-5-32-550", SID_NAME_WKN_GRP, "Print Operators", "", privilege_print_op, PR_ACCESS_FROM_NETWORK|PR_LOG_ON_LOCALLY);
181         add_initial_entry(-1, "S-1-5-32-551", SID_NAME_WKN_GRP, "Backup Operators", "", privilege_none, PR_ACCESS_FROM_NETWORK|PR_LOG_ON_LOCALLY);
182
183         add_initial_entry(-1, "S-1-5-32-552", SID_NAME_WKN_GRP, "Replicators", "", privilege_none, PR_ACCESS_FROM_NETWORK);
184
185         /* Add the defaults domain groups */
186
187         sid_copy(&sid_admins, get_global_sam_sid());
188         sid_append_rid(&sid_admins, DOMAIN_GROUP_RID_ADMINS);
189         sid_to_string(str_admins, &sid_admins);
190         add_initial_entry(-1, str_admins, SID_NAME_DOM_GRP, "Domain Admins", "", privilege_all, PR_ACCESS_FROM_NETWORK|PR_LOG_ON_LOCALLY);
191
192         sid_copy(&sid_users,  get_global_sam_sid());
193         sid_append_rid(&sid_users,  DOMAIN_GROUP_RID_USERS);
194         sid_to_string(str_users, &sid_users);
195         add_initial_entry(-1, str_users,  SID_NAME_DOM_GRP, "Domain Users",  "", privilege_none, PR_ACCESS_FROM_NETWORK|PR_LOG_ON_LOCALLY);
196
197         sid_copy(&sid_guests, get_global_sam_sid());
198         sid_append_rid(&sid_guests, DOMAIN_GROUP_RID_GUESTS);
199         sid_to_string(str_guests, &sid_guests);
200         add_initial_entry(-1, str_guests, SID_NAME_DOM_GRP, "Domain Guests", "", privilege_none, PR_ACCESS_FROM_NETWORK);
201
202         free_privilege(&privilege_none);
203         free_privilege(&privilege_all);
204         free_privilege(&privilege_print_op);
205
206         return True;
207 }
208
209 /****************************************************************************
210  Open the group mapping tdb.
211 ****************************************************************************/
212
213 static BOOL init_group_mapping(void)
214 {
215         static pid_t local_pid;
216         const char *vstring = "INFO/version";
217         int32 vers_id;
218         
219         if (tdb && local_pid == sys_getpid())
220                 return True;
221         tdb = tdb_open_log(lock_path("group_mapping.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
222         if (!tdb) {
223                 DEBUG(0,("Failed to open group mapping database\n"));
224                 return False;
225         }
226
227         local_pid = sys_getpid();
228
229         /* handle a Samba upgrade */
230         tdb_lock_bystring(tdb, vstring, 0);
231
232         /* Cope with byte-reversed older versions of the db. */
233         vers_id = tdb_fetch_int32(tdb, vstring);
234         if ((vers_id == DATABASE_VERSION_V1) || (IREV(vers_id) == DATABASE_VERSION_V1)) {
235                 /* Written on a bigendian machine with old fetch_int code. Save as le. */
236                 tdb_store_int32(tdb, vstring, DATABASE_VERSION_V2);
237                 vers_id = DATABASE_VERSION_V2;
238         }
239
240         if (vers_id != DATABASE_VERSION_V2) {
241                 tdb_traverse(tdb, tdb_traverse_delete_fn, NULL);
242                 tdb_store_int32(tdb, vstring, DATABASE_VERSION_V2);
243         }
244
245         tdb_unlock_bystring(tdb, vstring);
246
247         /* write a list of default groups */
248         if(!default_group_mapping())
249                 return False;
250
251         return True;
252 }
253
254 /****************************************************************************
255 ****************************************************************************/
256 static BOOL add_mapping_entry(GROUP_MAP *map, int flag)
257 {
258         TDB_DATA kbuf, dbuf;
259         pstring key, buf;
260         fstring string_sid="";
261         int len;
262         int i;
263         PRIVILEGE_SET *set;
264
265         if(!init_group_mapping()) {
266                 DEBUG(0,("failed to initialize group mapping"));
267                 return(False);
268         }
269         
270         sid_to_string(string_sid, &map->sid);
271
272         len = tdb_pack(buf, sizeof(buf), "ddffd",
273                         map->gid, map->sid_name_use, map->nt_name, map->comment, map->systemaccount);
274
275         /* write the privilege list in the TDB database */
276
277         set=&map->priv_set;
278         len += tdb_pack(buf+len, sizeof(buf)-len, "d", set->count);
279         for (i=0; i<set->count; i++)
280                 len += tdb_pack(buf+len, sizeof(buf)-len, "ddd", 
281                                 set->set[i].luid.low, set->set[i].luid.high, set->set[i].attr);
282
283         if (len > sizeof(buf))
284                 return False;
285
286         slprintf(key, sizeof(key), "%s%s", GROUP_PREFIX, string_sid);
287
288         kbuf.dsize = strlen(key)+1;
289         kbuf.dptr = key;
290         dbuf.dsize = len;
291         dbuf.dptr = buf;
292         if (tdb_store(tdb, kbuf, dbuf, flag) != 0) return False;
293
294         return True;
295 }
296
297 /****************************************************************************
298 initialise first time the mapping list
299 ****************************************************************************/
300 BOOL add_initial_entry(gid_t gid, const char *sid, enum SID_NAME_USE sid_name_use,
301                        const char *nt_name, const char *comment, PRIVILEGE_SET priv_set, uint32 systemaccount)
302 {
303         GROUP_MAP map;
304
305         if(!init_group_mapping()) {
306                 DEBUG(0,("failed to initialize group mapping"));
307                 return(False);
308         }
309         
310         map.gid=gid;
311         if (!string_to_sid(&map.sid, sid)) {
312                 DEBUG(0, ("string_to_sid failed: %s", sid));
313                 return False;
314         }
315         
316         map.sid_name_use=sid_name_use;
317         fstrcpy(map.nt_name, nt_name);
318         fstrcpy(map.comment, comment);
319         map.systemaccount=systemaccount;
320
321         map.priv_set.count=priv_set.count;
322         map.priv_set.set=priv_set.set;
323
324         pdb_add_group_mapping_entry(&map);
325
326         return True;
327 }
328
329 /****************************************************************************
330 initialise a privilege list
331 ****************************************************************************/
332 void init_privilege(PRIVILEGE_SET *priv_set)
333 {
334         priv_set->count=0;
335         priv_set->control=0;
336         priv_set->set=NULL;
337 }
338
339 /****************************************************************************
340 free a privilege list
341 ****************************************************************************/
342 BOOL free_privilege(PRIVILEGE_SET *priv_set)
343 {
344         if (priv_set->count==0) {
345                 DEBUG(100,("free_privilege: count=0, nothing to clear ?\n"));
346                 return False;
347         }
348
349         if (priv_set->set==NULL) {
350                 DEBUG(0,("free_privilege: list ptr is NULL, very strange !\n"));
351                 return False;
352         }
353
354         safe_free(priv_set->set);
355         priv_set->count=0;
356         priv_set->control=0;
357         priv_set->set=NULL;
358
359         return True;
360 }
361
362 /****************************************************************************
363 add a privilege to a privilege array
364 ****************************************************************************/
365 BOOL add_privilege(PRIVILEGE_SET *priv_set, LUID_ATTR set)
366 {
367         LUID_ATTR *new_set;
368
369         /* check if the privilege is not already in the list */
370         if (check_priv_in_privilege(priv_set, set))
371                 return False;
372
373         /* we can allocate memory to add the new privilege */
374
375         new_set=(LUID_ATTR *)Realloc(priv_set->set, (priv_set->count+1)*(sizeof(LUID_ATTR)));
376         if (new_set==NULL) {
377                 DEBUG(0,("add_privilege: could not Realloc memory to add a new privilege\n"));
378                 return False;
379         }
380
381         new_set[priv_set->count].luid.high=set.luid.high;
382         new_set[priv_set->count].luid.low=set.luid.low;
383         new_set[priv_set->count].attr=set.attr;
384         
385         priv_set->count++;
386         priv_set->set=new_set;
387         
388         return True;    
389 }
390
391 /****************************************************************************
392 add all the privileges to a privilege array
393 ****************************************************************************/
394 BOOL add_all_privilege(PRIVILEGE_SET *priv_set)
395 {
396         LUID_ATTR set;
397
398         set.attr=0;
399         set.luid.high=0;
400         
401         set.luid.low=SE_PRIV_ADD_USERS;
402         add_privilege(priv_set, set);
403
404         set.luid.low=SE_PRIV_ADD_MACHINES;
405         add_privilege(priv_set, set);
406
407         set.luid.low=SE_PRIV_PRINT_OPERATOR;
408         add_privilege(priv_set, set);
409         
410         return True;
411 }
412
413 /****************************************************************************
414 check if the privilege list is empty
415 ****************************************************************************/
416 BOOL check_empty_privilege(PRIVILEGE_SET *priv_set)
417 {
418         return (priv_set->count == 0);
419 }
420
421 /****************************************************************************
422 check if the privilege is in the privilege list
423 ****************************************************************************/
424 BOOL check_priv_in_privilege(PRIVILEGE_SET *priv_set, LUID_ATTR set)
425 {
426         int i;
427
428         /* if the list is empty, obviously we can't have it */
429         if (check_empty_privilege(priv_set))
430                 return False;
431
432         for (i=0; i<priv_set->count; i++) {
433                 LUID_ATTR *cur_set;
434
435                 cur_set=&priv_set->set[i];
436                 /* check only the low and high part. Checking the attr field has no meaning */
437                 if( (cur_set->luid.low==set.luid.low) && (cur_set->luid.high==set.luid.high) )
438                         return True;
439         }
440
441         return False;
442 }
443
444 /****************************************************************************
445 remove a privilege from a privilege array
446 ****************************************************************************/
447 BOOL remove_privilege(PRIVILEGE_SET *priv_set, LUID_ATTR set)
448 {
449         LUID_ATTR *new_set;
450         LUID_ATTR *old_set;
451         int i,j;
452
453         /* check if the privilege is in the list */
454         if (!check_priv_in_privilege(priv_set, set))
455                 return False;
456
457         /* special case if it's the only privilege in the list */
458         if (priv_set->count==1) {
459                 free_privilege(priv_set);
460                 init_privilege(priv_set);       
461         
462                 return True;
463         }
464
465         /* 
466          * the privilege is there, create a new list,
467          * and copy the other privileges
468          */
469
470         old_set=priv_set->set;
471
472         new_set=(LUID_ATTR *)malloc((priv_set->count-1)*(sizeof(LUID_ATTR)));
473         if (new_set==NULL) {
474                 DEBUG(0,("remove_privilege: could not malloc memory for new privilege list\n"));
475                 return False;
476         }
477
478         for (i=0, j=0; i<priv_set->count; i++) {
479                 if ((old_set[i].luid.low==set.luid.low) && 
480                     (old_set[i].luid.high==set.luid.high)) {
481                         continue;
482                 }
483                 
484                 new_set[j].luid.low=old_set[i].luid.low;
485                 new_set[j].luid.high=old_set[i].luid.high;
486                 new_set[j].attr=old_set[i].attr;
487
488                 j++;
489         }
490         
491         if (j!=priv_set->count-1) {
492                 DEBUG(0,("remove_privilege: mismatch ! difference is not -1\n"));
493                 DEBUGADD(0,("old count:%d, new count:%d\n", priv_set->count, j));
494                 safe_free(new_set);
495                 return False;
496         }
497                 
498         /* ok everything is fine */
499         
500         priv_set->count--;
501         priv_set->set=new_set;
502         
503         safe_free(old_set);
504         
505         return True;    
506 }
507
508 /****************************************************************************
509  Return the sid and the type of the unix group.
510 ****************************************************************************/
511
512 static BOOL get_group_map_from_sid(DOM_SID sid, GROUP_MAP *map, BOOL with_priv)
513 {
514         TDB_DATA kbuf, dbuf;
515         pstring key;
516         fstring string_sid;
517         int ret;
518         int i;
519         PRIVILEGE_SET *set;
520         
521         if(!init_group_mapping()) {
522                 DEBUG(0,("failed to initialize group mapping"));
523                 return(False);
524         }
525
526         /* the key is the SID, retrieving is direct */
527
528         sid_to_string(string_sid, &sid);
529         slprintf(key, sizeof(key), "%s%s", GROUP_PREFIX, string_sid);
530
531         kbuf.dptr = key;
532         kbuf.dsize = strlen(key)+1;
533                 
534         dbuf = tdb_fetch(tdb, kbuf);
535         if (!dbuf.dptr)
536                 return False;
537
538         ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddffd",
539                                 &map->gid, &map->sid_name_use, &map->nt_name, &map->comment, &map->systemaccount);
540
541         set=&map->priv_set;
542         init_privilege(set);
543         ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "d", &set->count);
544
545         DEBUG(10,("get_group_map_from_sid: %d privileges\n", map->priv_set.count));
546
547         set->set = NULL;
548         if (set->count) {
549                 set->set=(LUID_ATTR *)smb_xmalloc(set->count*sizeof(LUID_ATTR));
550         }
551
552         for (i=0; i<set->count; i++)
553                 ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "ddd", 
554                                 &(set->set[i].luid.low), &(set->set[i].luid.high), &(set->set[i].attr));
555
556         SAFE_FREE(dbuf.dptr);
557         if (ret != dbuf.dsize) {
558                 DEBUG(0,("get_group_map_from_sid: group mapping TDB corrupted ?\n"));
559                 free_privilege(set);
560                 return False;
561         }
562
563         /* we don't want the privileges */
564         if (with_priv==MAPPING_WITHOUT_PRIV)
565                 free_privilege(set);
566
567         sid_copy(&map->sid, &sid);
568         
569         return True;
570 }
571
572 /****************************************************************************
573  Return the sid and the type of the unix group.
574 ****************************************************************************/
575
576 static BOOL get_group_map_from_gid(gid_t gid, GROUP_MAP *map, BOOL with_priv)
577 {
578         TDB_DATA kbuf, dbuf, newkey;
579         fstring string_sid;
580         int ret;
581         int i;
582         PRIVILEGE_SET *set;
583
584         if(!init_group_mapping()) {
585                 DEBUG(0,("failed to initialize group mapping"));
586                 return(False);
587         }
588
589         /* we need to enumerate the TDB to find the GID */
590
591         for (kbuf = tdb_firstkey(tdb); 
592              kbuf.dptr; 
593              newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
594
595                 if (strncmp(kbuf.dptr, GROUP_PREFIX, strlen(GROUP_PREFIX)) != 0) continue;
596                 
597                 dbuf = tdb_fetch(tdb, kbuf);
598                 if (!dbuf.dptr)
599                         continue;
600
601                 fstrcpy(string_sid, kbuf.dptr+strlen(GROUP_PREFIX));
602
603                 string_to_sid(&map->sid, string_sid);
604                 
605                 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddffd",
606                                  &map->gid, &map->sid_name_use, &map->nt_name, &map->comment, &map->systemaccount);
607
608                 set=&map->priv_set;
609                 ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "d", &set->count);
610                 set->set = NULL;
611                 if (set->count) {
612                         set->set=(LUID_ATTR *)smb_xmalloc(set->count*sizeof(LUID_ATTR));
613                 }
614
615                 for (i=0; i<set->count; i++)
616                         ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "ddd", 
617                                         &(set->set[i].luid.low), &(set->set[i].luid.high), &(set->set[i].attr));
618
619                 SAFE_FREE(dbuf.dptr);
620                 if (ret != dbuf.dsize){
621                         free_privilege(set);
622                         continue;
623                 }
624
625                 if (gid==map->gid) {
626                         if (!with_priv)
627                                 free_privilege(&map->priv_set);
628                         SAFE_FREE(kbuf.dptr);
629                         return True;
630                 }
631                 
632                 free_privilege(set);
633         }
634
635         return False;
636 }
637
638 /****************************************************************************
639  Return the sid and the type of the unix group.
640 ****************************************************************************/
641
642 static BOOL get_group_map_from_ntname(char *name, GROUP_MAP *map, BOOL with_priv)
643 {
644         TDB_DATA kbuf, dbuf, newkey;
645         fstring string_sid;
646         int ret;
647         int i;
648         PRIVILEGE_SET *set;
649
650         if(!init_group_mapping()) {
651                 DEBUG(0,("get_group_map_from_ntname:failed to initialize group mapping"));
652                 return(False);
653         }
654
655         /* we need to enumerate the TDB to find the name */
656
657         for (kbuf = tdb_firstkey(tdb); 
658              kbuf.dptr; 
659              newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
660
661                 if (strncmp(kbuf.dptr, GROUP_PREFIX, strlen(GROUP_PREFIX)) != 0) continue;
662                 
663                 dbuf = tdb_fetch(tdb, kbuf);
664                 if (!dbuf.dptr)
665                         continue;
666
667                 fstrcpy(string_sid, kbuf.dptr+strlen(GROUP_PREFIX));
668
669                 string_to_sid(&map->sid, string_sid);
670                 
671                 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddffd",
672                                  &map->gid, &map->sid_name_use, &map->nt_name, &map->comment, &map->systemaccount);
673
674                 set=&map->priv_set;
675                 ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "d", &set->count);
676         
677                 set->set=(LUID_ATTR *)malloc(set->count*sizeof(LUID_ATTR));
678                 if (set->set==NULL) {
679                         DEBUG(0,("get_group_map_from_ntname: could not allocate memory for privileges\n"));
680                         return False;
681                 }
682
683                 for (i=0; i<set->count; i++)
684                         ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "ddd", 
685                                         &(set->set[i].luid.low), &(set->set[i].luid.high), &(set->set[i].attr));
686
687                 SAFE_FREE(dbuf.dptr);
688                 if (ret != dbuf.dsize) {
689                         free_privilege(set);
690                         continue;
691                 }
692
693                 if (StrCaseCmp(name, map->nt_name)==0) {
694                         if (!with_priv)
695                                 free_privilege(&map->priv_set);
696                         SAFE_FREE(kbuf.dptr);
697                         return True;
698                 }
699
700                 free_privilege(set);
701         }
702
703         return False;
704 }
705
706 /****************************************************************************
707  Remove a group mapping entry.
708 ****************************************************************************/
709
710 static BOOL group_map_remove(DOM_SID sid)
711 {
712         TDB_DATA kbuf, dbuf;
713         pstring key;
714         fstring string_sid;
715         
716         if(!init_group_mapping()) {
717                 DEBUG(0,("failed to initialize group mapping"));
718                 return(False);
719         }
720
721         /* the key is the SID, retrieving is direct */
722
723         sid_to_string(string_sid, &sid);
724         slprintf(key, sizeof(key), "%s%s", GROUP_PREFIX, string_sid);
725
726         kbuf.dptr = key;
727         kbuf.dsize = strlen(key)+1;
728                 
729         dbuf = tdb_fetch(tdb, kbuf);
730         if (!dbuf.dptr)
731                 return False;
732         
733         SAFE_FREE(dbuf.dptr);
734
735         if(tdb_delete(tdb, kbuf) != TDB_SUCCESS)
736                 return False;
737
738         return True;
739 }
740
741 /****************************************************************************
742  Enumerate the group mapping.
743 ****************************************************************************/
744
745 static BOOL enum_group_mapping(enum SID_NAME_USE sid_name_use, GROUP_MAP **rmap,
746                         int *num_entries, BOOL unix_only, BOOL with_priv)
747 {
748         TDB_DATA kbuf, dbuf, newkey;
749         fstring string_sid;
750         fstring group_type;
751         GROUP_MAP map;
752         GROUP_MAP *mapt;
753         int ret;
754         int entries=0;
755         int i;
756         PRIVILEGE_SET *set;
757
758         if(!init_group_mapping()) {
759                 DEBUG(0,("failed to initialize group mapping"));
760                 return(False);
761         }
762
763         *num_entries=0;
764         *rmap=NULL;
765
766         for (kbuf = tdb_firstkey(tdb); 
767              kbuf.dptr; 
768              newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
769
770                 if (strncmp(kbuf.dptr, GROUP_PREFIX, strlen(GROUP_PREFIX)) != 0)
771                         continue;
772
773                 dbuf = tdb_fetch(tdb, kbuf);
774                 if (!dbuf.dptr)
775                         continue;
776
777                 fstrcpy(string_sid, kbuf.dptr+strlen(GROUP_PREFIX));
778                                 
779                 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddffd",
780                                  &map.gid, &map.sid_name_use, &map.nt_name, &map.comment, &map.systemaccount);
781
782                 set=&map.priv_set;
783                 init_privilege(set);
784                 
785                 ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "d", &set->count);
786         
787                 if (set->count!=0) {
788                         set->set=(LUID_ATTR *)malloc(set->count*sizeof(LUID_ATTR));
789                         if (set->set==NULL) {
790                                 DEBUG(0,("enum_group_mapping: could not allocate memory for privileges\n"));
791                                 return False;
792                         }
793                 }
794
795                 for (i=0; i<set->count; i++)
796                         ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "ddd", 
797                                         &(set->set[i].luid.low), &(set->set[i].luid.high), &(set->set[i].attr));
798
799                 SAFE_FREE(dbuf.dptr);
800                 if (ret != dbuf.dsize) {
801                         DEBUG(11,("enum_group_mapping: error in memory size\n"));
802                         free_privilege(set);
803                         continue;
804                 }
805
806                 /* list only the type or everything if UNKNOWN */
807                 if (sid_name_use!=SID_NAME_UNKNOWN  && sid_name_use!=map.sid_name_use) {
808                         DEBUG(11,("enum_group_mapping: group %s is not of the requested type\n", map.nt_name));
809                         free_privilege(set);
810                         continue;
811                 }
812
813                 if (unix_only==ENUM_ONLY_MAPPED && map.gid==-1) {
814                         DEBUG(11,("enum_group_mapping: group %s is non mapped\n", map.nt_name));
815                         free_privilege(set);
816                         continue;
817                 }
818
819                 string_to_sid(&map.sid, string_sid);
820                 
821                 decode_sid_name_use(group_type, map.sid_name_use);
822                 DEBUG(11,("enum_group_mapping: returning group %s of type %s\n", map.nt_name ,group_type));
823
824                 mapt=(GROUP_MAP *)Realloc((*rmap), (entries+1)*sizeof(GROUP_MAP));
825                 if (!mapt) {
826                         DEBUG(0,("enum_group_mapping: Unable to enlarge group map!\n"));
827                         SAFE_FREE(*rmap);
828                         free_privilege(set);
829                         return False;
830                 }
831                 else
832                         (*rmap) = mapt;
833
834                 mapt[entries].gid = map.gid;
835                 sid_copy( &mapt[entries].sid, &map.sid);
836                 mapt[entries].sid_name_use = map.sid_name_use;
837                 fstrcpy(mapt[entries].nt_name, map.nt_name);
838                 fstrcpy(mapt[entries].comment, map.comment);
839                 mapt[entries].systemaccount=map.systemaccount;
840                 mapt[entries].priv_set.count=set->count;
841                 mapt[entries].priv_set.control=set->control;
842                 mapt[entries].priv_set.set=set->set;
843                 if (!with_priv)
844                         free_privilege(&(mapt[entries].priv_set));
845
846                 entries++;
847
848         }
849
850         *num_entries=entries;
851
852         return True;
853 }
854
855
856 /****************************************************************************
857 convert a privilege string to a privilege array
858 ****************************************************************************/
859 void convert_priv_from_text(PRIVILEGE_SET *se_priv, char *privilege)
860 {
861         pstring tok;
862         const char *p = privilege;
863         int i;
864         LUID_ATTR set;
865
866         /* By default no privilege */
867         init_privilege(se_priv);
868         
869         if (privilege==NULL)
870                 return;
871
872         while(next_token(&p, tok, " ", sizeof(tok)) ) {
873                 for (i=0; i<=PRIV_ALL_INDEX; i++) {
874                         if (StrCaseCmp(privs[i].priv, tok)==0) {
875                                 set.attr=0;
876                                 set.luid.high=0;
877                                 set.luid.low=privs[i].se_priv;
878                                 add_privilege(se_priv, set);
879                         }
880                 }               
881         }
882 }
883
884 /****************************************************************************
885 convert a privilege array to a privilege string
886 ****************************************************************************/
887 void convert_priv_to_text(PRIVILEGE_SET *se_priv, char *privilege)
888 {
889         int i,j;
890
891         if (privilege==NULL)
892                 return;
893
894         ZERO_STRUCTP(privilege);
895
896         if (check_empty_privilege(se_priv)) {
897                 fstrcat(privilege, "No privilege");
898                 return;
899         }
900
901         for(i=0; i<se_priv->count; i++) {
902                 j=1;
903                 while (privs[j].se_priv!=se_priv->set[i].luid.low && j<=PRIV_ALL_INDEX) {
904                         j++;
905                 }
906
907                 fstrcat(privilege, privs[j].priv);
908                 fstrcat(privilege, " ");
909         }
910 }
911
912
913 /*
914  *
915  * High level functions
916  * better to use them than the lower ones.
917  *
918  * we are checking if the group is in the mapping file
919  * and if the group is an existing unix group
920  *
921  */
922
923 /* get a domain group from it's SID */
924
925 BOOL get_domain_group_from_sid(DOM_SID sid, GROUP_MAP *map, BOOL with_priv)
926 {
927         struct group *grp;
928
929         if(!init_group_mapping()) {
930                 DEBUG(0,("failed to initialize group mapping"));
931                 return(False);
932         }
933
934         DEBUG(10, ("get_domain_group_from_sid\n"));
935
936         /* if the group is NOT in the database, it CAN NOT be a domain group */
937         if(!pdb_getgrsid(map, sid, with_priv))
938                 return False;
939
940         DEBUG(10, ("get_domain_group_from_sid: SID found in the TDB\n"));
941
942         /* if it's not a domain group, continue */
943         if (map->sid_name_use!=SID_NAME_DOM_GRP) {
944                 if (with_priv)
945                         free_privilege(&map->priv_set);
946                 return False;
947         }
948
949         DEBUG(10, ("get_domain_group_from_sid: SID is a domain group\n"));
950         
951         if (map->gid==-1) {
952                 if (with_priv)
953                         free_privilege(&map->priv_set);
954                 return False;
955         }
956
957         DEBUG(10, ("get_domain_group_from_sid: SID is mapped to gid:%d\n",map->gid));
958
959         if ( (grp=getgrgid(map->gid)) == NULL) {
960                 DEBUG(10, ("get_domain_group_from_sid: gid DOESN'T exist in UNIX security\n"));
961                 if (with_priv)
962                         free_privilege(&map->priv_set);
963                 return False;
964         }
965
966         DEBUG(10, ("get_domain_group_from_sid: gid exists in UNIX security\n"));
967
968         return True;
969 }
970
971
972 /* get a local (alias) group from it's SID */
973
974 BOOL get_local_group_from_sid(DOM_SID sid, GROUP_MAP *map, BOOL with_priv)
975 {
976         struct group *grp;
977
978         if(!init_group_mapping()) {
979                 DEBUG(0,("failed to initialize group mapping"));
980                 return(False);
981         }
982
983         /* The group is in the mapping table */
984         if(pdb_getgrsid(map, sid, with_priv)) {
985                 if (map->sid_name_use!=SID_NAME_ALIAS) {
986                         if (with_priv)
987                                 free_privilege(&map->priv_set);
988                         return False;
989                 }
990                 
991                 if (map->gid==-1) {
992                         if (with_priv)
993                                 free_privilege(&map->priv_set);
994                         return False;
995                 }
996
997                 if ( (grp=getgrgid(map->gid)) == NULL) {
998                         if (with_priv)
999                                 free_privilege(&map->priv_set);
1000                         return False;
1001                 }
1002         } else {
1003                 /* the group isn't in the mapping table.
1004                  * make one based on the unix information */
1005                 uint32 alias_rid;
1006
1007                 sid_peek_rid(&sid, &alias_rid);
1008                 map->gid=pdb_group_rid_to_gid(alias_rid);
1009
1010                 if ((grp=getgrgid(map->gid)) == NULL)
1011                         return False;
1012
1013                 map->sid_name_use=SID_NAME_ALIAS;
1014                 map->systemaccount=PR_ACCESS_FROM_NETWORK;
1015
1016                 fstrcpy(map->nt_name, grp->gr_name);
1017                 fstrcpy(map->comment, "Local Unix Group");
1018
1019                 init_privilege(&map->priv_set);
1020
1021                 sid_copy(&map->sid, &sid);
1022         }
1023
1024         return True;
1025 }
1026
1027 /* get a builtin group from it's SID */
1028
1029 BOOL get_builtin_group_from_sid(DOM_SID sid, GROUP_MAP *map, BOOL with_priv)
1030 {
1031         struct group *grp;
1032
1033         if(!init_group_mapping()) {
1034                 DEBUG(0,("failed to initialize group mapping"));
1035                 return(False);
1036         }
1037
1038         if(!pdb_getgrsid(map, sid, with_priv))
1039                 return False;
1040
1041         if (map->sid_name_use!=SID_NAME_WKN_GRP) {
1042                 if (with_priv)
1043                         free_privilege(&map->priv_set);
1044                 return False;
1045         }
1046
1047         if (map->gid==-1) {
1048                 if (with_priv)
1049                         free_privilege(&map->priv_set);
1050                 return False;
1051         }
1052
1053         if ( (grp=getgrgid(map->gid)) == NULL) {
1054                 if (with_priv)
1055                         free_privilege(&map->priv_set);
1056                 return False;
1057         }
1058
1059         return True;
1060 }
1061
1062
1063
1064 /****************************************************************************
1065 Returns a GROUP_MAP struct based on the gid.
1066 ****************************************************************************/
1067 BOOL get_group_from_gid(gid_t gid, GROUP_MAP *map, BOOL with_priv)
1068 {
1069         struct group *grp;
1070
1071         if(!init_group_mapping()) {
1072                 DEBUG(0,("failed to initialize group mapping"));
1073                 return(False);
1074         }
1075
1076         if ( (grp=getgrgid(gid)) == NULL)
1077                 return False;
1078
1079         /*
1080          * make a group map from scratch if doesn't exist.
1081          */
1082         if (!pdb_getgrgid(map, gid, with_priv)) {
1083                 map->gid=gid;
1084                 map->sid_name_use=SID_NAME_ALIAS;
1085                 map->systemaccount=PR_ACCESS_FROM_NETWORK;
1086                 init_privilege(&map->priv_set);
1087
1088                 /* interim solution until we have a last RID allocated */
1089
1090                 sid_copy(&map->sid, get_global_sam_sid());
1091                 sid_append_rid(&map->sid, pdb_gid_to_group_rid(gid));
1092
1093                 fstrcpy(map->nt_name, grp->gr_name);
1094                 fstrcpy(map->comment, "Local Unix Group");
1095         }
1096         
1097         return True;
1098 }
1099
1100
1101
1102
1103 /****************************************************************************
1104  Get the member users of a group and
1105  all the users who have that group as primary.
1106             
1107  give back an array of uid
1108  return the grand number of users
1109
1110
1111  TODO: sort the list and remove duplicate. JFM.
1112
1113 ****************************************************************************/
1114         
1115 BOOL get_uid_list_of_group(gid_t gid, uid_t **uid, int *num_uids)
1116 {
1117         struct group *grp;
1118         struct passwd *pwd;
1119         int i=0;
1120         char *gr;
1121         uid_t *u;
1122  
1123         if(!init_group_mapping()) {
1124                 DEBUG(0,("failed to initialize group mapping"));
1125                 return(False);
1126         }
1127
1128         *num_uids = 0;
1129         *uid=NULL;
1130         
1131         if ( (grp=getgrgid(gid)) == NULL)
1132                 return False;
1133
1134         gr = grp->gr_mem[0];
1135         DEBUG(10, ("getting members\n"));
1136         
1137         while (gr && (*gr != (char)'\0')) {
1138                 u = Realloc((*uid), sizeof(uid_t)*(*num_uids+1));
1139                 if (!u) {
1140                         DEBUG(0,("get_uid_list_of_group: unable to enlarge uid list!\n"));
1141                         return False;
1142                 }
1143                 else (*uid) = u;
1144
1145                 if( (pwd=getpwnam_alloc(gr)) !=NULL) {
1146                         (*uid)[*num_uids]=pwd->pw_uid;
1147                         (*num_uids)++;
1148                 }
1149                 passwd_free(&pwd);
1150                 gr = grp->gr_mem[++i];
1151         }
1152         DEBUG(10, ("got [%d] members\n", *num_uids));
1153
1154         setpwent();
1155         while ((pwd=getpwent()) != NULL) {
1156                 if (pwd->pw_gid==gid) {
1157                         u = Realloc((*uid), sizeof(uid_t)*(*num_uids+1));
1158                         if (!u) {
1159                                 DEBUG(0,("get_uid_list_of_group: unable to enlarge uid list!\n"));
1160                                 return False;
1161                         }
1162                         else (*uid) = u;
1163                         (*uid)[*num_uids]=pwd->pw_uid;
1164
1165                         (*num_uids)++;
1166                 }
1167         }
1168         endpwent();
1169         DEBUG(10, ("got primary groups, members: [%d]\n", *num_uids));
1170
1171         return True;
1172 }
1173
1174 /****************************************************************************
1175  Create a UNIX group on demand.
1176 ****************************************************************************/
1177
1178 int smb_create_group(char *unix_group, gid_t *new_gid)
1179 {
1180         pstring add_script;
1181         int ret;
1182         int fd = 0;
1183
1184         pstrcpy(add_script, lp_addgroup_script());
1185         if (! *add_script) return -1;
1186         pstring_sub(add_script, "%g", unix_group);
1187         ret = smbrun(add_script, (new_gid!=NULL) ? &fd : NULL);
1188         DEBUG(3,("smb_create_group: Running the command `%s' gave %d\n",add_script,ret));
1189         if (ret != 0)
1190                 return ret;
1191
1192         if (fd != 0) {
1193                 fstring output;
1194
1195                 *new_gid = 0;
1196                 if (read(fd, output, sizeof(output)) > 0) {
1197                         *new_gid = (gid_t)strtoul(output, NULL, 10);
1198                 }
1199                 close(fd);
1200
1201                 if (*new_gid == 0) {
1202                         /* The output was garbage. We assume nobody
1203                            will create group 0 via smbd. Now we try to
1204                            get the group via getgrnam. */
1205
1206                         struct group *grp = getgrnam(unix_group);
1207                         if (grp != NULL)
1208                                 *new_gid = grp->gr_gid;
1209                         else
1210                                 return 1;
1211                 }
1212         }
1213
1214         return ret;
1215 }
1216
1217 /****************************************************************************
1218  Delete a UNIX group on demand.
1219 ****************************************************************************/
1220
1221 int smb_delete_group(char *unix_group)
1222 {
1223         pstring del_script;
1224         int ret;
1225
1226         pstrcpy(del_script, lp_delgroup_script());
1227         if (! *del_script) return -1;
1228         pstring_sub(del_script, "%g", unix_group);
1229         ret = smbrun(del_script,NULL);
1230         DEBUG(3,("smb_delete_group: Running the command `%s' gave %d\n",del_script,ret));
1231         return ret;
1232 }
1233
1234 /****************************************************************************
1235  Set a user's primary UNIX group.
1236 ****************************************************************************/
1237 int smb_set_primary_group(const char *unix_group, const char* unix_user)
1238 {
1239         pstring add_script;
1240         int ret;
1241
1242         pstrcpy(add_script, lp_setprimarygroup_script());
1243         if (! *add_script) return -1;
1244         all_string_sub(add_script, "%g", unix_group, sizeof(add_script));
1245         all_string_sub(add_script, "%u", unix_user, sizeof(add_script));
1246         ret = smbrun(add_script,NULL);
1247         DEBUG(3,("smb_set_primary_group: "
1248                  "Running the command `%s' gave %d\n",add_script,ret));
1249         return ret;
1250 }
1251
1252 /****************************************************************************
1253  Add a user to a UNIX group.
1254 ****************************************************************************/
1255
1256 int smb_add_user_group(char *unix_group, char *unix_user)
1257 {
1258         pstring add_script;
1259         int ret;
1260
1261         pstrcpy(add_script, lp_addusertogroup_script());
1262         if (! *add_script) return -1;
1263         pstring_sub(add_script, "%g", unix_group);
1264         pstring_sub(add_script, "%u", unix_user);
1265         ret = smbrun(add_script,NULL);
1266         DEBUG(3,("smb_add_user_group: Running the command `%s' gave %d\n",add_script,ret));
1267         return ret;
1268 }
1269
1270 /****************************************************************************
1271  Delete a user from a UNIX group
1272 ****************************************************************************/
1273
1274 int smb_delete_user_group(const char *unix_group, const char *unix_user)
1275 {
1276         pstring del_script;
1277         int ret;
1278
1279         pstrcpy(del_script, lp_deluserfromgroup_script());
1280         if (! *del_script) return -1;
1281         pstring_sub(del_script, "%g", unix_group);
1282         pstring_sub(del_script, "%u", unix_user);
1283         ret = smbrun(del_script,NULL);
1284         DEBUG(3,("smb_delete_user_group: Running the command `%s' gave %d\n",del_script,ret));
1285         return ret;
1286 }
1287
1288
1289 NTSTATUS pdb_default_getgrsid(struct pdb_methods *methods, GROUP_MAP *map,
1290                                  DOM_SID sid, BOOL with_priv)
1291 {
1292         return get_group_map_from_sid(sid, map, with_priv) ?
1293                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1294 }
1295
1296 NTSTATUS pdb_default_getgrgid(struct pdb_methods *methods, GROUP_MAP *map,
1297                                  gid_t gid, BOOL with_priv)
1298 {
1299         return get_group_map_from_gid(gid, map, with_priv) ?
1300                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1301 }
1302
1303 NTSTATUS pdb_default_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
1304                                  char *name, BOOL with_priv)
1305 {
1306         return get_group_map_from_ntname(name, map, with_priv) ?
1307                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1308 }
1309
1310 NTSTATUS pdb_default_add_group_mapping_entry(struct pdb_methods *methods,
1311                                                 GROUP_MAP *map)
1312 {
1313         return add_mapping_entry(map, TDB_INSERT) ?
1314                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1315 }
1316
1317 NTSTATUS pdb_default_update_group_mapping_entry(struct pdb_methods *methods,
1318                                                    GROUP_MAP *map)
1319 {
1320         return add_mapping_entry(map, TDB_REPLACE) ?
1321                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1322 }
1323
1324 NTSTATUS pdb_default_delete_group_mapping_entry(struct pdb_methods *methods,
1325                                                    DOM_SID sid)
1326 {
1327         return group_map_remove(sid) ?
1328                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1329 }
1330
1331 NTSTATUS pdb_default_enum_group_mapping(struct pdb_methods *methods,
1332                                            enum SID_NAME_USE sid_name_use,
1333                                            GROUP_MAP **rmap, int *num_entries,
1334                                            BOOL unix_only, BOOL with_priv)
1335 {
1336         return enum_group_mapping(sid_name_use, rmap, num_entries, unix_only,
1337                                   with_priv) ?
1338                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1339 }
1340
1341 /**********************************************************************
1342  no ops for passdb backends that don't implement group mapping
1343  *********************************************************************/
1344
1345 NTSTATUS pdb_nop_getgrsid(struct pdb_methods *methods, GROUP_MAP *map,
1346                                  DOM_SID sid, BOOL with_priv)
1347 {
1348         return NT_STATUS_UNSUCCESSFUL;
1349 }
1350
1351 NTSTATUS pdb_nop_getgrgid(struct pdb_methods *methods, GROUP_MAP *map,
1352                                  gid_t gid, BOOL with_priv)
1353 {
1354         return NT_STATUS_UNSUCCESSFUL;
1355 }
1356
1357 NTSTATUS pdb_nop_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
1358                                  char *name, BOOL with_priv)
1359 {
1360         return NT_STATUS_UNSUCCESSFUL;
1361 }
1362
1363 NTSTATUS pdb_nop_add_group_mapping_entry(struct pdb_methods *methods,
1364                                                 GROUP_MAP *map)
1365 {
1366         return NT_STATUS_UNSUCCESSFUL;
1367 }
1368
1369 NTSTATUS pdb_nop_update_group_mapping_entry(struct pdb_methods *methods,
1370                                                    GROUP_MAP *map)
1371 {
1372         return NT_STATUS_UNSUCCESSFUL;
1373 }
1374
1375 NTSTATUS pdb_nop_delete_group_mapping_entry(struct pdb_methods *methods,
1376                                                    DOM_SID sid)
1377 {
1378         return NT_STATUS_UNSUCCESSFUL;
1379 }
1380
1381 NTSTATUS pdb_nop_enum_group_mapping(struct pdb_methods *methods,
1382                                            enum SID_NAME_USE sid_name_use,
1383                                            GROUP_MAP **rmap, int *num_entries,
1384                                            BOOL unix_only, BOOL with_priv)
1385 {
1386         return NT_STATUS_UNSUCCESSFUL;
1387 }
1388