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 /** List of various built-in passdb modules */
29 const struct pdb_init_function_entry builtin_pdb_init_functions[] = {
30 { "smbpasswd", pdb_init_smbpasswd },
31 { "smbpasswd_nua", pdb_init_smbpasswd_nua },
32 { "tdbsam", pdb_init_tdbsam },
33 { "tdbsam_nua", pdb_init_tdbsam_nua },
34 { "ldapsam", pdb_init_ldapsam },
35 { "ldapsam_nua", pdb_init_ldapsam_nua },
36 { "unixsam", pdb_init_unixsam },
37 { "plugin", pdb_init_plugin },
41 static BOOL context_setsampwent(struct pdb_context *context, BOOL update)
43 if ((!context) || (!context->pdb_methods) || (!context->pdb_methods->setsampwent)) {
44 DEBUG(0, ("invalid pdb_context specified!\n"));
48 context->pwent_methods = context->pdb_methods;
50 if (!context->pwent_methods) {
51 /* No passdbs at all */
55 while (!(context->pwent_methods->setsampwent(context->pwent_methods, update))) {
56 context->pwent_methods = context->pwent_methods->next;
57 if (context->pwent_methods == NULL)
63 static void context_endsampwent(struct pdb_context *context)
66 DEBUG(0, ("invalid pdb_context specified!\n"));
70 if (context->pwent_methods && context->pwent_methods->endsampwent)
71 context->pwent_methods->endsampwent(context->pwent_methods);
73 /* So we won't get strange data when calling getsampwent now */
74 context->pwent_methods = NULL;
77 static BOOL context_getsampwent(struct pdb_context *context, SAM_ACCOUNT *user)
79 if ((!context) || (!context->pwent_methods)) {
80 DEBUG(0, ("invalid pdb_context specified!\n"));
83 /* Loop until we find something useful */
84 while ((!context->pwent_methods->getsampwent) ||
85 context->pwent_methods->getsampwent(context->pwent_methods, user) == False){
87 if (context->pwent_methods->endsampwent)
88 context->pwent_methods->endsampwent(context->pwent_methods);
90 context->pwent_methods = context->pwent_methods->next;
92 /* All methods are checked now. There are no more entries */
93 if (context->pwent_methods == NULL)
96 if (!context->pwent_methods->setsampwent){
97 DEBUG(5, ("next backend does not implment setsampwent\n"));
101 context->pwent_methods->setsampwent(context->pwent_methods, False);
103 user->methods = context->pwent_methods;
107 static BOOL context_getsampwnam(struct pdb_context *context, SAM_ACCOUNT *sam_acct, const char *username)
109 struct pdb_methods *curmethods;
111 DEBUG(0, ("invalid pdb_context specified!\n"));
114 curmethods = context->pdb_methods;
116 if (curmethods->getsampwnam && curmethods->getsampwnam(curmethods, sam_acct, username) == True){
117 sam_acct->methods = curmethods;
120 curmethods = curmethods->next;
126 static BOOL context_getsampwsid(struct pdb_context *context, SAM_ACCOUNT *sam_acct, DOM_SID *sid)
128 struct pdb_methods *curmethods;
130 DEBUG(0, ("invalid pdb_context specified!\n"));
134 curmethods = context->pdb_methods;
137 if (curmethods->getsampwsid && curmethods->getsampwsid(curmethods, sam_acct, sid) == True){
138 sam_acct->methods = curmethods;
141 curmethods = curmethods->next;
147 static BOOL context_add_sam_account(struct pdb_context *context, SAM_ACCOUNT *sam_acct)
149 if ((!context) || (!context->pdb_methods) || (!context->pdb_methods->add_sam_account)) {
150 DEBUG(0, ("invalid pdb_context specified!\n"));
154 /** @todo This is where a 're-read on add' should be done */
155 /* We now add a new account to the first database listed.
158 return context->pdb_methods->add_sam_account(context->pdb_methods, sam_acct);
161 static BOOL context_update_sam_account(struct pdb_context *context, SAM_ACCOUNT *sam_acct)
164 DEBUG(0, ("invalid pdb_context specified!\n"));
168 if (!sam_acct || !sam_acct->methods){
169 DEBUG(0, ("invalid sam_acct specified\n"));
173 if (!sam_acct->methods->update_sam_account){
174 DEBUG(0, ("invalid sam_acct->methods\n"));
178 /** @todo This is where a 're-read on update' should be done */
180 return sam_acct->methods->update_sam_account(sam_acct->methods, sam_acct);
183 static BOOL context_delete_sam_account(struct pdb_context *context, SAM_ACCOUNT *sam_acct)
185 struct pdb_methods *pdb_selected;
187 DEBUG(0, ("invalid pdb_context specified!\n"));
191 if (!sam_acct->methods){
192 pdb_selected = context->pdb_methods;
193 /* There's no passdb backend specified for this account.
194 * Try to delete it in every passdb available
195 * Needed to delete accounts in smbpasswd that are not
198 while (pdb_selected){
199 if (pdb_selected->delete_sam_account && pdb_selected->delete_sam_account(pdb_selected, sam_acct)){
202 pdb_selected = pdb_selected->next;
207 if (!sam_acct->methods->delete_sam_account){
208 DEBUG(0,("invalid sam_acct->methods->delete_sam_account\n"));
212 return sam_acct->methods->delete_sam_account(sam_acct->methods, sam_acct);
215 /******************************************************************
216 Free and cleanup a pdb context, any associated data and anything
217 that the attached modules might have associated.
218 *******************************************************************/
220 static void free_pdb_context(struct pdb_context **context)
222 struct pdb_methods *pdb_selected = (*context)->pdb_methods;
224 while (pdb_selected){
225 if (pdb_selected->free_private_data) {
226 pdb_selected->free_private_data(&(pdb_selected->private_data));
228 pdb_selected = pdb_selected->next;
231 talloc_destroy((*context)->mem_ctx);
235 /******************************************************************
236 Make a pdb_methods from scratch
237 *******************************************************************/
239 static NTSTATUS make_pdb_methods_name(struct pdb_methods **methods, struct pdb_context *context, const char *selected)
241 char *module_name = smb_xstrdup(selected);
242 char *module_location = NULL, *p;
243 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
246 p = strchr(module_name, ':');
250 module_location = p+1;
251 trim_string(module_location, " ", " ");
254 trim_string(module_name, " ", " ");
256 DEBUG(5,("Attempting to find an passdb backend to match %s (%s)\n", selected, module_name));
257 for (i = 0; builtin_pdb_init_functions[i].name; i++)
259 if (strequal(builtin_pdb_init_functions[i].name, module_name))
261 DEBUG(5,("Found pdb backend %s (at pos %d)\n", module_name, i));
262 nt_status = builtin_pdb_init_functions[i].init(context, methods, module_location);
263 if (NT_STATUS_IS_OK(nt_status)) {
264 DEBUG(5,("pdb backend %s has a valid init\n", selected));
266 DEBUG(0,("pdb backend %s did not correctly init (error was %s)\n", selected, nt_errstr(nt_status)));
268 SAFE_FREE(module_name);
270 break; /* unreached */
274 /* No such backend found */
275 SAFE_FREE(module_name);
276 return NT_STATUS_INVALID_PARAMETER;
279 /******************************************************************
280 Make a pdb_context from scratch.
281 *******************************************************************/
283 static NTSTATUS make_pdb_context(struct pdb_context **context)
287 mem_ctx = talloc_init_named("pdb_context internal allocation context");
290 DEBUG(0, ("make_pdb_context: talloc init failed!\n"));
291 return NT_STATUS_NO_MEMORY;
294 *context = talloc(mem_ctx, sizeof(**context));
296 DEBUG(0, ("make_pdb_context: talloc failed!\n"));
297 return NT_STATUS_NO_MEMORY;
300 ZERO_STRUCTP(*context);
302 (*context)->mem_ctx = mem_ctx;
304 (*context)->pdb_setsampwent = context_setsampwent;
305 (*context)->pdb_endsampwent = context_endsampwent;
306 (*context)->pdb_getsampwent = context_getsampwent;
307 (*context)->pdb_getsampwnam = context_getsampwnam;
308 (*context)->pdb_getsampwsid = context_getsampwsid;
309 (*context)->pdb_add_sam_account = context_add_sam_account;
310 (*context)->pdb_update_sam_account = context_update_sam_account;
311 (*context)->pdb_delete_sam_account = context_delete_sam_account;
313 (*context)->free_fn = free_pdb_context;
319 /******************************************************************
320 Make a pdb_context, given an array of strings
321 *******************************************************************/
323 NTSTATUS make_pdb_context_list(struct pdb_context **context, char **selected)
326 struct pdb_methods *curmethods, *tmpmethods;
327 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
329 if (!NT_STATUS_IS_OK(nt_status = make_pdb_context(context))) {
334 /* Try to initialise pdb */
335 DEBUG(5,("Trying to load: %s\n", selected[i]));
336 if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods_name(&curmethods, *context, selected[i]))) {
337 DEBUG(1, ("Loading %s failed!\n", selected[i]));
338 free_pdb_context(context);
341 curmethods->parent = *context;
342 DLIST_ADD_END((*context)->pdb_methods, curmethods, tmpmethods);
349 /******************************************************************
350 Make a pdb_context, given a text string.
351 *******************************************************************/
353 NTSTATUS make_pdb_context_string(struct pdb_context **context, const char *selected)
356 char **newsel = str_list_make(selected, NULL);
357 ret = make_pdb_context_list(context, newsel);
358 str_list_free(&newsel);
362 /******************************************************************
363 Return an already initialised pdb_context, to facilitate backward
364 compatibility (see functions below).
365 *******************************************************************/
367 static struct pdb_context *pdb_get_static_context(BOOL reload)
369 static struct pdb_context *pdb_context = NULL;
371 if ((pdb_context) && (reload)) {
372 pdb_context->free_fn(&pdb_context);
373 if (!NT_STATUS_IS_OK(make_pdb_context_list(&pdb_context, lp_passdb_backend()))) {
379 if (!NT_STATUS_IS_OK(make_pdb_context_list(&pdb_context, lp_passdb_backend()))) {
387 #if !defined(WITH_NISPLUS_SAM)
389 /******************************************************************
390 Backward compatibility functions for the original passdb interface
391 *******************************************************************/
393 BOOL pdb_setsampwent(BOOL update)
395 struct pdb_context *pdb_context = pdb_get_static_context(False);
401 return pdb_context->pdb_setsampwent(pdb_context, update);
404 void pdb_endsampwent(void)
406 struct pdb_context *pdb_context = pdb_get_static_context(False);
412 pdb_context->pdb_endsampwent(pdb_context);
415 BOOL pdb_getsampwent(SAM_ACCOUNT *user)
417 struct pdb_context *pdb_context = pdb_get_static_context(False);
423 return pdb_context->pdb_getsampwent(pdb_context, user);
426 BOOL pdb_getsampwnam(SAM_ACCOUNT *sam_acct, const char *username)
428 struct pdb_context *pdb_context = pdb_get_static_context(False);
434 return pdb_context->pdb_getsampwnam(pdb_context, sam_acct, username);
437 BOOL pdb_getsampwsid(SAM_ACCOUNT *sam_acct, DOM_SID *sid)
439 struct pdb_context *pdb_context = pdb_get_static_context(False);
445 return pdb_context->pdb_getsampwsid(pdb_context, sam_acct, sid);
448 BOOL pdb_add_sam_account(SAM_ACCOUNT *sam_acct)
450 struct pdb_context *pdb_context = pdb_get_static_context(False);
456 return pdb_context->pdb_add_sam_account(pdb_context, sam_acct);
459 BOOL pdb_update_sam_account(SAM_ACCOUNT *sam_acct)
461 struct pdb_context *pdb_context = pdb_get_static_context(False);
467 return pdb_context->pdb_update_sam_account(pdb_context, sam_acct);
470 BOOL pdb_delete_sam_account(SAM_ACCOUNT *sam_acct)
472 struct pdb_context *pdb_context = pdb_get_static_context(False);
478 return pdb_context->pdb_delete_sam_account(pdb_context, sam_acct);
481 #endif /* !defined(WITH_NISPLUS_SAM) */
483 /***************************************************************
484 Initialize the static context (at smbd startup etc).
486 If uninitialised, context will auto-init on first use.
487 ***************************************************************/
489 BOOL initialize_password_db(BOOL reload)
491 return (pdb_get_static_context(reload) != NULL);
495 NTSTATUS make_pdb_methods(TALLOC_CTX *mem_ctx, PDB_METHODS **methods)
497 *methods = talloc(mem_ctx, sizeof(struct pdb_methods));
500 return NT_STATUS_NO_MEMORY;
503 ZERO_STRUCTP(*methods);