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