Prototype version of trust passwords moved to SAM/pdb. This is
[vlendec/samba-autobuild/.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 static NTSTATUS context_gettrustpwent(struct pdb_context *context,
389                                       SAM_TRUST_PASSWD *trust)
390 {
391         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
392         struct pdb_methods *cur_methods;
393         
394         if (!context) {
395                 DEBUG(0, ("invalid pdb_context specified!\n"));
396                 return ret;
397         }
398         
399         cur_methods = context->pdb_methods;
400         
401         while (cur_methods) {
402                 ret = cur_methods->gettrustpwent(cur_methods, trust);
403                 if (NT_STATUS_IS_OK(ret)) {
404                         trust->methods = cur_methods;
405                         return ret;
406                 }
407                 cur_methods = cur_methods->next;
408         }
409         
410         return ret;
411 }
412
413 static NTSTATUS context_gettrustpwsid(struct pdb_context *context,
414                                       SAM_TRUST_PASSWD *trust,
415                                       const DOM_SID *sid)
416 {
417         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
418         struct pdb_methods *cur_methods;
419         
420         if (!context) {
421                 DEBUG(0, ("invalid pdb_context specified!\n"));
422                 return ret;
423         }
424         
425         cur_methods = context->pdb_methods;
426         
427         while (cur_methods) {
428                 ret = cur_methods->gettrustpwsid(cur_methods, trust, sid);
429                 if (NT_STATUS_IS_OK(ret)) {
430                         trust->methods = cur_methods;
431                         return ret;
432                 }
433                 cur_methods = cur_methods->next;
434         }
435         
436         return ret;
437 }
438
439 static NTSTATUS context_add_trust_passwd(struct pdb_context *context,
440                                          SAM_TRUST_PASSWD *trust)
441 {
442         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
443         struct pdb_methods *methods;
444         
445         if (!context) {
446                 DEBUG(0, ("invalid pdb_context specified!\n"));
447                 return ret;
448         }
449         
450         return context->pdb_methods->add_trust_passwd(context->pdb_methods, trust);
451 }
452
453 static NTSTATUS context_update_trust_passwd(struct pdb_context *context,
454                                             SAM_TRUST_PASSWD *trust)
455 {
456         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
457         struct pdb_methods *methods;
458         
459         if (!context) {
460                 DEBUG(0, ("invalid pdb_context specified!\n"));
461                 return ret;
462         }
463         
464         if (!trust || !trust->methods) {
465                 DEBUG(0, ("invalid trust pointer specified!\n"));
466                 return ret;
467         }
468         
469         return trust->methods->update_trust_passwd(trust->methods, trust);
470 }
471
472 static NTSTATUS context_delete_trust_passwd(struct pdb_context *context,
473                                             SAM_TRUST_PASSWD *trust)
474 {
475         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
476         struct pdb_methods *methods;
477         
478         if (!context) {
479                 DEBUG(0, ("invalid pdb_context specified!\n"));
480                 return ret;
481         }
482         
483         if (!trust || !trust->methods) {
484                 DEBUG(0, ("invalid trust pointer specified!\n"));
485                 return ret;
486         }
487         
488         return trust->methods->delete_trust_passwd(trust->methods, trust);
489 }
490
491 /******************************************************************
492   Free and cleanup a pdb context, any associated data and anything
493   that the attached modules might have associated.
494  *******************************************************************/
495
496 static void free_pdb_context(struct pdb_context **context)
497 {
498         struct pdb_methods *pdb_selected = (*context)->pdb_methods;
499
500         while (pdb_selected){
501                 if(pdb_selected->free_private_data)
502                         pdb_selected->free_private_data(&(pdb_selected->private_data));
503                 pdb_selected = pdb_selected->next;
504         }
505
506         talloc_destroy((*context)->mem_ctx);
507         *context = NULL;
508 }
509
510 /******************************************************************
511   Make a pdb_methods from scratch
512  *******************************************************************/
513
514 static NTSTATUS make_pdb_methods_name(struct pdb_methods **methods, struct pdb_context *context, const char *selected)
515 {
516         char *module_name = smb_xstrdup(selected);
517         char *module_location = NULL, *p;
518         struct pdb_init_function_entry *entry;
519         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
520
521         lazy_initialize_passdb();
522
523         p = strchr(module_name, ':');
524
525         if (p) {
526                 *p = 0;
527                 module_location = p+1;
528                 trim_char(module_location, ' ', ' ');
529         }
530
531         trim_char(module_name, ' ', ' ');
532
533
534         DEBUG(5,("Attempting to find an passdb backend to match %s (%s)\n", selected, module_name));
535
536         entry = pdb_find_backend_entry(module_name);
537         
538         /* Try to find a module that contains this module */
539         if (!entry) { 
540                 DEBUG(2,("No builtin backend found, trying to load plugin\n"));
541                 if(NT_STATUS_IS_OK(smb_probe_module("pdb", module_name)) && !(entry = pdb_find_backend_entry(module_name))) {
542                         DEBUG(0,("Plugin is available, but doesn't register passdb backend %s\n", module_name));
543                         SAFE_FREE(module_name);
544                         return NT_STATUS_UNSUCCESSFUL;
545                 }
546         }
547         
548         /* No such backend found */
549         if(!entry) { 
550                 DEBUG(0,("No builtin nor plugin backend for %s found\n", module_name));
551                 SAFE_FREE(module_name);
552                 return NT_STATUS_INVALID_PARAMETER;
553         }
554
555         DEBUG(5,("Found pdb backend %s\n", module_name));
556         nt_status = entry->init(context, methods, module_location);
557         if (NT_STATUS_IS_OK(nt_status)) {
558                 DEBUG(5,("pdb backend %s has a valid init\n", selected));
559         } else {
560                 DEBUG(0,("pdb backend %s did not correctly init (error was %s)\n", selected, nt_errstr(nt_status)));
561         }
562         SAFE_FREE(module_name);
563         return nt_status;
564 }
565
566 /******************************************************************
567   Make a pdb_context from scratch.
568  *******************************************************************/
569
570 static NTSTATUS make_pdb_context(struct pdb_context **context) 
571 {
572         TALLOC_CTX *mem_ctx;
573
574         mem_ctx = talloc_init("pdb_context internal allocation context");
575
576         if (!mem_ctx) {
577                 DEBUG(0, ("make_pdb_context: talloc init failed!\n"));
578                 return NT_STATUS_NO_MEMORY;
579         }               
580
581         *context = talloc(mem_ctx, sizeof(**context));
582         if (!*context) {
583                 DEBUG(0, ("make_pdb_context: talloc failed!\n"));
584                 return NT_STATUS_NO_MEMORY;
585         }
586
587         ZERO_STRUCTP(*context);
588
589         (*context)->mem_ctx = mem_ctx;
590
591         (*context)->pdb_setsampwent = context_setsampwent;
592         (*context)->pdb_endsampwent = context_endsampwent;
593         (*context)->pdb_getsampwent = context_getsampwent;
594         (*context)->pdb_getsampwnam = context_getsampwnam;
595         (*context)->pdb_getsampwsid = context_getsampwsid;
596         (*context)->pdb_add_sam_account = context_add_sam_account;
597         (*context)->pdb_update_sam_account = context_update_sam_account;
598         (*context)->pdb_delete_sam_account = context_delete_sam_account;
599         (*context)->pdb_getgrsid = context_getgrsid;
600         (*context)->pdb_getgrgid = context_getgrgid;
601         (*context)->pdb_getgrnam = context_getgrnam;
602         (*context)->pdb_add_group_mapping_entry = context_add_group_mapping_entry;
603         (*context)->pdb_update_group_mapping_entry = context_update_group_mapping_entry;
604         (*context)->pdb_delete_group_mapping_entry = context_delete_group_mapping_entry;
605         (*context)->pdb_enum_group_mapping = context_enum_group_mapping;
606         (*context)->pdb_gettrustpwent = context_gettrustpwent;
607         (*context)->pdb_gettrustpwsid = context_gettrustpwsid;
608         (*context)->pdb_add_trust_passwd = context_add_trust_passwd;
609         (*context)->pdb_update_trust_passwd = context_update_trust_passwd;
610         (*context)->pdb_delete_trust_passwd = context_delete_trust_passwd;
611
612         (*context)->free_fn = free_pdb_context;
613
614         return NT_STATUS_OK;
615 }
616
617
618 /******************************************************************
619   Make a pdb_context, given an array of strings
620  *******************************************************************/
621
622 NTSTATUS make_pdb_context_list(struct pdb_context **context, const char **selected) 
623 {
624         int i = 0;
625         struct pdb_methods *curmethods, *tmpmethods;
626         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
627         BOOL have_guest = False;
628
629         if (!NT_STATUS_IS_OK(nt_status = make_pdb_context(context))) {
630                 return nt_status;
631         }
632
633         if (!selected) {
634                 DEBUG(0, ("ERROR: empty passdb backend list!\n"));
635                 return nt_status;
636         }
637
638         while (selected[i]){
639                 if (strcmp(selected[i], "guest") == 0) {
640                         have_guest = True;
641                 }
642                 /* Try to initialise pdb */
643                 DEBUG(5,("Trying to load: %s\n", selected[i]));
644                 if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods_name(&curmethods, *context, selected[i]))) {
645                         DEBUG(1, ("Loading %s failed!\n", selected[i]));
646                         free_pdb_context(context);
647                         return nt_status;
648                 }
649                 curmethods->parent = *context;
650                 DLIST_ADD_END((*context)->pdb_methods, curmethods, tmpmethods);
651                 i++;
652         }
653
654         if (have_guest)
655                 return NT_STATUS_OK;
656
657         if ( (lp_guestaccount() == NULL) ||
658              (*lp_guestaccount() == '\0') ) {
659                 /* We explicitly don't want guest access. No idea what
660                    else that breaks, but be it that way. */
661                 return NT_STATUS_OK;
662         }
663
664         if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods_name(&curmethods,
665                                                                *context,
666                                                                "guest"))) {
667                 DEBUG(1, ("Loading guest module failed!\n"));
668                 free_pdb_context(context);
669                 return nt_status;
670         }
671
672         curmethods->parent = *context;
673         DLIST_ADD_END((*context)->pdb_methods, curmethods, tmpmethods);
674         
675         return NT_STATUS_OK;
676 }
677
678 /******************************************************************
679   Make a pdb_context, given a text string.
680  *******************************************************************/
681
682 NTSTATUS make_pdb_context_string(struct pdb_context **context, const char *selected) 
683 {
684         NTSTATUS ret;
685         char **newsel = str_list_make(selected, NULL);
686         ret = make_pdb_context_list(context, (const char **)newsel);
687         str_list_free(&newsel);
688         return ret;
689 }
690
691 /******************************************************************
692  Return an already initialised pdb_context, to facilitate backward 
693  compatibility (see functions below).
694 *******************************************************************/
695
696 static struct pdb_context *pdb_get_static_context(BOOL reload) 
697 {
698         static struct pdb_context *pdb_context = NULL;
699
700         if ((pdb_context) && (reload)) {
701                 pdb_context->free_fn(&pdb_context);
702                 if (!NT_STATUS_IS_OK(make_pdb_context_list(&pdb_context, lp_passdb_backend()))) {
703                         return NULL;
704                 }
705         }
706
707         if (!pdb_context) {
708                 if (!NT_STATUS_IS_OK(make_pdb_context_list(&pdb_context, lp_passdb_backend()))) {
709                         return NULL;
710                 }
711         }
712
713         return pdb_context;
714 }
715
716 /******************************************************************
717  Backward compatibility functions for the original passdb interface
718 *******************************************************************/
719
720 BOOL pdb_setsampwent(BOOL update) 
721 {
722         struct pdb_context *pdb_context = pdb_get_static_context(False);
723
724         if (!pdb_context) {
725                 return False;
726         }
727
728         return NT_STATUS_IS_OK(pdb_context->pdb_setsampwent(pdb_context, update));
729 }
730
731 void pdb_endsampwent(void) 
732 {
733         struct pdb_context *pdb_context = pdb_get_static_context(False);
734
735         if (!pdb_context) {
736                 return;
737         }
738
739         pdb_context->pdb_endsampwent(pdb_context);
740 }
741
742 BOOL pdb_getsampwent(SAM_ACCOUNT *user) 
743 {
744         struct pdb_context *pdb_context = pdb_get_static_context(False);
745
746         if (!pdb_context) {
747                 return False;
748         }
749
750         return NT_STATUS_IS_OK(pdb_context->pdb_getsampwent(pdb_context, user));
751 }
752
753 BOOL pdb_getsampwnam(SAM_ACCOUNT *sam_acct, const char *username) 
754 {
755         struct pdb_context *pdb_context = pdb_get_static_context(False);
756
757         if (!pdb_context) {
758                 return False;
759         }
760
761         return NT_STATUS_IS_OK(pdb_context->pdb_getsampwnam(pdb_context, sam_acct, username));
762 }
763
764 BOOL pdb_getsampwsid(SAM_ACCOUNT *sam_acct, const DOM_SID *sid) 
765 {
766         struct pdb_context *pdb_context = pdb_get_static_context(False);
767
768         if (!pdb_context) {
769                 return False;
770         }
771
772         return NT_STATUS_IS_OK(pdb_context->pdb_getsampwsid(pdb_context, sam_acct, sid));
773 }
774
775 BOOL pdb_add_sam_account(SAM_ACCOUNT *sam_acct) 
776 {
777         struct pdb_context *pdb_context = pdb_get_static_context(False);
778
779         if (!pdb_context) {
780                 return False;
781         }
782
783         return NT_STATUS_IS_OK(pdb_context->pdb_add_sam_account(pdb_context, sam_acct));
784 }
785
786 BOOL pdb_update_sam_account(SAM_ACCOUNT *sam_acct) 
787 {
788         struct pdb_context *pdb_context = pdb_get_static_context(False);
789
790         if (!pdb_context) {
791                 return False;
792         }
793
794         return NT_STATUS_IS_OK(pdb_context->pdb_update_sam_account(pdb_context, sam_acct));
795 }
796
797 BOOL pdb_delete_sam_account(SAM_ACCOUNT *sam_acct) 
798 {
799         struct pdb_context *pdb_context = pdb_get_static_context(False);
800
801         if (!pdb_context) {
802                 return False;
803         }
804
805         return NT_STATUS_IS_OK(pdb_context->pdb_delete_sam_account(pdb_context, sam_acct));
806 }
807
808 BOOL pdb_getgrsid(GROUP_MAP *map, DOM_SID sid)
809 {
810         struct pdb_context *pdb_context = pdb_get_static_context(False);
811
812         if (!pdb_context) {
813                 return False;
814         }
815
816         return NT_STATUS_IS_OK(pdb_context->
817                                pdb_getgrsid(pdb_context, map, sid));
818 }
819
820 BOOL pdb_getgrgid(GROUP_MAP *map, gid_t gid)
821 {
822         struct pdb_context *pdb_context = pdb_get_static_context(False);
823
824         if (!pdb_context) {
825                 return False;
826         }
827
828         return NT_STATUS_IS_OK(pdb_context->
829                                pdb_getgrgid(pdb_context, map, gid));
830 }
831
832 BOOL pdb_getgrnam(GROUP_MAP *map, char *name)
833 {
834         struct pdb_context *pdb_context = pdb_get_static_context(False);
835
836         if (!pdb_context) {
837                 return False;
838         }
839
840         return NT_STATUS_IS_OK(pdb_context->
841                                pdb_getgrnam(pdb_context, map, name));
842 }
843
844 BOOL pdb_add_group_mapping_entry(GROUP_MAP *map)
845 {
846         struct pdb_context *pdb_context = pdb_get_static_context(False);
847
848         if (!pdb_context) {
849                 return False;
850         }
851
852         return NT_STATUS_IS_OK(pdb_context->
853                                pdb_add_group_mapping_entry(pdb_context, map));
854 }
855
856 BOOL pdb_update_group_mapping_entry(GROUP_MAP *map)
857 {
858         struct pdb_context *pdb_context = pdb_get_static_context(False);
859
860         if (!pdb_context) {
861                 return False;
862         }
863
864         return NT_STATUS_IS_OK(pdb_context->
865                                pdb_update_group_mapping_entry(pdb_context, map));
866 }
867
868 BOOL pdb_delete_group_mapping_entry(DOM_SID sid)
869 {
870         struct pdb_context *pdb_context = pdb_get_static_context(False);
871
872         if (!pdb_context) {
873                 return False;
874         }
875
876         return NT_STATUS_IS_OK(pdb_context->
877                                pdb_delete_group_mapping_entry(pdb_context, sid));
878 }
879
880 BOOL pdb_enum_group_mapping(enum SID_NAME_USE sid_name_use, GROUP_MAP **rmap,
881                             int *num_entries, BOOL unix_only)
882 {
883         struct pdb_context *pdb_context = pdb_get_static_context(False);
884
885         if (!pdb_context) {
886                 return False;
887         }
888
889         return NT_STATUS_IS_OK(pdb_context->
890                                pdb_enum_group_mapping(pdb_context, sid_name_use,
891                                                       rmap, num_entries, unix_only));
892 }
893
894 /***************************************************************
895   Initialize the static context (at smbd startup etc). 
896
897   If uninitialised, context will auto-init on first use.
898  ***************************************************************/
899
900 BOOL initialize_password_db(BOOL reload)
901 {       
902         return (pdb_get_static_context(reload) != NULL);
903 }
904
905
906 /***************************************************************************
907   Default implementations of some functions.
908  ****************************************************************************/
909
910 static NTSTATUS pdb_default_getsampwnam (struct pdb_methods *methods, SAM_ACCOUNT *user, const char *sname)
911 {
912         return NT_STATUS_NO_SUCH_USER;
913 }
914
915 static NTSTATUS pdb_default_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const DOM_SID *sid)
916 {
917         return NT_STATUS_NO_SUCH_USER;
918 }
919
920 static NTSTATUS pdb_default_add_sam_account (struct pdb_methods *methods, SAM_ACCOUNT *newpwd)
921 {
922         DEBUG(0,("this backend (%s) should not be listed as the first passdb backend! You can't add users to it.\n", methods->name));
923         return NT_STATUS_NOT_IMPLEMENTED;
924 }
925
926 static NTSTATUS pdb_default_update_sam_account (struct pdb_methods *methods, SAM_ACCOUNT *newpwd)
927 {
928         return NT_STATUS_NOT_IMPLEMENTED;
929 }
930
931 static NTSTATUS pdb_default_delete_sam_account (struct pdb_methods *methods, SAM_ACCOUNT *pwd)
932 {
933         return NT_STATUS_NOT_IMPLEMENTED;
934 }
935
936 static NTSTATUS pdb_default_setsampwent(struct pdb_methods *methods, BOOL update)
937 {
938         return NT_STATUS_NOT_IMPLEMENTED;
939 }
940
941 static NTSTATUS pdb_default_getsampwent(struct pdb_methods *methods, SAM_ACCOUNT *user)
942 {
943         return NT_STATUS_NOT_IMPLEMENTED;
944 }
945
946 static void pdb_default_endsampwent(struct pdb_methods *methods)
947 {
948         return; /* NT_STATUS_NOT_IMPLEMENTED; */
949 }
950
951 static NTSTATUS pdb_default_gettrustpwent(struct pdb_methods *methods, SAM_TRUST_PASSWD* trust)
952 {
953         return NT_STATUS_NOT_IMPLEMENTED;
954 }
955
956 static NTSTATUS pdb_default_gettrustpwsid(struct pdb_methods *methods, SAM_TRUST_PASSWD* trust,
957                                           const DOM_SID* sid)
958 {
959         return NT_STATUS_NOT_IMPLEMENTED;
960 }
961
962 static NTSTATUS pdb_default_add_trust_passwd(struct pdb_methods *methods, const SAM_TRUST_PASSWD* trust)
963 {
964         return NT_STATUS_NOT_IMPLEMENTED;
965 }
966
967 static NTSTATUS pdb_default_update_trust_passwd(struct pdb_methods *methods, const SAM_TRUST_PASSWD* trust)
968 {
969         return NT_STATUS_NOT_IMPLEMENTED;
970 }
971
972 static NTSTATUS pdb_default_delete_trust_passwd(struct pdb_methods *methods, const SAM_TRUST_PASSWD* trust)
973 {
974         return NT_STATUS_NOT_IMPLEMENTED;
975 }
976
977
978 NTSTATUS make_pdb_methods(TALLOC_CTX *mem_ctx, PDB_METHODS **methods) 
979 {
980         *methods = talloc(mem_ctx, sizeof(struct pdb_methods));
981
982         if (!*methods) {
983                 return NT_STATUS_NO_MEMORY;
984         }
985
986         ZERO_STRUCTP(*methods);
987
988         (*methods)->setsampwent = pdb_default_setsampwent;
989         (*methods)->endsampwent = pdb_default_endsampwent;
990         (*methods)->getsampwent = pdb_default_getsampwent;
991         (*methods)->getsampwnam = pdb_default_getsampwnam;
992         (*methods)->getsampwsid = pdb_default_getsampwsid;
993         (*methods)->add_sam_account = pdb_default_add_sam_account;
994         (*methods)->update_sam_account = pdb_default_update_sam_account;
995         (*methods)->delete_sam_account = pdb_default_delete_sam_account;
996
997         (*methods)->getgrsid = pdb_default_getgrsid;
998         (*methods)->getgrgid = pdb_default_getgrgid;
999         (*methods)->getgrnam = pdb_default_getgrnam;
1000         (*methods)->add_group_mapping_entry = pdb_default_add_group_mapping_entry;
1001         (*methods)->update_group_mapping_entry = pdb_default_update_group_mapping_entry;
1002         (*methods)->delete_group_mapping_entry = pdb_default_delete_group_mapping_entry;
1003         (*methods)->enum_group_mapping = pdb_default_enum_group_mapping;
1004         
1005         (*methods)->gettrustpwent = pdb_default_gettrustpwent;
1006         (*methods)->gettrustpwsid = pdb_default_gettrustpwsid;
1007         (*methods)->add_trust_passwd = pdb_default_add_trust_passwd;
1008         (*methods)->update_trust_passwd = pdb_default_update_trust_passwd;
1009         (*methods)->delete_trust_passwd = pdb_default_delete_trust_passwd;
1010
1011         return NT_STATUS_OK;
1012 }