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