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