BIG patch...
[jra/samba/.git] / source3 / passdb / pdb_interface.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Password and authentication handling
4    Copyright (C) Andrew Bartlett                        2002
5    Copyright (C) Jelmer Vernooij                        2002
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 #undef DBGC_CLASS
25 #define DBGC_CLASS DBGC_PASSDB
26
27 /** List of various built-in passdb modules */
28 static const struct {
29     const char *name;
30     /* Function to create a member of the pdb_methods list */
31     pdb_init_function init;
32 } builtin_pdb_init_functions[] = {
33         { "smbpasswd", pdb_init_smbpasswd },
34         { "smbpasswd_nua", pdb_init_smbpasswd_nua },
35         { "tdbsam", pdb_init_tdbsam },
36         { "tdbsam_nua", pdb_init_tdbsam_nua },
37         { "ldapsam", pdb_init_ldapsam },
38         { "ldapsam_nua", pdb_init_ldapsam_nua },
39         { "unixsam", pdb_init_unixsam },
40         { "nisplussam", pdb_init_nisplussam },
41         { NULL, NULL}
42 };
43
44 static struct pdb_init_function_entry *backends;
45 static void lazy_initialize_passdb(void);
46
47 static void lazy_initialize_passdb()
48 {
49         int i;
50         static BOOL initialised = False;
51         
52         if(!initialised) {
53                 initialised = True;
54
55                 for(i = 0; builtin_pdb_init_functions[i].name; i++) {
56                         smb_register_passdb(builtin_pdb_init_functions[i].name, builtin_pdb_init_functions[i].init, PASSDB_INTERFACE_VERSION);
57                 }
58         }
59 }
60
61 BOOL smb_register_passdb(const char *name, pdb_init_function init, int version) 
62 {
63         struct pdb_init_function_entry *entry = backends;
64
65         if(version != PASSDB_INTERFACE_VERSION)
66                 return False;
67
68         DEBUG(5,("Attempting to register passdb backend %s\n", name));
69
70         /* Check for duplicates */
71         while(entry) { 
72                 if(strcasecmp(name, entry->name) == 0) { 
73                         DEBUG(0,("There already is a passdb backend registered with the name %s!\n", name));
74                         return False;
75                 }
76                 entry = entry->next;
77         }
78
79         entry = smb_xmalloc(sizeof(struct pdb_init_function_entry));
80         entry->name = name;
81         entry->init = init;
82
83         DLIST_ADD(backends, entry);
84         DEBUG(5,("Successfully added passdb backend '%s'\n", name));
85         return True;
86 }
87
88 static NTSTATUS context_setsampwent(struct pdb_context *context, BOOL update)
89 {
90         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
91
92         if (!context) {
93                 DEBUG(0, ("invalid pdb_context specified!\n"));
94                 return ret;
95         }
96
97         context->pwent_methods = context->pdb_methods;
98
99         if (!context->pwent_methods) {
100                 /* No passdbs at all */
101                 return ret;
102         }
103
104         while (NT_STATUS_IS_ERR(ret = context->pwent_methods->setsampwent(context->pwent_methods, update))) {
105                 context->pwent_methods = context->pwent_methods->next;
106                 if (context->pwent_methods == NULL) 
107                         return NT_STATUS_UNSUCCESSFUL;
108         }
109         return ret;
110 }
111
112 static void context_endsampwent(struct pdb_context *context)
113 {
114         if ((!context)){
115                 DEBUG(0, ("invalid pdb_context specified!\n"));
116                 return;
117         }
118
119         if (context->pwent_methods && context->pwent_methods->endsampwent)
120                 context->pwent_methods->endsampwent(context->pwent_methods);
121
122         /* So we won't get strange data when calling getsampwent now */
123         context->pwent_methods = NULL;
124 }
125
126 static NTSTATUS context_getsampwent(struct pdb_context *context, SAM_ACCOUNT *user)
127 {
128         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
129
130         if ((!context) || (!context->pwent_methods)) {
131                 DEBUG(0, ("invalid pdb_context specified!\n"));
132                 return ret;
133         }
134         /* Loop until we find something useful */
135         while (NT_STATUS_IS_ERR(ret = context->pwent_methods->getsampwent(context->pwent_methods, user))) {
136
137                 context->pwent_methods->endsampwent(context->pwent_methods);
138
139                 context->pwent_methods = context->pwent_methods->next;
140
141                 /* All methods are checked now. There are no more entries */
142                 if (context->pwent_methods == NULL)
143                         return ret;
144         
145                 context->pwent_methods->setsampwent(context->pwent_methods, False);
146         }
147         user->methods = context->pwent_methods;
148         return ret;
149 }
150
151 static NTSTATUS context_getsampwnam(struct pdb_context *context, SAM_ACCOUNT *sam_acct, const char *username)
152 {
153         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
154
155         struct pdb_methods *curmethods;
156         if ((!context)) {
157                 DEBUG(0, ("invalid pdb_context specified!\n"));
158                 return ret;
159         }
160         curmethods = context->pdb_methods;
161         while (curmethods){
162                 if (NT_STATUS_IS_OK(ret = curmethods->getsampwnam(curmethods, sam_acct, username))) {
163                         sam_acct->methods = curmethods;
164                         return ret;
165                 }
166                 curmethods = curmethods->next;
167         }
168
169         return ret;
170 }
171
172 static NTSTATUS context_getsampwsid(struct pdb_context *context, SAM_ACCOUNT *sam_acct, const DOM_SID *sid)
173 {
174         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
175
176         struct pdb_methods *curmethods;
177         if ((!context)) {
178                 DEBUG(0, ("invalid pdb_context specified!\n"));
179                 return ret;
180         }
181         
182         curmethods = context->pdb_methods;
183
184         while (curmethods){
185                 if (NT_STATUS_IS_OK(ret = curmethods->getsampwsid(curmethods, sam_acct, sid))) {
186                         sam_acct->methods = curmethods;
187                         return ret;
188                 }
189                 curmethods = curmethods->next;
190         }
191
192         return ret;
193 }
194
195 static NTSTATUS context_add_sam_account(struct pdb_context *context, SAM_ACCOUNT *sam_acct)
196 {
197         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
198
199         if ((!context) || (!context->pdb_methods)) {
200                 DEBUG(0, ("invalid pdb_context specified!\n"));
201                 return ret;
202         }
203
204         /** @todo  This is where a 're-read on add' should be done */
205         /* We now add a new account to the first database listed. 
206          * Should we? */
207
208         return context->pdb_methods->add_sam_account(context->pdb_methods, sam_acct);
209 }
210
211 static NTSTATUS context_update_sam_account(struct pdb_context *context, SAM_ACCOUNT *sam_acct)
212 {
213         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
214
215         if (!context) {
216                 DEBUG(0, ("invalid pdb_context specified!\n"));
217                 return ret;
218         }
219
220         if (!sam_acct || !sam_acct->methods){
221                 DEBUG(0, ("invalid sam_acct specified\n"));
222                 return ret;
223         }
224
225         /** @todo  This is where a 're-read on update' should be done */
226
227         return sam_acct->methods->update_sam_account(sam_acct->methods, sam_acct);
228 }
229
230 static NTSTATUS context_delete_sam_account(struct pdb_context *context, SAM_ACCOUNT *sam_acct)
231 {
232         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
233
234         struct pdb_methods *pdb_selected;
235         if (!context) {
236                 DEBUG(0, ("invalid pdb_context specified!\n"));
237                 return ret;
238         }
239
240         if (!sam_acct->methods){
241                 pdb_selected = context->pdb_methods;
242                 /* There's no passdb backend specified for this account.
243                  * Try to delete it in every passdb available 
244                  * Needed to delete accounts in smbpasswd that are not
245                  * in /etc/passwd.
246                  */
247                 while (pdb_selected){
248                         if (NT_STATUS_IS_OK(ret = pdb_selected->delete_sam_account(pdb_selected, sam_acct))) {
249                                 return ret;
250                         }
251                         pdb_selected = pdb_selected->next;
252                 }
253                 return ret;
254         }
255
256         if (!sam_acct->methods->delete_sam_account){
257                 DEBUG(0,("invalid sam_acct->methods->delete_sam_account\n"));
258                 return ret;
259         }
260         
261         return sam_acct->methods->delete_sam_account(sam_acct->methods, sam_acct);
262 }
263
264 static NTSTATUS context_getgrsid(struct pdb_context *context,
265                                  GROUP_MAP *map, DOM_SID sid, BOOL with_priv)
266 {
267         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
268
269         struct pdb_methods *curmethods;
270         if ((!context)) {
271                 DEBUG(0, ("invalid pdb_context specified!\n"));
272                 return ret;
273         }
274         curmethods = context->pdb_methods;
275         while (curmethods){
276                 ret = curmethods->getgrsid(curmethods, map, sid, with_priv);
277                 if (NT_STATUS_IS_OK(ret)) {
278                         map->methods = curmethods;
279                         return ret;
280                 }
281                 curmethods = curmethods->next;
282         }
283
284         return ret;
285 }
286
287 static NTSTATUS context_getgrgid(struct pdb_context *context,
288                                  GROUP_MAP *map, gid_t gid, BOOL with_priv)
289 {
290         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
291
292         struct pdb_methods *curmethods;
293         if ((!context)) {
294                 DEBUG(0, ("invalid pdb_context specified!\n"));
295                 return ret;
296         }
297         curmethods = context->pdb_methods;
298         while (curmethods){
299                 ret = curmethods->getgrgid(curmethods, map, gid, with_priv);
300                 if (NT_STATUS_IS_OK(ret)) {
301                         map->methods = curmethods;
302                         return ret;
303                 }
304                 curmethods = curmethods->next;
305         }
306
307         return ret;
308 }
309
310 static NTSTATUS context_getgrnam(struct pdb_context *context,
311                                  GROUP_MAP *map, char *name, BOOL with_priv)
312 {
313         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
314
315         struct pdb_methods *curmethods;
316         if ((!context)) {
317                 DEBUG(0, ("invalid pdb_context specified!\n"));
318                 return ret;
319         }
320         curmethods = context->pdb_methods;
321         while (curmethods){
322                 ret = curmethods->getgrnam(curmethods, map, name, with_priv);
323                 if (NT_STATUS_IS_OK(ret)) {
324                         map->methods = curmethods;
325                         return ret;
326                 }
327                 curmethods = curmethods->next;
328         }
329
330         return ret;
331 }
332
333 static NTSTATUS context_add_group_mapping_entry(struct pdb_context *context,
334                                                 GROUP_MAP *map)
335 {
336         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
337
338         if ((!context) || (!context->pdb_methods)) {
339                 DEBUG(0, ("invalid pdb_context specified!\n"));
340                 return ret;
341         }
342
343         return context->pdb_methods->add_group_mapping_entry(context->pdb_methods,
344                                                              map);
345 }
346
347 static NTSTATUS context_update_group_mapping_entry(struct pdb_context *context,
348                                                    GROUP_MAP *map)
349 {
350         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
351
352         if ((!context) || (!context->pdb_methods)) {
353                 DEBUG(0, ("invalid pdb_context specified!\n"));
354                 return ret;
355         }
356
357         return context->
358                 pdb_methods->update_group_mapping_entry(context->pdb_methods, map);
359 }
360
361 static NTSTATUS context_delete_group_mapping_entry(struct pdb_context *context,
362                                                    DOM_SID sid)
363 {
364         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
365
366         if ((!context) || (!context->pdb_methods)) {
367                 DEBUG(0, ("invalid pdb_context specified!\n"));
368                 return ret;
369         }
370
371         return context->
372                 pdb_methods->delete_group_mapping_entry(context->pdb_methods, sid);
373 }
374
375 static NTSTATUS context_enum_group_mapping(struct pdb_context *context,
376                                            enum SID_NAME_USE sid_name_use,
377                                            GROUP_MAP **rmap, int *num_entries,
378                                            BOOL unix_only, BOOL with_priv)
379 {
380         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
381
382         if ((!context) || (!context->pdb_methods)) {
383                 DEBUG(0, ("invalid pdb_context specified!\n"));
384                 return ret;
385         }
386
387         return context->pdb_methods->enum_group_mapping(context->pdb_methods,
388                                                         sid_name_use, rmap,
389                                                         num_entries, unix_only,
390                                                         with_priv);
391 }
392
393 /******************************************************************
394   Free and cleanup a pdb context, any associated data and anything
395   that the attached modules might have associated.
396  *******************************************************************/
397
398 static void free_pdb_context(struct pdb_context **context)
399 {
400         struct pdb_methods *pdb_selected = (*context)->pdb_methods;
401
402         while (pdb_selected){
403                 if(pdb_selected->free_private_data)
404                         pdb_selected->free_private_data(&(pdb_selected->private_data));
405                 pdb_selected = pdb_selected->next;
406         }
407
408         talloc_destroy((*context)->mem_ctx);
409         *context = NULL;
410 }
411
412 /******************************************************************
413   Make a pdb_methods from scratch
414  *******************************************************************/
415
416 static NTSTATUS make_pdb_methods_name(struct pdb_methods **methods, struct pdb_context *context, const char *selected)
417 {
418         char *module_name = smb_xstrdup(selected);
419         char *module_location = NULL, *p;
420         struct pdb_init_function_entry *entry;
421         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
422
423         lazy_initialize_passdb();
424
425         entry = backends;
426
427         p = strchr(module_name, ':');
428
429         if (p) {
430                 *p = 0;
431                 module_location = p+1;
432                 trim_string(module_location, " ", " ");
433         }
434
435         trim_string(module_name, " ", " ");
436
437         DEBUG(5,("Attempting to find an passdb backend to match %s (%s)\n", selected, module_name));
438         while(entry) {
439                 if (strequal(entry->name, module_name))
440                 {
441                         DEBUG(5,("Found pdb backend %s\n", module_name));
442                         nt_status = entry->init(context, methods, module_location);
443                         if (NT_STATUS_IS_OK(nt_status)) {
444                                 DEBUG(5,("pdb backend %s has a valid init\n", selected));
445                         } else {
446                                 DEBUG(0,("pdb backend %s did not correctly init (error was %s)\n", selected, nt_errstr(nt_status)));
447                         }
448                         SAFE_FREE(module_name);
449                         return nt_status;
450                         break; /* unreached */
451                 }
452                 entry = entry->next;
453         }
454
455         /* No such backend found */
456         SAFE_FREE(module_name);
457         return NT_STATUS_INVALID_PARAMETER;
458 }
459
460 /******************************************************************
461   Make a pdb_context from scratch.
462  *******************************************************************/
463
464 static NTSTATUS make_pdb_context(struct pdb_context **context) 
465 {
466         TALLOC_CTX *mem_ctx;
467
468         mem_ctx = talloc_init("pdb_context internal allocation context");
469
470         if (!mem_ctx) {
471                 DEBUG(0, ("make_pdb_context: talloc init failed!\n"));
472                 return NT_STATUS_NO_MEMORY;
473         }               
474
475         *context = talloc(mem_ctx, sizeof(**context));
476         if (!*context) {
477                 DEBUG(0, ("make_pdb_context: talloc failed!\n"));
478                 return NT_STATUS_NO_MEMORY;
479         }
480
481         ZERO_STRUCTP(*context);
482
483         (*context)->mem_ctx = mem_ctx;
484
485         (*context)->pdb_setsampwent = context_setsampwent;
486         (*context)->pdb_endsampwent = context_endsampwent;
487         (*context)->pdb_getsampwent = context_getsampwent;
488         (*context)->pdb_getsampwnam = context_getsampwnam;
489         (*context)->pdb_getsampwsid = context_getsampwsid;
490         (*context)->pdb_add_sam_account = context_add_sam_account;
491         (*context)->pdb_update_sam_account = context_update_sam_account;
492         (*context)->pdb_delete_sam_account = context_delete_sam_account;
493         (*context)->pdb_getgrsid = context_getgrsid;
494         (*context)->pdb_getgrgid = context_getgrgid;
495         (*context)->pdb_getgrnam = context_getgrnam;
496         (*context)->pdb_add_group_mapping_entry = context_add_group_mapping_entry;
497         (*context)->pdb_update_group_mapping_entry = context_update_group_mapping_entry;
498         (*context)->pdb_delete_group_mapping_entry = context_delete_group_mapping_entry;
499         (*context)->pdb_enum_group_mapping = context_enum_group_mapping;
500
501         (*context)->free_fn = free_pdb_context;
502
503         return NT_STATUS_OK;
504 }
505
506
507 /******************************************************************
508   Make a pdb_context, given an array of strings
509  *******************************************************************/
510
511 NTSTATUS make_pdb_context_list(struct pdb_context **context, const char **selected) 
512 {
513         int i = 0;
514         struct pdb_methods *curmethods, *tmpmethods;
515         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
516
517         if (!NT_STATUS_IS_OK(nt_status = make_pdb_context(context))) {
518                 return nt_status;
519         }
520
521         while (selected[i]){
522                 /* Try to initialise pdb */
523                 DEBUG(5,("Trying to load: %s\n", selected[i]));
524                 if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods_name(&curmethods, *context, selected[i]))) {
525                         DEBUG(1, ("Loading %s failed!\n", selected[i]));
526                         free_pdb_context(context);
527                         return nt_status;
528                 }
529                 curmethods->parent = *context;
530                 DLIST_ADD_END((*context)->pdb_methods, curmethods, tmpmethods);
531                 i++;
532         }
533
534         return NT_STATUS_OK;
535 }
536
537 /******************************************************************
538   Make a pdb_context, given a text string.
539  *******************************************************************/
540
541 NTSTATUS make_pdb_context_string(struct pdb_context **context, const char *selected) 
542 {
543         NTSTATUS ret;
544         char **newsel = str_list_make(selected, NULL);
545         ret = make_pdb_context_list(context, (const char **)newsel);
546         str_list_free(&newsel);
547         return ret;
548 }
549
550 /******************************************************************
551  Return an already initialised pdb_context, to facilitate backward 
552  compatibility (see functions below).
553 *******************************************************************/
554
555 static struct pdb_context *pdb_get_static_context(BOOL reload) 
556 {
557         static struct pdb_context *pdb_context = NULL;
558
559         if ((pdb_context) && (reload)) {
560                 pdb_context->free_fn(&pdb_context);
561                 if (NT_STATUS_IS_ERR(make_pdb_context_list(&pdb_context, lp_passdb_backend()))) {
562                         return NULL;
563                 }
564         }
565
566         if (!pdb_context) {
567                 if (NT_STATUS_IS_ERR(make_pdb_context_list(&pdb_context, lp_passdb_backend()))) {
568                         return NULL;
569                 }
570         }
571
572         return pdb_context;
573 }
574
575 /******************************************************************
576  Backward compatibility functions for the original passdb interface
577 *******************************************************************/
578
579 BOOL pdb_setsampwent(BOOL update) 
580 {
581         struct pdb_context *pdb_context = pdb_get_static_context(False);
582
583         if (!pdb_context) {
584                 return False;
585         }
586
587         return NT_STATUS_IS_OK(pdb_context->pdb_setsampwent(pdb_context, update));
588 }
589
590 void pdb_endsampwent(void) 
591 {
592         struct pdb_context *pdb_context = pdb_get_static_context(False);
593
594         if (!pdb_context) {
595                 return;
596         }
597
598         pdb_context->pdb_endsampwent(pdb_context);
599 }
600
601 BOOL pdb_getsampwent(SAM_ACCOUNT *user) 
602 {
603         struct pdb_context *pdb_context = pdb_get_static_context(False);
604
605         if (!pdb_context) {
606                 return False;
607         }
608
609         return NT_STATUS_IS_OK(pdb_context->pdb_getsampwent(pdb_context, user));
610 }
611
612 BOOL pdb_getsampwnam(SAM_ACCOUNT *sam_acct, const char *username) 
613 {
614         struct pdb_context *pdb_context = pdb_get_static_context(False);
615
616         if (!pdb_context) {
617                 return False;
618         }
619
620         return NT_STATUS_IS_OK(pdb_context->pdb_getsampwnam(pdb_context, sam_acct, username));
621 }
622
623 BOOL pdb_getsampwsid(SAM_ACCOUNT *sam_acct, const DOM_SID *sid) 
624 {
625         struct pdb_context *pdb_context = pdb_get_static_context(False);
626
627         if (!pdb_context) {
628                 return False;
629         }
630
631         return NT_STATUS_IS_OK(pdb_context->pdb_getsampwsid(pdb_context, sam_acct, sid));
632 }
633
634 BOOL pdb_add_sam_account(SAM_ACCOUNT *sam_acct) 
635 {
636         struct pdb_context *pdb_context = pdb_get_static_context(False);
637
638         if (!pdb_context) {
639                 return False;
640         }
641
642         return NT_STATUS_IS_OK(pdb_context->pdb_add_sam_account(pdb_context, sam_acct));
643 }
644
645 BOOL pdb_update_sam_account(SAM_ACCOUNT *sam_acct) 
646 {
647         struct pdb_context *pdb_context = pdb_get_static_context(False);
648
649         if (!pdb_context) {
650                 return False;
651         }
652
653         return NT_STATUS_IS_OK(pdb_context->pdb_update_sam_account(pdb_context, sam_acct));
654 }
655
656 BOOL pdb_delete_sam_account(SAM_ACCOUNT *sam_acct) 
657 {
658         struct pdb_context *pdb_context = pdb_get_static_context(False);
659
660         if (!pdb_context) {
661                 return False;
662         }
663
664         return NT_STATUS_IS_OK(pdb_context->pdb_delete_sam_account(pdb_context, sam_acct));
665 }
666
667 BOOL pdb_getgrsid(GROUP_MAP *map, DOM_SID sid, BOOL with_priv)
668 {
669         struct pdb_context *pdb_context = pdb_get_static_context(False);
670
671         if (!pdb_context) {
672                 return False;
673         }
674
675         return NT_STATUS_IS_OK(pdb_context->
676                                pdb_getgrsid(pdb_context, map, sid, with_priv));
677 }
678
679 BOOL pdb_getgrgid(GROUP_MAP *map, gid_t gid, BOOL with_priv)
680 {
681         struct pdb_context *pdb_context = pdb_get_static_context(False);
682
683         if (!pdb_context) {
684                 return False;
685         }
686
687         return NT_STATUS_IS_OK(pdb_context->
688                                pdb_getgrgid(pdb_context, map, gid, with_priv));
689 }
690
691 BOOL pdb_getgrnam(GROUP_MAP *map, char *name, BOOL with_priv)
692 {
693         struct pdb_context *pdb_context = pdb_get_static_context(False);
694
695         if (!pdb_context) {
696                 return False;
697         }
698
699         return NT_STATUS_IS_OK(pdb_context->
700                                pdb_getgrnam(pdb_context, map, name, with_priv));
701 }
702
703 BOOL pdb_add_group_mapping_entry(GROUP_MAP *map)
704 {
705         struct pdb_context *pdb_context = pdb_get_static_context(False);
706
707         if (!pdb_context) {
708                 return False;
709         }
710
711         return NT_STATUS_IS_OK(pdb_context->
712                                pdb_add_group_mapping_entry(pdb_context, map));
713 }
714
715 BOOL pdb_update_group_mapping_entry(GROUP_MAP *map)
716 {
717         struct pdb_context *pdb_context = pdb_get_static_context(False);
718
719         if (!pdb_context) {
720                 return False;
721         }
722
723         return NT_STATUS_IS_OK(pdb_context->
724                                pdb_update_group_mapping_entry(pdb_context, map));
725 }
726
727 BOOL pdb_delete_group_mapping_entry(DOM_SID sid)
728 {
729         struct pdb_context *pdb_context = pdb_get_static_context(False);
730
731         if (!pdb_context) {
732                 return False;
733         }
734
735         return NT_STATUS_IS_OK(pdb_context->
736                                pdb_delete_group_mapping_entry(pdb_context, sid));
737 }
738
739 BOOL pdb_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         struct pdb_context *pdb_context = pdb_get_static_context(False);
743
744         if (!pdb_context) {
745                 return False;
746         }
747
748         return NT_STATUS_IS_OK(pdb_context->
749                                pdb_enum_group_mapping(pdb_context, sid_name_use,
750                                                       rmap, num_entries, unix_only,
751                                                       with_priv));
752 }
753
754 /***************************************************************
755   Initialize the static context (at smbd startup etc). 
756
757   If uninitialised, context will auto-init on first use.
758  ***************************************************************/
759
760 BOOL initialize_password_db(BOOL reload)
761 {       
762         return (pdb_get_static_context(reload) != NULL);
763 }
764
765
766 NTSTATUS make_pdb_methods(TALLOC_CTX *mem_ctx, PDB_METHODS **methods) 
767 {
768         *methods = talloc(mem_ctx, sizeof(struct pdb_methods));
769
770         if (!*methods) {
771                 return NT_STATUS_NO_MEMORY;
772         }
773
774         ZERO_STRUCTP(*methods);
775
776         return NT_STATUS_OK;
777 }