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