Initial design of some of the functions to operate on trust passwords
[tprouty/samba.git] / source3 / passdb / pdb_tdb.c
1 /*
2  * Unix SMB/CIFS implementation. 
3  * SMB parameters and setup
4  * Copyright (C) Andrew Tridgell   1992-1998
5  * Copyright (C) Simo Sorce        2000-2002
6  * Copyright (C) Gerald Carter     2000
7  * Copyright (C) Jeremy Allison    2001
8  * Copyright (C) Andrew Bartlett   2002
9  * 
10  * This program is free software; you can redistribute it and/or modify it under
11  * the terms of the GNU General Public License as published by the Free
12  * Software Foundation; either version 2 of the License, or (at your option)
13  * any later version.
14  * 
15  * This program is distributed in the hope that it will be useful, but WITHOUT
16  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
18  * more details.
19  * 
20  * You should have received a copy of the GNU General Public License along with
21  * this program; if not, write to the Free Software Foundation, Inc., 675
22  * Mass Ave, Cambridge, MA 02139, USA.
23  */
24
25 #include "includes.h"
26
27 #if 0 /* when made a module use this */
28
29 static int tdbsam_debug_level = DBGC_ALL;
30 #undef DBGC_CLASS
31 #define DBGC_CLASS tdbsam_debug_level
32
33 #else
34
35 #undef DBGC_CLASS
36 #define DBGC_CLASS DBGC_PASSDB
37
38 #endif
39
40 #define TDBSAM_VERSION  1                       /* Most recent TDBSAM version */
41 #define PDB_VERSION             "20010830"
42 #define PASSDB_FILE_NAME        "passdb.tdb"
43 #define USERPREFIX              "USER_"
44 #define RIDPREFIX               "RID_"
45 #define tdbsamver_t     int32
46
47 struct tdbsam_privates {
48         TDB_CONTEXT     *passwd_tdb;
49         TDB_DATA        key;
50
51         /* retrive-once info */
52         const char *tdbsam_location;
53 };
54
55 /**
56  * Convert old TDBSAM to the latest version.
57  * @param pdb_tdb A pointer to the opened TDBSAM file which must be converted. 
58  *                This file must be opened with read/write access.
59  * @param from Current version of the TDBSAM file.
60  * @return True if the conversion has been successful, false otherwise. 
61  **/
62
63 static BOOL tdbsam_convert(TDB_CONTEXT *pdb_tdb, tdbsamver_t from) 
64 {
65         const char * vstring = "INFO/version";
66         SAM_ACCOUNT *user = NULL;
67         const char *prefix = USERPREFIX;
68         TDB_DATA        data, key, old_key;
69         uint8           *buf = NULL;
70         BOOL            ret;
71
72         if (pdb_tdb == NULL) {
73                 DEBUG(0,("tdbsam_convert: Bad TDB Context pointer.\n"));
74                 return False;
75         }
76
77         /* handle a Samba upgrade */
78         tdb_lock_bystring(pdb_tdb, vstring, 0);
79         
80         if (!NT_STATUS_IS_OK(pdb_init_sam(&user))) {
81                 DEBUG(0,("tdbsam_convert: cannot initialized a SAM_ACCOUNT.\n"));
82                 return False;
83         }
84
85         /* Enumerate all records and convert them */
86         key = tdb_firstkey(pdb_tdb);
87
88         while (key.dptr) {
89         
90                 /* skip all non-USER entries (eg. RIDs) */
91                 while ((key.dsize != 0) && (strncmp(key.dptr, prefix, strlen (prefix)))) {
92                         old_key = key;
93                         /* increment to next in line */
94                         key = tdb_nextkey(pdb_tdb, key);
95                         SAFE_FREE(old_key.dptr);
96                 }
97         
98                 if (key.dptr) {
99                         
100                         /* read from tdbsam */
101                         data = tdb_fetch(pdb_tdb, key);
102                         if (!data.dptr) {
103                                 DEBUG(0,("tdbsam_convert: database entry not found: %s.\n",key.dptr));
104                                 return False;
105                         }
106         
107                         if (!NT_STATUS_IS_OK(pdb_reset_sam(user))) {
108                                 DEBUG(0,("tdbsam_convert: cannot reset SAM_ACCOUNT.\n"));
109                                 SAFE_FREE(data.dptr);
110                                 return False;
111                         }
112                         
113                         /* unpack the buffer from the former format */
114                         DEBUG(10,("tdbsam_convert: Try unpacking a record with (key:%s) (version:%d)\n", key.dptr, from));
115                         switch (from) {
116                                 case 0:
117                                         ret = init_sam_from_buffer_v0(user, (uint8 *)data.dptr, data.dsize);
118                                         break;
119                                 case 1:
120                                         ret = init_sam_from_buffer_v1(user, (uint8 *)data.dptr, data.dsize);
121                                         break;
122                                 default:
123                                         /* unknown tdbsam version */
124                                         ret = False;
125                         }
126                         if (!ret) {
127                                 DEBUG(0,("tdbsam_convert: Bad SAM_ACCOUNT entry returned from TDB (key:%s) (version:%d)\n", key.dptr, from));
128                                 SAFE_FREE(data.dptr);
129                                 return False;
130                         }
131         
132                         /* pack from the buffer into the new format */
133                         DEBUG(10,("tdbsam_convert: Try packing a record (key:%s) (version:%d)\n", key.dptr, from));
134                         if ((data.dsize=init_buffer_from_sam (&buf, user, False)) == -1) {
135                                 DEBUG(0,("tdbsam_convert: cannot pack the SAM_ACCOUNT into the new format\n"));
136                                 SAFE_FREE(data.dptr);
137                                 return False;
138                         }
139                         data.dptr = (char *)buf;
140                         
141                         /* Store the buffer inside the TDBSAM */
142                         if (tdb_store(pdb_tdb, key, data, TDB_MODIFY) != TDB_SUCCESS) {
143                                 DEBUG(0,("tdbsam_convert: cannot store the SAM_ACCOUNT (key:%s) in new format\n",key.dptr));
144                                 SAFE_FREE(data.dptr);
145                                 return False;
146                         }
147                         
148                         SAFE_FREE(data.dptr);
149                         
150                         /* increment to next in line */
151                         old_key = key;
152                         key = tdb_nextkey(pdb_tdb, key);
153                         SAFE_FREE(old_key.dptr);
154                 }
155                 
156         }
157
158         pdb_free_sam(&user);
159         
160         /* upgrade finished */
161         tdb_store_int32(pdb_tdb, vstring, TDBSAM_VERSION);
162         tdb_unlock_bystring(pdb_tdb, vstring);
163
164         return(True);   
165 }
166
167 /**
168  * Open the TDB passwd database, check version and convert it if needed.
169  * @param name filename of the tdbsam file.
170  * @param open_flags file access mode.
171  * @return a TDB_CONTEXT handle on the tdbsam file.
172  **/
173
174 static TDB_CONTEXT * tdbsam_tdbopen (const char *name, int open_flags)
175 {
176         TDB_CONTEXT     *pdb_tdb;
177         tdbsamver_t     version;
178         
179         /* Try to open tdb passwd */
180         if (!(pdb_tdb = tdb_open_log(name, 0, TDB_DEFAULT, open_flags, 0600)))
181                 return NULL;
182
183         /* Check the version */
184         version = (tdbsamver_t) tdb_fetch_int32(pdb_tdb, "INFO/version");
185         if (version == -1)
186                 version = 0;    /* Version not found, assume version 0 */
187         
188         /* Compare the version */
189         if (version > TDBSAM_VERSION) {
190                 /* Version more recent than the latest known */ 
191                 DEBUG(0, ("TDBSAM version unknown: %d\n", version));
192                 tdb_close(pdb_tdb);
193                 pdb_tdb = NULL;
194         } 
195         else if (version < TDBSAM_VERSION) {
196                 /* Older version, must be converted */
197                 DEBUG(1, ("TDBSAM version too old (%d), trying to convert it.\n", version));
198                 
199                 /* Reopen the pdb file with read-write access if needed */
200                 if (!(open_flags & O_RDWR)) {
201                         DEBUG(10, ("tdbsam_tdbopen: TDB file opened with read only access, reopen it with read-write access.\n"));
202                         tdb_close(pdb_tdb);
203                         pdb_tdb = tdb_open_log(name, 0, TDB_DEFAULT, (open_flags & 07777770) | O_RDWR, 0600);
204                 }
205                 
206                 /* Convert */
207                 if (!tdbsam_convert(pdb_tdb, version)){
208                         DEBUG(0, ("tdbsam_tdbopen: Error when trying to convert tdbsam: %s\n",name));
209                         tdb_close(pdb_tdb);
210                         pdb_tdb = NULL;
211                 } else {
212                         DEBUG(1, ("TDBSAM converted successfully.\n"));
213                 }
214
215                 /* Reopen the pdb file as it must be */
216                 if (!(open_flags & O_RDWR)) {
217                         tdb_close(pdb_tdb);
218                         pdb_tdb = tdb_open_log(name, 0, TDB_DEFAULT, open_flags, 0600);
219                 }
220         }
221         
222         return pdb_tdb;
223 }
224
225 /***************************************************************
226  Open the TDB passwd database for SAM account enumeration.
227 ****************************************************************/
228
229 static NTSTATUS tdbsam_setsampwent(struct pdb_methods *my_methods, BOOL update)
230 {
231         struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data;
232         
233         /* Open tdb passwd */
234         if (!(tdb_state->passwd_tdb = tdbsam_tdbopen(tdb_state->tdbsam_location, update?(O_RDWR|O_CREAT):O_RDONLY)))
235         {
236                 DEBUG(0, ("Unable to open/create TDB passwd\n"));
237                 return NT_STATUS_UNSUCCESSFUL;
238         }
239         
240         tdb_state->key = tdb_firstkey(tdb_state->passwd_tdb);
241
242         return NT_STATUS_OK;
243 }
244
245 static void close_tdb(struct tdbsam_privates *tdb_state) 
246 {
247         if (tdb_state->passwd_tdb) {
248                 tdb_close(tdb_state->passwd_tdb);
249                 tdb_state->passwd_tdb = NULL;
250         }
251 }
252
253 /***************************************************************
254  End enumeration of the TDB passwd list.
255 ****************************************************************/
256
257 static void tdbsam_endsampwent(struct pdb_methods *my_methods)
258 {
259         struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data;
260         SAFE_FREE(tdb_state->key.dptr);
261         close_tdb(tdb_state);
262         
263         DEBUG(7, ("endtdbpwent: closed sam database.\n"));
264 }
265
266 /*****************************************************************
267  Get one SAM_ACCOUNT from the TDB (next in line)
268 *****************************************************************/
269
270 static NTSTATUS tdbsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT *user)
271 {
272         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
273         struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data;
274         TDB_DATA        data, old_key;
275         const char *prefix = USERPREFIX;
276         int  prefixlen = strlen (prefix);
277
278
279         if (user==NULL) {
280                 DEBUG(0,("pdb_get_sampwent: SAM_ACCOUNT is NULL.\n"));
281                 return nt_status;
282         }
283
284         /* skip all non-USER entries (eg. RIDs) */
285         while ((tdb_state->key.dsize != 0) && (strncmp(tdb_state->key.dptr, prefix, prefixlen))) {
286
287                 old_key = tdb_state->key;
288
289                 /* increment to next in line */
290                 tdb_state->key = tdb_nextkey(tdb_state->passwd_tdb, tdb_state->key);
291
292                 SAFE_FREE(old_key.dptr);
293         }
294
295         /* do we have an valid iteration pointer? */
296         if(tdb_state->passwd_tdb == NULL) {
297                 DEBUG(0,("pdb_get_sampwent: Bad TDB Context pointer.\n"));
298                 return nt_status;
299         }
300
301         data = tdb_fetch(tdb_state->passwd_tdb, tdb_state->key);
302         if (!data.dptr) {
303                 DEBUG(5,("pdb_getsampwent: database entry not found.\n"));
304                 return nt_status;
305         }
306   
307         /* unpack the buffer */
308         if (!init_sam_from_buffer(user, (unsigned char *)data.dptr, data.dsize)) {
309                 DEBUG(0,("pdb_getsampwent: Bad SAM_ACCOUNT entry returned from TDB!\n"));
310                 SAFE_FREE(data.dptr);
311                 return nt_status;
312         }
313         SAFE_FREE(data.dptr);
314         
315         old_key = tdb_state->key;
316         
317         /* increment to next in line */
318         tdb_state->key = tdb_nextkey(tdb_state->passwd_tdb, tdb_state->key);
319
320         SAFE_FREE(old_key.dptr);
321
322         return NT_STATUS_OK;
323 }
324
325 /******************************************************************
326  Lookup a name in the SAM TDB
327 ******************************************************************/
328
329 static NTSTATUS tdbsam_getsampwnam (struct pdb_methods *my_methods, SAM_ACCOUNT *user, const char *sname)
330 {
331         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
332         struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data;
333         TDB_CONTEXT     *pwd_tdb;
334         TDB_DATA        data, key;
335         fstring         keystr;
336         fstring         name;
337
338         if (user==NULL) {
339                 DEBUG(0,("pdb_getsampwnam: SAM_ACCOUNT is NULL.\n"));
340                 return nt_status;
341         }
342
343         
344         /* Data is stored in all lower-case */
345         fstrcpy(name, sname);
346         strlower_m(name);
347
348         /* set search key */
349         slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
350         key.dptr = keystr;
351         key.dsize = strlen(keystr) + 1;
352
353         /* open the accounts TDB */
354         if (!(pwd_tdb = tdbsam_tdbopen(tdb_state->tdbsam_location, O_RDONLY))) {
355         
356                 if (errno == ENOENT) {
357                         /*
358                          * TDB file doesn't exist, so try to create new one. This is useful to avoid
359                          * confusing error msg when adding user account first time
360                          */
361                         if (!(pwd_tdb = tdb_open_log(tdb_state->tdbsam_location, 0, TDB_DEFAULT, O_CREAT, 0600))) {
362                                 DEBUG(0, ("pdb_getsampwnam: TDB passwd (%s) did not exist. File successfully created.\n",
363                                           tdb_state->tdbsam_location));
364                         } else {
365                                 DEBUG(0, ("pdb_getsampwnam: TDB passwd (%s) does not exist. Couldn't create new one. Error was: %s\n",
366                                           tdb_state->tdbsam_location, strerror(errno)));
367                         }
368                         
369                         /* requested user isn't there anyway */
370                         nt_status = NT_STATUS_NO_SUCH_USER;
371                         return nt_status;
372                 }
373                 DEBUG(0, ("pdb_getsampwnam: Unable to open TDB passwd (%s)!\n", tdb_state->tdbsam_location));
374                 return nt_status;
375         }
376
377         /* get the record */
378         data = tdb_fetch(pwd_tdb, key);
379         if (!data.dptr) {
380                 DEBUG(5,("pdb_getsampwnam (TDB): error fetching database.\n"));
381                 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(pwd_tdb)));
382                 DEBUGADD(5, (" Key: %s\n", keystr));
383                 tdb_close(pwd_tdb);
384                 return nt_status;
385         }
386   
387         /* unpack the buffer */
388         if (!init_sam_from_buffer(user, (unsigned char *)data.dptr, data.dsize)) {
389                 DEBUG(0,("pdb_getsampwent: Bad SAM_ACCOUNT entry returned from TDB!\n"));
390                 SAFE_FREE(data.dptr);
391                 tdb_close(pwd_tdb);
392                 return nt_status;
393         }
394         SAFE_FREE(data.dptr);
395
396         /* no further use for database, close it now */
397         tdb_close(pwd_tdb);
398         
399         return NT_STATUS_OK;
400 }
401
402 /***************************************************************************
403  Search by rid
404  **************************************************************************/
405
406 static NTSTATUS tdbsam_getsampwrid (struct pdb_methods *my_methods, SAM_ACCOUNT *user, uint32 rid)
407 {
408         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
409         struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data;
410         TDB_CONTEXT             *pwd_tdb;
411         TDB_DATA                data, key;
412         fstring                 keystr;
413         fstring                 name;
414         
415         if (user==NULL) {
416                 DEBUG(0,("pdb_getsampwrid: SAM_ACCOUNT is NULL.\n"));
417                 return nt_status;
418         }
419
420         /* set search key */
421         slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, rid);
422         key.dptr = keystr;
423         key.dsize = strlen (keystr) + 1;
424
425         /* open the accounts TDB */
426         if (!(pwd_tdb = tdbsam_tdbopen(tdb_state->tdbsam_location, O_RDONLY))) {
427                 DEBUG(0, ("pdb_getsampwrid: Unable to open TDB rid database!\n"));
428                 return nt_status;
429         }
430
431         /* get the record */
432         data = tdb_fetch (pwd_tdb, key);
433         if (!data.dptr) {
434                 DEBUG(5,("pdb_getsampwrid (TDB): error looking up RID %d by key %s.\n", rid, keystr));
435                 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(pwd_tdb)));
436                 tdb_close (pwd_tdb);
437                 return nt_status;
438         }
439
440
441         fstrcpy(name, data.dptr);
442         SAFE_FREE(data.dptr);
443         
444         tdb_close (pwd_tdb);
445         
446         return tdbsam_getsampwnam (my_methods, user, name);
447 }
448
449 static NTSTATUS tdbsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const DOM_SID *sid)
450 {
451         uint32 rid;
452         if (!sid_peek_check_rid(get_global_sam_sid(), sid, &rid))
453                 return NT_STATUS_UNSUCCESSFUL;
454         return tdbsam_getsampwrid(my_methods, user, rid);
455 }
456
457 /***************************************************************************
458  Delete a SAM_ACCOUNT
459 ****************************************************************************/
460
461 static NTSTATUS tdbsam_delete_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT *sam_pass)
462 {
463         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
464         struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data;
465         TDB_CONTEXT     *pwd_tdb;
466         TDB_DATA        key;
467         fstring         keystr;
468         uint32          rid;
469         fstring         name;
470         
471         fstrcpy(name, pdb_get_username(sam_pass));
472         strlower_m(name);
473         
474         /* open the TDB */
475         if (!(pwd_tdb = tdbsam_tdbopen(tdb_state->tdbsam_location, O_RDWR))) {
476                 DEBUG(0, ("Unable to open TDB passwd!"));
477                 return nt_status;
478         }
479   
480         /* set the search key */
481         slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
482         key.dptr = keystr;
483         key.dsize = strlen (keystr) + 1;
484         
485         rid = pdb_get_user_rid(sam_pass);
486
487         /* it's outaa here!  8^) */
488         if (tdb_delete(pwd_tdb, key) != TDB_SUCCESS) {
489                 DEBUG(5, ("Error deleting entry from tdb passwd database!\n"));
490                 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(pwd_tdb)));
491                 tdb_close(pwd_tdb); 
492                 return nt_status;
493         }       
494
495         /* delete also the RID key */
496
497         /* set the search key */
498         slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, rid);
499         key.dptr = keystr;
500         key.dsize = strlen (keystr) + 1;
501
502         /* it's outaa here!  8^) */
503         if (tdb_delete(pwd_tdb, key) != TDB_SUCCESS) {
504                 DEBUG(5, ("Error deleting entry from tdb rid database!\n"));
505                 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(pwd_tdb)));
506                 tdb_close(pwd_tdb); 
507                 return nt_status;
508         }
509         
510         tdb_close(pwd_tdb);
511         
512         return NT_STATUS_OK;
513 }
514
515 /***************************************************************************
516  Update the TDB SAM
517 ****************************************************************************/
518
519 static BOOL tdb_update_sam(struct pdb_methods *my_methods, SAM_ACCOUNT* newpwd, int flag)
520 {
521         struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data;
522         TDB_CONTEXT     *pwd_tdb = NULL;
523         TDB_DATA        key, data;
524         uint8           *buf = NULL;
525         fstring         keystr;
526         fstring         name;
527         BOOL            ret = True;
528         uint32          user_rid;
529
530         /* invalidate the existing TDB iterator if it is open */
531         
532         if (tdb_state->passwd_tdb) {
533                 tdb_close(tdb_state->passwd_tdb);
534                 tdb_state->passwd_tdb = NULL;
535         }
536
537         /* open the account TDB passwd*/
538         
539         pwd_tdb = tdbsam_tdbopen(tdb_state->tdbsam_location, O_RDWR | O_CREAT);
540         
541         if (!pwd_tdb) {
542                 DEBUG(0, ("tdb_update_sam: Unable to open TDB passwd (%s)!\n", 
543                         tdb_state->tdbsam_location));
544                 return False;
545         }
546
547         if (!pdb_get_group_rid(newpwd)) {
548                 DEBUG (0,("tdb_update_sam: Failing to store a SAM_ACCOUNT for [%s] without a primary group RID\n",
549                         pdb_get_username(newpwd)));
550                 ret = False;
551                 goto done;
552         }
553
554         if ( !(user_rid = pdb_get_user_rid(newpwd)) ) {
555                 DEBUG(0,("tdb_update_sam: SAM_ACCOUNT (%s) with no RID!\n", pdb_get_username(newpwd)));
556                 ret = False;
557                 goto done;
558         }
559
560         /* copy the SAM_ACCOUNT struct into a BYTE buffer for storage */
561         if ((data.dsize=init_buffer_from_sam (&buf, newpwd, False)) == -1) {
562                 DEBUG(0,("tdb_update_sam: ERROR - Unable to copy SAM_ACCOUNT info BYTE buffer!\n"));
563                 ret = False;
564                 goto done;
565         }
566         data.dptr = (char *)buf;
567
568         fstrcpy(name, pdb_get_username(newpwd));
569         strlower_m(name);
570         
571         DEBUG(5, ("Storing %saccount %s with RID %d\n", flag == TDB_INSERT ? "(new) " : "", name, user_rid));
572
573         /* setup the USER index key */
574         slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
575         key.dptr = keystr;
576         key.dsize = strlen(keystr) + 1;
577
578         /* add the account */
579         if (tdb_store(pwd_tdb, key, data, flag) != TDB_SUCCESS) {
580                 DEBUG(0, ("Unable to modify passwd TDB!"));
581                 DEBUGADD(0, (" Error: %s", tdb_errorstr(pwd_tdb)));
582                 DEBUGADD(0, (" occured while storing the main record (%s)\n", keystr));
583                 ret = False;
584                 goto done;
585         }
586         
587         /* setup RID data */
588         data.dsize = strlen(name) + 1;
589         data.dptr = name;
590
591         /* setup the RID index key */
592         slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, user_rid);
593         key.dptr = keystr;
594         key.dsize = strlen (keystr) + 1;
595         
596         /* add the reference */
597         if (tdb_store(pwd_tdb, key, data, flag) != TDB_SUCCESS) {
598                 DEBUG(0, ("Unable to modify TDB passwd !"));
599                 DEBUGADD(0, (" Error: %s\n", tdb_errorstr(pwd_tdb)));
600                 DEBUGADD(0, (" occured while storing the RID index (%s)\n", keystr));
601                 ret = False;
602                 goto done;
603         }
604
605 done:   
606         /* cleanup */
607         tdb_close (pwd_tdb);
608         SAFE_FREE(buf);
609         
610         return (ret);   
611 }
612
613 /***************************************************************************
614  Modifies an existing SAM_ACCOUNT
615 ****************************************************************************/
616
617 static NTSTATUS tdbsam_update_sam_account (struct pdb_methods *my_methods, SAM_ACCOUNT *newpwd)
618 {
619         if (tdb_update_sam(my_methods, newpwd, TDB_MODIFY))
620                 return NT_STATUS_OK;
621         else
622                 return NT_STATUS_UNSUCCESSFUL;
623 }
624
625 /***************************************************************************
626  Adds an existing SAM_ACCOUNT
627 ****************************************************************************/
628
629 static NTSTATUS tdbsam_add_sam_account (struct pdb_methods *my_methods, SAM_ACCOUNT *newpwd)
630 {
631         if (tdb_update_sam(my_methods, newpwd, TDB_INSERT))
632                 return NT_STATUS_OK;
633         else
634                 return NT_STATUS_UNSUCCESSFUL;
635 }
636
637 static void free_private_data(void **vp) 
638 {
639         struct tdbsam_privates **tdb_state = (struct tdbsam_privates **)vp;
640         close_tdb(*tdb_state);
641         *tdb_state = NULL;
642
643         /* No need to free any further, as it is talloc()ed */
644 }
645
646 /**
647  * Start enumerating through trust passwords (machine and
648  * interdomain nt/ads)
649  *
650  * @param methods methods belonging in pdb context (module)
651  * @param trust trust password structure
652  *
653  * @return nt status of performed operation
654  **/
655
656 static NTSTATUS tdbsam_gettrustpwent(struct pdb_methods *methods, SAM_TRUST_PASSWD *trust)
657 {
658         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
659         struct trust_passwd_data t;
660         TALLOC_CTX *mem_ctx;
661         
662         TRUSTDOM **trustdom;
663         static int enum_ctx;
664         int num_domains = 0;
665         unsigned int max_domains = 1;
666         char *dom_name, *dom_pass;
667         
668         smb_ucs2_t *uni_dom_name;
669         uint8 mach_pass[16];
670         uint32 sec_chan;
671         
672         if (!methods) return NT_STATUS_UNSUCCESSFUL;
673         
674         /*
675          * NT domain trust passwords
676          */
677         
678         /* rewind enumeration when passed NULL pointer as a trust */
679         if (!trust) {
680                 enum_ctx = 0;
681                 return NT_STATUS_OK;
682         }
683         
684         mem_ctx = talloc_init("tdbsam_gettrustpwent: trust password enumeration");
685
686         /* fetch next trusted domain (one at a time) and its full information */
687         nt_status = secrets_get_trusted_domains(mem_ctx, &enum_ctx, max_domains, &num_domains,
688                                                 &trustdom);
689         if (num_domains) {
690                 pull_ucs2_talloc(mem_ctx, &dom_name, trustdom[0]->name);
691                 if (secrets_fetch_trusted_domain_password(dom_name, &dom_pass, &t.domain_sid,
692                                                           &t.mod_time)) {
693
694                         t.uni_name_len = strnlen_w(trustdom[0]->name, 32);
695                         strncpy_w(t.uni_name, trustdom[0]->name, t.uni_name_len);
696                         safe_strcpy(t.pass, dom_pass, FSTRING_LEN - 1);
697                         t.flags = PASS_DOMAIN_TRUST_NT;
698
699                         SAFE_FREE(dom_pass);
700                         talloc_destroy(mem_ctx);
701                         trust->private = t;
702                         return nt_status;
703                 } else {
704                         talloc_destroy(mem_ctx);
705                         return NT_STATUS_UNSUCCESSFUL;
706                 }
707         }
708         
709         /*
710          * NT machine trust password
711          */
712         
713         if (secrets_lock_trust_account_password(lp_workgroup(), True)) {
714                 sec_chan = get_default_sec_channel();
715                 if (secrets_fetch_trust_account_password(lp_workgroup(), mach_pass, &t.mod_time,
716                                                          &sec_chan)) {
717                         
718                         t.uni_name_len = strlen(lp_workgroup());
719                         push_ucs2_talloc(mem_ctx, &uni_dom_name, lp_workgroup());
720                         strncpy_w(t.uni_name, uni_dom_name, t.uni_name_len);
721                         safe_strcpy(t.pass, mach_pass, FSTRING_LEN - 1);
722                         t.flags = PASS_MACHINE_TRUST_NT;
723                         if (!secrets_fetch_domain_sid(lp_workgroup(), &t.domain_sid)) {
724                                 talloc_destroy(mem_ctx);
725                                 return NT_STATUS_UNSUCCESSFUL;
726                         }
727                         
728                         talloc_destroy(mem_ctx);
729                         trust->private = t;
730                         return NT_STATUS_OK;
731                 }
732                 secrets_lock_trust_account_password(lp_workgroup(), False);
733         } else {
734                 talloc_destroy(mem_ctx);
735                 return NT_STATUS_UNSUCCESSFUL;
736         }
737
738         /*
739          * ADS machine trust password (TODO)
740          */
741
742         talloc_destroy(mem_ctx);
743         return nt_status;
744 }
745
746 /**
747  * Get trust password by trusted party sid
748  *
749  * @param methods methods belonging to pdb context (module)
750  * @param trust trust password structure
751  * @param sid trusted party sid
752  *
753  * @return nt status of performed operation
754  **/
755  
756 static NTSTATUS tdbsam_gettrustpwsid(struct pdb_methods *methods, SAM_TRUST_PASSWD *trust,
757                                      const DOM_SID *sid)
758 {
759         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
760         return nt_status;
761 }
762
763
764 /**
765  * Add new trust password.
766  *
767  * @param methods methods belonging in pdb context (module)
768  * @param trust trust password structure
769  *
770  * @return nt status of performed operation
771  **/
772
773 static NTSTATUS tdbsam_add_trust_passwd(struct pdb_methods *methods, const SAM_TRUST_PASSWD *trust)
774 {
775         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
776         BOOL status = False;
777         TALLOC_CTX *mem_ctx;
778         
779         char* domain = NULL;
780         struct trust_passwd_data t = trust->private;
781         uint32 sec_chan;
782
783         mem_ctx = talloc_init("tdbsam_add_trust_passwd: storing new trust password");
784                 
785         /* convert unicode name to char* (used to form the key) */
786         pull_ucs2_talloc(mem_ctx, &domain, t.uni_name);
787         
788         /* add nt machine trust password */
789         if (t.flags & (PASS_MACHINE_TRUST_NT | PASS_SERVER_TRUST_NT)) {
790                 sec_chan = (t.flags & PASS_MACHINE_TRUST_NT) ? SEC_CHAN_WKSTA : SEC_CHAN_BDC;
791                 status = secrets_store_machine_password(t.pass, domain, sec_chan);
792                 if (status)
793                         status = secrets_store_domain_sid(domain, &t.domain_sid);
794                 
795                 nt_status = status ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
796                 
797         /* add nt domain trust password */
798         } else if (t.flags & PASS_DOMAIN_TRUST_NT) {
799                 status = secrets_store_trusted_domain_password(domain, t.uni_name, t.uni_name_len,
800                                                                t.pass, t.domain_sid);
801                 nt_status = status ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
802                 
803         /* add ads machine trust password (TODO) */
804         } else if (t.flags & PASS_MACHINE_TRUST_ADS) {
805         }
806
807         talloc_destroy(mem_ctx);        
808         return nt_status;
809 }
810
811
812 /**
813  * Update trust password.
814  *
815  * @param methods methods belonging in pdb context (module)
816  * @param trust trust password structure
817  *
818  * @return nt status of performed operation
819  **/
820
821 static NTSTATUS tdbsam_update_trust_passwd(struct pdb_methods *methods, const SAM_TRUST_PASSWD* trust)
822 {
823         NTSTATUS nt_status = NT_STATUS_NOT_IMPLEMENTED;
824         return nt_status;
825 }
826
827
828 /**
829  * Delete trust password.
830  *
831  * @param methods methods belonging in pdb context (module)
832  * @param trust trust password structure
833  *
834  * @return nt status of performed operation
835  **/
836
837 static NTSTATUS tdbsam_delete_trust_passwd(struct pdb_methods *methods, const SAM_TRUST_PASSWD* trust)
838 {
839         NTSTATUS nt_status = NT_STATUS_NOT_IMPLEMENTED;
840         return nt_status;
841 }
842
843
844 static NTSTATUS pdb_init_tdbsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
845 {
846         NTSTATUS nt_status;
847         struct tdbsam_privates *tdb_state;
848
849         if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
850                 return nt_status;
851         }
852
853         (*pdb_method)->name = "tdbsam";
854
855         (*pdb_method)->setsampwent = tdbsam_setsampwent;
856         (*pdb_method)->endsampwent = tdbsam_endsampwent;
857         (*pdb_method)->getsampwent = tdbsam_getsampwent;
858         (*pdb_method)->getsampwnam = tdbsam_getsampwnam;
859         (*pdb_method)->getsampwsid = tdbsam_getsampwsid;
860         (*pdb_method)->add_sam_account = tdbsam_add_sam_account;
861         (*pdb_method)->update_sam_account = tdbsam_update_sam_account;
862         (*pdb_method)->delete_sam_account = tdbsam_delete_sam_account;
863         (*pdb_method)->gettrustpwent = tdbsam_gettrustpwent;
864         (*pdb_method)->gettrustpwsid = tdbsam_gettrustpwsid;
865         (*pdb_method)->add_trust_passwd = tdbsam_add_trust_passwd;
866         (*pdb_method)->update_trust_passwd = tdbsam_update_trust_passwd;
867         (*pdb_method)->delete_trust_passwd = tdbsam_delete_trust_passwd;
868
869         tdb_state = talloc_zero(pdb_context->mem_ctx, sizeof(struct tdbsam_privates));
870
871         if (!tdb_state) {
872                 DEBUG(0, ("talloc() failed for tdbsam private_data!\n"));
873                 return NT_STATUS_NO_MEMORY;
874         }
875
876         if (location) {
877                 tdb_state->tdbsam_location = talloc_strdup(pdb_context->mem_ctx, location);
878         } else {
879                 pstring tdbfile;
880                 get_private_directory(tdbfile);
881                 pstrcat(tdbfile, "/");
882                 pstrcat(tdbfile, PASSDB_FILE_NAME);
883                 tdb_state->tdbsam_location = talloc_strdup(pdb_context->mem_ctx, tdbfile);
884         }
885
886         (*pdb_method)->private_data = tdb_state;
887
888         (*pdb_method)->free_private_data = free_private_data;
889
890         return NT_STATUS_OK;
891 }
892
893 NTSTATUS pdb_tdbsam_init(void)
894 {
895         return smb_register_passdb(PASSDB_INTERFACE_VERSION, "tdbsam", pdb_init_tdbsam);
896 }