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