7b44df193fccfd72da0c6c027a41d8fc46ce61d4
[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 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 (strcasecmp(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, BOOL with_priv)
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, with_priv);
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, BOOL with_priv)
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, with_priv);
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, BOOL with_priv)
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, with_priv);
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, BOOL with_priv)
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                                                         with_priv);
387 }
388
389 /******************************************************************
390   Free and cleanup a pdb context, any associated data and anything
391   that the attached modules might have associated.
392  *******************************************************************/
393
394 static void free_pdb_context(struct pdb_context **context)
395 {
396         struct pdb_methods *pdb_selected = (*context)->pdb_methods;
397
398         while (pdb_selected){
399                 if(pdb_selected->free_private_data)
400                         pdb_selected->free_private_data(&(pdb_selected->private_data));
401                 pdb_selected = pdb_selected->next;
402         }
403
404         talloc_destroy((*context)->mem_ctx);
405         *context = NULL;
406 }
407
408 /******************************************************************
409   Make a pdb_methods from scratch
410  *******************************************************************/
411
412 static NTSTATUS make_pdb_methods_name(struct pdb_methods **methods, struct pdb_context *context, const char *selected)
413 {
414         char *module_name = smb_xstrdup(selected);
415         char *module_location = NULL, *p;
416         struct pdb_init_function_entry *entry;
417         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
418
419         lazy_initialize_passdb();
420
421         p = strchr(module_name, ':');
422
423         if (p) {
424                 *p = 0;
425                 module_location = p+1;
426                 trim_string(module_location, " ", " ");
427         }
428
429         trim_string(module_name, " ", " ");
430
431
432         DEBUG(5,("Attempting to find an passdb backend to match %s (%s)\n", selected, module_name));
433
434         entry = pdb_find_backend_entry(module_name);
435         
436         /* Try to find a module that contains this module */
437         if (!entry) { 
438                 DEBUG(2,("No builtin backend found, trying to load plugin\n"));
439                 if(NT_STATUS_IS_OK(smb_probe_module("pdb", module_name)) && !(entry = pdb_find_backend_entry(module_name))) {
440                         DEBUG(0,("Plugin is available, but doesn't register passdb backend %s\n", module_name));
441                         SAFE_FREE(module_name);
442                         return NT_STATUS_UNSUCCESSFUL;
443                 }
444         }
445         
446         /* No such backend found */
447         if(!entry) { 
448                 DEBUG(0,("No builtin nor plugin backend for %s found\n", module_name));
449                 SAFE_FREE(module_name);
450                 return NT_STATUS_INVALID_PARAMETER;
451         }
452
453         DEBUG(5,("Found pdb backend %s\n", module_name));
454         nt_status = entry->init(context, methods, module_location);
455         if (NT_STATUS_IS_OK(nt_status)) {
456                 DEBUG(5,("pdb backend %s has a valid init\n", selected));
457         } else {
458                 DEBUG(0,("pdb backend %s did not correctly init (error was %s)\n", selected, nt_errstr(nt_status)));
459         }
460         SAFE_FREE(module_name);
461         return nt_status;
462 }
463
464 /******************************************************************
465   Make a pdb_context from scratch.
466  *******************************************************************/
467
468 static NTSTATUS make_pdb_context(struct pdb_context **context) 
469 {
470         TALLOC_CTX *mem_ctx;
471
472         mem_ctx = talloc_init("pdb_context internal allocation context");
473
474         if (!mem_ctx) {
475                 DEBUG(0, ("make_pdb_context: talloc init failed!\n"));
476                 return NT_STATUS_NO_MEMORY;
477         }               
478
479         *context = talloc(mem_ctx, sizeof(**context));
480         if (!*context) {
481                 DEBUG(0, ("make_pdb_context: talloc failed!\n"));
482                 return NT_STATUS_NO_MEMORY;
483         }
484
485         ZERO_STRUCTP(*context);
486
487         (*context)->mem_ctx = mem_ctx;
488
489         (*context)->pdb_setsampwent = context_setsampwent;
490         (*context)->pdb_endsampwent = context_endsampwent;
491         (*context)->pdb_getsampwent = context_getsampwent;
492         (*context)->pdb_getsampwnam = context_getsampwnam;
493         (*context)->pdb_getsampwsid = context_getsampwsid;
494         (*context)->pdb_add_sam_account = context_add_sam_account;
495         (*context)->pdb_update_sam_account = context_update_sam_account;
496         (*context)->pdb_delete_sam_account = context_delete_sam_account;
497         (*context)->pdb_getgrsid = context_getgrsid;
498         (*context)->pdb_getgrgid = context_getgrgid;
499         (*context)->pdb_getgrnam = context_getgrnam;
500         (*context)->pdb_add_group_mapping_entry = context_add_group_mapping_entry;
501         (*context)->pdb_update_group_mapping_entry = context_update_group_mapping_entry;
502         (*context)->pdb_delete_group_mapping_entry = context_delete_group_mapping_entry;
503         (*context)->pdb_enum_group_mapping = context_enum_group_mapping;
504
505         (*context)->free_fn = free_pdb_context;
506
507         return NT_STATUS_OK;
508 }
509
510
511 /******************************************************************
512   Make a pdb_context, given an array of strings
513  *******************************************************************/
514
515 NTSTATUS make_pdb_context_list(struct pdb_context **context, const char **selected) 
516 {
517         int i = 0;
518         struct pdb_methods *curmethods, *tmpmethods;
519         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
520
521         if (!NT_STATUS_IS_OK(nt_status = make_pdb_context(context))) {
522                 return nt_status;
523         }
524
525         while (selected[i]){
526                 /* Try to initialise pdb */
527                 DEBUG(5,("Trying to load: %s\n", selected[i]));
528                 if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods_name(&curmethods, *context, selected[i]))) {
529                         DEBUG(1, ("Loading %s failed!\n", selected[i]));
530                         free_pdb_context(context);
531                         return nt_status;
532                 }
533                 curmethods->parent = *context;
534                 DLIST_ADD_END((*context)->pdb_methods, curmethods, tmpmethods);
535                 i++;
536         }
537
538         return NT_STATUS_OK;
539 }
540
541 /******************************************************************
542   Make a pdb_context, given a text string.
543  *******************************************************************/
544
545 NTSTATUS make_pdb_context_string(struct pdb_context **context, const char *selected) 
546 {
547         NTSTATUS ret;
548         char **newsel = str_list_make(selected, NULL);
549         ret = make_pdb_context_list(context, (const char **)newsel);
550         str_list_free(&newsel);
551         return ret;
552 }
553
554 /******************************************************************
555  Return an already initialised pdb_context, to facilitate backward 
556  compatibility (see functions below).
557 *******************************************************************/
558
559 static struct pdb_context *pdb_get_static_context(BOOL reload) 
560 {
561         static struct pdb_context *pdb_context = NULL;
562
563         if ((pdb_context) && (reload)) {
564                 pdb_context->free_fn(&pdb_context);
565                 if (NT_STATUS_IS_ERR(make_pdb_context_list(&pdb_context, lp_passdb_backend()))) {
566                         return NULL;
567                 }
568         }
569
570         if (!pdb_context) {
571                 if (NT_STATUS_IS_ERR(make_pdb_context_list(&pdb_context, lp_passdb_backend()))) {
572                         return NULL;
573                 }
574         }
575
576         return pdb_context;
577 }
578
579 /******************************************************************
580  Backward compatibility functions for the original passdb interface
581 *******************************************************************/
582
583 BOOL pdb_setsampwent(BOOL update) 
584 {
585         struct pdb_context *pdb_context = pdb_get_static_context(False);
586
587         if (!pdb_context) {
588                 return False;
589         }
590
591         return NT_STATUS_IS_OK(pdb_context->pdb_setsampwent(pdb_context, update));
592 }
593
594 void pdb_endsampwent(void) 
595 {
596         struct pdb_context *pdb_context = pdb_get_static_context(False);
597
598         if (!pdb_context) {
599                 return;
600         }
601
602         pdb_context->pdb_endsampwent(pdb_context);
603 }
604
605 BOOL pdb_getsampwent(SAM_ACCOUNT *user) 
606 {
607         struct pdb_context *pdb_context = pdb_get_static_context(False);
608
609         if (!pdb_context) {
610                 return False;
611         }
612
613         return NT_STATUS_IS_OK(pdb_context->pdb_getsampwent(pdb_context, user));
614 }
615
616 BOOL pdb_getsampwnam(SAM_ACCOUNT *sam_acct, const char *username) 
617 {
618         struct pdb_context *pdb_context = pdb_get_static_context(False);
619
620         if (!pdb_context) {
621                 return False;
622         }
623
624         return NT_STATUS_IS_OK(pdb_context->pdb_getsampwnam(pdb_context, sam_acct, username));
625 }
626
627 BOOL pdb_getsampwsid(SAM_ACCOUNT *sam_acct, const DOM_SID *sid) 
628 {
629         struct pdb_context *pdb_context = pdb_get_static_context(False);
630
631         if (!pdb_context) {
632                 return False;
633         }
634
635         return NT_STATUS_IS_OK(pdb_context->pdb_getsampwsid(pdb_context, sam_acct, sid));
636 }
637
638 BOOL pdb_add_sam_account(SAM_ACCOUNT *sam_acct) 
639 {
640         struct pdb_context *pdb_context = pdb_get_static_context(False);
641
642         if (!pdb_context) {
643                 return False;
644         }
645
646         return NT_STATUS_IS_OK(pdb_context->pdb_add_sam_account(pdb_context, sam_acct));
647 }
648
649 BOOL pdb_update_sam_account(SAM_ACCOUNT *sam_acct) 
650 {
651         struct pdb_context *pdb_context = pdb_get_static_context(False);
652
653         if (!pdb_context) {
654                 return False;
655         }
656
657         return NT_STATUS_IS_OK(pdb_context->pdb_update_sam_account(pdb_context, sam_acct));
658 }
659
660 BOOL pdb_delete_sam_account(SAM_ACCOUNT *sam_acct) 
661 {
662         struct pdb_context *pdb_context = pdb_get_static_context(False);
663
664         if (!pdb_context) {
665                 return False;
666         }
667
668         return NT_STATUS_IS_OK(pdb_context->pdb_delete_sam_account(pdb_context, sam_acct));
669 }
670
671 BOOL pdb_getgrsid(GROUP_MAP *map, DOM_SID sid, BOOL with_priv)
672 {
673         struct pdb_context *pdb_context = pdb_get_static_context(False);
674
675         if (!pdb_context) {
676                 return False;
677         }
678
679         return NT_STATUS_IS_OK(pdb_context->
680                                pdb_getgrsid(pdb_context, map, sid, with_priv));
681 }
682
683 BOOL pdb_getgrgid(GROUP_MAP *map, gid_t gid, 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_getgrgid(pdb_context, map, gid, with_priv));
693 }
694
695 BOOL pdb_getgrnam(GROUP_MAP *map, char *name, 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_getgrnam(pdb_context, map, name, with_priv));
705 }
706
707 BOOL pdb_add_group_mapping_entry(GROUP_MAP *map)
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_add_group_mapping_entry(pdb_context, map));
717 }
718
719 BOOL pdb_update_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_update_group_mapping_entry(pdb_context, map));
729 }
730
731 BOOL pdb_delete_group_mapping_entry(DOM_SID sid)
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_delete_group_mapping_entry(pdb_context, sid));
741 }
742
743 BOOL pdb_enum_group_mapping(enum SID_NAME_USE sid_name_use, GROUP_MAP **rmap,
744                             int *num_entries, BOOL unix_only, BOOL with_priv)
745 {
746         struct pdb_context *pdb_context = pdb_get_static_context(False);
747
748         if (!pdb_context) {
749                 return False;
750         }
751
752         return NT_STATUS_IS_OK(pdb_context->
753                                pdb_enum_group_mapping(pdb_context, sid_name_use,
754                                                       rmap, num_entries, unix_only,
755                                                       with_priv));
756 }
757
758 /***************************************************************
759   Initialize the static context (at smbd startup etc). 
760
761   If uninitialised, context will auto-init on first use.
762  ***************************************************************/
763
764 BOOL initialize_password_db(BOOL reload)
765 {       
766         return (pdb_get_static_context(reload) != NULL);
767 }
768
769
770 /***************************************************************************
771   Default implementations of some functions.
772  ****************************************************************************/
773
774 static NTSTATUS pdb_default_getsampwnam (struct pdb_methods *methods, SAM_ACCOUNT *user, const char *sname)
775 {
776         return NT_STATUS_NO_SUCH_USER;
777 }
778
779 static NTSTATUS pdb_default_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const DOM_SID *sid)
780 {
781         return NT_STATUS_NO_SUCH_USER;
782 }
783
784 static NTSTATUS pdb_default_add_sam_account (struct pdb_methods *methods, SAM_ACCOUNT *newpwd)
785 {
786         DEBUG(0,("this backend (%s) should not be listed as the first passdb backend! You can't add users to it.\n", methods->name));
787         return NT_STATUS_NOT_IMPLEMENTED;
788 }
789
790 static NTSTATUS pdb_default_update_sam_account (struct pdb_methods *methods, SAM_ACCOUNT *newpwd)
791 {
792         return NT_STATUS_NOT_IMPLEMENTED;
793 }
794
795 static NTSTATUS pdb_default_delete_sam_account (struct pdb_methods *methods, SAM_ACCOUNT *pwd)
796 {
797         return NT_STATUS_NOT_IMPLEMENTED;
798 }
799
800 static NTSTATUS pdb_default_setsampwent(struct pdb_methods *methods, BOOL update)
801 {
802         return NT_STATUS_NOT_IMPLEMENTED;
803 }
804
805 static NTSTATUS pdb_default_getsampwent(struct pdb_methods *methods, SAM_ACCOUNT *user)
806 {
807         return NT_STATUS_NOT_IMPLEMENTED;
808 }
809
810 static void pdb_default_endsampwent(struct pdb_methods *methods)
811 {
812         return; /* NT_STATUS_NOT_IMPLEMENTED; */
813 }
814
815 NTSTATUS make_pdb_methods(TALLOC_CTX *mem_ctx, PDB_METHODS **methods) 
816 {
817         *methods = talloc(mem_ctx, sizeof(struct pdb_methods));
818
819         if (!*methods) {
820                 return NT_STATUS_NO_MEMORY;
821         }
822
823         ZERO_STRUCTP(*methods);
824
825         (*methods)->setsampwent = pdb_default_setsampwent;
826         (*methods)->endsampwent = pdb_default_endsampwent;
827         (*methods)->getsampwent = pdb_default_getsampwent;
828         (*methods)->getsampwnam = pdb_default_getsampwnam;
829         (*methods)->getsampwsid = pdb_default_getsampwsid;
830         (*methods)->add_sam_account = pdb_default_add_sam_account;
831         (*methods)->update_sam_account = pdb_default_update_sam_account;
832         (*methods)->delete_sam_account = pdb_default_delete_sam_account;
833
834         (*methods)->getgrsid = pdb_default_getgrsid;
835         (*methods)->getgrgid = pdb_default_getgrgid;
836         (*methods)->getgrnam = pdb_default_getgrnam;
837         (*methods)->add_group_mapping_entry = pdb_default_add_group_mapping_entry;
838         (*methods)->update_group_mapping_entry = pdb_default_update_group_mapping_entry;
839         (*methods)->delete_group_mapping_entry = pdb_default_delete_group_mapping_entry;
840         (*methods)->enum_group_mapping = pdb_default_enum_group_mapping;
841
842         return NT_STATUS_OK;
843 }