LCOV - code coverage report
Current view: top level - source4/torture/rpc - samlogon.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 664 1011 65.7 %
Date: 2024-02-28 12:06:22 Functions: 39 39 100.0 %

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

Generated by: LCOV version 1.14