Ok here it is my latest work on privileges
[Samba.git] / source / passdb / pdb_interface.c
blob180db58c2d9bd93dc3f51951e8b3b26cc67db2ca
1 /*
2 Unix SMB/CIFS implementation.
3 Password and authentication handling
4 Copyright (C) Andrew Bartlett 2002
5 Copyright (C) Jelmer Vernooij 2002
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.
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.
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.
22 #include "includes.h"
24 #undef DBGC_CLASS
25 #define DBGC_CLASS DBGC_PASSDB
27 static struct pdb_init_function_entry *backends = NULL;
29 static void lazy_initialize_passdb(void)
31 static BOOL initialized = False;
32 if(initialized)return;
33 static_init_pdb;
34 initialized = True;
37 static struct pdb_init_function_entry *pdb_find_backend_entry(const char *name);
39 /*******************************************************************
40 Clean up uninitialised passwords. The only way to tell
41 that these values are not 'real' is that they do not
42 have a valid last set time. Instead, the value is fixed at 0.
43 Therefore we use that as the key for 'is this a valid password'.
44 However, it is perfectly valid to have a 'default' last change
45 time, such LDAP with a missing attribute would produce.
46 ********************************************************************/
48 static void pdb_force_pw_initialization(SAM_ACCOUNT *pass)
50 const char *lm_pwd, *nt_pwd;
52 /* only reset a password if the last set time has been
53 explicitly been set to zero. A default last set time
54 is ignored */
56 if ( (pdb_get_init_flags(pass, PDB_PASSLASTSET) != PDB_DEFAULT)
57 && (pdb_get_pass_last_set_time(pass) == 0) )
60 if (pdb_get_init_flags(pass, PDB_LMPASSWD) != PDB_DEFAULT)
62 lm_pwd = pdb_get_lanman_passwd(pass);
63 if (lm_pwd)
64 pdb_set_lanman_passwd(pass, NULL, PDB_CHANGED);
66 if (pdb_get_init_flags(pass, PDB_NTPASSWD) != PDB_DEFAULT)
68 nt_pwd = pdb_get_nt_passwd(pass);
69 if (nt_pwd)
70 pdb_set_nt_passwd(pass, NULL, PDB_CHANGED);
74 return;
77 NTSTATUS smb_register_passdb(int version, const char *name, pdb_init_function init)
79 struct pdb_init_function_entry *entry = backends;
81 if(version != PASSDB_INTERFACE_VERSION) {
82 DEBUG(0,("Can't register passdb backend!\n"
83 "You tried to register a passdb module with PASSDB_INTERFACE_VERSION %d, "
84 "while this version of samba uses version %d\n",
85 version,PASSDB_INTERFACE_VERSION));
86 return NT_STATUS_OBJECT_TYPE_MISMATCH;
89 if (!name || !init) {
90 return NT_STATUS_INVALID_PARAMETER;
93 DEBUG(5,("Attempting to register passdb backend %s\n", name));
95 /* Check for duplicates */
96 if (pdb_find_backend_entry(name)) {
97 DEBUG(0,("There already is a passdb backend registered with the name %s!\n", name));
98 return NT_STATUS_OBJECT_NAME_COLLISION;
101 entry = smb_xmalloc(sizeof(struct pdb_init_function_entry));
102 entry->name = smb_xstrdup(name);
103 entry->init = init;
105 DLIST_ADD(backends, entry);
106 DEBUG(5,("Successfully added passdb backend '%s'\n", name));
107 return NT_STATUS_OK;
110 static struct pdb_init_function_entry *pdb_find_backend_entry(const char *name)
112 struct pdb_init_function_entry *entry = backends;
114 while(entry) {
115 if (strcmp(entry->name, name)==0) return entry;
116 entry = entry->next;
119 return NULL;
122 static NTSTATUS context_setsampwent(struct pdb_context *context, BOOL update)
124 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
126 if (!context) {
127 DEBUG(0, ("invalid pdb_context specified!\n"));
128 return ret;
131 context->pwent_methods = context->pdb_methods;
133 if (!context->pwent_methods) {
134 /* No passdbs at all */
135 return ret;
138 while (NT_STATUS_IS_ERR(ret = context->pwent_methods->setsampwent(context->pwent_methods, update))) {
139 context->pwent_methods = context->pwent_methods->next;
140 if (context->pwent_methods == NULL)
141 return NT_STATUS_UNSUCCESSFUL;
143 return ret;
146 static void context_endsampwent(struct pdb_context *context)
148 if ((!context)){
149 DEBUG(0, ("invalid pdb_context specified!\n"));
150 return;
153 if (context->pwent_methods && context->pwent_methods->endsampwent)
154 context->pwent_methods->endsampwent(context->pwent_methods);
156 /* So we won't get strange data when calling getsampwent now */
157 context->pwent_methods = NULL;
160 static NTSTATUS context_getsampwent(struct pdb_context *context, SAM_ACCOUNT *user)
162 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
164 if ((!context) || (!context->pwent_methods)) {
165 DEBUG(0, ("invalid pdb_context specified!\n"));
166 return ret;
168 /* Loop until we find something useful */
169 while (NT_STATUS_IS_ERR(ret = context->pwent_methods->getsampwent(context->pwent_methods, user))) {
171 context->pwent_methods->endsampwent(context->pwent_methods);
173 context->pwent_methods = context->pwent_methods->next;
175 /* All methods are checked now. There are no more entries */
176 if (context->pwent_methods == NULL)
177 return ret;
179 context->pwent_methods->setsampwent(context->pwent_methods, False);
181 user->methods = context->pwent_methods;
182 pdb_force_pw_initialization(user);
183 return ret;
186 static NTSTATUS context_getsampwnam(struct pdb_context *context, SAM_ACCOUNT *sam_acct, const char *username)
188 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
190 struct pdb_methods *curmethods;
191 if ((!context)) {
192 DEBUG(0, ("invalid pdb_context specified!\n"));
193 return ret;
195 curmethods = context->pdb_methods;
196 while (curmethods){
197 if (NT_STATUS_IS_OK(ret = curmethods->getsampwnam(curmethods, sam_acct, username))) {
198 pdb_force_pw_initialization(sam_acct);
199 sam_acct->methods = curmethods;
200 return ret;
202 curmethods = curmethods->next;
205 return ret;
208 static NTSTATUS context_getsampwsid(struct pdb_context *context, SAM_ACCOUNT *sam_acct, const DOM_SID *sid)
210 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
212 struct pdb_methods *curmethods;
213 if ((!context)) {
214 DEBUG(0, ("invalid pdb_context specified!\n"));
215 return ret;
218 curmethods = context->pdb_methods;
220 while (curmethods){
221 if (NT_STATUS_IS_OK(ret = curmethods->getsampwsid(curmethods, sam_acct, sid))) {
222 pdb_force_pw_initialization(sam_acct);
223 sam_acct->methods = curmethods;
224 return ret;
226 curmethods = curmethods->next;
229 return ret;
232 static NTSTATUS context_add_sam_account(struct pdb_context *context, SAM_ACCOUNT *sam_acct)
234 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
236 if ((!context) || (!context->pdb_methods)) {
237 DEBUG(0, ("invalid pdb_context specified!\n"));
238 return ret;
241 /** @todo This is where a 're-read on add' should be done */
242 /* We now add a new account to the first database listed.
243 * Should we? */
245 return context->pdb_methods->add_sam_account(context->pdb_methods, sam_acct);
248 static NTSTATUS context_update_sam_account(struct pdb_context *context, SAM_ACCOUNT *sam_acct)
250 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
252 if (!context) {
253 DEBUG(0, ("invalid pdb_context specified!\n"));
254 return ret;
257 if (!sam_acct || !sam_acct->methods){
258 DEBUG(0, ("invalid sam_acct specified\n"));
259 return ret;
262 /** @todo This is where a 're-read on update' should be done */
264 return sam_acct->methods->update_sam_account(sam_acct->methods, sam_acct);
267 static NTSTATUS context_delete_sam_account(struct pdb_context *context, SAM_ACCOUNT *sam_acct)
269 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
271 struct pdb_methods *pdb_selected;
272 if (!context) {
273 DEBUG(0, ("invalid pdb_context specified!\n"));
274 return ret;
277 if (!sam_acct->methods){
278 pdb_selected = context->pdb_methods;
279 /* There's no passdb backend specified for this account.
280 * Try to delete it in every passdb available
281 * Needed to delete accounts in smbpasswd that are not
282 * in /etc/passwd.
284 while (pdb_selected){
285 if (NT_STATUS_IS_OK(ret = pdb_selected->delete_sam_account(pdb_selected, sam_acct))) {
286 return ret;
288 pdb_selected = pdb_selected->next;
290 return ret;
293 if (!sam_acct->methods->delete_sam_account){
294 DEBUG(0,("invalid sam_acct->methods->delete_sam_account\n"));
295 return ret;
298 return sam_acct->methods->delete_sam_account(sam_acct->methods, sam_acct);
301 static NTSTATUS context_getgrsid(struct pdb_context *context,
302 GROUP_MAP *map, DOM_SID sid)
304 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
306 struct pdb_methods *curmethods;
307 if ((!context)) {
308 DEBUG(0, ("invalid pdb_context specified!\n"));
309 return ret;
311 curmethods = context->pdb_methods;
312 while (curmethods){
313 ret = curmethods->getgrsid(curmethods, map, sid);
314 if (NT_STATUS_IS_OK(ret)) {
315 map->methods = curmethods;
316 return ret;
318 curmethods = curmethods->next;
321 return ret;
324 static NTSTATUS context_getgrgid(struct pdb_context *context,
325 GROUP_MAP *map, gid_t gid)
327 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
329 struct pdb_methods *curmethods;
330 if ((!context)) {
331 DEBUG(0, ("invalid pdb_context specified!\n"));
332 return ret;
334 curmethods = context->pdb_methods;
335 while (curmethods){
336 ret = curmethods->getgrgid(curmethods, map, gid);
337 if (NT_STATUS_IS_OK(ret)) {
338 map->methods = curmethods;
339 return ret;
341 curmethods = curmethods->next;
344 return ret;
347 static NTSTATUS context_getgrnam(struct pdb_context *context,
348 GROUP_MAP *map, const char *name)
350 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
352 struct pdb_methods *curmethods;
353 if ((!context)) {
354 DEBUG(0, ("invalid pdb_context specified!\n"));
355 return ret;
357 curmethods = context->pdb_methods;
358 while (curmethods){
359 ret = curmethods->getgrnam(curmethods, map, name);
360 if (NT_STATUS_IS_OK(ret)) {
361 map->methods = curmethods;
362 return ret;
364 curmethods = curmethods->next;
367 return ret;
370 static NTSTATUS context_add_group_mapping_entry(struct pdb_context *context,
371 GROUP_MAP *map)
373 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
375 if ((!context) || (!context->pdb_methods)) {
376 DEBUG(0, ("invalid pdb_context specified!\n"));
377 return ret;
380 return context->pdb_methods->add_group_mapping_entry(context->pdb_methods,
381 map);
384 static NTSTATUS context_update_group_mapping_entry(struct pdb_context *context,
385 GROUP_MAP *map)
387 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
389 if ((!context) || (!context->pdb_methods)) {
390 DEBUG(0, ("invalid pdb_context specified!\n"));
391 return ret;
394 return context->
395 pdb_methods->update_group_mapping_entry(context->pdb_methods, map);
398 static NTSTATUS context_delete_group_mapping_entry(struct pdb_context *context,
399 DOM_SID sid)
401 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
403 if ((!context) || (!context->pdb_methods)) {
404 DEBUG(0, ("invalid pdb_context specified!\n"));
405 return ret;
408 return context->
409 pdb_methods->delete_group_mapping_entry(context->pdb_methods, sid);
412 static NTSTATUS context_enum_group_mapping(struct pdb_context *context,
413 enum SID_NAME_USE sid_name_use,
414 GROUP_MAP **rmap, int *num_entries,
415 BOOL unix_only)
417 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
419 if ((!context) || (!context->pdb_methods)) {
420 DEBUG(0, ("invalid pdb_context specified!\n"));
421 return ret;
424 return context->pdb_methods->enum_group_mapping(context->pdb_methods,
425 sid_name_use, rmap,
426 num_entries, unix_only);
429 static NTSTATUS context_add_aliasmem(struct pdb_context *context,
430 const DOM_SID *alias,
431 const DOM_SID *member)
433 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
435 if ((!context) || (!context->pdb_methods)) {
436 DEBUG(0, ("invalid pdb_context specified!\n"));
437 return ret;
440 return context->pdb_methods->add_aliasmem(context->pdb_methods,
441 alias, member);
444 static NTSTATUS context_del_aliasmem(struct pdb_context *context,
445 const DOM_SID *alias,
446 const DOM_SID *member)
448 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
450 if ((!context) || (!context->pdb_methods)) {
451 DEBUG(0, ("invalid pdb_context specified!\n"));
452 return ret;
455 return context->pdb_methods->del_aliasmem(context->pdb_methods,
456 alias, member);
459 static NTSTATUS context_enum_aliasmem(struct pdb_context *context,
460 const DOM_SID *alias, DOM_SID **members,
461 int *num)
463 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
465 if ((!context) || (!context->pdb_methods)) {
466 DEBUG(0, ("invalid pdb_context specified!\n"));
467 return ret;
470 return context->pdb_methods->enum_aliasmem(context->pdb_methods,
471 alias, members, num);
474 static NTSTATUS context_enum_alias_memberships(struct pdb_context *context,
475 const DOM_SID *sid,
476 DOM_SID **aliases, int *num)
478 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
480 if ((!context) || (!context->pdb_methods)) {
481 DEBUG(0, ("invalid pdb_context specified!\n"));
482 return ret;
485 return context->pdb_methods->
486 enum_alias_memberships(context->pdb_methods, sid, aliases,
487 num);
490 static NTSTATUS context_gettrustpwent(struct pdb_context *context,
491 SAM_TRUST_PASSWD *trust)
493 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
494 struct pdb_methods *cur_methods;
496 if (!context) {
497 DEBUG(0, ("invalid pdb_context specified!\n"));
498 return ret;
501 cur_methods = context->pdb_methods;
503 while (cur_methods) {
504 ret = cur_methods->gettrustpwent(cur_methods, trust);
505 if (NT_STATUS_IS_OK(ret)) {
506 trust->methods = cur_methods;
507 return ret;
509 cur_methods = cur_methods->next;
512 return ret;
515 static NTSTATUS context_gettrustpwsid(struct pdb_context *context,
516 SAM_TRUST_PASSWD *trust,
517 const DOM_SID *sid)
519 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
520 struct pdb_methods *cur_methods;
522 if (!context) {
523 DEBUG(0, ("invalid pdb_context specified!\n"));
524 return ret;
527 cur_methods = context->pdb_methods;
529 while (cur_methods) {
530 ret = cur_methods->gettrustpwsid(cur_methods, trust, sid);
531 if (NT_STATUS_IS_OK(ret)) {
532 trust->methods = cur_methods;
533 return ret;
535 cur_methods = cur_methods->next;
538 return ret;
541 static NTSTATUS context_add_trust_passwd(struct pdb_context *context,
542 SAM_TRUST_PASSWD *trust)
544 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
546 if (!context) {
547 DEBUG(0, ("invalid pdb_context specified!\n"));
548 return ret;
551 return context->pdb_methods->add_trust_passwd(context->pdb_methods, trust);
554 static NTSTATUS context_update_trust_passwd(struct pdb_context *context,
555 SAM_TRUST_PASSWD *trust)
557 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
559 if (!context) {
560 DEBUG(0, ("invalid pdb_context specified!\n"));
561 return ret;
564 if (!trust || !trust->methods) {
565 DEBUG(0, ("invalid trust pointer specified!\n"));
566 return ret;
569 return trust->methods->update_trust_passwd(trust->methods, trust);
572 static NTSTATUS context_delete_trust_passwd(struct pdb_context *context,
573 SAM_TRUST_PASSWD *trust)
575 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
577 if (!context) {
578 DEBUG(0, ("invalid pdb_context specified!\n"));
579 return ret;
582 if (!trust || !trust->methods) {
583 DEBUG(0, ("invalid trust pointer specified!\n"));
584 return ret;
587 return trust->methods->delete_trust_passwd(trust->methods, trust);
590 static NTSTATUS context_add_sid_to_privilege(struct pdb_context *context, const char *priv_name, const DOM_SID *sid)
592 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
594 struct pdb_methods *curmethods;
595 if ((!context)) {
596 DEBUG(0, ("invalid pdb_context specified!\n"));
597 return ret;
599 curmethods = context->pdb_methods;
600 while (curmethods){
601 if (NT_STATUS_IS_OK(ret = curmethods->add_sid_to_privilege(curmethods, priv_name, sid))) {
602 return ret;
604 curmethods = curmethods->next;
607 return ret;
610 static NTSTATUS context_remove_sid_from_privilege(struct pdb_context *context, const char *priv_name, const DOM_SID *sid)
612 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
614 struct pdb_methods *curmethods;
615 if ((!context)) {
616 DEBUG(0, ("invalid pdb_context specified!\n"));
617 return ret;
619 curmethods = context->pdb_methods;
620 while (curmethods){
621 if (NT_STATUS_IS_OK(ret = curmethods->remove_sid_from_privilege(curmethods, priv_name, sid))) {
622 return ret;
624 curmethods = curmethods->next;
627 return ret;
630 static NTSTATUS context_get_privilege_set(struct pdb_context *context, NT_USER_TOKEN *token, PRIVILEGE_SET *privset)
632 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
634 struct pdb_methods *curmethods;
635 if ((!context)) {
636 DEBUG(0, ("invalid pdb_context specified!\n"));
637 return ret;
639 curmethods = context->pdb_methods;
640 while (curmethods){
641 if (NT_STATUS_IS_OK(ret = curmethods->get_privilege_set(curmethods, token, privset))) {
642 return ret;
644 curmethods = curmethods->next;
647 return ret;
650 static NTSTATUS context_get_privilege_entry(struct pdb_context *context, const char *privname, char **sid_list)
652 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
654 struct pdb_methods *curmethods;
655 if ((!context)) {
656 DEBUG(0, ("invalid pdb_context specified!\n"));
657 return ret;
659 curmethods = context->pdb_methods;
660 while (curmethods){
661 if (NT_STATUS_IS_OK(ret = curmethods->get_privilege_entry(curmethods, privname, sid_list))) {
662 return ret;
664 curmethods = curmethods->next;
667 return ret;
670 /******************************************************************
671 Free and cleanup a pdb context, any associated data and anything
672 that the attached modules might have associated.
673 *******************************************************************/
675 static void free_pdb_context(struct pdb_context **context)
677 struct pdb_methods *pdb_selected = (*context)->pdb_methods;
679 while (pdb_selected){
680 if(pdb_selected->free_private_data)
681 pdb_selected->free_private_data(&(pdb_selected->private_data));
682 pdb_selected = pdb_selected->next;
685 talloc_destroy((*context)->mem_ctx);
686 *context = NULL;
689 /******************************************************************
690 Make a pdb_methods from scratch
691 *******************************************************************/
693 static NTSTATUS make_pdb_methods_name(struct pdb_methods **methods, struct pdb_context *context, const char *selected)
695 char *module_name = smb_xstrdup(selected);
696 char *module_location = NULL, *p;
697 struct pdb_init_function_entry *entry;
698 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
700 lazy_initialize_passdb();
702 p = strchr(module_name, ':');
704 if (p) {
705 *p = 0;
706 module_location = p+1;
707 trim_char(module_location, ' ', ' ');
710 trim_char(module_name, ' ', ' ');
713 DEBUG(5,("Attempting to find an passdb backend to match %s (%s)\n", selected, module_name));
715 entry = pdb_find_backend_entry(module_name);
717 /* Try to find a module that contains this module */
718 if (!entry) {
719 DEBUG(2,("No builtin backend found, trying to load plugin\n"));
720 if(NT_STATUS_IS_OK(smb_probe_module("pdb", module_name)) && !(entry = pdb_find_backend_entry(module_name))) {
721 DEBUG(0,("Plugin is available, but doesn't register passdb backend %s\n", module_name));
722 SAFE_FREE(module_name);
723 return NT_STATUS_UNSUCCESSFUL;
727 /* No such backend found */
728 if(!entry) {
729 DEBUG(0,("No builtin nor plugin backend for %s found\n", module_name));
730 SAFE_FREE(module_name);
731 return NT_STATUS_INVALID_PARAMETER;
734 DEBUG(5,("Found pdb backend %s\n", module_name));
735 nt_status = entry->init(context, methods, module_location);
736 if (NT_STATUS_IS_OK(nt_status)) {
737 DEBUG(5,("pdb backend %s has a valid init\n", selected));
738 } else {
739 DEBUG(0,("pdb backend %s did not correctly init (error was %s)\n", selected, nt_errstr(nt_status)));
741 SAFE_FREE(module_name);
742 return nt_status;
745 /******************************************************************
746 Make a pdb_context from scratch.
747 *******************************************************************/
749 static NTSTATUS make_pdb_context(struct pdb_context **context)
751 TALLOC_CTX *mem_ctx;
753 mem_ctx = talloc_init("pdb_context internal allocation context");
755 if (!mem_ctx) {
756 DEBUG(0, ("make_pdb_context: talloc init failed!\n"));
757 return NT_STATUS_NO_MEMORY;
760 *context = talloc(mem_ctx, sizeof(**context));
761 if (!*context) {
762 DEBUG(0, ("make_pdb_context: talloc failed!\n"));
763 return NT_STATUS_NO_MEMORY;
766 ZERO_STRUCTP(*context);
768 (*context)->mem_ctx = mem_ctx;
770 (*context)->pdb_setsampwent = context_setsampwent;
771 (*context)->pdb_endsampwent = context_endsampwent;
772 (*context)->pdb_getsampwent = context_getsampwent;
773 (*context)->pdb_getsampwnam = context_getsampwnam;
774 (*context)->pdb_getsampwsid = context_getsampwsid;
775 (*context)->pdb_add_sam_account = context_add_sam_account;
776 (*context)->pdb_update_sam_account = context_update_sam_account;
777 (*context)->pdb_delete_sam_account = context_delete_sam_account;
778 (*context)->pdb_getgrsid = context_getgrsid;
779 (*context)->pdb_getgrgid = context_getgrgid;
780 (*context)->pdb_getgrnam = context_getgrnam;
781 (*context)->pdb_add_group_mapping_entry = context_add_group_mapping_entry;
782 (*context)->pdb_update_group_mapping_entry = context_update_group_mapping_entry;
783 (*context)->pdb_delete_group_mapping_entry = context_delete_group_mapping_entry;
784 (*context)->pdb_enum_group_mapping = context_enum_group_mapping;
785 (*context)->pdb_add_aliasmem = context_add_aliasmem;
786 (*context)->pdb_del_aliasmem = context_del_aliasmem;
787 (*context)->pdb_enum_aliasmem = context_enum_aliasmem;
788 (*context)->pdb_enum_alias_memberships = context_enum_alias_memberships;
789 (*context)->pdb_gettrustpwent = context_gettrustpwent;
790 (*context)->pdb_gettrustpwsid = context_gettrustpwsid;
791 (*context)->pdb_add_trust_passwd = context_add_trust_passwd;
792 (*context)->pdb_update_trust_passwd = context_update_trust_passwd;
793 (*context)->pdb_delete_trust_passwd = context_delete_trust_passwd;
794 (*context)->pdb_add_sid_to_privilege = context_add_sid_to_privilege;
795 (*context)->pdb_remove_sid_from_privilege = context_remove_sid_from_privilege;
796 (*context)->pdb_get_privilege_set = context_get_privilege_set;
797 (*context)->pdb_get_privilege_entry = context_get_privilege_entry;
799 (*context)->free_fn = free_pdb_context;
801 return NT_STATUS_OK;
805 /******************************************************************
806 Make a pdb_context, given an array of strings
807 *******************************************************************/
809 NTSTATUS make_pdb_context_list(struct pdb_context **context, const char **selected)
811 int i = 0;
812 struct pdb_methods *curmethods, *tmpmethods;
813 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
814 BOOL have_guest = False;
816 if (!NT_STATUS_IS_OK(nt_status = make_pdb_context(context))) {
817 return nt_status;
820 if (!selected) {
821 DEBUG(0, ("ERROR: empty passdb backend list!\n"));
822 return nt_status;
825 while (selected[i]){
826 if (strcmp(selected[i], "guest") == 0) {
827 have_guest = True;
829 /* Try to initialise pdb */
830 DEBUG(5,("Trying to load: %s\n", selected[i]));
831 if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods_name(&curmethods, *context, selected[i]))) {
832 DEBUG(1, ("Loading %s failed!\n", selected[i]));
833 free_pdb_context(context);
834 return nt_status;
836 curmethods->parent = *context;
837 DLIST_ADD_END((*context)->pdb_methods, curmethods, tmpmethods);
838 i++;
841 if (have_guest)
842 return NT_STATUS_OK;
844 if ( (lp_guestaccount() == NULL) ||
845 (*lp_guestaccount() == '\0') ) {
846 /* We explicitly don't want guest access. No idea what
847 else that breaks, but be it that way. */
848 return NT_STATUS_OK;
851 if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods_name(&curmethods,
852 *context,
853 "guest"))) {
854 DEBUG(1, ("Loading guest module failed!\n"));
855 free_pdb_context(context);
856 return nt_status;
859 curmethods->parent = *context;
860 DLIST_ADD_END((*context)->pdb_methods, curmethods, tmpmethods);
862 return NT_STATUS_OK;
865 /******************************************************************
866 Make a pdb_context, given a text string.
867 *******************************************************************/
869 NTSTATUS make_pdb_context_string(struct pdb_context **context, const char *selected)
871 NTSTATUS ret;
872 char **newsel = str_list_make(selected, NULL);
873 ret = make_pdb_context_list(context, (const char **)newsel);
874 str_list_free(&newsel);
875 return ret;
878 /******************************************************************
879 Return an already initialised pdb_context, to facilitate backward
880 compatibility (see functions below).
881 *******************************************************************/
883 static struct pdb_context *pdb_get_static_context(BOOL reload)
885 static struct pdb_context *pdb_context = NULL;
887 if ((pdb_context) && (reload)) {
888 pdb_context->free_fn(&pdb_context);
889 if (!NT_STATUS_IS_OK(make_pdb_context_list(&pdb_context, lp_passdb_backend()))) {
890 return NULL;
894 if (!pdb_context) {
895 if (!NT_STATUS_IS_OK(make_pdb_context_list(&pdb_context, lp_passdb_backend()))) {
896 return NULL;
900 return pdb_context;
903 /******************************************************************
904 Backward compatibility functions for the original passdb interface
905 *******************************************************************/
907 BOOL pdb_setsampwent(BOOL update)
909 struct pdb_context *pdb_context = pdb_get_static_context(False);
911 if (!pdb_context) {
912 return False;
915 return NT_STATUS_IS_OK(pdb_context->pdb_setsampwent(pdb_context, update));
918 void pdb_endsampwent(void)
920 struct pdb_context *pdb_context = pdb_get_static_context(False);
922 if (!pdb_context) {
923 return;
926 pdb_context->pdb_endsampwent(pdb_context);
929 BOOL pdb_getsampwent(SAM_ACCOUNT *user)
931 struct pdb_context *pdb_context = pdb_get_static_context(False);
933 if (!pdb_context) {
934 return False;
937 return NT_STATUS_IS_OK(pdb_context->pdb_getsampwent(pdb_context, user));
940 BOOL pdb_getsampwnam(SAM_ACCOUNT *sam_acct, const char *username)
942 struct pdb_context *pdb_context = pdb_get_static_context(False);
944 if (!pdb_context) {
945 return False;
948 return NT_STATUS_IS_OK(pdb_context->pdb_getsampwnam(pdb_context, sam_acct, username));
951 BOOL pdb_getsampwsid(SAM_ACCOUNT *sam_acct, const DOM_SID *sid)
953 struct pdb_context *pdb_context = pdb_get_static_context(False);
955 if (!pdb_context) {
956 return False;
959 return NT_STATUS_IS_OK(pdb_context->pdb_getsampwsid(pdb_context, sam_acct, sid));
962 BOOL pdb_add_sam_account(SAM_ACCOUNT *sam_acct)
964 struct pdb_context *pdb_context = pdb_get_static_context(False);
965 const char *lm_pw, *nt_pw;
966 uint16 acb_flags;
968 if (!pdb_context) {
969 return False;
972 /* disable acccounts with no passwords (that has not
973 been allowed by the ACB_PWNOTREQ bit */
975 lm_pw = pdb_get_lanman_passwd( sam_acct );
976 nt_pw = pdb_get_nt_passwd( sam_acct );
977 acb_flags = pdb_get_acct_ctrl( sam_acct );
978 if ( !lm_pw && !nt_pw && !(acb_flags&ACB_PWNOTREQ) ) {
979 acb_flags |= ACB_DISABLED;
980 pdb_set_acct_ctrl( sam_acct, acb_flags, PDB_CHANGED );
983 return NT_STATUS_IS_OK(pdb_context->pdb_add_sam_account(pdb_context, sam_acct));
986 BOOL pdb_update_sam_account(SAM_ACCOUNT *sam_acct)
988 struct pdb_context *pdb_context = pdb_get_static_context(False);
989 const char *lm_pw, *nt_pw;
990 uint16 acb_flags;
992 if (!pdb_context) {
993 return False;
996 /* disable acccounts with no passwords (that has not
997 been allowed by the ACB_PWNOTREQ bit */
999 lm_pw = pdb_get_lanman_passwd( sam_acct );
1000 nt_pw = pdb_get_nt_passwd( sam_acct );
1001 acb_flags = pdb_get_acct_ctrl( sam_acct );
1002 if ( !lm_pw && !nt_pw && !(acb_flags&ACB_PWNOTREQ) ) {
1003 acb_flags |= ACB_DISABLED;
1004 pdb_set_acct_ctrl( sam_acct, acb_flags, PDB_CHANGED );
1007 return NT_STATUS_IS_OK(pdb_context->pdb_update_sam_account(pdb_context, sam_acct));
1010 BOOL pdb_delete_sam_account(SAM_ACCOUNT *sam_acct)
1012 struct pdb_context *pdb_context = pdb_get_static_context(False);
1014 if (!pdb_context) {
1015 return False;
1018 return NT_STATUS_IS_OK(pdb_context->pdb_delete_sam_account(pdb_context, sam_acct));
1021 BOOL pdb_getgrsid(GROUP_MAP *map, DOM_SID sid)
1023 struct pdb_context *pdb_context = pdb_get_static_context(False);
1025 if (!pdb_context) {
1026 return False;
1029 return NT_STATUS_IS_OK(pdb_context->
1030 pdb_getgrsid(pdb_context, map, sid));
1033 BOOL pdb_getgrgid(GROUP_MAP *map, gid_t gid)
1035 struct pdb_context *pdb_context = pdb_get_static_context(False);
1037 if (!pdb_context) {
1038 return False;
1041 return NT_STATUS_IS_OK(pdb_context->
1042 pdb_getgrgid(pdb_context, map, gid));
1045 BOOL pdb_getgrnam(GROUP_MAP *map, const char *name)
1047 struct pdb_context *pdb_context = pdb_get_static_context(False);
1049 if (!pdb_context) {
1050 return False;
1053 return NT_STATUS_IS_OK(pdb_context->
1054 pdb_getgrnam(pdb_context, map, name));
1057 BOOL pdb_add_group_mapping_entry(GROUP_MAP *map)
1059 struct pdb_context *pdb_context = pdb_get_static_context(False);
1061 if (!pdb_context) {
1062 return False;
1065 return NT_STATUS_IS_OK(pdb_context->
1066 pdb_add_group_mapping_entry(pdb_context, map));
1069 BOOL pdb_update_group_mapping_entry(GROUP_MAP *map)
1071 struct pdb_context *pdb_context = pdb_get_static_context(False);
1073 if (!pdb_context) {
1074 return False;
1077 return NT_STATUS_IS_OK(pdb_context->
1078 pdb_update_group_mapping_entry(pdb_context, map));
1081 BOOL pdb_delete_group_mapping_entry(DOM_SID sid)
1083 struct pdb_context *pdb_context = pdb_get_static_context(False);
1085 if (!pdb_context) {
1086 return False;
1089 return NT_STATUS_IS_OK(pdb_context->
1090 pdb_delete_group_mapping_entry(pdb_context, sid));
1093 BOOL pdb_enum_group_mapping(enum SID_NAME_USE sid_name_use, GROUP_MAP **rmap,
1094 int *num_entries, BOOL unix_only)
1096 struct pdb_context *pdb_context = pdb_get_static_context(False);
1098 if (!pdb_context) {
1099 return False;
1102 return NT_STATUS_IS_OK(pdb_context->
1103 pdb_enum_group_mapping(pdb_context, sid_name_use,
1104 rmap, num_entries, unix_only));
1107 BOOL pdb_add_aliasmem(const DOM_SID *alias, const DOM_SID *member)
1109 struct pdb_context *pdb_context = pdb_get_static_context(False);
1111 if (!pdb_context) {
1112 return False;
1115 return NT_STATUS_IS_OK(pdb_context->
1116 pdb_add_aliasmem(pdb_context, alias, member));
1119 BOOL pdb_del_aliasmem(const DOM_SID *alias, const DOM_SID *member)
1121 struct pdb_context *pdb_context = pdb_get_static_context(False);
1123 if (!pdb_context) {
1124 return False;
1127 return NT_STATUS_IS_OK(pdb_context->
1128 pdb_del_aliasmem(pdb_context, alias, member));
1131 BOOL pdb_enum_aliasmem(const DOM_SID *alias,
1132 DOM_SID **members, int *num_members)
1134 struct pdb_context *pdb_context = pdb_get_static_context(False);
1136 if (!pdb_context) {
1137 return False;
1140 return NT_STATUS_IS_OK(pdb_context->
1141 pdb_enum_aliasmem(pdb_context, alias,
1142 members, num_members));
1145 BOOL pdb_enum_alias_memberships(const DOM_SID *sid,
1146 DOM_SID **aliases, int *num)
1148 struct pdb_context *pdb_context = pdb_get_static_context(False);
1150 if (!pdb_context) {
1151 return False;
1154 return NT_STATUS_IS_OK(pdb_context->
1155 pdb_enum_alias_memberships(pdb_context, sid,
1156 aliases, num));
1159 BOOL pdb_add_sid_to_privilege(char *priv_name, DOM_SID *sid)
1161 struct pdb_context *pdb_context = pdb_get_static_context(False);
1163 if (!pdb_context) {
1164 return False;
1167 return NT_STATUS_IS_OK(pdb_context->
1168 pdb_add_sid_to_privilege(pdb_context, priv_name, sid));
1171 BOOL pdb_remove_sid_from_privilege(char *priv_name, DOM_SID *sid)
1173 struct pdb_context *pdb_context = pdb_get_static_context(False);
1175 if (!pdb_context) {
1176 return False;
1179 return NT_STATUS_IS_OK(pdb_context->
1180 pdb_remove_sid_from_privilege(pdb_context, priv_name, sid));
1183 BOOL pdb_get_privilege_set(NT_USER_TOKEN *token, PRIVILEGE_SET *privset)
1185 struct pdb_context *pdb_context = pdb_get_static_context(False);
1187 if (!pdb_context) {
1188 return False;
1191 return NT_STATUS_IS_OK(pdb_context->
1192 pdb_get_privilege_set(pdb_context, token, privset));
1195 BOOL pdb_get_privilege_entry(const char *privname, char **sid_list)
1197 struct pdb_context *pdb_context = pdb_get_static_context(False);
1199 if (!pdb_context) {
1200 return False;
1203 return NT_STATUS_IS_OK(pdb_context->
1204 pdb_get_privilege_entry(pdb_context, privname, sid_list));
1207 /***************************************************************
1208 Initialize the static context (at smbd startup etc).
1210 If uninitialised, context will auto-init on first use.
1211 ***************************************************************/
1213 BOOL initialize_password_db(BOOL reload)
1215 return (pdb_get_static_context(reload) != NULL);
1219 /***************************************************************************
1220 Default implementations of some functions.
1221 ****************************************************************************/
1223 static NTSTATUS pdb_default_getsampwnam (struct pdb_methods *methods, SAM_ACCOUNT *user, const char *sname)
1225 return NT_STATUS_NO_SUCH_USER;
1228 static NTSTATUS pdb_default_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const DOM_SID *sid)
1230 return NT_STATUS_NO_SUCH_USER;
1233 static NTSTATUS pdb_default_add_sam_account (struct pdb_methods *methods, SAM_ACCOUNT *newpwd)
1235 DEBUG(0,("this backend (%s) should not be listed as the first passdb backend! You can't add users to it.\n", methods->name));
1236 return NT_STATUS_NOT_IMPLEMENTED;
1239 static NTSTATUS pdb_default_update_sam_account (struct pdb_methods *methods, SAM_ACCOUNT *newpwd)
1241 return NT_STATUS_NOT_IMPLEMENTED;
1244 static NTSTATUS pdb_default_delete_sam_account (struct pdb_methods *methods, SAM_ACCOUNT *pwd)
1246 return NT_STATUS_NOT_IMPLEMENTED;
1249 static NTSTATUS pdb_default_setsampwent(struct pdb_methods *methods, BOOL update)
1251 return NT_STATUS_NOT_IMPLEMENTED;
1254 static NTSTATUS pdb_default_getsampwent(struct pdb_methods *methods, SAM_ACCOUNT *user)
1256 return NT_STATUS_NOT_IMPLEMENTED;
1259 static void pdb_default_endsampwent(struct pdb_methods *methods)
1261 return; /* NT_STATUS_NOT_IMPLEMENTED; */
1264 static NTSTATUS pdb_default_gettrustpwent(struct pdb_methods *methods, SAM_TRUST_PASSWD* trust)
1266 return NT_STATUS_NOT_IMPLEMENTED;
1269 static NTSTATUS pdb_default_gettrustpwsid(struct pdb_methods *methods, SAM_TRUST_PASSWD* trust,
1270 const DOM_SID* sid)
1272 return NT_STATUS_NOT_IMPLEMENTED;
1275 static NTSTATUS pdb_default_add_trust_passwd(struct pdb_methods *methods, const SAM_TRUST_PASSWD* trust)
1277 return NT_STATUS_NOT_IMPLEMENTED;
1280 static NTSTATUS pdb_default_update_trust_passwd(struct pdb_methods *methods, const SAM_TRUST_PASSWD* trust)
1282 return NT_STATUS_NOT_IMPLEMENTED;
1285 static NTSTATUS pdb_default_delete_trust_passwd(struct pdb_methods *methods, const SAM_TRUST_PASSWD* trust)
1287 return NT_STATUS_NOT_IMPLEMENTED;
1290 static NTSTATUS pdb_default_add_sid_to_privilege(struct pdb_methods *methods, const char *priv_name, const DOM_SID *sid)
1292 return NT_STATUS_NOT_IMPLEMENTED;
1295 static NTSTATUS pdb_default_remove_sid_from_privilege(struct pdb_methods *methods, const char *priv_name, const DOM_SID *sid)
1297 return NT_STATUS_NOT_IMPLEMENTED;
1300 static NTSTATUS pdb_default_get_privilege_set(struct pdb_methods *methods, NT_USER_TOKEN *token, PRIVILEGE_SET *privset)
1302 return NT_STATUS_NOT_IMPLEMENTED;
1305 static NTSTATUS pdb_default_get_privilege_entry(struct pdb_methods *methods, const char *privname, char **sid_list)
1307 return NT_STATUS_NOT_IMPLEMENTED;
1311 NTSTATUS make_pdb_methods(TALLOC_CTX *mem_ctx, PDB_METHODS **methods)
1313 *methods = talloc(mem_ctx, sizeof(struct pdb_methods));
1315 if (!*methods) {
1316 return NT_STATUS_NO_MEMORY;
1319 ZERO_STRUCTP(*methods);
1321 (*methods)->setsampwent = pdb_default_setsampwent;
1322 (*methods)->endsampwent = pdb_default_endsampwent;
1323 (*methods)->getsampwent = pdb_default_getsampwent;
1324 (*methods)->getsampwnam = pdb_default_getsampwnam;
1325 (*methods)->getsampwsid = pdb_default_getsampwsid;
1326 (*methods)->add_sam_account = pdb_default_add_sam_account;
1327 (*methods)->update_sam_account = pdb_default_update_sam_account;
1328 (*methods)->delete_sam_account = pdb_default_delete_sam_account;
1330 (*methods)->getgrsid = pdb_default_getgrsid;
1331 (*methods)->getgrgid = pdb_default_getgrgid;
1332 (*methods)->getgrnam = pdb_default_getgrnam;
1333 (*methods)->add_group_mapping_entry = pdb_default_add_group_mapping_entry;
1334 (*methods)->update_group_mapping_entry = pdb_default_update_group_mapping_entry;
1335 (*methods)->delete_group_mapping_entry = pdb_default_delete_group_mapping_entry;
1336 (*methods)->enum_group_mapping = pdb_default_enum_group_mapping;
1337 (*methods)->add_aliasmem = pdb_default_add_aliasmem;
1338 (*methods)->del_aliasmem = pdb_default_del_aliasmem;
1339 (*methods)->enum_aliasmem = pdb_default_enum_aliasmem;
1340 (*methods)->enum_alias_memberships = pdb_default_alias_memberships;
1342 (*methods)->gettrustpwent = pdb_default_gettrustpwent;
1343 (*methods)->gettrustpwsid = pdb_default_gettrustpwsid;
1344 (*methods)->add_trust_passwd = pdb_default_add_trust_passwd;
1345 (*methods)->update_trust_passwd = pdb_default_update_trust_passwd;
1346 (*methods)->delete_trust_passwd = pdb_default_delete_trust_passwd;
1348 (*methods)->add_sid_to_privilege = pdb_default_add_sid_to_privilege;
1349 (*methods)->remove_sid_from_privilege = pdb_default_remove_sid_from_privilege;
1350 (*methods)->get_privilege_set = pdb_default_get_privilege_set;
1351 (*methods)->get_privilege_entry = pdb_default_get_privilege_entry;
1353 return NT_STATUS_OK;