s4:libcli/raw/raw*.c - add unhandled enum values
[idra/samba.git] / source3 / torture / pdbtest.c
1 /* 
2    Unix SMB/CIFS implementation.
3    passdb testing utility
4    
5    Copyright (C) Wilco Baan Hofman 2006
6    Copyright (C) Jelmer Vernooij 2006
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22
23 #include "includes.h"
24 #include "popt_common.h"
25 #include "passdb.h"
26
27 static bool samu_correct(struct samu *s1, struct samu *s2)
28 {
29         bool ret = True;
30         uint32 s1_len, s2_len;
31         const char *s1_buf, *s2_buf;
32         const uint8 *d1_buf, *d2_buf;
33                 
34         /* Check Unix username */
35         s1_buf = pdb_get_username(s1);
36         s2_buf = pdb_get_username(s2);
37         if (s2_buf == NULL && s1_buf != NULL) {
38                 DEBUG(0, ("Username is not set\n"));
39                 ret = False;
40         } else if (s1_buf == NULL) {
41                 /* Do nothing */
42         } else if (strcmp(s1_buf,s2_buf)) {
43                 DEBUG(0, ("Username not written correctly, want %s, got \"%s\"\n",
44                                         pdb_get_username(s1),
45                                         pdb_get_username(s2)));
46                 ret = False;
47         }
48
49         /* Check NT username */
50         s1_buf = pdb_get_nt_username(s1);
51         s2_buf = pdb_get_nt_username(s2);
52         if (s2_buf == NULL && s1_buf != NULL) {
53                 DEBUG(0, ("NT Username is not set\n"));
54                 ret = False;
55         } else if (s1_buf == NULL) {
56                 /* Do nothing */
57         } else if (strcmp(s1_buf, s2_buf)) {
58                 DEBUG(0, ("NT Username not written correctly, want \"%s\", got \"%s\"\n",
59                                         pdb_get_nt_username(s1),
60                                         pdb_get_nt_username(s2)));
61                 ret = False;
62         }
63
64         /* Check acct ctrl */
65         if (pdb_get_acct_ctrl(s1) != pdb_get_acct_ctrl(s2)) {
66                 DEBUG(0, ("Acct ctrl field not written correctly, want %d (0x%X), got %d (0x%X)\n",
67                                         pdb_get_acct_ctrl(s1),
68                                         pdb_get_acct_ctrl(s1),
69                                         pdb_get_acct_ctrl(s2),
70                                         pdb_get_acct_ctrl(s2)));
71                 ret = False;
72         }
73
74         /* Check NT password */
75         d1_buf = pdb_get_nt_passwd(s1);
76         d2_buf = pdb_get_nt_passwd(s2);
77         if (d2_buf == NULL && d1_buf != NULL) {
78                 DEBUG(0, ("NT password is not set\n"));
79                 ret = False;
80         } else if (d1_buf == NULL) {
81                 /* Do nothing */
82         } else if (memcmp(d1_buf, d2_buf, NT_HASH_LEN)) {
83                 DEBUG(0, ("NT password not written correctly\n"));
84                 ret = False;
85         }
86
87         /* Check lanman password */
88         d1_buf = pdb_get_lanman_passwd(s1);
89         d2_buf = pdb_get_lanman_passwd(s2);
90         if (d2_buf == NULL && d1_buf != NULL) {
91                 DEBUG(0, ("Lanman password is not set\n"));
92         } else if (d1_buf == NULL) {
93                 /* Do nothing */
94         } else if (memcmp(d1_buf, d2_buf, NT_HASH_LEN)) {
95                 DEBUG(0, ("Lanman password not written correctly\n"));
96                 ret = False;
97         }
98
99         /* Check password history */
100         d1_buf = pdb_get_pw_history(s1, &s1_len);
101         d2_buf = pdb_get_pw_history(s2, &s2_len);
102         if (d2_buf == NULL && d1_buf != NULL) {
103                 DEBUG(0, ("Password history is not set\n"));
104         } else if (d1_buf == NULL) {
105                 /* Do nothing */
106         } else if (s1_len != s1_len) {
107                 DEBUG(0, ("Password history not written correctly, lengths differ, want %d, got %d\n",
108                                         s1_len, s2_len));
109                 ret = False;
110         } else if (strncmp(s1_buf, s2_buf, s1_len)) {
111                 DEBUG(0, ("Password history not written correctly\n"));
112                 ret = False;
113         }
114
115         /* Check logon time */
116         if (pdb_get_logon_time(s1) != pdb_get_logon_time(s2)) {
117                 DEBUG(0, ("Logon time is not written correctly\n"));
118                 ret = False;
119         }
120
121         /* Check logoff time */
122         if (pdb_get_logoff_time(s1) != pdb_get_logoff_time(s2)) {
123                 DEBUG(0, ("Logoff time is not written correctly\n"));
124                 ret = False;
125         }
126         
127         /* Check kickoff time */
128         if (pdb_get_kickoff_time(s1) != pdb_get_logoff_time(s2)) {
129                 DEBUG(0, ("Kickoff time is not written correctly\n"));
130                 ret = False;
131         }
132         
133         /* Check bad password time */
134         if (pdb_get_bad_password_time(s1) != pdb_get_bad_password_time(s2)) {
135                 DEBUG(0, ("Bad password time is not written correctly\n"));
136                 ret = False;
137         }
138         
139         /* Check password last set time */
140         if (pdb_get_pass_last_set_time(s1) != pdb_get_pass_last_set_time(s2)) {
141                 DEBUG(0, ("Password last set time is not written correctly\n"));
142                 ret = False;
143         }
144         
145         /* Check password can change time */
146         if (pdb_get_pass_can_change_time(s1) != pdb_get_pass_can_change_time(s2)) {
147                 DEBUG(0, ("Password can change time is not written correctly\n"));
148                 ret = False;
149         }
150         
151         /* Check password must change time */
152         if (pdb_get_pass_must_change_time(s1) != pdb_get_pass_must_change_time(s2)) {
153                 DEBUG(0, ("Password must change time is not written correctly\n"));
154                 ret = False;
155         }
156         
157         /* Check logon divs */
158         if (pdb_get_logon_divs(s1) != pdb_get_logon_divs(s2)) {
159                 DEBUG(0, ("Logon divs not written correctly\n"));
160                 ret = False;
161         }
162         
163         /* Check logon hours */
164         if (pdb_get_hours_len(s1) != pdb_get_hours_len(s2)) {
165                 DEBUG(0, ("Logon hours length not written correctly\n"));
166                 ret = False;
167         } else if (pdb_get_hours_len(s1) != 0) {
168                 d1_buf = pdb_get_hours(s1);
169                 d2_buf = pdb_get_hours(s2);
170                 if (d2_buf == NULL && d2_buf != NULL) {
171                         DEBUG(0, ("Logon hours is not set\n"));
172                         ret = False;
173                 } else if (d1_buf == NULL) {
174                         /* Do nothing */
175                 } else if (memcmp(d1_buf, d2_buf, MAX_HOURS_LEN)) {
176                         DEBUG(0, ("Logon hours is not written correctly\n"));
177                         ret = False;
178                 }
179         }
180         
181         /* Check profile path */
182         s1_buf = pdb_get_profile_path(s1);
183         s2_buf = pdb_get_profile_path(s2);
184         if (s2_buf == NULL && s1_buf != NULL) {
185                 DEBUG(0, ("Profile path is not set\n"));
186                 ret = False;
187         } else if (s1_buf == NULL) {
188                 /* Do nothing */
189         } else if (strcmp(s1_buf, s2_buf)) {
190                 DEBUG(0, ("Profile path is not written correctly\n"));
191                 ret = False;
192         }
193
194         /* Check home dir */
195         s1_buf = pdb_get_homedir(s1);
196         s2_buf = pdb_get_homedir(s2);
197         if (s2_buf == NULL && s1_buf != NULL) {
198                 DEBUG(0, ("Home dir is not set\n"));
199                 ret = False;
200         } else if (s1_buf == NULL) {
201                 /* Do nothing */
202         } else if (strcmp(s1_buf, s2_buf)) {
203                 DEBUG(0, ("Home dir is not written correctly\n"));
204                 ret = False;
205         }
206         
207         /* Check logon script */
208         s1_buf = pdb_get_logon_script(s1);
209         s2_buf = pdb_get_logon_script(s2);
210         if (s2_buf == NULL && s1_buf != NULL) {
211                 DEBUG(0, ("Logon script not set\n"));
212                 ret = False;
213         } else if (s1_buf == NULL) {
214                 /* Do nothing */
215         } else if (strcmp(s1_buf, s2_buf)) {
216                 DEBUG(0, ("Logon script is not written correctly\n"));
217                 ret = False;
218         }
219         
220         /* TODO Check user and group sids */
221                 
222         return ret;     
223 }
224
225
226 int main(int argc, char **argv)
227 {
228         TALLOC_CTX *ctx;
229         struct samu *out = NULL;
230         struct samu *in = NULL;
231         NTSTATUS rv;
232         int i;
233         struct timeval tv;
234         bool error = False;
235         struct passwd *pwd;
236         uint8 *buf;
237         uint32 expire, min_age, history;
238         struct pdb_methods *pdb;
239         poptContext pc;
240         static const char *backend = NULL;
241         static const char *unix_user = "nobody";
242         struct poptOption long_options[] = {
243                 {"username", 'u', POPT_ARG_STRING, &unix_user, 0, "Unix user to use for testing", "USERNAME" },
244                 {"backend", 'b', POPT_ARG_STRING, &backend, 0, "Backend to use if not default", "BACKEND[:SETTINGS]" },
245                 POPT_AUTOHELP
246                 POPT_COMMON_SAMBA
247                 POPT_TABLEEND
248         };
249
250         load_case_tables();
251
252         pc = poptGetContext("pdbtest", argc, (const char **) argv,
253                             long_options, 0);
254
255         poptSetOtherOptionHelp(pc, "backend[:settings] username");
256         
257         while(poptGetNextOpt(pc) != -1);
258
259         poptFreeContext(pc);
260
261         /* Load configuration */
262         lp_load(get_dyn_CONFIGFILE(), False, False, True, True);
263         setup_logging("pdbtest", DEBUG_STDOUT);
264
265         if (backend == NULL) {
266                 backend = lp_passdb_backend();
267         }
268
269         rv = make_pdb_method_name(&pdb, backend);
270         if (NT_STATUS_IS_ERR(rv)) {
271                 fprintf(stderr, "Error initializing '%s': %s\n", backend, get_friendly_nt_error_msg(rv));
272                 exit(1);
273         }
274         
275         ctx = talloc_init("PDBTEST");
276         
277         if (!(out = samu_new(ctx))) {
278                 fprintf(stderr, "Can't create samu structure.\n");
279                 exit(1);
280         }
281         
282         if ((pwd = Get_Pwnam_alloc(ctx, unix_user)) == NULL) {
283                 fprintf(stderr, "Error getting user information for %s\n", unix_user);
284                 exit(1);
285         }
286         
287         samu_set_unix(out, pwd);
288
289         pdb_set_profile_path(out, "\\\\torture\\profile", PDB_SET);
290         pdb_set_homedir(out, "\\\\torture\\home", PDB_SET);
291         pdb_set_logon_script(out, "torture_script.cmd", PDB_SET);
292
293         pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &history);
294         if (history * PW_HISTORY_ENTRY_LEN < NT_HASH_LEN) {
295                 buf = (uint8 *)TALLOC(ctx, NT_HASH_LEN);
296         } else {
297                 buf = (uint8 *)TALLOC(ctx, history * PW_HISTORY_ENTRY_LEN);
298         }
299
300         /* Generate some random hashes */
301         GetTimeOfDay(&tv);
302         srand(tv.tv_usec);
303         for (i = 0; i < NT_HASH_LEN; i++) {
304                 buf[i] = (uint8) rand();
305         }
306         pdb_set_nt_passwd(out, buf, PDB_SET);
307         for (i = 0; i < LM_HASH_LEN; i++) {
308                 buf[i] = (uint8) rand();
309         }
310         pdb_set_lanman_passwd(out, buf, PDB_SET);
311         for (i = 0; i < history * PW_HISTORY_ENTRY_LEN; i++) {
312                 buf[i] = (uint8) rand();
313         }
314         pdb_set_pw_history(out, buf, history, PDB_SET);
315
316         pdb_get_account_policy(PDB_POLICY_MAX_PASSWORD_AGE, &expire);
317         pdb_get_account_policy(PDB_POLICY_MIN_PASSWORD_AGE, &min_age);
318         pdb_set_pass_last_set_time(out, time(NULL), PDB_SET);
319         
320         if (expire == 0 || expire == (uint32)-1) {
321                 pdb_set_pass_must_change_time(out, get_time_t_max(), PDB_SET);
322         } else {
323                 pdb_set_pass_must_change_time(out, time(NULL)+expire, PDB_SET);
324         }
325
326         if (min_age == (uint32)-1) {
327                 pdb_set_pass_can_change_time(out, 0, PDB_SET);
328         } else {
329                 pdb_set_pass_can_change_time(out, time(NULL)+min_age, PDB_SET);
330         }
331         
332         /* Create account */
333         if (!NT_STATUS_IS_OK(rv = pdb->add_sam_account(pdb, out))) {
334                 fprintf(stderr, "Error in add_sam_account: %s\n", 
335                                 get_friendly_nt_error_msg(rv));
336                 exit(1);
337         }
338
339         if (!(in = samu_new(ctx))) {
340                 fprintf(stderr, "Can't create samu structure.\n");
341                 exit(1);
342         }
343         
344         /* Get account information through getsampwnam() */
345         if (NT_STATUS_IS_ERR(pdb->getsampwnam(pdb, in, out->username))) {
346                 fprintf(stderr, "Error getting sampw of added user %s.\n",
347                                 out->username);
348                 if (!NT_STATUS_IS_OK(rv = pdb->delete_sam_account(pdb, out))) {
349                         fprintf(stderr, "Error in delete_sam_account %s\n", 
350                                         get_friendly_nt_error_msg(rv));
351                 }
352                 TALLOC_FREE(ctx);
353         }
354         
355         /* Verify integrity */
356         if (samu_correct(out, in)) {
357                 printf("User info written correctly\n");
358         } else {
359                 printf("User info NOT written correctly\n");
360                 error = True;
361         }
362         
363         /* Delete account */
364         if (!NT_STATUS_IS_OK(rv = pdb->delete_sam_account(pdb, out))) {
365                 fprintf(stderr, "Error in delete_sam_account %s\n", 
366                                         get_friendly_nt_error_msg(rv));
367         }
368
369         TALLOC_FREE(ctx);
370
371         if (error) {
372                 return 1;
373         }
374         return 0;
375 }