r9555: More updates. Everything except for secrets.c compiles now..
[ira/wip.git] / source4 / lib / samba3 / tdbsam.c
1 /* 
2    Unix SMB/CIFS implementation.
3    tdb passdb backend format routines
4
5     Copyright (C) Andrew Tridgell   1992-1998
6         Copyright (C) Simo Sorce        2000-2003
7         Copyright (C) Gerald Carter     2000
8         Copyright (C) Jeremy Allison    2001
9         Copyright (C) Andrew Bartlett   2002
10     Copyright (C) Jelmer Vernooij       2005
11    
12    This program is free software; you can redistribute it and/or modify
13    it under the terms of the GNU General Public License as published by
14    the Free Software Foundation; either version 2 of the License, or
15    (at your option) any later version.
16    
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20    GNU General Public License for more details.
21    
22    You should have received a copy of the GNU General Public License
23    along with this program; if not, write to the Free Software
24    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 */
26
27 #include "includes.h"
28 #include "system/iconv.h"
29 #include "system/filesys.h"
30 #include "lib/tdb/include/tdbutil.h"
31 #include "lib/samba3/samba3.h"
32
33 #define TDB_FORMAT_STRING_V0       "ddddddBBBBBBBBBBBBddBBwdwdBwwd"
34 #define TDB_FORMAT_STRING_V1       "dddddddBBBBBBBBBBBBddBBwdwdBwwd"
35 #define TDB_FORMAT_STRING_V2       "dddddddBBBBBBBBBBBBddBBBwwdBwwd"
36 #define TDBSAM_VERSION_STRING      "INFO/version"
37
38 /**
39  * Open the TDB passwd database, check version and convert it if needed.
40  * @param name filename of the tdbsam file.
41  * @param version version of the tdbsam database
42  * @return a TDB_CONTEXT handle on the tdbsam file.
43  **/
44
45 static TDB_CONTEXT *tdbsam_open (const char *name, int32_t *version)
46 {
47         TDB_CONTEXT     *pdb_tdb;
48         
49         /* Try to open tdb passwd */
50         if (!(pdb_tdb = tdb_open(name, 0, TDB_DEFAULT, 
51                                      O_RDONLY, 0600))) {
52                 DEBUG(0, ("Unable to open TDB passwd\n"));
53                 return NULL;
54         }
55
56         /* Check the version */
57         *version = tdb_fetch_int32(pdb_tdb, 
58                                                 TDBSAM_VERSION_STRING);
59         if (*version == -1)
60                 *version = 0;   /* Version not found, assume version 0 */
61         
62         /* Compare the version */
63         if (*version > 2) {
64                 /* Version more recent than the latest known */ 
65                 DEBUG(0, ("TDBSAM version unknown: %d\n", *version));
66                 tdb_close(pdb_tdb);
67                 pdb_tdb = NULL;
68         } 
69         
70         return pdb_tdb;
71 }
72
73 static BOOL init_sam_from_buffer_v0(TDB_CONTEXT *tdb, struct samba3_samaccount *sampass, TDB_DATA buf)
74 {
75         uint32_t        username_len, domain_len, nt_username_len,
76                 dir_drive_len, unknown_str_len, munged_dial_len,
77                 fullname_len, homedir_len, logon_script_len,
78                 profile_path_len, acct_desc_len, workstations_len;
79                 
80         uint32_t        remove_me;
81         uint32_t                len = 0;
82         uint32_t                lm_pw_len, nt_pw_len, hourslen;
83         
84         if(sampass == NULL || buf.dptr == NULL) {
85                 DEBUG(0, ("init_sam_from_buffer_v0: NULL parameters found!\n"));
86                 return False;
87         }
88
89         /* unpack the buffer into variables */
90         len = tdb_unpack (tdb, (char *)buf.dptr, buf.dsize, TDB_FORMAT_STRING_V0,
91                 &sampass->logon_time,                                   /* d */
92                 &sampass->logoff_time,                                  /* d */
93                 &sampass->kickoff_time,                                 /* d */
94                 &sampass->pass_last_set_time,                           /* d */
95                 &sampass->pass_can_change_time,                         /* d */
96                 &sampass->pass_must_change_time,                        /* d */
97                 &username_len, &sampass->username,                      /* B */
98                 &domain_len, &sampass->domain,                          /* B */
99                 &nt_username_len, &sampass->nt_username,                /* B */
100                 &fullname_len, &sampass->fullname,                      /* B */
101                 &homedir_len, &sampass->homedir,                        /* B */
102                 &dir_drive_len, &sampass->dir_drive,                    /* B */
103                 &logon_script_len, &sampass->logon_script,              /* B */
104                 &profile_path_len, &sampass->profile_path,              /* B */
105                 &acct_desc_len, &sampass->acct_desc,                    /* B */
106                 &workstations_len, &sampass->workstations,              /* B */
107                 &unknown_str_len, &sampass->unknown_str,                /* B */
108                 &munged_dial_len, &sampass->munged_dial,                /* B */
109                 &sampass->user_rid,                                     /* d */
110                 &sampass->group_rid,                                    /* d */
111                 &lm_pw_len, &sampass->lm_pw_ptr,                        /* B */
112                 &nt_pw_len, &sampass->nt_pw_ptr,                        /* B */
113                 &sampass->acct_ctrl,                                    /* w */
114                 &remove_me, /* remove on the next TDB_FORMAT upgarde */ /* d */
115                 &sampass->logon_divs,                                   /* w */
116                 &sampass->hours_len,                                    /* d */
117                 &hourslen, &sampass->hours,                             /* B */
118                 &sampass->bad_password_count,                           /* w */
119                 &sampass->logon_count,                                  /* w */
120                 &sampass->unknown_6);                                   /* d */
121                 
122         if (len == (uint32_t) -1)  {
123                 return False;
124         }
125
126         if (lm_pw_len != 16) {
127                 sampass->lm_pw_ptr = NULL;
128         }
129
130         if (nt_pw_len != 16) {
131                 sampass->nt_pw_ptr = NULL;
132         }
133
134         return True;
135 }
136
137 static BOOL init_sam_from_buffer_v1(TDB_CONTEXT *tdb, struct samba3_samaccount *sampass, TDB_DATA buf)
138 {
139         uint32_t        username_len, domain_len, nt_username_len,
140                 dir_drive_len, unknown_str_len, munged_dial_len,
141                 fullname_len, homedir_len, logon_script_len,
142                 profile_path_len, acct_desc_len, workstations_len;
143                 
144         uint32_t        remove_me;
145         uint32_t                len = 0;
146         uint32_t                lm_pw_len, nt_pw_len, hourslen;
147         
148         if(sampass == NULL || buf.dptr == NULL) {
149                 DEBUG(0, ("init_sam_from_buffer_v1: NULL parameters found!\n"));
150                 return False;
151         }
152
153         /* unpack the buffer into variables */
154         len = tdb_unpack (tdb, (char *)buf.dptr, buf.dsize, TDB_FORMAT_STRING_V1,
155                 &sampass->logon_time,                                   /* d */
156                 &sampass->logoff_time,                                  /* d */
157                 &sampass->kickoff_time,                         /* d */
158                 /* Change from V0 is addition of bad_password_time field. */
159                 &sampass->bad_password_time,                            /* d */
160                 &sampass->pass_last_set_time,                           /* d */
161                 &sampass->pass_can_change_time,                 /* d */
162                 &sampass->pass_must_change_time,                        /* d */
163                 &username_len, &sampass->username,                      /* B */
164                 &domain_len, &sampass->domain,          /* B */
165                 &nt_username_len, &sampass->nt_username,        /* B */
166                 &fullname_len, &sampass->fullname,                      /* B */
167                 &homedir_len, &sampass->homedir,                        /* B */
168                 &dir_drive_len, &sampass->dir_drive,                    /* B */
169                 &logon_script_len, &sampass->logon_script,              /* B */
170                 &profile_path_len, &sampass->profile_path,              /* B */
171                 &acct_desc_len, &sampass->acct_desc,                    /* B */
172                 &workstations_len, &sampass->workstations,              /* B */
173                 &unknown_str_len, &sampass->unknown_str,                /* B */
174                 &munged_dial_len, &sampass->munged_dial,                /* B */
175                 &sampass->user_rid,                                     /* d */
176                 &sampass->group_rid,                                    /* d */
177                 &lm_pw_len, &sampass->lm_pw_ptr,                        /* B */
178                 &nt_pw_len, &sampass->nt_pw_ptr,                        /* B */
179                 &sampass->acct_ctrl,                                    /* w */
180                 &remove_me,                                             /* d */
181                 &sampass->logon_divs,                                   /* w */
182                 &sampass->hours_len,                                    /* d */
183                 &hourslen, &sampass->hours,                             /* B */
184                 &sampass->bad_password_count,                           /* w */
185                 &sampass->logon_count,                                  /* w */
186                 &sampass->unknown_6);                                   /* d */
187                 
188         if (len == (uint32_t) -1)  {
189                 return False;
190         }
191
192         if (sampass->lm_pw_ptr && lm_pw_len != 16) {
193                 sampass->lm_pw_ptr = NULL;
194         }
195
196         if (sampass->nt_pw_ptr && nt_pw_len != 16) {
197                 sampass->nt_pw_ptr = NULL;
198         }
199
200         return True;
201 }
202
203 static BOOL init_sam_from_buffer_v2(TDB_CONTEXT *tdb, struct samba3_samaccount *sampass, TDB_DATA buf)
204 {
205         uint32_t        username_len, domain_len, nt_username_len,
206                 dir_drive_len, unknown_str_len, munged_dial_len,
207                 fullname_len, homedir_len, logon_script_len,
208                 profile_path_len, acct_desc_len, workstations_len;
209                 
210         uint32_t                len = 0;
211         uint32_t                lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen;
212         
213         if(sampass == NULL || buf.dptr == NULL) {
214                 DEBUG(0, ("init_sam_from_buffer_v2: NULL parameters found!\n"));
215                 return False;
216         }
217
218         /* unpack the buffer into variables */
219         len = tdb_unpack (tdb, (char *)buf.dptr, buf.dsize, TDB_FORMAT_STRING_V2,
220                 &sampass->logon_time,                                   /* d */
221                 &sampass->logoff_time,                                  /* d */
222                 &sampass->kickoff_time,                                 /* d */
223                 &sampass->bad_password_time,                            /* d */
224                 &sampass->pass_last_set_time,                           /* d */
225                 &sampass->pass_can_change_time,                         /* d */
226                 &sampass->pass_must_change_time,                        /* d */
227                 &username_len, &sampass->username,                      /* B */
228                 &domain_len, &sampass->domain,                          /* B */
229                 &nt_username_len, &sampass->nt_username,                /* B */
230                 &fullname_len, &sampass->fullname,                      /* B */
231                 &homedir_len, &sampass->homedir,                        /* B */
232                 &dir_drive_len, &sampass->dir_drive,                    /* B */
233                 &logon_script_len, &sampass->logon_script,              /* B */
234                 &profile_path_len, &sampass->profile_path,              /* B */
235                 &acct_desc_len, &sampass->acct_desc,                    /* B */
236                 &workstations_len, &sampass->workstations,              /* B */
237                 &unknown_str_len, &sampass->unknown_str,                /* B */
238                 &munged_dial_len, &sampass->munged_dial,                /* B */
239                 &sampass->user_rid,                                     /* d */
240                 &sampass->group_rid,                                    /* d */
241                 &lm_pw_len, &sampass->lm_pw_ptr,                        /* B */
242                 &nt_pw_len, &sampass->nt_pw_ptr,                        /* B */
243                 /* Change from V1 is addition of password history field. */
244                 &nt_pw_hist_len, &sampass->nt_pw_hist_ptr,              /* B */
245                 &sampass->acct_ctrl,                                    /* w */
246                 /* Also "remove_me" field was removed. */
247                 &sampass->logon_divs,                                   /* w */
248                 &sampass->hours_len,                                    /* d */
249                 &hourslen, &sampass->hours,                             /* B */
250                 &sampass->bad_password_count,                           /* w */
251                 &sampass->logon_count,                                  /* w */
252                 &sampass->unknown_6);                                   /* d */
253                 
254         if (len == (uint32_t) -1)  {
255                 return False;
256         }
257
258         if (sampass->lm_pw_ptr && lm_pw_len != 16) {
259                 sampass->lm_pw_ptr = NULL;
260         }
261
262         if (sampass->nt_pw_ptr && nt_pw_len != 16) {
263                 sampass->nt_pw_ptr = NULL;
264         }
265
266         return True;
267 }
268
269 NTSTATUS samba3_read_tdbsam(TALLOC_CTX *ctx, const char *filename, struct samba3_samaccount **accounts, uint32_t *count)
270 {
271         int32_t version;
272         TDB_CONTEXT *tdb = tdbsam_open(filename, &version);
273         TDB_DATA key, val;
274
275         if (tdb == NULL)
276                 return NT_STATUS_UNSUCCESSFUL;
277
278         if (version < 0 || version > 2) {
279                 return NT_STATUS_NOT_SUPPORTED;
280         }
281         
282         *accounts = NULL;
283         *count = 0;
284
285         for (key = tdb_firstkey(tdb); key.dptr; key = tdb_nextkey(tdb, key))
286         {
287                 if (strncmp(key.dptr, "RID/", 4) == 0) continue;
288
289                 val = tdb_fetch(tdb, key);
290
291                 *accounts = talloc_realloc(ctx, *accounts, struct samba3_samaccount, (*count)+1);
292
293                 switch (version) 
294                 {
295                         case 0: init_sam_from_buffer_v0(tdb, &(*accounts)[*count], val); break;
296                         case 1: init_sam_from_buffer_v1(tdb, &(*accounts)[*count], val); break;
297                         case 2: init_sam_from_buffer_v2(tdb, &(*accounts)[*count], val); break;
298
299                 }
300
301                 (*count)++;
302         }
303         
304         tdb_close(tdb);
305         
306         return NT_STATUS_OK;
307 }