LCOV - code coverage report
Current view: top level - source4/torture/rpc - samlogon.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 664 927 71.6 %
Date: 2021-09-23 10:06:22 Functions: 39 40 97.5 %

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

Generated by: LCOV version 1.13