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.
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;
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
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);
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);
70 pdb_set_nt_passwd(pass, NULL, PDB_CHANGED);
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;
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);
105 DLIST_ADD(backends, entry);
106 DEBUG(5,("Successfully added passdb backend '%s'\n", name));
110 static struct pdb_init_function_entry *pdb_find_backend_entry(const char *name)
112 struct pdb_init_function_entry *entry = backends;
115 if (strcmp(entry->name, name)==0) return entry;
122 static NTSTATUS context_setsampwent(struct pdb_context *context, BOOL update)
124 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
127 DEBUG(0, ("invalid pdb_context specified!\n"));
131 context->pwent_methods = context->pdb_methods;
133 if (!context->pwent_methods) {
134 /* No passdbs at all */
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;
146 static void context_endsampwent(struct pdb_context *context)
149 DEBUG(0, ("invalid pdb_context specified!\n"));
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"));
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)
179 context->pwent_methods->setsampwent(context->pwent_methods, False);
181 user->methods = context->pwent_methods;
182 pdb_force_pw_initialization(user);
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;
192 DEBUG(0, ("invalid pdb_context specified!\n"));
195 curmethods = context->pdb_methods;
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;
202 curmethods = curmethods->next;
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;
214 DEBUG(0, ("invalid pdb_context specified!\n"));
218 curmethods = context->pdb_methods;
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;
226 curmethods = curmethods->next;
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"));
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.
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;
253 DEBUG(0, ("invalid pdb_context specified!\n"));
257 if (!sam_acct || !sam_acct->methods){
258 DEBUG(0, ("invalid sam_acct specified\n"));
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;
273 DEBUG(0, ("invalid pdb_context specified!\n"));
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
284 while (pdb_selected){
285 if (NT_STATUS_IS_OK(ret = pdb_selected->delete_sam_account(pdb_selected, sam_acct))) {
288 pdb_selected = pdb_selected->next;
293 if (!sam_acct->methods->delete_sam_account){
294 DEBUG(0,("invalid sam_acct->methods->delete_sam_account\n"));
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;
308 DEBUG(0, ("invalid pdb_context specified!\n"));
311 curmethods = context->pdb_methods;
313 ret = curmethods->getgrsid(curmethods, map, sid);
314 if (NT_STATUS_IS_OK(ret)) {
315 map->methods = curmethods;
318 curmethods = curmethods->next;
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;
331 DEBUG(0, ("invalid pdb_context specified!\n"));
334 curmethods = context->pdb_methods;
336 ret = curmethods->getgrgid(curmethods, map, gid);
337 if (NT_STATUS_IS_OK(ret)) {
338 map->methods = curmethods;
341 curmethods = curmethods->next;
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;
354 DEBUG(0, ("invalid pdb_context specified!\n"));
357 curmethods = context->pdb_methods;
359 ret = curmethods->getgrnam(curmethods, map, name);
360 if (NT_STATUS_IS_OK(ret)) {
361 map->methods = curmethods;
364 curmethods = curmethods->next;
370 static NTSTATUS context_add_group_mapping_entry(struct pdb_context *context,
373 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
375 if ((!context) || (!context->pdb_methods)) {
376 DEBUG(0, ("invalid pdb_context specified!\n"));
380 return context->pdb_methods->add_group_mapping_entry(context->pdb_methods,
384 static NTSTATUS context_update_group_mapping_entry(struct pdb_context *context,
387 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
389 if ((!context) || (!context->pdb_methods)) {
390 DEBUG(0, ("invalid pdb_context specified!\n"));
395 pdb_methods->update_group_mapping_entry(context->pdb_methods, map);
398 static NTSTATUS context_delete_group_mapping_entry(struct pdb_context *context,
401 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
403 if ((!context) || (!context->pdb_methods)) {
404 DEBUG(0, ("invalid pdb_context specified!\n"));
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,
417 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
419 if ((!context) || (!context->pdb_methods)) {
420 DEBUG(0, ("invalid pdb_context specified!\n"));
424 return context->pdb_methods->enum_group_mapping(context->pdb_methods,
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"));
440 return context->pdb_methods->add_aliasmem(context->pdb_methods,
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"));
455 return context->pdb_methods->del_aliasmem(context->pdb_methods,
459 static NTSTATUS context_enum_aliasmem(struct pdb_context *context,
460 const DOM_SID *alias, DOM_SID **members,
463 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
465 if ((!context) || (!context->pdb_methods)) {
466 DEBUG(0, ("invalid pdb_context specified!\n"));
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,
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"));
485 return context->pdb_methods->
486 enum_alias_memberships(context->pdb_methods, sid, aliases,
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;
497 DEBUG(0, ("invalid pdb_context specified!\n"));
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;
509 cur_methods = cur_methods->next;
515 static NTSTATUS context_gettrustpwsid(struct pdb_context *context,
516 SAM_TRUST_PASSWD *trust,
519 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
520 struct pdb_methods *cur_methods;
523 DEBUG(0, ("invalid pdb_context specified!\n"));
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;
535 cur_methods = cur_methods->next;
541 static NTSTATUS context_add_trust_passwd(struct pdb_context *context,
542 SAM_TRUST_PASSWD *trust)
544 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
547 DEBUG(0, ("invalid pdb_context specified!\n"));
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;
560 DEBUG(0, ("invalid pdb_context specified!\n"));
564 if (!trust || !trust->methods) {
565 DEBUG(0, ("invalid trust pointer specified!\n"));
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;
578 DEBUG(0, ("invalid pdb_context specified!\n"));
582 if (!trust || !trust->methods) {
583 DEBUG(0, ("invalid trust pointer specified!\n"));
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;
596 DEBUG(0, ("invalid pdb_context specified!\n"));
599 curmethods = context->pdb_methods;
601 if (NT_STATUS_IS_OK(ret = curmethods->add_sid_to_privilege(curmethods, priv_name, sid))) {
604 curmethods = curmethods->next;
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;
616 DEBUG(0, ("invalid pdb_context specified!\n"));
619 curmethods = context->pdb_methods;
621 if (NT_STATUS_IS_OK(ret = curmethods->remove_sid_from_privilege(curmethods, priv_name, sid))) {
624 curmethods = curmethods->next;
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;
636 DEBUG(0, ("invalid pdb_context specified!\n"));
639 curmethods = context->pdb_methods;
641 if (NT_STATUS_IS_OK(ret = curmethods->get_privilege_set(curmethods, token, privset))) {
644 curmethods = curmethods->next;
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;
656 DEBUG(0, ("invalid pdb_context specified!\n"));
659 curmethods = context->pdb_methods;
661 if (NT_STATUS_IS_OK(ret = curmethods->get_privilege_entry(curmethods, privname, sid_list))) {
664 curmethods = curmethods->next;
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);
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, ':');
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 */
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 */
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));
739 DEBUG(0,("pdb backend %s did not correctly init (error was %s)\n", selected, nt_errstr(nt_status)));
741 SAFE_FREE(module_name);
745 /******************************************************************
746 Make a pdb_context from scratch.
747 *******************************************************************/
749 static NTSTATUS make_pdb_context(struct pdb_context **context)
753 mem_ctx = talloc_init("pdb_context internal allocation context");
756 DEBUG(0, ("make_pdb_context: talloc init failed!\n"));
757 return NT_STATUS_NO_MEMORY;
760 *context = talloc(mem_ctx, sizeof(**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;
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)
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))) {
821 DEBUG(0, ("ERROR: empty passdb backend list!\n"));
826 if (strcmp(selected[i], "guest") == 0) {
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);
836 curmethods->parent = *context;
837 DLIST_ADD_END((*context)->pdb_methods, curmethods, tmpmethods);
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. */
851 if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods_name(&curmethods,
854 DEBUG(1, ("Loading guest module failed!\n"));
855 free_pdb_context(context);
859 curmethods->parent = *context;
860 DLIST_ADD_END((*context)->pdb_methods, curmethods, tmpmethods);
865 /******************************************************************
866 Make a pdb_context, given a text string.
867 *******************************************************************/
869 NTSTATUS make_pdb_context_string(struct pdb_context **context, const char *selected)
872 char **newsel = str_list_make(selected, NULL);
873 ret = make_pdb_context_list(context, (const char **)newsel);
874 str_list_free(&newsel);
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()))) {
895 if (!NT_STATUS_IS_OK(make_pdb_context_list(&pdb_context, lp_passdb_backend()))) {
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);
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);
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);
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);
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);
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;
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;
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
1154 return NT_STATUS_IS_OK(pdb_context->
1155 pdb_enum_alias_memberships(pdb_context, sid,
1159 BOOL pdb_add_sid_to_privilege(char *priv_name, DOM_SID *sid)
1161 struct pdb_context *pdb_context = pdb_get_static_context(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);
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);
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);
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,
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 /* by default return the empty privilege set as otherwise login will
1303 * be denied if a backend does not support privilege sets */
1304 return NT_STATUS_OK;
1307 static NTSTATUS pdb_default_get_privilege_entry(struct pdb_methods *methods, const char *privname, char **sid_list)
1309 return NT_STATUS_NOT_IMPLEMENTED;
1313 NTSTATUS make_pdb_methods(TALLOC_CTX *mem_ctx, PDB_METHODS **methods)
1315 *methods = talloc(mem_ctx, sizeof(struct pdb_methods));
1318 return NT_STATUS_NO_MEMORY;
1321 ZERO_STRUCTP(*methods);
1323 (*methods)->setsampwent = pdb_default_setsampwent;
1324 (*methods)->endsampwent = pdb_default_endsampwent;
1325 (*methods)->getsampwent = pdb_default_getsampwent;
1326 (*methods)->getsampwnam = pdb_default_getsampwnam;
1327 (*methods)->getsampwsid = pdb_default_getsampwsid;
1328 (*methods)->add_sam_account = pdb_default_add_sam_account;
1329 (*methods)->update_sam_account = pdb_default_update_sam_account;
1330 (*methods)->delete_sam_account = pdb_default_delete_sam_account;
1332 (*methods)->getgrsid = pdb_default_getgrsid;
1333 (*methods)->getgrgid = pdb_default_getgrgid;
1334 (*methods)->getgrnam = pdb_default_getgrnam;
1335 (*methods)->add_group_mapping_entry = pdb_default_add_group_mapping_entry;
1336 (*methods)->update_group_mapping_entry = pdb_default_update_group_mapping_entry;
1337 (*methods)->delete_group_mapping_entry = pdb_default_delete_group_mapping_entry;
1338 (*methods)->enum_group_mapping = pdb_default_enum_group_mapping;
1339 (*methods)->add_aliasmem = pdb_default_add_aliasmem;
1340 (*methods)->del_aliasmem = pdb_default_del_aliasmem;
1341 (*methods)->enum_aliasmem = pdb_default_enum_aliasmem;
1342 (*methods)->enum_alias_memberships = pdb_default_alias_memberships;
1344 (*methods)->gettrustpwent = pdb_default_gettrustpwent;
1345 (*methods)->gettrustpwsid = pdb_default_gettrustpwsid;
1346 (*methods)->add_trust_passwd = pdb_default_add_trust_passwd;
1347 (*methods)->update_trust_passwd = pdb_default_update_trust_passwd;
1348 (*methods)->delete_trust_passwd = pdb_default_delete_trust_passwd;
1350 (*methods)->add_sid_to_privilege = pdb_default_add_sid_to_privilege;
1351 (*methods)->remove_sid_from_privilege = pdb_default_remove_sid_from_privilege;
1352 (*methods)->get_privilege_set = pdb_default_get_privilege_set;
1353 (*methods)->get_privilege_entry = pdb_default_get_privilege_entry;
1355 return NT_STATUS_OK;