Removed version number from file header.
[sharpe/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       
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "includes.h"
22
23 /** List of various built-in passdb modules */
24
25 const struct pdb_init_function builtin_pdb_init_functions[] = {
26         { "smbpasswd", pdb_init_smbpasswd },
27         { "smbpasswd_nua", pdb_init_smbpasswd_nua },
28         { "tdbsam", pdb_init_tdbsam },
29         { "tdbsam_nua", pdb_init_tdbsam_nua },
30 #if 0
31         { "ldap", pdb_init_ldap },
32         { "nisplus", pdb_init_nisplus },        
33         { "unix", pdb_init_unix },
34 #endif
35         { NULL, NULL}
36 };
37
38 static BOOL context_setsampwent(struct pdb_context *context, BOOL update)
39 {
40         if ((!context) || (!context->pdb_selected)) {
41                 DEBUG(0, ("invalid pdb_context specified!\n"));
42                 return False;
43         }
44         
45         return context->pdb_selected->setsampwent(context, update);
46 }
47
48 static void context_endsampwent(struct pdb_context *context)
49 {
50         if ((!context) || (!context->pdb_selected)) {
51                 DEBUG(0, ("invalid pdb_context specified!\n"));
52                 return;
53         }
54         
55         context->pdb_selected->endsampwent(context);
56 }
57
58 static BOOL context_getsampwent(struct pdb_context *context, SAM_ACCOUNT *user)
59 {
60         if ((!context) || (!context->pdb_selected)) {
61                 DEBUG(0, ("invalid pdb_context specified!\n"));
62                 return False;
63         }
64         
65         return context->pdb_selected->getsampwent(context, user);
66 }
67
68 static BOOL context_getsampwnam(struct pdb_context *context, SAM_ACCOUNT *sam_acct, const char *username)
69 {
70         if ((!context) || (!context->pdb_selected)) {
71                 DEBUG(0, ("invalid pdb_context specified!\n"));
72                 return False;
73         }
74         
75         return context->pdb_selected->getsampwnam(context, sam_acct, username);
76 }
77
78 static BOOL context_getsampwrid(struct pdb_context *context, SAM_ACCOUNT *sam_acct, uint32 rid)
79 {
80         if ((!context) || (!context->pdb_selected)) {
81                 DEBUG(0, ("invalid pdb_context specified!\n"));
82                 return False;
83         }
84         
85         return context->pdb_selected->getsampwrid(context, sam_acct, rid);
86 }
87
88 static BOOL context_add_sam_account(struct pdb_context *context, SAM_ACCOUNT *sam_acct)
89 {
90         if ((!context) || (!context->pdb_selected)) {
91                 DEBUG(0, ("invalid pdb_context specified!\n"));
92                 return False;
93         }
94         
95         /** @todo  This is where a 're-read on add' should be done */
96   
97         return context->pdb_selected->add_sam_account(context, sam_acct);
98 }
99
100 static BOOL context_update_sam_account(struct pdb_context *context, SAM_ACCOUNT *sam_acct)
101 {
102         if ((!context) || (!context->pdb_selected)) {
103                 DEBUG(0, ("invalid pdb_context specified!\n"));
104                 return False;
105         }
106         
107         /** @todo  This is where a 're-read on update' should be done */
108         
109         return context->pdb_selected->update_sam_account(context, sam_acct);
110 }
111
112 static BOOL context_delete_sam_account(struct pdb_context *context, SAM_ACCOUNT *sam_acct)
113 {
114         if ((!context) || (!context->pdb_selected)) {
115                 DEBUG(0, ("invalid pdb_context specified!\n"));
116                 return False;
117         }
118         
119         return context->pdb_selected->delete_sam_account(context, sam_acct);
120 }
121
122 static void free_pdb_context(struct pdb_context **context) 
123 {
124         if (((*context)->pdb_selected) && ((*context)->pdb_selected->free_private_data)) {
125                 (*context)->pdb_selected->free_private_data((*context)->pdb_selected->private_data);
126         }
127
128         talloc_destroy((*context)->mem_ctx);
129         *context = NULL;
130 }
131
132 /******************************************************************
133  Make a pdb_context from scratch.
134 *******************************************************************/
135
136 static NTSTATUS make_pdb_context(struct pdb_context **context) 
137 {
138         TALLOC_CTX *mem_ctx;
139         
140         mem_ctx = talloc_init_named("pdb_context internal allocation context");
141
142         if (!mem_ctx) {
143                 DEBUG(0, ("make_pdb_context: talloc init failed!\n"));
144                 return NT_STATUS_NO_MEMORY;
145         }               
146
147         *context = talloc(mem_ctx, sizeof(**context));
148         if (!*context) {
149                 DEBUG(0, ("make_pdb_context: talloc failed!\n"));
150                 return NT_STATUS_NO_MEMORY;
151         }
152
153         ZERO_STRUCTP(*context);
154
155         (*context)->mem_ctx = mem_ctx;
156
157         (*context)->pdb_setsampwent = context_setsampwent;
158         (*context)->pdb_endsampwent = context_endsampwent;
159         (*context)->pdb_getsampwent = context_getsampwent;
160         (*context)->pdb_getsampwnam = context_getsampwnam;
161         (*context)->pdb_getsampwrid = context_getsampwrid;
162         (*context)->pdb_add_sam_account = context_add_sam_account;
163         (*context)->pdb_update_sam_account = context_update_sam_account;
164         (*context)->pdb_delete_sam_account = context_delete_sam_account;
165
166         (*context)->free_fn = free_pdb_context;
167         
168         return NT_STATUS_OK;
169 }
170
171
172 /******************************************************************
173  Make a pdb_context, given a text string.
174 *******************************************************************/
175
176 NTSTATUS make_pdb_context_name(struct pdb_context **context, const char *selected) 
177 {
178         /* HINT: Don't store 'selected' becouse its often an lp_ string and will 'go away' */
179         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
180         int i;
181         char *module_name = smb_xstrdup(selected);
182         char *module_location = NULL;
183         char *p;
184
185         p = strchr(module_name, ':');
186         
187         if (p) {
188                 *p = 0;
189         
190                 module_location = p+1;
191                 
192                 trim_string(module_location, " ", " ");
193         }
194
195         trim_string(module_name, " ", " ");
196
197         if (!NT_STATUS_IS_OK(nt_status = make_pdb_context(context))) {
198                 return nt_status;
199         }
200         
201         DEBUG(5,("Attempting to find an passdb backend to match %s\n", selected));
202         for (i = 0; builtin_pdb_init_functions[i].name; i++)
203         {
204                 if (strequal(builtin_pdb_init_functions[i].name, module_name))
205                 {
206                         DEBUG(5,("Found pdb backend %s (at pos %d)\n", module_name, i));
207                         if (NT_STATUS_IS_OK(nt_status 
208                                             = builtin_pdb_init_functions[i].init(*context, &(*context)->pdb_selected, module_location))) {
209                                 DEBUG(5,("pdb backend %s has a valid init\n", selected));
210                         } else {
211                                 DEBUG(0,("pdb backend %s did not correctly init (error was %s)\n", selected, get_nt_error_msg(nt_status)));
212                                 (*context)->pdb_selected = NULL;
213                         }
214                         break;
215                 }
216         }
217         
218         if (!(*context)->pdb_selected) {
219                 DEBUG(0,("failed to select passdb backed!\n"));
220                 talloc_destroy((*context)->mem_ctx);
221                 *context = NULL;
222                 return nt_status;
223         }
224
225         return NT_STATUS_OK;
226 }
227
228
229 /******************************************************************
230  Return an already initilised pdb_context, to facilitate backward 
231  compatiablity (see functions below).
232 *******************************************************************/
233
234 static struct pdb_context *pdb_get_static_context(BOOL reload) 
235 {
236         static struct pdb_context *pdb_context = NULL;
237         
238         if ((pdb_context) && (reload)) {
239                 pdb_context->free_fn(&pdb_context);
240                 if (!NT_STATUS_IS_OK(make_pdb_context_name(&pdb_context, lp_passdb_backend()))) {
241                         return NULL;
242                 }
243         }
244         
245         if (!pdb_context) {
246                 if (!NT_STATUS_IS_OK(make_pdb_context_name(&pdb_context, lp_passdb_backend()))) {
247                         return NULL;
248                 }
249         }
250         
251         return pdb_context;
252 }
253
254 #if !defined(WITH_LDAP_SAM) && !defined(WITH_NISPLUS_SAM)
255
256 /******************************************************************
257  Backward compatability functions for the original passdb interface
258 *******************************************************************/
259
260 BOOL pdb_setsampwent(BOOL update) 
261 {
262         struct pdb_context *pdb_context = pdb_get_static_context(False);
263
264         if (!pdb_context) {
265                 return False;
266         }
267
268         return pdb_context->pdb_setsampwent(pdb_context, update);
269 }
270
271 void pdb_endsampwent(void) 
272 {
273         struct pdb_context *pdb_context = pdb_get_static_context(False);
274
275         if (!pdb_context) {
276                 return;
277         }
278
279         pdb_context->pdb_endsampwent(pdb_context);
280 }
281
282 BOOL pdb_getsampwent(SAM_ACCOUNT *user) 
283 {
284         struct pdb_context *pdb_context = pdb_get_static_context(False);
285
286         if (!pdb_context) {
287                 return False;
288         }
289
290         return pdb_context->pdb_getsampwent(pdb_context, user);
291 }
292
293 BOOL pdb_getsampwnam(SAM_ACCOUNT *sam_acct, const char *username) 
294 {
295         struct pdb_context *pdb_context = pdb_get_static_context(False);
296
297         if (!pdb_context) {
298                 return False;
299         }
300
301         return pdb_context->pdb_getsampwnam(pdb_context, sam_acct, username);
302 }
303
304 BOOL pdb_getsampwrid(SAM_ACCOUNT *sam_acct, uint32 rid) 
305 {
306         struct pdb_context *pdb_context = pdb_get_static_context(False);
307
308         if (!pdb_context) {
309                 return False;
310         }
311
312         return pdb_context->pdb_getsampwrid(pdb_context, sam_acct, rid);
313 }
314
315 BOOL pdb_add_sam_account(SAM_ACCOUNT *sam_acct) 
316 {
317         struct pdb_context *pdb_context = pdb_get_static_context(False);
318
319         if (!pdb_context) {
320                 return False;
321         }
322
323         return pdb_context->pdb_add_sam_account(pdb_context, sam_acct);
324 }
325
326 BOOL pdb_update_sam_account(SAM_ACCOUNT *sam_acct) 
327 {
328         struct pdb_context *pdb_context = pdb_get_static_context(False);
329
330         if (!pdb_context) {
331                 return False;
332         }
333
334         return pdb_context->pdb_update_sam_account(pdb_context, sam_acct);
335 }
336
337 BOOL pdb_delete_sam_account(SAM_ACCOUNT *sam_acct) 
338 {
339         struct pdb_context *pdb_context = pdb_get_static_context(False);
340         
341         if (!pdb_context) {
342                 return False;
343         }
344         
345         return pdb_context->pdb_delete_sam_account(pdb_context, sam_acct);
346 }
347
348 #endif /* !defined(WITH_LDAP_SAM) && !defined(WITH_NISPLUS_SAM) */
349
350 /***************************************************************
351  Initialize the static context (at smbd startup etc). 
352
353  If uninitialised, context will auto-init on first use.
354 ***************************************************************/
355
356 BOOL initialize_password_db(BOOL reload)
357 {       
358         return (pdb_get_static_context(reload) != NULL);
359 }
360
361
362 NTSTATUS make_pdb_methods(TALLOC_CTX *mem_ctx, PDB_METHODS **methods) 
363 {
364         *methods = talloc(mem_ctx, sizeof(struct pdb_methods));
365
366         if (!*methods) {
367                 return NT_STATUS_NO_MEMORY;
368         }
369
370         ZERO_STRUCTP(*methods);
371
372         return NT_STATUS_OK;
373 }
374
375
376
377
378
379
380
381