root/source4/torture/rpc/samlogon.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. check_samlogon
  2. test_lm_ntlm_broken
  3. test_lm
  4. test_ntlm
  5. test_ntlm_in_lm
  6. test_ntlm_in_both
  7. test_lmv2_ntlmv2_broken
  8. test_lmv2_ntlm_broken
  9. test_lmv2_ntlmv2
  10. test_lmv2_ntlmv2_no_dom
  11. test_lmv2
  12. test_lmv2_no_dom
  13. test_ntlmv2
  14. test_ntlmv2_no_dom
  15. test_lm_ntlm
  16. test_ntlm_lm_broken
  17. test_ntlm_ntlm_broken
  18. test_lm_ntlm_both_broken
  19. test_ntlmv2_lmv2_broken
  20. test_ntlmv2_lmv2_broken_no_dom
  21. test_ntlmv2_ntlmv2_broken
  22. test_ntlmv2_ntlmv2_broken_no_dom
  23. test_ntlmv2_both_broken
  24. test_ntlmv2_both_broken_no_dom
  25. test_lmv2_ntlm_both_broken
  26. test_lmv2_ntlm_both_broken_no_dom
  27. test_lmv2_ntlm_break_ntlm
  28. test_lmv2_ntlm_break_ntlm_no_dom
  29. test_lmv2_ntlm_break_lm
  30. test_lmv2_ntlm_break_lm_no_dom
  31. test_ntlm2
  32. test_plaintext
  33. test_plaintext_none_broken
  34. test_plaintext_lm_broken
  35. test_plaintext_nt_broken
  36. test_plaintext_nt_only
  37. test_plaintext_lm_only
  38. test_SamLogon
  39. test_InteractiveLogon
  40. torture_rpc_samlogon

   1 /* 
   2    Unix SMB/CIFS implementation.
   3 
   4    test suite for netlogon SamLogon operations
   5 
   6    Copyright (C) Andrew Tridgell 2003
   7    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003-2004
   8    Copyright (C) Tim Potter      2003
   9    
  10    This program is free software; you can redistribute it and/or modify
  11    it under the terms of the GNU General Public License as published by
  12    the Free Software Foundation; either version 3 of the License, or
  13    (at your option) any later version.
  14    
  15    This program is distributed in the hope that it will be useful,
  16    but WITHOUT ANY WARRANTY; without even the implied warranty of
  17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18    GNU General Public License for more details.
  19    
  20    You should have received a copy of the GNU General Public License
  21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  22 */
  23 
  24 #include "includes.h"
  25 #include "librpc/gen_ndr/ndr_netlogon.h"
  26 #include "librpc/gen_ndr/ndr_netlogon_c.h"
  27 #include "librpc/gen_ndr/ndr_samr_c.h"
  28 #include "auth/auth.h"
  29 #include "../lib/crypto/crypto.h"
  30 #include "lib/cmdline/popt_common.h"
  31 #include "torture/rpc/rpc.h"
  32 #include "auth/gensec/schannel_proto.h"
  33 #include "auth/gensec/gensec.h"
  34 #include "libcli/auth/libcli_auth.h"
  35 #include "param/param.h"
  36 
  37 #define TEST_MACHINE_NAME "samlogontest"
  38 #define TEST_USER_NAME "samlogontestuser"
  39 #define TEST_USER_NAME_WRONG_WKS "samlogontest2"
  40 #define TEST_USER_NAME_WRONG_TIME "samlogontest3"
  41 
  42 enum ntlm_break {
  43         BREAK_BOTH,
  44         BREAK_NONE,
  45         BREAK_LM,
  46         BREAK_NT,
  47         NO_LM,
  48         NO_NT
  49 };
  50 
  51 struct samlogon_state {
  52         TALLOC_CTX *mem_ctx;
  53         const char *comment;
  54         const char *account_name;
  55         const char *account_domain;
  56         const char *netbios_name;
  57         const char *password;
  58         const char *workgroup;
  59         struct dcerpc_pipe *p;
  60         int function_level;
  61         uint32_t parameter_control;
  62         struct netr_LogonSamLogon r;
  63         struct netr_LogonSamLogonEx r_ex;
  64         struct netr_LogonSamLogonWithFlags r_flags;
  65         struct netr_Authenticator auth, auth2;
  66         struct creds_CredentialState *creds;
  67         NTSTATUS expected_error;
  68         bool old_password; /* Allow an old password to be accepted or rejected without error, as well as session key bugs */
  69         DATA_BLOB chall;
  70         struct smb_iconv_convenience *iconv_convenience;
  71 };
  72 
  73 /* 
  74    Authenticate a user with a challenge/response, checking session key
  75    and valid authentication types
  76 */
  77 static NTSTATUS check_samlogon(struct samlogon_state *samlogon_state, 
     /* [<][>][^][v][top][bottom][index][help] */
  78                                enum ntlm_break break_which,
  79                                uint32_t parameter_control,
  80                                DATA_BLOB *chall, 
  81                                DATA_BLOB *lm_response, 
  82                                DATA_BLOB *nt_response, 
  83                                uint8_t lm_key[8], 
  84                                uint8_t user_session_key[16], 
  85                                char **error_string)
  86 {
  87         NTSTATUS status;
  88         struct netr_LogonSamLogon *r = &samlogon_state->r;
  89         struct netr_LogonSamLogonEx *r_ex = &samlogon_state->r_ex;
  90         struct netr_LogonSamLogonWithFlags *r_flags = &samlogon_state->r_flags;
  91         struct netr_NetworkInfo ninfo;
  92         struct netr_SamBaseInfo *base = NULL;
  93         uint16_t validation_level = 0;
  94         
  95         samlogon_state->r.in.logon->network = &ninfo;
  96         samlogon_state->r_ex.in.logon->network = &ninfo;
  97         samlogon_state->r_flags.in.logon->network = &ninfo;
  98         
  99         ninfo.identity_info.domain_name.string = samlogon_state->account_domain;
 100         ninfo.identity_info.parameter_control = parameter_control;
 101         ninfo.identity_info.logon_id_low = 0;
 102         ninfo.identity_info.logon_id_high = 0;
 103         ninfo.identity_info.account_name.string = samlogon_state->account_name;
 104         ninfo.identity_info.workstation.string = TEST_MACHINE_NAME;
 105                 
 106         memcpy(ninfo.challenge, chall->data, 8);
 107                 
 108         switch (break_which) {
 109         case BREAK_NONE:
 110                 break;
 111         case BREAK_LM:
 112                 if (lm_response && lm_response->data) {
 113                         lm_response->data[0]++;
 114                 }
 115                 break;
 116         case BREAK_NT:
 117                 if (nt_response && nt_response->data) {
 118                         nt_response->data[0]++;
 119                 }
 120                 break;
 121         case BREAK_BOTH:
 122                 if (lm_response && lm_response->data) {
 123                         lm_response->data[0]++;
 124                 }
 125                 if (nt_response && nt_response->data) {
 126                         nt_response->data[0]++;
 127                 }
 128                 break;
 129         case NO_LM:
 130                 data_blob_free(lm_response);
 131                 break;
 132         case NO_NT:
 133                 data_blob_free(nt_response);
 134                 break;
 135         }
 136                 
 137         if (nt_response) {
 138                 ninfo.nt.data = nt_response->data;
 139                 ninfo.nt.length = nt_response->length;
 140         } else {
 141                 ninfo.nt.data = NULL;
 142                 ninfo.nt.length = 0;
 143         }
 144                 
 145         if (lm_response) {
 146                 ninfo.lm.data = lm_response->data;
 147                 ninfo.lm.length = lm_response->length;
 148         } else {
 149                 ninfo.lm.data = NULL;
 150                 ninfo.lm.length = 0;
 151         }
 152         
 153         switch (samlogon_state->function_level) {
 154         case NDR_NETR_LOGONSAMLOGON: 
 155                 ZERO_STRUCT(samlogon_state->auth2);
 156                 creds_client_authenticator(samlogon_state->creds, &samlogon_state->auth);
 157 
 158                 r->out.return_authenticator = NULL;
 159                 status = dcerpc_netr_LogonSamLogon(samlogon_state->p, samlogon_state->mem_ctx, r);
 160                 if (!r->out.return_authenticator || 
 161                     !creds_client_check(samlogon_state->creds, &r->out.return_authenticator->cred)) {
 162                         d_printf("Credential chaining failed\n");
 163                 }
 164                 if (!NT_STATUS_IS_OK(status)) {
 165                         if (error_string) {
 166                                 *error_string = strdup(nt_errstr(status));
 167                         }
 168                         return status;
 169                 }
 170 
 171                 validation_level = r->in.validation_level;
 172 
 173                 creds_decrypt_samlogon(samlogon_state->creds, validation_level, r->out.validation);
 174 
 175                 switch (validation_level) {
 176                 case 2:
 177                         base = &r->out.validation->sam2->base;
 178                         break;
 179                 case 3:
 180                         base = &r->out.validation->sam3->base;
 181                         break;
 182                 case 6:
 183                         base = &r->out.validation->sam6->base;
 184                         break;
 185                 }
 186                 break;
 187         case NDR_NETR_LOGONSAMLOGONEX: 
 188                 status = dcerpc_netr_LogonSamLogonEx(samlogon_state->p, samlogon_state->mem_ctx, r_ex);
 189                 if (!NT_STATUS_IS_OK(status)) {
 190                         if (error_string) {
 191                                 *error_string = strdup(nt_errstr(status));
 192                         }
 193                         return status;
 194                 }
 195 
 196                 validation_level = r_ex->in.validation_level;
 197 
 198                 creds_decrypt_samlogon(samlogon_state->creds, validation_level, r_ex->out.validation);
 199 
 200                 switch (validation_level) {
 201                 case 2:
 202                         base = &r_ex->out.validation->sam2->base;
 203                         break;
 204                 case 3:
 205                         base = &r_ex->out.validation->sam3->base;
 206                         break;
 207                 case 6:
 208                         base = &r_ex->out.validation->sam6->base;
 209                         break;
 210                 }
 211                 break;
 212         case NDR_NETR_LOGONSAMLOGONWITHFLAGS: 
 213                 ZERO_STRUCT(samlogon_state->auth2);
 214                 creds_client_authenticator(samlogon_state->creds, &samlogon_state->auth);
 215 
 216                 r_flags->out.return_authenticator = NULL;
 217                 status = dcerpc_netr_LogonSamLogonWithFlags(samlogon_state->p, samlogon_state->mem_ctx, r_flags);
 218                 if (!r_flags->out.return_authenticator || 
 219                     !creds_client_check(samlogon_state->creds, &r_flags->out.return_authenticator->cred)) {
 220                         d_printf("Credential chaining failed\n");
 221                 }
 222                 if (!NT_STATUS_IS_OK(status)) {
 223                         if (error_string) {
 224                                 *error_string = strdup(nt_errstr(status));
 225                         }
 226                         return status;
 227                 }
 228                 
 229                 validation_level = r_flags->in.validation_level;
 230 
 231                 creds_decrypt_samlogon(samlogon_state->creds, validation_level, r_flags->out.validation);
 232 
 233                 switch (validation_level) {
 234                 case 2:
 235                         base = &r_flags->out.validation->sam2->base;
 236                         break;
 237                 case 3:
 238                         base = &r_flags->out.validation->sam3->base;
 239                         break;
 240                 case 6:
 241                         base = &r_flags->out.validation->sam6->base;
 242                         break;
 243                 }
 244                 break;
 245         default:
 246                 /* can't happen */
 247                 return NT_STATUS_INVALID_PARAMETER;
 248         }
 249                 
 250         if (!base) {
 251                 d_printf("No user info returned from 'successful' SamLogon*() call!\n");
 252                 return NT_STATUS_INVALID_PARAMETER;
 253         }
 254 
 255         if (user_session_key) {
 256                 memcpy(user_session_key, base->key.key, 16);
 257         }
 258         if (lm_key) {
 259                 memcpy(lm_key, base->LMSessKey.key, 8);
 260         }
 261                         
 262         return status;
 263 } 
 264 
 265 
 266 /* 
 267  * Test the normal 'LM and NTLM' combination
 268  */
 269 
 270 static bool test_lm_ntlm_broken(struct samlogon_state *samlogon_state, enum ntlm_break break_which, char **error_string) 
     /* [<][>][^][v][top][bottom][index][help] */
 271 {
 272         bool pass = true;
 273         bool lm_good;
 274         NTSTATUS nt_status;
 275         DATA_BLOB lm_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
 276         DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
 277         DATA_BLOB session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16);
 278 
 279         uint8_t lm_key[8];
 280         uint8_t user_session_key[16];
 281         uint8_t lm_hash[16];
 282         uint8_t nt_hash[16];
 283         
 284         ZERO_STRUCT(lm_key);
 285         ZERO_STRUCT(user_session_key);
 286 
 287         lm_good = SMBencrypt(samlogon_state->password, samlogon_state->chall.data, lm_response.data);
 288         if (!lm_good) {
 289                 ZERO_STRUCT(lm_hash);
 290         } else {
 291                 E_deshash(samlogon_state->password, lm_hash); 
 292         }
 293                 
 294         SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, nt_response.data);
 295 
 296         E_md4hash(samlogon_state->password, nt_hash);
 297         SMBsesskeygen_ntv1(nt_hash, session_key.data);
 298 
 299         nt_status = check_samlogon(samlogon_state,
 300                                    break_which,
 301                                    samlogon_state->parameter_control,
 302                                    &samlogon_state->chall,
 303                                    &lm_response,
 304                                    &nt_response,
 305                                    lm_key, 
 306                                    user_session_key,
 307                                    error_string);
 308         
 309         data_blob_free(&lm_response);
 310 
 311         if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
 312                 /* for 'long' passwords, the LM password is invalid */
 313                 if (break_which == NO_NT && !lm_good) {
 314                         return true;
 315                 }
 316                 /* for 'old' passwords, we allow the server to be OK or wrong password */
 317                 if (samlogon_state->old_password) {
 318                         return true;
 319                 }
 320                 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH));
 321         } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND, nt_status) && strchr_m(samlogon_state->account_name, '@')) {
 322                 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH) || (break_which == NO_NT));
 323         } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
 324                 SAFE_FREE(*error_string);
 325                 asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
 326                 return false;
 327         } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
 328                 return true;
 329         } else if (!NT_STATUS_IS_OK(nt_status)) {
 330                 return false;
 331         }
 332 
 333         if (break_which == NO_NT && !lm_good) {
 334                 *error_string = strdup("LM password is 'long' (> 14 chars and therefore invalid) but login did not fail!");
 335                 return false;
 336         }
 337 
 338         if (memcmp(lm_hash, lm_key, 
 339                    sizeof(lm_key)) != 0) {
 340                 d_printf("LM Key does not match expectations!\n");
 341                 d_printf("lm_key:\n");
 342                 dump_data(1, lm_key, 8);
 343                 d_printf("expected:\n");
 344                 dump_data(1, lm_hash, 8);
 345                 pass = false;
 346         }
 347 
 348         switch (break_which) {
 349         case NO_NT:
 350         {
 351                 uint8_t lm_key_expected[16];
 352                 memcpy(lm_key_expected, lm_hash, 8);
 353                 memset(lm_key_expected+8, '\0', 8);
 354                 if (memcmp(lm_key_expected, user_session_key, 
 355                            16) != 0) {
 356                         *error_string = strdup("NT Session Key does not match expectations (should be first-8 LM hash)!\n");
 357                         d_printf("user_session_key:\n");
 358                         dump_data(1, user_session_key, sizeof(user_session_key));
 359                         d_printf("expected:\n");
 360                         dump_data(1, lm_key_expected, sizeof(lm_key_expected));
 361                         pass = false;
 362                 }
 363                 break;
 364         }
 365         default:
 366                 if (memcmp(session_key.data, user_session_key, 
 367                            sizeof(user_session_key)) != 0) {
 368                         *error_string = strdup("NT Session Key does not match expectations!\n");
 369                         d_printf("user_session_key:\n");
 370                         dump_data(1, user_session_key, 16);
 371                         d_printf("expected:\n");
 372                         dump_data(1, session_key.data, session_key.length);
 373                         pass = false;
 374                 }
 375         }
 376         return pass;
 377 }
 378 
 379 /* 
 380  * Test LM authentication, no NT response supplied
 381  */
 382 
 383 static bool test_lm(struct samlogon_state *samlogon_state, char **error_string) 
     /* [<][>][^][v][top][bottom][index][help] */
 384 {
 385 
 386         return test_lm_ntlm_broken(samlogon_state, NO_NT, error_string);
 387 }
 388 
 389 /* 
 390  * Test the NTLM response only, no LM.
 391  */
 392 
 393 static bool test_ntlm(struct samlogon_state *samlogon_state, char **error_string) 
     /* [<][>][^][v][top][bottom][index][help] */
 394 {
 395         return test_lm_ntlm_broken(samlogon_state, NO_LM, error_string);
 396 }
 397 
 398 /* 
 399  * Test the NTLM response only, but in the LM field.
 400  */
 401 
 402 static bool test_ntlm_in_lm(struct samlogon_state *samlogon_state, char **error_string) 
     /* [<][>][^][v][top][bottom][index][help] */
 403 {
 404         bool lm_good;
 405         bool pass = true;
 406         NTSTATUS nt_status;
 407         DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
 408         DATA_BLOB session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16);
 409 
 410         uint8_t lm_key[8];
 411         uint8_t lm_hash[16];
 412         uint8_t user_session_key[16];
 413         uint8_t nt_hash[16];
 414         
 415         ZERO_STRUCT(lm_key);
 416         ZERO_STRUCT(user_session_key);
 417 
 418         SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, 
 419                      nt_response.data);
 420         E_md4hash(samlogon_state->password, nt_hash);
 421         SMBsesskeygen_ntv1(nt_hash, 
 422                            session_key.data);
 423 
 424         lm_good = E_deshash(samlogon_state->password, lm_hash); 
 425         if (!lm_good) {
 426                 ZERO_STRUCT(lm_hash);
 427         }
 428         nt_status = check_samlogon(samlogon_state,
 429                                    BREAK_NONE,
 430                                    samlogon_state->parameter_control,
 431                                    &samlogon_state->chall,
 432                                    &nt_response,
 433                                    NULL,
 434                                    lm_key, 
 435                                    user_session_key,
 436                                    error_string);
 437         
 438         if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
 439                 /* for 'old' passwords, we allow the server to be OK or wrong password */
 440                 if (samlogon_state->old_password) {
 441                         return true;
 442                 }
 443                 return false;
 444         } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
 445                 SAFE_FREE(*error_string);
 446                 asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
 447                 return false;
 448         } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
 449                 return true;
 450         } else if (!NT_STATUS_IS_OK(nt_status)) {
 451                 return false;
 452         }
 453 
 454         if (lm_good) {
 455                 if (memcmp(lm_hash, lm_key, 
 456                            sizeof(lm_key)) != 0) {
 457                         d_printf("LM Key does not match expectations!\n");
 458                         d_printf("lm_key:\n");
 459                         dump_data(1, lm_key, 8);
 460                         d_printf("expected:\n");
 461                         dump_data(1, lm_hash, 8);
 462                         pass = false;
 463                 }
 464 #if 0
 465         } else {
 466                 if (memcmp(session_key.data, lm_key, 
 467                            sizeof(lm_key)) != 0) {
 468                         d_printf("LM Key does not match expectations (first 8 session key)!\n");
 469                         d_printf("lm_key:\n");
 470                         dump_data(1, lm_key, 8);
 471                         d_printf("expected:\n");
 472                         dump_data(1, session_key.data, 8);
 473                         pass = false;
 474                 }
 475 #endif
 476         }
 477         if (lm_good && memcmp(lm_hash, user_session_key, 8) != 0) {
 478                 uint8_t lm_key_expected[16];
 479                 memcpy(lm_key_expected, lm_hash, 8);
 480                 memset(lm_key_expected+8, '\0', 8);
 481                 if (memcmp(lm_key_expected, user_session_key, 
 482                            16) != 0) {
 483                         d_printf("NT Session Key does not match expectations (should be first-8 LM hash)!\n");
 484                         d_printf("user_session_key:\n");
 485                         dump_data(1, user_session_key, sizeof(user_session_key));
 486                         d_printf("expected:\n");
 487                         dump_data(1, lm_key_expected, sizeof(lm_key_expected));
 488                         pass = false;
 489                 }
 490         }
 491         return pass;
 492 }
 493 
 494 /* 
 495  * Test the NTLM response only, but in the both the NT and LM fields.
 496  */
 497 
 498 static bool test_ntlm_in_both(struct samlogon_state *samlogon_state, char **error_string) 
     /* [<][>][^][v][top][bottom][index][help] */
 499 {
 500         bool pass = true;
 501         bool lm_good;
 502         NTSTATUS nt_status;
 503         DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
 504         DATA_BLOB session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16);
 505 
 506         uint8_t lm_key[8];
 507         uint8_t lm_hash[16];
 508         uint8_t user_session_key[16];
 509         uint8_t nt_hash[16];
 510         
 511         ZERO_STRUCT(lm_key);
 512         ZERO_STRUCT(user_session_key);
 513 
 514         SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, 
 515                      nt_response.data);
 516         E_md4hash(samlogon_state->password, nt_hash);
 517         SMBsesskeygen_ntv1(nt_hash, 
 518                            session_key.data);
 519 
 520         lm_good = E_deshash(samlogon_state->password, lm_hash); 
 521         if (!lm_good) {
 522                 ZERO_STRUCT(lm_hash);
 523         }
 524 
 525         nt_status = check_samlogon(samlogon_state,
 526                                    BREAK_NONE,
 527                                    samlogon_state->parameter_control,
 528                                    &samlogon_state->chall,
 529                                    NULL, 
 530                                    &nt_response,
 531                                    lm_key, 
 532                                    user_session_key,
 533                                    error_string);
 534         
 535         if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
 536                 /* for 'old' passwords, we allow the server to be OK or wrong password */
 537                 if (samlogon_state->old_password) {
 538                         return true;
 539                 }
 540                 return false;
 541         } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
 542                 SAFE_FREE(*error_string);
 543                 asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
 544                 return false;
 545         } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
 546                 return true;
 547         } else if (!NT_STATUS_IS_OK(nt_status)) {
 548                 return false;
 549         }
 550 
 551         if (!NT_STATUS_IS_OK(nt_status)) {
 552                 return false;
 553         }
 554 
 555         if (memcmp(lm_hash, lm_key, 
 556                    sizeof(lm_key)) != 0) {
 557                 d_printf("LM Key does not match expectations!\n");
 558                 d_printf("lm_key:\n");
 559                 dump_data(1, lm_key, 8);
 560                 d_printf("expected:\n");
 561                 dump_data(1, lm_hash, 8);
 562                 pass = false;
 563         }
 564         if (memcmp(session_key.data, user_session_key, 
 565                    sizeof(user_session_key)) != 0) {
 566                 d_printf("NT Session Key does not match expectations!\n");
 567                 d_printf("user_session_key:\n");
 568                 dump_data(1, user_session_key, 16);
 569                 d_printf("expected:\n");
 570                 dump_data(1, session_key.data, session_key.length);
 571                 pass = false;
 572         }
 573 
 574 
 575         return pass;
 576 }
 577 
 578 /* 
 579  * Test the NTLMv2 and LMv2 responses
 580  */
 581 
 582 enum ntlmv2_domain {
 583         UPPER_DOMAIN,
 584         NO_DOMAIN
 585 };
 586 
 587 static bool test_lmv2_ntlmv2_broken(struct samlogon_state *samlogon_state, 
     /* [<][>][^][v][top][bottom][index][help] */
 588                                     enum ntlm_break break_which, 
 589                                     enum ntlmv2_domain ntlmv2_domain, 
 590                                     char **error_string) 
 591 {
 592         bool pass = true;
 593         NTSTATUS nt_status;
 594         DATA_BLOB ntlmv2_response = data_blob(NULL, 0);
 595         DATA_BLOB lmv2_response = data_blob(NULL, 0);
 596         DATA_BLOB lmv2_session_key = data_blob(NULL, 0);
 597         DATA_BLOB ntlmv2_session_key = data_blob(NULL, 0);
 598         DATA_BLOB names_blob = NTLMv2_generate_names_blob(samlogon_state->mem_ctx, TEST_MACHINE_NAME, samlogon_state->workgroup);
 599 
 600         uint8_t lm_session_key[8];
 601         uint8_t user_session_key[16];
 602 
 603         ZERO_STRUCT(lm_session_key);
 604         ZERO_STRUCT(user_session_key);
 605         
 606         switch (ntlmv2_domain) {
 607         case UPPER_DOMAIN:
 608                 if (!SMBNTLMv2encrypt(samlogon_state->mem_ctx, 
 609                                       samlogon_state->account_name, samlogon_state->account_domain, 
 610                                       samlogon_state->password, &samlogon_state->chall,
 611                                       &names_blob,
 612                                       &lmv2_response, &ntlmv2_response, 
 613                                       &lmv2_session_key, &ntlmv2_session_key)) {
 614                         data_blob_free(&names_blob);
 615                         return false;
 616                 }
 617                 break;
 618         case NO_DOMAIN:
 619                 if (!SMBNTLMv2encrypt(samlogon_state->mem_ctx, 
 620                                       samlogon_state->account_name, "",
 621                                       samlogon_state->password, &samlogon_state->chall,
 622                                       &names_blob,
 623                                       &lmv2_response, &ntlmv2_response, 
 624                                       &lmv2_session_key, &ntlmv2_session_key)) {
 625                         data_blob_free(&names_blob);
 626                         return false;
 627                 }
 628                 break;
 629         }
 630         data_blob_free(&names_blob);
 631 
 632         nt_status = check_samlogon(samlogon_state,
 633                                    break_which,
 634                                    samlogon_state->parameter_control,
 635                                    &samlogon_state->chall,
 636                                    &lmv2_response,
 637                                    &ntlmv2_response,
 638                                    lm_session_key, 
 639                                    user_session_key,
 640                                    error_string);
 641         
 642         data_blob_free(&lmv2_response);
 643         data_blob_free(&ntlmv2_response);
 644 
 645 
 646         if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
 647                 /* for 'old' passwords, we allow the server to be OK or wrong password */
 648                 if (samlogon_state->old_password) {
 649                         return true;
 650                 }
 651                 return break_which == BREAK_BOTH;
 652         } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND, nt_status) && strchr_m(samlogon_state->account_name, '@')) {
 653                 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH) || (break_which == NO_NT));
 654         } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
 655                 SAFE_FREE(*error_string);
 656                 asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
 657                 return false;
 658         } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
 659                 return true;
 660         } else if (!NT_STATUS_IS_OK(nt_status)) {
 661                 return false;
 662         }
 663 
 664 
 665         switch (break_which) {
 666         case NO_NT:
 667                 if (memcmp(lmv2_session_key.data, user_session_key,
 668                            sizeof(user_session_key)) != 0) {
 669                         d_printf("USER (LMv2) Session Key does not match expectations!\n");
 670                         d_printf("user_session_key:\n");
 671                         dump_data(1, user_session_key, 16);
 672                         d_printf("expected:\n");
 673                         dump_data(1, lmv2_session_key.data, ntlmv2_session_key.length);
 674                         pass = false;
 675                 }
 676                 if (memcmp(lmv2_session_key.data, lm_session_key, 
 677                                    sizeof(lm_session_key)) != 0) {
 678                         d_printf("LM (LMv2) Session Key does not match expectations!\n");
 679                         d_printf("lm_session_key:\n");
 680                         dump_data(1, lm_session_key, 8);
 681                         d_printf("expected:\n");
 682                         dump_data(1, lmv2_session_key.data, 8);
 683                         pass = false;
 684                 }
 685                 break;
 686         default:
 687                 if (memcmp(ntlmv2_session_key.data, user_session_key, 
 688                            sizeof(user_session_key)) != 0) {
 689                         if (memcmp(lmv2_session_key.data, user_session_key,
 690                                    sizeof(user_session_key)) == 0) {
 691                                 d_printf("USER (NTLMv2) Session Key expected, got LMv2 sessesion key instead:\n");
 692                                 d_printf("user_session_key:\n");
 693                                 dump_data(1, user_session_key, 16);
 694                                 d_printf("expected:\n");
 695                                 dump_data(1, ntlmv2_session_key.data, ntlmv2_session_key.length);
 696                                 pass = false;
 697                                 
 698                         } else {
 699                                 d_printf("USER (NTLMv2) Session Key does not match expectations!\n");
 700                                 d_printf("user_session_key:\n");
 701                                 dump_data(1, user_session_key, 16);
 702                                 d_printf("expected:\n");
 703                                 dump_data(1, ntlmv2_session_key.data, ntlmv2_session_key.length);
 704                                 pass = false;
 705                         }
 706                 }
 707                 if (memcmp(ntlmv2_session_key.data, lm_session_key, 
 708                            sizeof(lm_session_key)) != 0) {
 709                         if (memcmp(lmv2_session_key.data, lm_session_key,
 710                                    sizeof(lm_session_key)) == 0) {
 711                                 d_printf("LM (NTLMv2) Session Key expected, got LMv2 sessesion key instead:\n");
 712                                 d_printf("user_session_key:\n");
 713                                 dump_data(1, lm_session_key, 8);
 714                                 d_printf("expected:\n");
 715                                 dump_data(1, ntlmv2_session_key.data, 8);
 716                                 pass = false;
 717                         } else {
 718                                 d_printf("LM (NTLMv2) Session Key does not match expectations!\n");
 719                                 d_printf("lm_session_key:\n");
 720                                 dump_data(1, lm_session_key, 8);
 721                                 d_printf("expected:\n");
 722                                 dump_data(1, ntlmv2_session_key.data, 8);
 723                                 pass = false;
 724                         }
 725                 }
 726         }
 727 
 728         return pass;
 729 }
 730 
 731 /* 
 732  * Test the NTLM and LMv2 responses
 733  */
 734 
 735 static bool test_lmv2_ntlm_broken(struct samlogon_state *samlogon_state, 
     /* [<][>][^][v][top][bottom][index][help] */
 736                                   enum ntlm_break break_which, 
 737                                   enum ntlmv2_domain ntlmv2_domain, 
 738                                   char **error_string) 
 739 {
 740         bool pass = true;
 741         NTSTATUS nt_status;
 742         DATA_BLOB ntlmv2_response = data_blob(NULL, 0);
 743         DATA_BLOB lmv2_response = data_blob(NULL, 0);
 744         DATA_BLOB lmv2_session_key = data_blob(NULL, 0);
 745         DATA_BLOB ntlmv2_session_key = data_blob(NULL, 0);
 746         DATA_BLOB names_blob = NTLMv2_generate_names_blob(samlogon_state->mem_ctx, samlogon_state->netbios_name, samlogon_state->workgroup);
 747 
 748         DATA_BLOB ntlm_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
 749         DATA_BLOB ntlm_session_key = data_blob_talloc(samlogon_state->mem_ctx, NULL, 16);
 750 
 751         bool lm_good;
 752         uint8_t lm_hash[16];
 753         uint8_t lm_session_key[8];
 754         uint8_t user_session_key[16];
 755         uint8_t nt_hash[16];
 756 
 757         SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, 
 758                      ntlm_response.data);
 759         E_md4hash(samlogon_state->password, nt_hash);
 760         SMBsesskeygen_ntv1(nt_hash, 
 761                            ntlm_session_key.data);
 762 
 763         lm_good = E_deshash(samlogon_state->password, lm_hash); 
 764         if (!lm_good) {
 765                 ZERO_STRUCT(lm_hash);
 766         }
 767 
 768         ZERO_STRUCT(lm_session_key);
 769         ZERO_STRUCT(user_session_key);
 770 
 771         switch (ntlmv2_domain) {
 772         case UPPER_DOMAIN:
 773                 /* TODO - test with various domain cases, and without domain */
 774                 if (!SMBNTLMv2encrypt(samlogon_state->mem_ctx, 
 775                                       samlogon_state->account_name, samlogon_state->account_domain, 
 776                                       samlogon_state->password, &samlogon_state->chall,
 777                                       &names_blob,
 778                                       &lmv2_response, &ntlmv2_response, 
 779                                       &lmv2_session_key, &ntlmv2_session_key)) {
 780                         data_blob_free(&names_blob);
 781                         return false;
 782                 }
 783                 break;
 784         case NO_DOMAIN:
 785                 /* TODO - test with various domain cases, and without domain */
 786                 if (!SMBNTLMv2encrypt(samlogon_state->mem_ctx, 
 787                                       samlogon_state->account_name, "",
 788                                       samlogon_state->password, &samlogon_state->chall,
 789                                       &names_blob,
 790                                       &lmv2_response, &ntlmv2_response, 
 791                                       &lmv2_session_key, &ntlmv2_session_key)) {
 792                         data_blob_free(&names_blob);
 793                         return false;
 794                 }
 795                 break;
 796         }
 797 
 798         data_blob_free(&names_blob);
 799 
 800         nt_status = check_samlogon(samlogon_state,
 801                                    break_which,
 802                                    samlogon_state->parameter_control,
 803                                    &samlogon_state->chall,
 804                                    &lmv2_response,
 805                                    &ntlm_response,
 806                                    lm_session_key, 
 807                                    user_session_key,
 808                                    error_string);
 809         
 810         data_blob_free(&lmv2_response);
 811         data_blob_free(&ntlmv2_response);
 812 
 813 
 814         if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
 815                 /* for 'old' passwords, we allow the server to be OK or wrong password */
 816                 if (samlogon_state->old_password) {
 817                         return true;
 818                 }
 819                 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH));
 820         } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND, nt_status) && strchr_m(samlogon_state->account_name, '@')) {
 821                 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH));
 822         } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
 823                 SAFE_FREE(*error_string);
 824                 asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
 825                 return false;
 826         } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
 827                 return true;
 828         } else if (!NT_STATUS_IS_OK(nt_status)) {
 829                 return false;
 830         }
 831 
 832         switch (break_which) {
 833         case NO_NT:
 834                 if (memcmp(lmv2_session_key.data, user_session_key, 
 835                            sizeof(user_session_key)) != 0) {
 836                         d_printf("USER (LMv2) Session Key does not match expectations!\n");
 837                         d_printf("user_session_key:\n");
 838                         dump_data(1, user_session_key, 16);
 839                         d_printf("expected:\n");
 840                         dump_data(1, lmv2_session_key.data, ntlmv2_session_key.length);
 841                         pass = false;
 842                 }
 843                 if (memcmp(lmv2_session_key.data, lm_session_key, 
 844                            sizeof(lm_session_key)) != 0) {
 845                         d_printf("LM (LMv2) Session Key does not match expectations!\n");
 846                         d_printf("lm_session_key:\n");
 847                         dump_data(1, lm_session_key, 8);
 848                         d_printf("expected:\n");
 849                         dump_data(1, lmv2_session_key.data, 8);
 850                         pass = false;
 851                 }
 852                 break;
 853         case BREAK_LM:
 854                 if (memcmp(ntlm_session_key.data, user_session_key, 
 855                            sizeof(user_session_key)) != 0) {
 856                         d_printf("USER (NTLMv2) Session Key does not match expectations!\n");
 857                         d_printf("user_session_key:\n");
 858                         dump_data(1, user_session_key, 16);
 859                         d_printf("expected:\n");
 860                         dump_data(1, ntlm_session_key.data, ntlm_session_key.length);
 861                         pass = false;
 862                 }
 863                 if (lm_good) {
 864                         if (memcmp(lm_hash, lm_session_key, 
 865                                    sizeof(lm_session_key)) != 0) {
 866                                 d_printf("LM Session Key does not match expectations!\n");
 867                                 d_printf("lm_session_key:\n");
 868                                 dump_data(1, lm_session_key, 8);
 869                                 d_printf("expected:\n");
 870                                 dump_data(1, lm_hash, 8);
 871                                 pass = false;
 872                         }
 873                 } else {
 874                         static const uint8_t zeros[8];
 875                         if (memcmp(zeros, lm_session_key, 
 876                                    sizeof(lm_session_key)) != 0) {
 877                                 d_printf("LM Session Key does not match expectations (zeros)!\n");
 878                                 d_printf("lm_session_key:\n");
 879                                 dump_data(1, lm_session_key, 8);
 880                                 d_printf("expected:\n");
 881                                 dump_data(1, zeros, 8);
 882                                 pass = false;
 883                         }
 884                 }
 885                 break;
 886         default:
 887                 if (memcmp(ntlm_session_key.data, user_session_key, 
 888                            sizeof(user_session_key)) != 0) {
 889                         d_printf("USER (NTLMv2) Session Key does not match expectations!\n");
 890                         d_printf("user_session_key:\n");
 891                         dump_data(1, user_session_key, 16);
 892                         d_printf("expected:\n");
 893                         dump_data(1, ntlm_session_key.data, ntlm_session_key.length);
 894                         pass = false;
 895                 }
 896                 if (memcmp(ntlm_session_key.data, lm_session_key, 
 897                            sizeof(lm_session_key)) != 0) {
 898                         d_printf("LM (NTLMv2) Session Key does not match expectations!\n");
 899                         d_printf("lm_session_key:\n");
 900                         dump_data(1, lm_session_key, 8);
 901                         d_printf("expected:\n");
 902                         dump_data(1, ntlm_session_key.data, 8);
 903                         pass = false;
 904                 }
 905         }
 906 
 907         return pass;
 908 }
 909 
 910 /* 
 911  * Test the NTLMv2 and LMv2 responses
 912  */
 913 
 914 static bool test_lmv2_ntlmv2(struct samlogon_state *samlogon_state, char **error_string) 
     /* [<][>][^][v][top][bottom][index][help] */
 915 {
 916         return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NONE, UPPER_DOMAIN, error_string);
 917 }
 918 
 919 #if 0
 920 static bool test_lmv2_ntlmv2_no_dom(struct samlogon_state *samlogon_state, char **error_string) 
     /* [<][>][^][v][top][bottom][index][help] */
 921 {
 922         return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NONE, NO_DOMAIN, error_string);
 923 }
 924 #endif
 925 
 926 /* 
 927  * Test the LMv2 response only
 928  */
 929 
 930 static bool test_lmv2(struct samlogon_state *samlogon_state, char **error_string) 
     /* [<][>][^][v][top][bottom][index][help] */
 931 {
 932         return test_lmv2_ntlmv2_broken(samlogon_state, NO_NT, UPPER_DOMAIN, error_string);
 933 }
 934 
 935 static bool test_lmv2_no_dom(struct samlogon_state *samlogon_state, char **error_string) 
     /* [<][>][^][v][top][bottom][index][help] */
 936 {
 937         return test_lmv2_ntlmv2_broken(samlogon_state, NO_NT, NO_DOMAIN, error_string);
 938 }
 939 
 940 /* 
 941  * Test the NTLMv2 response only
 942  */
 943 
 944 static bool test_ntlmv2(struct samlogon_state *samlogon_state, char **error_string) 
     /* [<][>][^][v][top][bottom][index][help] */
 945 {
 946         return test_lmv2_ntlmv2_broken(samlogon_state, NO_LM, UPPER_DOMAIN, error_string);
 947 }
 948 
 949 static bool test_ntlmv2_no_dom(struct samlogon_state *samlogon_state, char **error_string) 
     /* [<][>][^][v][top][bottom][index][help] */
 950 {
 951         return test_lmv2_ntlmv2_broken(samlogon_state, NO_LM, NO_DOMAIN, error_string);
 952 }
 953 
 954 static bool test_lm_ntlm(struct samlogon_state *samlogon_state, char **error_string) 
     /* [<][>][^][v][top][bottom][index][help] */
 955 {
 956         return test_lm_ntlm_broken(samlogon_state, BREAK_NONE, error_string);
 957 }
 958 
 959 static bool test_ntlm_lm_broken(struct samlogon_state *samlogon_state, char **error_string) 
     /* [<][>][^][v][top][bottom][index][help] */
 960 {
 961         return test_lm_ntlm_broken(samlogon_state, BREAK_LM, error_string);
 962 }
 963 
 964 static bool test_ntlm_ntlm_broken(struct samlogon_state *samlogon_state, char **error_string) 
     /* [<][>][^][v][top][bottom][index][help] */
 965 {
 966         return test_lm_ntlm_broken(samlogon_state, BREAK_NT, error_string);
 967 }
 968 
 969 static bool test_lm_ntlm_both_broken(struct samlogon_state *samlogon_state, char **error_string) 
     /* [<][>][^][v][top][bottom][index][help] */
 970 {
 971         return test_lm_ntlm_broken(samlogon_state, BREAK_BOTH, error_string);
 972 }
 973 static bool test_ntlmv2_lmv2_broken(struct samlogon_state *samlogon_state, char **error_string) 
     /* [<][>][^][v][top][bottom][index][help] */
 974 {
 975         return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_LM, UPPER_DOMAIN, error_string);
 976 }
 977 
 978 static bool test_ntlmv2_lmv2_broken_no_dom(struct samlogon_state *samlogon_state, char **error_string) 
     /* [<][>][^][v][top][bottom][index][help] */
 979 {
 980         return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_LM, NO_DOMAIN, error_string);
 981 }
 982 
 983 static bool test_ntlmv2_ntlmv2_broken(struct samlogon_state *samlogon_state, char **error_string) 
     /* [<][>][^][v][top][bottom][index][help] */
 984 {
 985         return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NT, UPPER_DOMAIN, error_string);
 986 }
 987 
 988 #if 0
 989 static bool test_ntlmv2_ntlmv2_broken_no_dom(struct samlogon_state *samlogon_state, char **error_string) 
     /* [<][>][^][v][top][bottom][index][help] */
 990 {
 991         return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_NT, NO_DOMAIN, error_string);
 992 }
 993 #endif
 994 
 995 static bool test_ntlmv2_both_broken(struct samlogon_state *samlogon_state, char **error_string) 
     /* [<][>][^][v][top][bottom][index][help] */
 996 {
 997         return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_BOTH, UPPER_DOMAIN, error_string);
 998 }
 999 
1000 static bool test_ntlmv2_both_broken_no_dom(struct samlogon_state *samlogon_state, char **error_string) 
     /* [<][>][^][v][top][bottom][index][help] */
1001 {
1002         return test_lmv2_ntlmv2_broken(samlogon_state, BREAK_BOTH, NO_DOMAIN, error_string);
1003 }
1004 
1005 static bool test_lmv2_ntlm_both_broken(struct samlogon_state *samlogon_state, char **error_string) 
     /* [<][>][^][v][top][bottom][index][help] */
1006 {
1007         return test_lmv2_ntlm_broken(samlogon_state, BREAK_BOTH, UPPER_DOMAIN, error_string);
1008 }
1009 
1010 static bool test_lmv2_ntlm_both_broken_no_dom(struct samlogon_state *samlogon_state, char **error_string) 
     /* [<][>][^][v][top][bottom][index][help] */
1011 {
1012         return test_lmv2_ntlm_broken(samlogon_state, BREAK_BOTH, NO_DOMAIN, error_string);
1013 }
1014 
1015 static bool test_lmv2_ntlm_break_ntlm(struct samlogon_state *samlogon_state, char **error_string) 
     /* [<][>][^][v][top][bottom][index][help] */
1016 {
1017         return test_lmv2_ntlm_broken(samlogon_state, BREAK_NT, UPPER_DOMAIN, error_string);
1018 }
1019 
1020 static bool test_lmv2_ntlm_break_ntlm_no_dom(struct samlogon_state *samlogon_state, char **error_string) 
     /* [<][>][^][v][top][bottom][index][help] */
1021 {
1022         return test_lmv2_ntlm_broken(samlogon_state, BREAK_NT, NO_DOMAIN, error_string);
1023 }
1024 
1025 static bool test_lmv2_ntlm_break_lm(struct samlogon_state *samlogon_state, char **error_string) 
     /* [<][>][^][v][top][bottom][index][help] */
1026 {
1027         return test_lmv2_ntlm_broken(samlogon_state, BREAK_LM, UPPER_DOMAIN, error_string);
1028 }
1029 
1030 static bool test_lmv2_ntlm_break_lm_no_dom(struct samlogon_state *samlogon_state, char **error_string) 
     /* [<][>][^][v][top][bottom][index][help] */
1031 {
1032         return test_lmv2_ntlm_broken(samlogon_state, BREAK_LM, NO_DOMAIN, error_string);
1033 }
1034 
1035 /* 
1036  * Test the NTLM2 response (extra challenge in LM feild)
1037  *
1038  * This test is the same as the 'break LM' test, but checks that the
1039  * server implements NTLM2 session security in the right place
1040  * (NETLOGON is the wrong place).
1041  */
1042 
1043 static bool test_ntlm2(struct samlogon_state *samlogon_state, char **error_string) 
     /* [<][>][^][v][top][bottom][index][help] */
1044 {
1045         bool pass = true;
1046         NTSTATUS nt_status;
1047         DATA_BLOB lm_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
1048         DATA_BLOB nt_response = data_blob_talloc(samlogon_state->mem_ctx, NULL, 24);
1049 
1050         bool lm_good;
1051         uint8_t lm_key[8];
1052         uint8_t nt_hash[16];
1053         uint8_t lm_hash[16];
1054         uint8_t nt_key[16];
1055         uint8_t user_session_key[16];
1056         uint8_t expected_user_session_key[16];
1057         uint8_t session_nonce_hash[16];
1058         uint8_t client_chall[8];
1059         
1060         struct MD5Context md5_session_nonce_ctx;
1061         HMACMD5Context hmac_ctx;
1062                         
1063         ZERO_STRUCT(user_session_key);
1064         ZERO_STRUCT(lm_key);
1065         generate_random_buffer(client_chall, 8);
1066         
1067         MD5Init(&md5_session_nonce_ctx);
1068         MD5Update(&md5_session_nonce_ctx, samlogon_state->chall.data, 8);
1069         MD5Update(&md5_session_nonce_ctx, client_chall, 8);
1070         MD5Final(session_nonce_hash, &md5_session_nonce_ctx);
1071         
1072         E_md4hash(samlogon_state->password, (uint8_t *)nt_hash);
1073         lm_good = E_deshash(samlogon_state->password, (uint8_t *)lm_hash);
1074         SMBsesskeygen_ntv1((const uint8_t *)nt_hash, 
1075                            nt_key);
1076 
1077         SMBNTencrypt(samlogon_state->password, samlogon_state->chall.data, nt_response.data);
1078 
1079         memcpy(lm_response.data, session_nonce_hash, 8);
1080         memset(lm_response.data + 8, 0, 16);
1081 
1082         hmac_md5_init_rfc2104(nt_key, 16, &hmac_ctx);
1083         hmac_md5_update(samlogon_state->chall.data, 8, &hmac_ctx);
1084         hmac_md5_update(client_chall, 8, &hmac_ctx);
1085         hmac_md5_final(expected_user_session_key, &hmac_ctx);
1086 
1087         nt_status = check_samlogon(samlogon_state,
1088                                    BREAK_NONE,
1089                                    samlogon_state->parameter_control,
1090                                    &samlogon_state->chall,
1091                                    &lm_response,
1092                                    &nt_response,
1093                                    lm_key, 
1094                                    user_session_key,
1095                                    error_string);
1096         
1097         if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
1098                 /* for 'old' passwords, we allow the server to be OK or wrong password */
1099                 if (samlogon_state->old_password) {
1100                         return true;
1101                 }
1102                 return false;
1103         } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
1104                 SAFE_FREE(*error_string);
1105                 asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
1106                 return false;
1107         } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
1108                 return true;
1109         } else if (!NT_STATUS_IS_OK(nt_status)) {
1110                 return false;
1111         }
1112 
1113         if (lm_good) {
1114                 if (memcmp(lm_hash, lm_key, 
1115                            sizeof(lm_key)) != 0) {
1116                         d_printf("LM Key does not match expectations!\n");
1117                         d_printf("lm_key:\n");
1118                         dump_data(1, lm_key, 8);
1119                         d_printf("expected:\n");
1120                         dump_data(1, lm_hash, 8);
1121                         pass = false;
1122                 }
1123         } else {
1124                 static const uint8_t zeros[8];
1125                 if (memcmp(zeros, lm_key, 
1126                            sizeof(lm_key)) != 0) {
1127                         d_printf("LM Session Key does not match expectations (zeros)!\n");
1128                         d_printf("lm_key:\n");
1129                         dump_data(1, lm_key, 8);
1130                         d_printf("expected:\n");
1131                         dump_data(1, zeros, 8);
1132                         pass = false;
1133                 }
1134         }
1135         if (memcmp(nt_key, user_session_key, 16) != 0) {
1136                 d_printf("NT Session Key does not match expectations (should be NT Key)!\n");
1137                 d_printf("user_session_key:\n");
1138                 dump_data(1, user_session_key, sizeof(user_session_key));
1139                 d_printf("expected:\n");
1140                 dump_data(1, nt_key, sizeof(nt_key));
1141                 pass = false;
1142         }
1143         return pass;
1144 }
1145 
1146 static bool test_plaintext(struct samlogon_state *samlogon_state, enum ntlm_break break_which, char **error_string)
     /* [<][>][^][v][top][bottom][index][help] */
1147 {
1148         NTSTATUS nt_status;
1149         DATA_BLOB nt_response = data_blob(NULL, 0);
1150         DATA_BLOB lm_response = data_blob(NULL, 0);
1151         char *password;
1152         char *dospw;
1153         smb_ucs2_t *unicodepw;
1154 
1155         uint8_t user_session_key[16];
1156         uint8_t lm_key[16];
1157         uint8_t lm_hash[16];
1158         static const uint8_t zeros[8];
1159         DATA_BLOB chall = data_blob_talloc(samlogon_state->mem_ctx, zeros, sizeof(zeros));
1160         bool lm_good = E_deshash(samlogon_state->password, lm_hash); 
1161 
1162         ZERO_STRUCT(user_session_key);
1163         
1164         if (!push_ucs2_talloc(samlogon_state->mem_ctx, 
1165                               &unicodepw, samlogon_state->password, NULL)) {
1166                 DEBUG(0, ("push_ucs2_allocate failed!\n"));
1167                 exit(1);
1168         }
1169 
1170         nt_response = data_blob_talloc(samlogon_state->mem_ctx, unicodepw, strlen_m(samlogon_state->password)*2);
1171 
1172         password = strupper_talloc(samlogon_state->mem_ctx, samlogon_state->password);
1173 
1174         if (!convert_string_talloc_convenience(samlogon_state->mem_ctx, 
1175                                    samlogon_state->iconv_convenience,
1176                                    CH_UNIX, CH_DOS, 
1177                                    password, strlen(password)+1, 
1178                                    (void**)&dospw, NULL, false)) {
1179                 DEBUG(0, ("convert_string_talloc failed!\n"));
1180                 exit(1);
1181         }
1182 
1183         lm_response = data_blob_talloc(samlogon_state->mem_ctx, dospw, strlen(dospw));
1184 
1185         nt_status = check_samlogon(samlogon_state,
1186                                    break_which,
1187                                    samlogon_state->parameter_control | MSV1_0_CLEARTEXT_PASSWORD_ALLOWED,
1188                                    &chall,
1189                                    &lm_response,
1190                                    &nt_response,
1191                                    lm_key, 
1192                                    user_session_key,
1193                                    error_string);
1194         
1195         if (NT_STATUS_EQUAL(NT_STATUS_WRONG_PASSWORD, nt_status)) {
1196                 /* for 'old' passwords, we allow the server to be OK or wrong password */
1197                 if (samlogon_state->old_password) {
1198                         return true;
1199                 }
1200                 /* for 'long' passwords, the LM password is invalid */
1201                 if (break_which == NO_NT && !lm_good) {
1202                         return true;
1203                 }
1204                 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH));
1205         } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND, nt_status) && strchr_m(samlogon_state->account_name, '@')) {
1206                 return ((break_which == BREAK_NT) || (break_which == BREAK_BOTH) || (break_which == NO_NT));
1207         } else if (!NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status)) {
1208                 SAFE_FREE(*error_string);
1209                 asprintf(error_string, "Expected error: %s, got %s", nt_errstr(samlogon_state->expected_error), nt_errstr(nt_status));
1210                 return false;
1211         } else if (NT_STATUS_EQUAL(samlogon_state->expected_error, nt_status) && !NT_STATUS_IS_OK(nt_status)) {
1212                 return true;
1213         } else if (!NT_STATUS_IS_OK(nt_status)) {
1214                 return false;
1215         }
1216 
1217         if (break_which == NO_NT && !lm_good) {
1218                 *error_string = strdup("LM password is 'long' (> 14 chars and therefore invalid) but login did not fail!");
1219                 return false;
1220         }
1221 
1222         return true;
1223 }
1224 
1225 static bool test_plaintext_none_broken(struct samlogon_state *samlogon_state, 
     /* [<][>][^][v][top][bottom][index][help] */
1226                                        char **error_string) {
1227         return test_plaintext(samlogon_state, BREAK_NONE, error_string);
1228 }
1229 
1230 static bool test_plaintext_lm_broken(struct samlogon_state *samlogon_state, 
     /* [<][>][^][v][top][bottom][index][help] */
1231                                      char **error_string) {
1232         return test_plaintext(samlogon_state, BREAK_LM, error_string);
1233 }
1234 
1235 static bool test_plaintext_nt_broken(struct samlogon_state *samlogon_state, 
     /* [<][>][^][v][top][bottom][index][help] */
1236                                      char **error_string) {
1237         return test_plaintext(samlogon_state, BREAK_NT, error_string);
1238 }
1239 
1240 static bool test_plaintext_nt_only(struct samlogon_state *samlogon_state, 
     /* [<][>][^][v][top][bottom][index][help] */
1241                                    char **error_string) {
1242         return test_plaintext(samlogon_state, NO_LM, error_string);
1243 }
1244 
1245 static bool test_plaintext_lm_only(struct samlogon_state *samlogon_state, 
     /* [<][>][^][v][top][bottom][index][help] */
1246                                    char **error_string) {
1247         return test_plaintext(samlogon_state, NO_NT, error_string);
1248 }
1249 
1250 /* 
1251    Tests:
1252    
1253    - LM only
1254    - NT and LM             
1255    - NT
1256    - NT in LM field
1257    - NT in both fields
1258    - NTLMv2
1259    - NTLMv2 and LMv2
1260    - LMv2
1261    - plaintext tests (in challenge-response fields)
1262   
1263    check we get the correct session key in each case
1264    check what values we get for the LM session key
1265    
1266 */
1267 
1268 static const struct ntlm_tests {
1269         bool (*fn)(struct samlogon_state *, char **);
1270         const char *name;
1271         bool expect_fail;
1272 } test_table[] = {
1273         {test_lmv2_ntlmv2, "NTLMv2 and LMv2", false},
1274 #if 0
1275         {test_lmv2_ntlmv2_no_dom, "NTLMv2 and LMv2 (no domain)", false},
1276 #endif
1277         {test_lm, "LM", false},
1278         {test_lm_ntlm, "LM and NTLM", false},
1279         {test_lm_ntlm_both_broken, "LM and NTLM, both broken", false},
1280         {test_ntlm, "NTLM", false},
1281         {test_ntlm_in_lm, "NTLM in LM", false},
1282         {test_ntlm_in_both, "NTLM in both", false},
1283         {test_ntlmv2, "NTLMv2", false},
1284         {test_ntlmv2_no_dom, "NTLMv2 (no domain)", false},
1285         {test_lmv2, "LMv2", false},
1286         {test_lmv2_no_dom, "LMv2 (no domain)", false},
1287         {test_ntlmv2_lmv2_broken, "NTLMv2 and LMv2, LMv2 broken", false},
1288         {test_ntlmv2_lmv2_broken_no_dom, "NTLMv2 and LMv2, LMv2 broken (no domain)", false},
1289         {test_ntlmv2_ntlmv2_broken, "NTLMv2 and LMv2, NTLMv2 broken", false},
1290 #if 0
1291         {test_ntlmv2_ntlmv2_broken_no_dom, "NTLMv2 and LMv2, NTLMv2 broken (no domain)", false},
1292 #endif
1293         {test_ntlmv2_both_broken, "NTLMv2 and LMv2, both broken", false},
1294         {test_ntlmv2_both_broken_no_dom, "NTLMv2 and LMv2, both broken (no domain)", false},
1295         {test_ntlm_lm_broken, "NTLM and LM, LM broken", false},
1296         {test_ntlm_ntlm_broken, "NTLM and LM, NTLM broken", false},
1297         {test_ntlm2, "NTLM2 (NTLMv2 session security)", false},
1298         {test_lmv2_ntlm_both_broken, "LMv2 and NTLM, both broken", false},
1299         {test_lmv2_ntlm_both_broken_no_dom, "LMv2 and NTLM, both broken (no domain)", false},
1300         {test_lmv2_ntlm_break_ntlm, "LMv2 and NTLM, NTLM broken", false},
1301         {test_lmv2_ntlm_break_ntlm_no_dom, "LMv2 and NTLM, NTLM broken (no domain)", false},
1302         {test_lmv2_ntlm_break_lm, "LMv2 and NTLM, LMv2 broken", false},
1303         {test_lmv2_ntlm_break_lm_no_dom, "LMv2 and NTLM, LMv2 broken (no domain)", false},
1304         {test_plaintext_none_broken, "Plaintext", false},
1305         {test_plaintext_lm_broken, "Plaintext LM broken", false},
1306         {test_plaintext_nt_broken, "Plaintext NT broken", false},
1307         {test_plaintext_nt_only, "Plaintext NT only", false},
1308         {test_plaintext_lm_only, "Plaintext LM only", false},
1309         {NULL, NULL}
1310 };
1311 
1312 /*
1313   try a netlogon SamLogon
1314 */
1315 static bool test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
     /* [<][>][^][v][top][bottom][index][help] */
1316                           struct torture_context *tctx,
1317                           struct creds_CredentialState *creds, 
1318                           const char *comment,
1319                           const char *account_domain, const char *account_name, 
1320                           const char *plain_pass, uint32_t parameter_control,
1321                           NTSTATUS expected_error, bool old_password,
1322                           int n_subtests)
1323 {
1324         TALLOC_CTX *fn_ctx = talloc_named(mem_ctx, 0, "test_SamLogon function-level context");
1325         int i, v, l, f;
1326         bool ret = true;
1327         int validation_levels[] = {2,3,6};
1328         int logon_levels[] = { 2, 6 };
1329         int function_levels[] = { 
1330                 NDR_NETR_LOGONSAMLOGON,
1331                 NDR_NETR_LOGONSAMLOGONEX,
1332                 NDR_NETR_LOGONSAMLOGONWITHFLAGS };
1333         struct samlogon_state samlogon_state;
1334 
1335         union netr_LogonLevel logon;
1336         union netr_Validation validation;
1337         uint8_t authoritative = 0;
1338         uint32_t flags = 0;
1339 
1340         ZERO_STRUCT(logon);
1341 
1342         d_printf("testing netr_LogonSamLogon and netr_LogonSamLogonWithFlags\n");
1343         
1344         samlogon_state.comment = comment;
1345         samlogon_state.account_name = account_name;
1346         samlogon_state.account_domain = account_domain;
1347         samlogon_state.password = plain_pass;
1348         samlogon_state.workgroup = lp_workgroup(tctx->lp_ctx);
1349         samlogon_state.netbios_name = lp_netbios_name(tctx->lp_ctx);
1350         samlogon_state.p = p;
1351         samlogon_state.creds = creds;
1352         samlogon_state.expected_error = expected_error;
1353         samlogon_state.chall = data_blob_talloc(fn_ctx, NULL, 8);
1354         samlogon_state.parameter_control = parameter_control;
1355         samlogon_state.old_password = old_password;
1356         samlogon_state.iconv_convenience = lp_iconv_convenience(tctx->lp_ctx);
1357 
1358         generate_random_buffer(samlogon_state.chall.data, 8);
1359         samlogon_state.r_flags.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p));
1360         samlogon_state.r_flags.in.computer_name = TEST_MACHINE_NAME;
1361         samlogon_state.r_flags.in.credential = &samlogon_state.auth;
1362         samlogon_state.r_flags.in.return_authenticator = &samlogon_state.auth2;
1363         samlogon_state.r_flags.in.flags = &flags;
1364         samlogon_state.r_flags.in.logon = &logon;
1365         samlogon_state.r_flags.out.validation = &validation;
1366         samlogon_state.r_flags.out.authoritative = &authoritative;
1367         samlogon_state.r_flags.out.flags = &flags;
1368 
1369         samlogon_state.r_ex.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p));
1370         samlogon_state.r_ex.in.computer_name = TEST_MACHINE_NAME;
1371         samlogon_state.r_ex.in.flags = &flags;
1372         samlogon_state.r_ex.in.logon = &logon;
1373         samlogon_state.r_ex.out.validation = &validation;
1374         samlogon_state.r_ex.out.authoritative = &authoritative;
1375         samlogon_state.r_ex.out.flags = &flags;
1376 
1377         samlogon_state.r.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p));
1378         samlogon_state.r.in.computer_name = TEST_MACHINE_NAME;
1379         samlogon_state.r.in.credential = &samlogon_state.auth;
1380         samlogon_state.r.in.return_authenticator = &samlogon_state.auth2;
1381         samlogon_state.r.in.logon = &logon;
1382         samlogon_state.r.out.validation = &validation;
1383         samlogon_state.r.out.authoritative = &authoritative;
1384 
1385 
1386         for (f=0;f<ARRAY_SIZE(function_levels);f++) {
1387                 for (i=0; test_table[i].fn; i++) {
1388                         if (n_subtests && (i > n_subtests)) {
1389                                 continue;
1390                         }
1391                         for (v=0;v<ARRAY_SIZE(validation_levels);v++) {
1392                                 for (l=0;l<ARRAY_SIZE(logon_levels);l++) {
1393                                         char *error_string = NULL;
1394                                         TALLOC_CTX *tmp_ctx = talloc_named(fn_ctx, 0, "test_SamLogon inner loop");
1395                                         samlogon_state.mem_ctx = tmp_ctx;
1396                                         samlogon_state.function_level = function_levels[f];
1397                                         samlogon_state.r.in.validation_level = validation_levels[v];
1398                                         samlogon_state.r.in.logon_level = logon_levels[l];
1399                                         samlogon_state.r_ex.in.validation_level = validation_levels[v];
1400                                         samlogon_state.r_ex.in.logon_level = logon_levels[l];
1401                                         samlogon_state.r_flags.in.validation_level = validation_levels[v];
1402                                         samlogon_state.r_flags.in.logon_level = logon_levels[l];
1403                                         if (!test_table[i].fn(&samlogon_state, &error_string)) {
1404                                                 d_printf("Testing '%s' [%s]\\[%s] '%s' at validation level %d, logon level %d, function %d: \n",
1405                                                        samlogon_state.comment,
1406                                                        samlogon_state.account_domain,
1407                                                        samlogon_state.account_name,
1408                                                        test_table[i].name, validation_levels[v], 
1409                                                        logon_levels[l], function_levels[f]);
1410                                                 
1411                                                 if (test_table[i].expect_fail) {
1412                                                         d_printf(" failed (expected, test incomplete): %s\n", error_string);
1413                                                 } else {
1414                                                         d_printf(" failed: %s\n", error_string);
1415                                                         ret = false;
1416                                                 }
1417                                                 SAFE_FREE(error_string);
1418                                         }
1419                                         talloc_free(tmp_ctx);
1420                                 }
1421                         }
1422                 }
1423         }
1424         talloc_free(fn_ctx);
1425         return ret;
1426 }
1427 
1428 /*
1429   test an ADS style interactive domain logon
1430 */
1431 bool test_InteractiveLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
1432                            struct creds_CredentialState *creds, 
1433                            const char *comment,
1434                            const char *workstation_name,
1435                            const char *account_domain, const char *account_name,
1436                            const char *plain_pass, uint32_t parameter_control, 
1437                            NTSTATUS expected_error)
1438 {
1439         NTSTATUS status;
1440         TALLOC_CTX *fn_ctx = talloc_named(mem_ctx, 0, "test_InteractiveLogon function-level context");
1441         struct netr_LogonSamLogonWithFlags r;
1442         struct netr_Authenticator a, ra;
1443         struct netr_PasswordInfo pinfo;
1444         uint32_t flags = 0;
1445 
1446         union netr_LogonLevel logon;
1447         union netr_Validation validation;
1448         uint8_t authoritative = 0;
1449 
1450         ZERO_STRUCT(a);
1451         ZERO_STRUCT(r);
1452         ZERO_STRUCT(ra);
1453 
1454         ZERO_STRUCT(logon);
1455         ZERO_STRUCT(validation);
1456 
1457         creds_client_authenticator(creds, &a);
1458 
1459         logon.password = &pinfo;
1460 
1461         r.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p));
1462         r.in.computer_name = TEST_MACHINE_NAME;
1463         r.in.credential = &a;
1464         r.in.return_authenticator = &ra;
1465         r.in.logon_level = 5;
1466         r.in.logon = &logon;
1467         r.in.validation_level = 6;
1468         r.in.flags = &flags;
1469         r.out.validation = &validation;
1470         r.out.authoritative = &authoritative;
1471         r.out.flags = &flags;
1472 
1473         pinfo.identity_info.domain_name.string = account_domain;
1474         pinfo.identity_info.parameter_control = parameter_control;
1475         pinfo.identity_info.logon_id_low = 0;
1476         pinfo.identity_info.logon_id_high = 0;
1477         pinfo.identity_info.account_name.string = account_name;
1478         pinfo.identity_info.workstation.string = workstation_name;
1479 
1480         if (!E_deshash(plain_pass, pinfo.lmpassword.hash)) {
1481                 ZERO_STRUCT(pinfo.lmpassword.hash);
1482         }
1483         E_md4hash(plain_pass, pinfo.ntpassword.hash);
1484 
1485         if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
1486                 creds_arcfour_crypt(creds, pinfo.lmpassword.hash, 16);
1487                 creds_arcfour_crypt(creds, pinfo.ntpassword.hash, 16);
1488         } else {
1489                 creds_des_encrypt(creds, &pinfo.lmpassword);
1490                 creds_des_encrypt(creds, &pinfo.ntpassword);
1491         }
1492 
1493         d_printf("Testing netr_LogonSamLogonWithFlags '%s' (Interactive Logon)\n", comment);
1494 
1495         status = dcerpc_netr_LogonSamLogonWithFlags(p, fn_ctx, &r);
1496         if (!r.out.return_authenticator 
1497             || !creds_client_check(creds, &r.out.return_authenticator->cred)) {
1498                 d_printf("Credential chaining failed\n");
1499                 talloc_free(fn_ctx);
1500                 return false;
1501         }
1502 
1503         talloc_free(fn_ctx);
1504 
1505         if (!NT_STATUS_EQUAL(expected_error, status)) {
1506                 d_printf("[%s]\\[%s] netr_LogonSamLogonWithFlags - expected %s got %s\n", 
1507                        account_domain, account_name, nt_errstr(expected_error), nt_errstr(status));
1508                 return false;
1509         }
1510 
1511         return true;
1512 }
1513 
1514 
1515 
1516 bool torture_rpc_samlogon(struct torture_context *torture)
     /* [<][>][^][v][top][bottom][index][help] */
1517 {
1518         NTSTATUS status;
1519         struct dcerpc_pipe *p;
1520         struct dcerpc_binding *b;
1521         struct cli_credentials *machine_credentials;
1522         TALLOC_CTX *mem_ctx = talloc_init("torture_rpc_netlogon");
1523         bool ret = true;
1524         struct test_join *join_ctx = NULL;
1525         struct test_join *user_ctx = NULL, *user_ctx_wrong_wks = NULL, *user_ctx_wrong_time = NULL;
1526         char *user_password, *user_password_wrong_wks, *user_password_wrong_time;
1527         const char *old_user_password;
1528         char *test_machine_account;
1529         const char *userdomain;
1530         struct samr_SetUserInfo s;
1531         union samr_UserInfo u;
1532         int i;
1533         int ci;
1534 
1535         unsigned int credential_flags[] = {
1536                 NETLOGON_NEG_AUTH2_FLAGS,
1537                 NETLOGON_NEG_ARCFOUR,
1538                 NETLOGON_NEG_ARCFOUR | NETLOGON_NEG_128BIT,
1539                 NETLOGON_NEG_AUTH2_ADS_FLAGS, 
1540                 0 /* yes, this is a valid flag, causes the use of DES */ 
1541         };
1542 
1543         struct creds_CredentialState *creds;
1544 
1545         test_machine_account = talloc_asprintf(mem_ctx, "%s$", TEST_MACHINE_NAME);
1546         /* We only need to join as a workstation here, and in future,
1547          * if we wish to test against trusted domains, we must be a
1548          * workstation here */
1549         join_ctx = torture_join_domain(torture, TEST_MACHINE_NAME, ACB_WSTRUST, 
1550                                        &machine_credentials);
1551         if (!join_ctx) {
1552                 d_printf("Failed to join as Workstation\n");
1553                 return false;
1554         }
1555 
1556         userdomain = torture_setting_string(torture, "userdomain", lp_workgroup(torture->lp_ctx));
1557 
1558         user_ctx = torture_create_testuser(torture,
1559                                            TEST_USER_NAME,
1560                                            userdomain,
1561                                            ACB_NORMAL, 
1562                                            (const char **)&user_password);
1563         if (!user_ctx) {
1564                 d_printf("Failed to create a test user\n");
1565                 return false;
1566         }
1567 
1568         old_user_password = user_password;
1569 
1570         test_ChangePasswordUser3(torture_join_samr_pipe(user_ctx), torture,
1571                                  TEST_USER_NAME, 16 /* > 14 */, &user_password, 
1572                                  NULL, 0, false);
1573 
1574         user_ctx_wrong_wks = torture_create_testuser(torture,
1575                                                      TEST_USER_NAME_WRONG_WKS,
1576                                            userdomain,
1577                                            ACB_NORMAL, 
1578                                            (const char **)&user_password_wrong_wks);
1579         if (!user_ctx_wrong_wks) {
1580                 d_printf("Failed to create a test user (wrong workstation test)\n");
1581                 return false;
1582         }
1583 
1584         ZERO_STRUCT(u);
1585         s.in.user_handle = torture_join_samr_user_policy(user_ctx_wrong_wks);
1586         s.in.info = &u;
1587         s.in.level = 21;
1588 
1589         u.info21.fields_present = SAMR_FIELD_WORKSTATIONS;
1590         u.info21.workstations.string = "not" TEST_MACHINE_NAME;
1591 
1592         status = dcerpc_samr_SetUserInfo(torture_join_samr_pipe(user_ctx_wrong_wks), mem_ctx, &s);
1593         if (!NT_STATUS_IS_OK(status)) {
1594                 printf("SetUserInfo (list of workstations) failed - %s\n", nt_errstr(status));
1595                 ret = false;
1596                 goto failed;
1597         }
1598 
1599         user_ctx_wrong_time
1600                 = torture_create_testuser(torture, TEST_USER_NAME_WRONG_TIME,
1601                                            userdomain,
1602                                            ACB_NORMAL, 
1603                                            (const char **)&user_password_wrong_time);
1604         if (!user_ctx_wrong_time) {
1605                 d_printf("Failed to create a test user (wrong workstation test)\n");
1606                 return false;
1607         }
1608 
1609         ZERO_STRUCT(u);
1610         s.in.user_handle = torture_join_samr_user_policy(user_ctx_wrong_time);
1611         s.in.info = &u;
1612         s.in.level = 21;
1613 
1614         u.info21.fields_present = SAMR_FIELD_WORKSTATIONS | SAMR_FIELD_LOGON_HOURS;
1615         u.info21.workstations.string = TEST_MACHINE_NAME;
1616         u.info21.logon_hours.units_per_week = 168;
1617         u.info21.logon_hours.bits = talloc_zero_array(mem_ctx, uint8_t, 168);
1618 
1619         status = dcerpc_samr_SetUserInfo(torture_join_samr_pipe(user_ctx_wrong_time), mem_ctx, &s);
1620         if (!NT_STATUS_IS_OK(status)) {
1621                 printf("SetUserInfo (logon times and list of workstations) failed - %s\n", nt_errstr(status));
1622                 ret = false;
1623                 goto failed;
1624         }
1625 
1626         status = torture_rpc_binding(torture, &b);
1627         if (!NT_STATUS_IS_OK(status)) {
1628                 ret = false;
1629                 goto failed;
1630         }
1631 
1632         /* We have to use schannel, otherwise the SamLogonEx fails
1633          * with INTERNAL_ERROR */
1634 
1635         b->flags &= ~DCERPC_AUTH_OPTIONS;
1636         b->flags |= DCERPC_SCHANNEL | DCERPC_SIGN | DCERPC_SCHANNEL_128;
1637 
1638         status = dcerpc_pipe_connect_b(mem_ctx, &p, b, 
1639                                        &ndr_table_netlogon,
1640                                        machine_credentials, torture->ev, torture->lp_ctx);
1641 
1642         if (!NT_STATUS_IS_OK(status)) {
1643                 d_printf("RPC pipe connect as domain member failed: %s\n", nt_errstr(status));
1644                 ret = false;
1645                 goto failed;
1646         }
1647 
1648         status = dcerpc_schannel_creds(p->conn->security_state.generic_state, mem_ctx, &creds);
1649         if (!NT_STATUS_IS_OK(status)) {
1650                 ret = false;
1651                 goto failed;
1652         }
1653 
1654         {
1655                 
1656                 struct {
1657                         const char *comment;
1658                         const char *domain;
1659                         const char *username;
1660                         const char *password;
1661                         bool network_login;
1662                         NTSTATUS expected_interactive_error;
1663                         NTSTATUS expected_network_error;
1664                         uint32_t parameter_control;
1665                         bool old_password; /* Allow an old password to be accepted or rejected without error, as well as session key bugs */
1666                 } usercreds[] = {
1667                         {
1668                                 .comment       = "domain\\user",
1669                                 .domain        = cli_credentials_get_domain(cmdline_credentials),
1670                                 .username      = cli_credentials_get_username(cmdline_credentials),
1671                                 .password      = cli_credentials_get_password(cmdline_credentials),
1672                                 .network_login = true,
1673                                 .expected_interactive_error = NT_STATUS_OK,
1674                                 .expected_network_error     = NT_STATUS_OK
1675                         },
1676                         {
1677                                 .comment       = "realm\\user",
1678                                 .domain        = cli_credentials_get_realm(cmdline_credentials),
1679                                 .username      = cli_credentials_get_username(cmdline_credentials),
1680                                 .password      = cli_credentials_get_password(cmdline_credentials),
1681                                 .network_login = true,
1682                                 .expected_interactive_error = NT_STATUS_OK,
1683                                 .expected_network_error     = NT_STATUS_OK
1684                         },
1685                         {
1686                                 .comment       = "user@domain",
1687                                 .domain        = NULL,
1688                                 .username      = talloc_asprintf(mem_ctx, 
1689                                                 "%s@%s", 
1690                                                 cli_credentials_get_username(cmdline_credentials),
1691                                                 cli_credentials_get_domain(cmdline_credentials)
1692                                         ),
1693                                 .password      = cli_credentials_get_password(cmdline_credentials),
1694                                 .network_login = false, /* works for some things, but not NTLMv2.  Odd */
1695                                 .expected_interactive_error = NT_STATUS_OK,
1696                                 .expected_network_error     = NT_STATUS_OK
1697                         },
1698                         {
1699                                 .comment       = "user@realm",
1700                                 .domain        = NULL,
1701                                 .username      = talloc_asprintf(mem_ctx, 
1702                                                 "%s@%s", 
1703                                                 cli_credentials_get_username(cmdline_credentials),
1704                                                 cli_credentials_get_realm(cmdline_credentials)
1705                                         ),
1706                                 .password      = cli_credentials_get_password(cmdline_credentials),
1707                                 .network_login = true,
1708                                 .expected_interactive_error = NT_STATUS_OK,
1709                                 .expected_network_error     = NT_STATUS_OK
1710                         },
1711                         {
1712                                 .comment      = "machine domain\\user",
1713                                 .domain       = cli_credentials_get_domain(machine_credentials),
1714                                 .username     = cli_credentials_get_username(machine_credentials),
1715                                 .password     = cli_credentials_get_password(machine_credentials),
1716                                 .network_login = true,
1717                                 .expected_interactive_error = NT_STATUS_NO_SUCH_USER,
1718                                 .parameter_control = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
1719                         },
1720                         {
1721                                 .comment      = "machine domain\\user",
1722                                 .domain       = cli_credentials_get_domain(machine_credentials),
1723                                 .username     = cli_credentials_get_username(machine_credentials),
1724                                 .password     = cli_credentials_get_password(machine_credentials),
1725                                 .network_login = true,
1726                                 .expected_interactive_error = NT_STATUS_NO_SUCH_USER,
1727                                 .expected_network_error = NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT
1728                         },
1729                         {
1730                                 .comment       = "machine realm\\user",
1731                                 .domain        = cli_credentials_get_realm(machine_credentials),
1732                                 .username      = cli_credentials_get_username(machine_credentials),
1733                                 .password      = cli_credentials_get_password(machine_credentials),
1734                                 .network_login = true,
1735                                 .expected_interactive_error = NT_STATUS_NO_SUCH_USER,
1736                                 .parameter_control = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
1737                         },
1738                         {
1739                                 .comment       = "machine user@domain",
1740                                 .domain        = NULL,
1741                                 .username      = talloc_asprintf(mem_ctx, 
1742                                                                 "%s@%s", 
1743                                                                 cli_credentials_get_username(machine_credentials),
1744                                                                 cli_credentials_get_domain(machine_credentials)
1745                                         ), 
1746                                 .password      = cli_credentials_get_password(machine_credentials),
1747                                 .network_login = false, /* works for some things, but not NTLMv2.  Odd */
1748                                 .expected_interactive_error = NT_STATUS_NO_SUCH_USER,
1749                                 .parameter_control = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
1750                         },
1751                         {
1752                                 .comment       = "machine user@realm",
1753                                 .domain        = NULL,
1754                                 .username      = talloc_asprintf(mem_ctx, 
1755                                                                 "%s@%s", 
1756                                                                 cli_credentials_get_username(machine_credentials),
1757                                                                 cli_credentials_get_realm(machine_credentials)
1758                                         ),
1759                                 .password      = cli_credentials_get_password(machine_credentials),
1760                                 .network_login = true,
1761                                 .expected_interactive_error = NT_STATUS_NO_SUCH_USER,
1762                                 .parameter_control = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT
1763                         },
1764                         {       
1765                                 .comment       = "test user (long pw): domain\\user",
1766                                 .domain        = userdomain,
1767                                 .username      = TEST_USER_NAME,
1768                                 .password      = user_password,
1769                                 .network_login = true,
1770                                 .expected_interactive_error = NT_STATUS_OK,
1771                                 .expected_network_error     = NT_STATUS_OK
1772                         },
1773                         {
1774                                 .comment       = "test user (long pw): user@realm", 
1775                                 .domain        = NULL,
1776                                 .username      = talloc_asprintf(mem_ctx, 
1777                                                                  "%s@%s", 
1778                                                                  TEST_USER_NAME,
1779                                                                  lp_realm(torture->lp_ctx)),
1780                                 .password      = user_password,
1781                                 .network_login = true,
1782                                 .expected_interactive_error = NT_STATUS_OK,
1783                                 .expected_network_error     = NT_STATUS_OK
1784                         },
1785                         {
1786                                 .comment       = "test user (long pw): user@domain",
1787                                 .domain        = NULL,
1788                                 .username      = talloc_asprintf(mem_ctx, 
1789                                                                  "%s@%s", 
1790                                                                  TEST_USER_NAME,
1791                                                                  userdomain),
1792                                 .password      = user_password,
1793                                 .network_login = false, /* works for some things, but not NTLMv2.  Odd */
1794                                 .expected_interactive_error = NT_STATUS_OK,
1795                                 .expected_network_error     = NT_STATUS_OK
1796                         },
1797                         /* Oddball, can we use the old password ? */
1798                         {       
1799                                 .comment       = "test user: user\\domain OLD PASSWORD",
1800                                 .domain        = userdomain,
1801                                 .username      = TEST_USER_NAME,
1802                                 .password      = old_user_password,
1803                                 .network_login = true,
1804                                 .expected_interactive_error = NT_STATUS_WRONG_PASSWORD,
1805                                 .expected_network_error     = NT_STATUS_OK,
1806                                 .old_password  = true
1807                         },
1808                         {       
1809                                 .comment       = "test user (wong workstation): domain\\user",
1810                                 .domain        = userdomain,
1811                                 .username      = TEST_USER_NAME_WRONG_WKS,
1812                                 .password      = user_password_wrong_wks,
1813                                 .network_login = true,
1814                                 .expected_interactive_error = NT_STATUS_INVALID_WORKSTATION,
1815                                 .expected_network_error     = NT_STATUS_INVALID_WORKSTATION
1816                         }
1817                 };
1818                 
1819                 /* Try all the tests for different username forms */
1820                 for (ci = 0; ci < ARRAY_SIZE(usercreds); ci++) {
1821                 
1822                         if (!test_InteractiveLogon(p, mem_ctx, creds,
1823                                                    usercreds[ci].comment,
1824                                                    TEST_MACHINE_NAME,
1825                                                    usercreds[ci].domain,
1826                                                    usercreds[ci].username,
1827                                                    usercreds[ci].password,
1828                                                    usercreds[ci].parameter_control,
1829                                                    usercreds[ci].expected_interactive_error)) {
1830                                 ret = false;
1831                         }
1832                 
1833                         if (usercreds[ci].network_login) {
1834                                 if (!test_SamLogon(p, mem_ctx, torture, creds, 
1835                                                    usercreds[ci].comment,
1836                                                    usercreds[ci].domain,
1837                                                    usercreds[ci].username,
1838                                                    usercreds[ci].password,
1839                                                    usercreds[ci].parameter_control,
1840                                                    usercreds[ci].expected_network_error,
1841                                                    usercreds[ci].old_password,
1842                                                    0)) {
1843                                         ret = false;
1844                                 }
1845                         }
1846                 }
1847 
1848                 /* Using the first username form, try the different
1849                  * credentials flag setups, on only one of the tests (checks
1850                  * session key encryption) */
1851 
1852                 for (i=0; i < ARRAY_SIZE(credential_flags); i++) {
1853                         /* TODO:  Somehow we lost setting up the different credential flags here! */
1854 
1855                         if (!test_InteractiveLogon(p, mem_ctx, creds,
1856                                                    usercreds[0].comment,
1857                                                    TEST_MACHINE_NAME,
1858                                                    usercreds[0].domain,
1859                                                    usercreds[0].username,
1860                                                    usercreds[0].password,
1861                                                    usercreds[0].parameter_control,
1862                                                    usercreds[0].expected_interactive_error)) {
1863                                 ret = false;
1864                         }
1865                 
1866                         if (usercreds[0].network_login) {
1867                                 if (!test_SamLogon(p, mem_ctx, torture, creds,
1868                                                    usercreds[0].comment,
1869                                                    usercreds[0].domain,
1870                                                    usercreds[0].username,
1871                                                    usercreds[0].password,
1872                                                    usercreds[0].parameter_control,
1873                                                    usercreds[0].expected_network_error,
1874                                                    usercreds[0].old_password,
1875                                                    1)) {
1876                                         ret = false;
1877                                 }
1878                         }
1879                 }
1880 
1881         }
1882 failed:
1883         talloc_free(mem_ctx);
1884 
1885         torture_leave_domain(torture, join_ctx);
1886         torture_leave_domain(torture, user_ctx);
1887         torture_leave_domain(torture, user_ctx_wrong_wks);
1888         torture_leave_domain(torture, user_ctx_wrong_time);
1889         return ret;
1890 }

/* [<][>][^][v][top][bottom][index][help] */