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