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