LCOV - code coverage report
Current view: top level - source4/torture/rpc - schannel.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 300 473 63.4 %
Date: 2021-09-23 10:06:22 Functions: 9 12 75.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    test suite for schannel operations
       5             : 
       6             :    Copyright (C) Andrew Tridgell 2004
       7             : 
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             : 
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include "includes.h"
      23             : #include "librpc/gen_ndr/ndr_netlogon_c.h"
      24             : #include "librpc/gen_ndr/ndr_lsa_c.h"
      25             : #include "librpc/gen_ndr/ndr_samr_c.h"
      26             : #include "auth/credentials/credentials.h"
      27             : #include "auth/credentials/credentials_krb5.h"
      28             : #include "torture/rpc/torture_rpc.h"
      29             : #include "lib/cmdline/cmdline.h"
      30             : #include "../libcli/auth/schannel.h"
      31             : #include "libcli/auth/libcli_auth.h"
      32             : #include "libcli/security/security.h"
      33             : #include "system/filesys.h"
      34             : #include "param/param.h"
      35             : #include "librpc/rpc/dcerpc_proto.h"
      36             : #include "libcli/composite/composite.h"
      37             : #include "lib/events/events.h"
      38             : 
      39             : #define TEST_MACHINE_NAME "schannel"
      40             : 
      41             : /*
      42             :   try a netlogon SamLogon
      43             : */
      44         920 : bool test_netlogon_ex_ops(struct dcerpc_pipe *p, struct torture_context *tctx,
      45             :                           struct cli_credentials *credentials,
      46             :                           struct netlogon_creds_CredentialState *creds)
      47             : {
      48             :         NTSTATUS status;
      49             :         struct netr_LogonSamLogonEx r;
      50             :         struct netr_NetworkInfo ninfo;
      51             :         union netr_LogonLevel logon;
      52             :         union netr_Validation validation;
      53         920 :         uint8_t authoritative = 0;
      54         920 :         uint32_t _flags = 0;
      55             :         DATA_BLOB names_blob, chal, lm_resp, nt_resp;
      56             :         int i;
      57         920 :         int flags = CLI_CRED_NTLM_AUTH;
      58         920 :         struct dcerpc_binding_handle *b = p->binding_handle;
      59             : 
      60             :         struct netr_UserSessionKey key;
      61             :         struct netr_LMSessionKey LMSessKey;
      62         920 :         uint32_t validation_levels[] = { 2, 3 };
      63         920 :         struct netr_SamBaseInfo *base = NULL;
      64         920 :         const char *crypto_alg = "";
      65         920 :         bool can_do_validation_6 = true;
      66         920 :         enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
      67             : 
      68         920 :         if (lpcfg_client_lanman_auth(tctx->lp_ctx)) {
      69         800 :                 flags |= CLI_CRED_LANMAN_AUTH;
      70             :         }
      71             : 
      72         920 :         if (lpcfg_client_ntlmv2_auth(tctx->lp_ctx)) {
      73         920 :                 flags |= CLI_CRED_NTLMv2_AUTH;
      74             :         }
      75             : 
      76         920 :         cli_credentials_get_ntlm_username_domain(samba_cmdline_get_creds(),
      77             :                                 tctx,
      78             :                                 &ninfo.identity_info.account_name.string,
      79             :                                 &ninfo.identity_info.domain_name.string);
      80             : 
      81         920 :         generate_random_buffer(ninfo.challenge,
      82             :                                sizeof(ninfo.challenge));
      83         920 :         chal = data_blob_const(ninfo.challenge,
      84             :                                sizeof(ninfo.challenge));
      85             : 
      86         920 :         names_blob = NTLMv2_generate_names_blob(tctx, cli_credentials_get_workstation(credentials),
      87             :                                                 cli_credentials_get_domain(credentials));
      88             : 
      89         920 :         status = cli_credentials_get_ntlm_response(
      90             :                         samba_cmdline_get_creds(),
      91             :                         tctx,
      92             :                         &flags,
      93             :                         chal,
      94             :                         NULL, /* server_timestamp */
      95             :                         names_blob,
      96             :                         &lm_resp, &nt_resp,
      97             :                         NULL, NULL);
      98         920 :         torture_assert_ntstatus_ok(tctx, status,
      99             :                                    "cli_credentials_get_ntlm_response failed");
     100             : 
     101         920 :         ninfo.lm.data = lm_resp.data;
     102         920 :         ninfo.lm.length = lm_resp.length;
     103             : 
     104         920 :         ninfo.nt.data = nt_resp.data;
     105         920 :         ninfo.nt.length = nt_resp.length;
     106             : 
     107         920 :         ninfo.identity_info.parameter_control = 0;
     108         920 :         ninfo.identity_info.logon_id = 0;
     109         920 :         ninfo.identity_info.workstation.string = cli_credentials_get_workstation(credentials);
     110             : 
     111         920 :         logon.network = &ninfo;
     112             : 
     113         920 :         r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
     114         920 :         r.in.computer_name = cli_credentials_get_workstation(credentials);
     115         920 :         r.in.logon_level = NetlogonNetworkInformation;
     116         920 :         r.in.logon= &logon;
     117         920 :         r.in.flags = &_flags;
     118         920 :         r.out.validation = &validation;
     119         920 :         r.out.authoritative = &authoritative;
     120         920 :         r.out.flags = &_flags;
     121             : 
     122             :         /*
     123             :         - retrieve level6
     124             :         - save usrsession and lmsession key
     125             :         - retrieve level 2
     126             :         - calculate, compare
     127             :         - retrieve level 3
     128             :         - calculate, compare
     129             :         */
     130             : 
     131         920 :         if (creds) {
     132         828 :                 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
     133         456 :                         crypto_alg = "AES";
     134         276 :                 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
     135         276 :                         crypto_alg = "ARCFOUR";
     136             :                 }
     137             :         }
     138             : 
     139         920 :         dcerpc_binding_handle_auth_info(b, NULL, &auth_level);
     140         920 :         if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
     141         276 :                 r.in.validation_level = 6;
     142             : 
     143         276 :                 torture_comment(tctx,
     144             :                                 "Testing LogonSamLogonEx with name %s using %s and validation_level: %d\n",
     145             :                                 ninfo.identity_info.account_name.string, crypto_alg,
     146         228 :                                 r.in.validation_level);
     147             : 
     148         276 :                 torture_assert_ntstatus_ok(tctx,
     149             :                         dcerpc_netr_LogonSamLogonEx_r(b, tctx, &r),
     150             :                         "LogonSamLogonEx failed");
     151             :         } else {
     152         644 :                 torture_comment(tctx,
     153             :                                 "Skip auth_level[%u] Testing LogonSamLogonEx with name %s using %s and validation_level: %d\n",
     154             :                                 auth_level, ninfo.identity_info.account_name.string, crypto_alg,
     155         644 :                                 r.in.validation_level);
     156         644 :                 r.out.result = NT_STATUS_INVALID_INFO_CLASS;
     157             :         }
     158             : 
     159         920 :         if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_INFO_CLASS)) {
     160         556 :                 can_do_validation_6 = false;
     161             :         } else {
     162         252 :                 torture_assert_ntstatus_ok(tctx, r.out.result,
     163             :                         "LogonSamLogonEx failed");
     164             : 
     165         252 :                 key = r.out.validation->sam6->base.key;
     166         252 :                 LMSessKey = r.out.validation->sam6->base.LMSessKey;
     167             : 
     168         252 :                 DEBUG(1,("unencrypted session keys from validation_level 6:\n"));
     169         252 :                 dump_data(1, r.out.validation->sam6->base.key.key, 16);
     170         252 :                 dump_data(1, r.out.validation->sam6->base.LMSessKey.key, 8);
     171             :         }
     172             : 
     173        2208 :         for (i=0; i < ARRAY_SIZE(validation_levels); i++) {
     174             : 
     175        1564 :                 r.in.validation_level = validation_levels[i];
     176             : 
     177        1564 :                 torture_comment(tctx,
     178             :                         "Testing LogonSamLogonEx with name %s using %s and validation_level: %d\n",
     179             :                         ninfo.identity_info.account_name.string, crypto_alg,
     180        1292 :                         r.in.validation_level);
     181             : 
     182        1564 :                 torture_assert_ntstatus_ok(tctx,
     183             :                         dcerpc_netr_LogonSamLogonEx_r(b, tctx, &r),
     184             :                         "LogonSamLogonEx failed");
     185        1564 :                 torture_assert_ntstatus_ok(tctx, r.out.result,
     186             :                         "LogonSamLogonEx failed");
     187             : 
     188        1288 :                 if (creds == NULL) {
     189             :                         /* when this test is called without creds no point in
     190             :                          * testing the session keys */
     191         184 :                         continue;
     192             :                 }
     193             : 
     194        1104 :                 switch (validation_levels[i]) {
     195         552 :                 case 2:
     196         552 :                         base = &r.out.validation->sam2->base;
     197         552 :                         break;
     198         552 :                 case 3:
     199         552 :                         base = &r.out.validation->sam3->base;
     200         552 :                         break;
     201           0 :                 default:
     202           0 :                         break;
     203             :                 }
     204             : 
     205        1104 :                 DEBUG(1,("encrypted keys validation_level %d:\n",
     206             :                         validation_levels[i]));
     207        1104 :                 dump_data(1, base->key.key, 16);
     208        1104 :                 dump_data(1, base->LMSessKey.key, 8);
     209             : 
     210        1104 :                 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
     211         736 :                         netlogon_creds_aes_decrypt(creds, base->key.key, 16);
     212         736 :                         netlogon_creds_aes_decrypt(creds, base->LMSessKey.key, 8);
     213         368 :                 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
     214         368 :                         netlogon_creds_arcfour_crypt(creds, base->key.key, 16);
     215         368 :                         netlogon_creds_arcfour_crypt(creds, base->LMSessKey.key, 8);
     216             :                 }
     217             : 
     218        1104 :                 DEBUG(1,("decryped keys validation_level %d\n",
     219             :                         validation_levels[i]));
     220             : 
     221        1104 :                 dump_data(1, base->key.key, 16);
     222        1104 :                 dump_data(1, base->LMSessKey.key, 8);
     223             : 
     224        1104 :                 if (!can_do_validation_6) {
     225             :                         /* we cant compare against unencrypted keys */
     226         600 :                         continue;
     227             :                 }
     228             : 
     229         504 :                 torture_assert_mem_equal(tctx,
     230             :                                          base->key.key,
     231             :                                          key.key,
     232             :                                          16,
     233             :                                          "unexpected user session key\n");
     234         504 :                 torture_assert_mem_equal(tctx,
     235             :                                          base->LMSessKey.key,
     236             :                                          LMSessKey.key,
     237             :                                          8,
     238             :                                          "unexpected LM session key\n");
     239             :         }
     240             : 
     241         532 :         return true;
     242             : }
     243             : 
     244             : /*
     245             :   do some samr ops using the schannel connection
     246             :  */
     247         552 : static bool test_samr_ops(struct torture_context *tctx,
     248             :                           struct dcerpc_binding_handle *b)
     249             : {
     250             :         struct samr_GetDomPwInfo r;
     251             :         struct samr_PwInfo info;
     252             :         struct samr_Connect connect_r;
     253             :         struct samr_OpenDomain opendom;
     254             :         int i;
     255             :         struct lsa_String name;
     256             :         struct policy_handle handle;
     257             :         struct policy_handle domain_handle;
     258             : 
     259         552 :         name.string = lpcfg_workgroup(tctx->lp_ctx);
     260         552 :         r.in.domain_name = &name;
     261         552 :         r.out.info = &info;
     262             : 
     263         552 :         connect_r.in.system_name = 0;
     264         552 :         connect_r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
     265         552 :         connect_r.out.connect_handle = &handle;
     266             : 
     267         552 :         torture_comment(tctx, "Testing Connect and OpenDomain on BUILTIN\n");
     268             : 
     269         552 :         torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect_r(b, tctx, &connect_r),
     270             :                 "Connect failed");
     271         552 :         if (!NT_STATUS_IS_OK(connect_r.out.result)) {
     272           0 :                 if (NT_STATUS_EQUAL(connect_r.out.result, NT_STATUS_ACCESS_DENIED)) {
     273           0 :                         torture_comment(tctx, "Connect failed (expected, schannel mapped to anonymous): %s\n",
     274             :                                nt_errstr(connect_r.out.result));
     275             :                 } else {
     276           0 :                         torture_comment(tctx, "Connect failed - %s\n", nt_errstr(connect_r.out.result));
     277           0 :                         return false;
     278             :                 }
     279             :         } else {
     280         552 :                 opendom.in.connect_handle = &handle;
     281         552 :                 opendom.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
     282         552 :                 opendom.in.sid = dom_sid_parse_talloc(tctx, "S-1-5-32");
     283         552 :                 opendom.out.domain_handle = &domain_handle;
     284             : 
     285         552 :                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenDomain_r(b, tctx, &opendom),
     286             :                         "OpenDomain failed");
     287         552 :                 if (!NT_STATUS_IS_OK(opendom.out.result)) {
     288           0 :                         torture_comment(tctx, "OpenDomain failed - %s\n", nt_errstr(opendom.out.result));
     289           0 :                         return false;
     290             :                 }
     291             :         }
     292             : 
     293         552 :         torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
     294             : 
     295             :         /* do several ops to test credential chaining */
     296        3312 :         for (i=0;i<5;i++) {
     297        2760 :                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r),
     298             :                         "GetDomPwInfo failed");
     299        2760 :                 if (!NT_STATUS_IS_OK(r.out.result)) {
     300           0 :                         if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED)) {
     301           0 :                                 torture_comment(tctx, "GetDomPwInfo op %d failed - %s\n", i, nt_errstr(r.out.result));
     302           0 :                                 return false;
     303             :                         }
     304             :                 }
     305             :         }
     306             : 
     307         456 :         return true;
     308             : }
     309             : 
     310             : 
     311             : /*
     312             :   do some lsa ops using the schannel connection
     313             :  */
     314         276 : static bool test_lsa_ops(struct torture_context *tctx, struct dcerpc_pipe *p)
     315             : {
     316             :         struct lsa_GetUserName r;
     317         276 :         bool ret = true;
     318         276 :         struct lsa_String *account_name_p = NULL;
     319         276 :         struct lsa_String *authority_name_p = NULL;
     320         276 :         struct dcerpc_binding_handle *b = p->binding_handle;
     321             : 
     322         276 :         torture_comment(tctx, "\nTesting GetUserName\n");
     323             : 
     324         276 :         r.in.system_name = "\\";
     325         276 :         r.in.account_name = &account_name_p;
     326         276 :         r.in.authority_name = &authority_name_p;
     327         276 :         r.out.account_name = &account_name_p;
     328             : 
     329             :         /* do several ops to test credential chaining and various operations */
     330         276 :         torture_assert_ntstatus_ok(tctx, dcerpc_lsa_GetUserName_r(b, tctx, &r),
     331             :                 "lsa_GetUserName failed");
     332             : 
     333         276 :         authority_name_p = *r.out.authority_name;
     334             : 
     335         276 :         if (!NT_STATUS_IS_OK(r.out.result)) {
     336           0 :                 torture_comment(tctx, "GetUserName failed - %s\n", nt_errstr(r.out.result));
     337           0 :                 return false;
     338             :         } else {
     339         276 :                 if (!r.out.account_name) {
     340           0 :                         return false;
     341             :                 }
     342             : 
     343         276 :                 if (strcmp(account_name_p->string, "ANONYMOUS LOGON") != 0) {
     344          24 :                         torture_comment(tctx, "GetUserName returned wrong user: %s, expected %s\n",
     345          24 :                                account_name_p->string, "ANONYMOUS LOGON");
     346             :                         /* FIXME: gd */
     347          24 :                         if (!torture_setting_bool(tctx, "samba3", false)) {
     348           0 :                                 return false;
     349             :                         }
     350             :                 }
     351         276 :                 if (!authority_name_p || !authority_name_p->string) {
     352           0 :                         return false;
     353             :                 }
     354             : 
     355         276 :                 if (strcmp(authority_name_p->string, "NT AUTHORITY") != 0) {
     356          24 :                         torture_comment(tctx, "GetUserName returned wrong user: %s, expected %s\n",
     357          24 :                                authority_name_p->string, "NT AUTHORITY");
     358             :                         /* FIXME: gd */
     359          24 :                         if (!torture_setting_bool(tctx, "samba3", false)) {
     360           0 :                                 return false;
     361             :                         }
     362             :                 }
     363             :         }
     364             : 
     365         228 :         return ret;
     366             : }
     367             : 
     368             : 
     369             : /*
     370             :   test a schannel connection with the given flags
     371             :  */
     372         276 : static bool test_schannel(struct torture_context *tctx,
     373             :                           uint16_t acct_flags, uint32_t dcerpc_flags,
     374             :                           int i)
     375             : {
     376             :         struct test_join *join_ctx;
     377             :         NTSTATUS status;
     378         276 :         const char *binding = torture_setting_string(tctx, "binding", NULL);
     379             :         struct dcerpc_binding *b;
     380         276 :         struct dcerpc_pipe *p = NULL;
     381         276 :         struct dcerpc_pipe *p_netlogon = NULL;
     382         276 :         struct dcerpc_pipe *p_netlogon2 = NULL;
     383         276 :         struct dcerpc_pipe *p_netlogon3 = NULL;
     384         276 :         struct dcerpc_pipe *p_samr2 = NULL;
     385         276 :         struct dcerpc_pipe *p_lsa = NULL;
     386             :         struct netlogon_creds_CredentialState *creds;
     387             :         struct cli_credentials *credentials;
     388             :         enum dcerpc_transport_t transport;
     389             : 
     390         504 :         join_ctx = torture_join_domain(tctx,
     391         276 :                                        talloc_asprintf(tctx, "%s%d", TEST_MACHINE_NAME, i),
     392             :                                        acct_flags, &credentials);
     393         276 :         torture_assert(tctx, join_ctx != NULL, "Failed to join domain");
     394             : 
     395         276 :         status = dcerpc_parse_binding(tctx, binding, &b);
     396         276 :         torture_assert_ntstatus_ok(tctx, status, "Bad binding string");
     397             : 
     398         276 :         status = dcerpc_binding_set_flags(b, dcerpc_flags, DCERPC_AUTH_OPTIONS);
     399         276 :         torture_assert_ntstatus_ok(tctx, status, "set flags");
     400             : 
     401         276 :         status = dcerpc_pipe_connect_b(tctx, &p, b, &ndr_table_samr,
     402             :                                        credentials, tctx->ev, tctx->lp_ctx);
     403         276 :         torture_assert_ntstatus_ok(tctx, status,
     404             :                 "Failed to connect to samr with schannel");
     405             : 
     406         276 :         torture_assert(tctx, test_samr_ops(tctx, p->binding_handle),
     407             :                        "Failed to process schannel secured SAMR ops");
     408             : 
     409             :         /* Also test that when we connect to the netlogon pipe, that
     410             :          * the credentials we setup on the first pipe are valid for
     411             :          * the second */
     412             : 
     413             :         /* Swap the binding details from SAMR to NETLOGON */
     414         276 :         status = dcerpc_epm_map_binding(tctx, b, &ndr_table_netlogon, tctx->ev, tctx->lp_ctx);
     415         276 :         torture_assert_ntstatus_ok(tctx, status, "epm map");
     416             : 
     417         276 :         status = dcerpc_binding_set_flags(b, dcerpc_flags, DCERPC_AUTH_OPTIONS);
     418         276 :         torture_assert_ntstatus_ok(tctx, status, "set flags");
     419             : 
     420         276 :         status = dcerpc_secondary_auth_connection(p, b, &ndr_table_netlogon,
     421             :                                                   credentials, tctx->lp_ctx,
     422             :                                                   tctx, &p_netlogon);
     423         276 :         torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
     424             : 
     425         276 :         creds = cli_credentials_get_netlogon_creds(credentials);
     426         276 :         torture_assert(tctx, (creds != NULL), "schannel creds");
     427             : 
     428             :         /* checks the capabilities */
     429         276 :         torture_assert(tctx, test_netlogon_capabilities(p_netlogon, tctx, credentials, creds),
     430             :                        "Failed to process schannel secured capability ops (on fresh connection)");
     431             : 
     432             :         /* do a couple of logins */
     433         276 :         torture_assert(tctx, test_netlogon_ops(p_netlogon, tctx, credentials, creds),
     434             :                 "Failed to process schannel secured NETLOGON ops");
     435             : 
     436         276 :         torture_assert(tctx, test_netlogon_ex_ops(p_netlogon, tctx, credentials, creds),
     437             :                 "Failed to process schannel secured NETLOGON EX ops");
     438             : 
     439             :         /* we *MUST* use ncacn_np for openpolicy etc. */
     440         276 :         transport = dcerpc_binding_get_transport(b);
     441         276 :         status = dcerpc_binding_set_transport(b, NCACN_NP);
     442         276 :         torture_assert_ntstatus_ok(tctx, status, "set transport");
     443             : 
     444             :         /* Swap the binding details from SAMR to LSARPC */
     445         276 :         status = dcerpc_epm_map_binding(tctx, b, &ndr_table_lsarpc, tctx->ev, tctx->lp_ctx);
     446         276 :         torture_assert_ntstatus_ok(tctx, status, "epm map");
     447             : 
     448         276 :         torture_assert_ntstatus_ok(tctx,
     449             :                 dcerpc_pipe_connect_b(tctx, &p_lsa, b, &ndr_table_lsarpc,
     450             :                                       credentials, tctx->ev, tctx->lp_ctx),
     451             :                 "failed to connect lsarpc with schannel");
     452             : 
     453         276 :         torture_assert(tctx, test_lsa_ops(tctx, p_lsa),
     454             :                 "Failed to process schannel secured LSA ops");
     455             : 
     456         276 :         talloc_free(p_lsa);
     457         276 :         p_lsa = NULL;
     458             : 
     459             :         /* we *MUST* use ncacn_ip_tcp for lookupsids3/lookupnames4 */
     460         276 :         status = dcerpc_binding_set_transport(b, NCACN_IP_TCP);
     461         276 :         torture_assert_ntstatus_ok(tctx, status, "set transport");
     462             : 
     463         276 :         torture_assert_ntstatus_ok(tctx,
     464             :                 dcerpc_epm_map_binding(tctx, b, &ndr_table_lsarpc, tctx->ev, tctx->lp_ctx),
     465             :                 "failed to call epm map");
     466             : 
     467         276 :         torture_assert_ntstatus_ok(tctx,
     468             :                 dcerpc_pipe_connect_b(tctx, &p_lsa, b, &ndr_table_lsarpc,
     469             :                                       credentials, tctx->ev, tctx->lp_ctx),
     470             :                 "failed to connect lsarpc with schannel");
     471             : 
     472         276 :         torture_assert(tctx,
     473             :                 test_many_LookupSids(p_lsa, tctx, NULL, LSA_LOOKUP_NAMES_ALL),
     474             :                 "LsaLookupSids3 failed!\n");
     475             : 
     476         276 :         status = dcerpc_binding_set_transport(b, transport);
     477         276 :         torture_assert_ntstatus_ok(tctx, status, "set transport");
     478             : 
     479             : 
     480             :         /* Drop the socket, we want to start from scratch */
     481         276 :         talloc_free(p);
     482         276 :         p = NULL;
     483             : 
     484             :         /* Now see what we are still allowed to do */
     485             : 
     486         276 :         status = dcerpc_parse_binding(tctx, binding, &b);
     487         276 :         torture_assert_ntstatus_ok(tctx, status, "Bad binding string");
     488             : 
     489         276 :         status = dcerpc_binding_set_flags(b, dcerpc_flags, DCERPC_AUTH_OPTIONS);
     490         276 :         torture_assert_ntstatus_ok(tctx, status, "set flags");
     491             : 
     492         276 :         status = dcerpc_pipe_connect_b(tctx, &p_samr2, b, &ndr_table_samr,
     493             :                                        credentials, tctx->ev, tctx->lp_ctx);
     494         276 :         torture_assert_ntstatus_ok(tctx, status,
     495             :                 "Failed to connect with schannel");
     496             : 
     497             :         /* do a some SAMR operations.  We have *not* done a new serverauthenticate */
     498         276 :         torture_assert (tctx, test_samr_ops(tctx, p_samr2->binding_handle),
     499             :                         "Failed to process schannel secured SAMR ops (on fresh connection)");
     500             : 
     501             :         /* Swap the binding details from SAMR to NETLOGON */
     502         276 :         status = dcerpc_epm_map_binding(tctx, b, &ndr_table_netlogon, tctx->ev, tctx->lp_ctx);
     503         276 :         torture_assert_ntstatus_ok(tctx, status, "epm");
     504             : 
     505         276 :         status = dcerpc_binding_set_flags(b, dcerpc_flags, DCERPC_AUTH_OPTIONS);
     506         276 :         torture_assert_ntstatus_ok(tctx, status, "set flags");
     507             : 
     508         276 :         status = dcerpc_secondary_auth_connection(p_samr2, b, &ndr_table_netlogon,
     509             :                                                   credentials, tctx->lp_ctx,
     510             :                                                   tctx, &p_netlogon2);
     511         276 :         torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
     512             : 
     513             :         /* checks the capabilities */
     514         276 :         torture_assert(tctx, test_netlogon_capabilities(p_netlogon2, tctx, credentials, creds),
     515             :                        "Failed to process schannel secured capability ops (on fresh connection)");
     516             : 
     517             :         /* Try the schannel-only SamLogonEx operation */
     518         276 :         torture_assert(tctx, test_netlogon_ex_ops(p_netlogon2, tctx, credentials, creds),
     519             :                        "Failed to process schannel secured NETLOGON EX ops (on fresh connection)");
     520             : 
     521             : 
     522             :         /* And the more traditional style, proving that the
     523             :          * credentials chaining state is fully present */
     524         276 :         torture_assert(tctx, test_netlogon_ops(p_netlogon2, tctx, credentials, creds),
     525             :                              "Failed to process schannel secured NETLOGON ops (on fresh connection)");
     526             : 
     527             :         /* Drop the socket, we want to start from scratch (again) */
     528         276 :         talloc_free(p_samr2);
     529             : 
     530             :         /* We don't want schannel for this test */
     531         276 :         status = dcerpc_binding_set_flags(b, 0, DCERPC_AUTH_OPTIONS);
     532         276 :         torture_assert_ntstatus_ok(tctx, status, "set flags");
     533             : 
     534         276 :         status = dcerpc_pipe_connect_b(tctx, &p_netlogon3, b, &ndr_table_netlogon,
     535             :                                        credentials, tctx->ev, tctx->lp_ctx);
     536         276 :         torture_assert_ntstatus_ok(tctx, status, "Failed to connect without schannel");
     537             : 
     538         276 :         torture_assert(tctx, !test_netlogon_ex_ops(p_netlogon3, tctx, credentials, creds),
     539             :                         "Processed NOT schannel secured NETLOGON EX ops without SCHANNEL (unsafe)");
     540             : 
     541             :         /* Required because the previous call will mark the current context as having failed */
     542         276 :         tctx->last_result = TORTURE_OK;
     543         276 :         tctx->last_reason = NULL;
     544             : 
     545         276 :         torture_assert(tctx, test_netlogon_ops(p_netlogon3, tctx, credentials, creds),
     546             :                         "Failed to processed NOT schannel secured NETLOGON ops without new ServerAuth");
     547             : 
     548         276 :         torture_leave_domain(tctx, join_ctx);
     549         276 :         return true;
     550             : }
     551             : 
     552             : /*
     553             :  * Purpose of this test is to demonstrate that a netlogon server carefully deals
     554             :  * with anonymous attempts to set passwords, in particular when the server
     555             :  * enforces the use of schannel. This test makes most sense to be run in an
     556             :  * environment where the netlogon server enforces use of schannel.
     557             :  */
     558             : 
     559          20 : static bool test_schannel_anonymous_setPassword(struct torture_context *tctx,
     560             :                                                 uint32_t dcerpc_flags,
     561             :                                                 bool use2)
     562             : {
     563             :         NTSTATUS status, result;
     564          20 :         const char *binding = torture_setting_string(tctx, "binding", NULL);
     565             :         struct dcerpc_binding *b;
     566          20 :         struct dcerpc_pipe *p = NULL;
     567             :         struct cli_credentials *credentials;
     568          20 :         bool ok = true;
     569             : 
     570          20 :         credentials = cli_credentials_init(NULL);
     571          20 :         torture_assert(tctx, credentials != NULL, "Bad credentials");
     572          20 :         cli_credentials_set_anonymous(credentials);
     573             : 
     574          20 :         status = dcerpc_parse_binding(tctx, binding, &b);
     575          20 :         torture_assert_ntstatus_ok(tctx, status, "Bad binding string");
     576             : 
     577          20 :         status = dcerpc_binding_set_flags(b, dcerpc_flags, DCERPC_AUTH_OPTIONS);
     578          20 :         torture_assert_ntstatus_ok(tctx, status, "set flags");
     579             : 
     580          20 :         status = dcerpc_pipe_connect_b(tctx,
     581             :                                        &p,
     582             :                                        b,
     583             :                                        &ndr_table_netlogon,
     584             :                                        credentials,
     585             :                                        tctx->ev,
     586             :                                        tctx->lp_ctx);
     587          20 :         torture_assert_ntstatus_ok(tctx, status, "Failed to connect without schannel");
     588             : 
     589          20 :         if (use2) {
     590          10 :                 struct netr_ServerPasswordSet2 r = {};
     591          10 :                 struct netr_Authenticator credential = {};
     592          10 :                 struct netr_Authenticator return_authenticator = {};
     593          10 :                 struct netr_CryptPassword new_password = {};
     594             : 
     595          10 :                 r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
     596          10 :                 r.in.account_name = talloc_asprintf(tctx, "%s$", TEST_MACHINE_NAME);
     597          10 :                 r.in.secure_channel_type = 0;
     598          10 :                 r.in.computer_name = TEST_MACHINE_NAME;
     599          10 :                 r.in.credential = &credential;
     600          10 :                 r.in.new_password = &new_password;
     601          10 :                 r.out.return_authenticator = &return_authenticator;
     602             : 
     603          10 :                 status = dcerpc_netr_ServerPasswordSet2_r(p->binding_handle, tctx, &r);
     604          10 :                 result = r.out.result;
     605             :         } else {
     606          10 :                 struct netr_ServerPasswordSet r = {};
     607          10 :                 struct netr_Authenticator credential = {};
     608          10 :                 struct netr_Authenticator return_authenticator = {};
     609          10 :                 struct samr_Password new_password = {};
     610             : 
     611          10 :                 r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
     612          10 :                 r.in.account_name = talloc_asprintf(tctx, "%s$", TEST_MACHINE_NAME);
     613          10 :                 r.in.secure_channel_type = 0;
     614          10 :                 r.in.computer_name = TEST_MACHINE_NAME;
     615          10 :                 r.in.credential = &credential;
     616          10 :                 r.in.new_password = &new_password;
     617          10 :                 r.out.return_authenticator = &return_authenticator;
     618             : 
     619          10 :                 status = dcerpc_netr_ServerPasswordSet_r(p->binding_handle, tctx, &r);
     620          10 :                 result = r.out.result;
     621             :         }
     622             : 
     623          20 :         torture_assert_ntstatus_ok(tctx, status, "ServerPasswordSet failed");
     624             : 
     625          20 :         if (NT_STATUS_IS_OK(result)) {
     626           0 :                 torture_fail(tctx, "unexpectedly received NT_STATUS_OK");
     627             :         }
     628             : 
     629          18 :         return ok;
     630             : }
     631             : 
     632             : 
     633             : /*
     634             :   a schannel test suite
     635             :  */
     636          23 : bool torture_rpc_schannel(struct torture_context *torture)
     637             : {
     638          23 :         bool ret = true;
     639             :         struct {
     640             :                 uint16_t acct_flags;
     641             :                 uint32_t dcerpc_flags;
     642          23 :         } tests[] = {
     643             :                 { ACB_WSTRUST,   DCERPC_SCHANNEL | DCERPC_SIGN | DCERPC_SCHANNEL_AUTO},
     644             :                 { ACB_WSTRUST,   DCERPC_SCHANNEL | DCERPC_SEAL | DCERPC_SCHANNEL_AUTO},
     645             :                 { ACB_WSTRUST,   DCERPC_SCHANNEL | DCERPC_SIGN | DCERPC_SCHANNEL_128},
     646             :                 { ACB_WSTRUST,   DCERPC_SCHANNEL | DCERPC_SEAL | DCERPC_SCHANNEL_128 },
     647             :                 { ACB_WSTRUST,   DCERPC_SCHANNEL | DCERPC_SIGN | DCERPC_SCHANNEL_AES},
     648             :                 { ACB_WSTRUST,   DCERPC_SCHANNEL | DCERPC_SEAL | DCERPC_SCHANNEL_AES },
     649             :                 { ACB_SVRTRUST,  DCERPC_SCHANNEL | DCERPC_SIGN | DCERPC_SCHANNEL_AUTO},
     650             :                 { ACB_SVRTRUST,  DCERPC_SCHANNEL | DCERPC_SEAL | DCERPC_SCHANNEL_AUTO},
     651             :                 { ACB_SVRTRUST,  DCERPC_SCHANNEL | DCERPC_SIGN | DCERPC_SCHANNEL_128 },
     652             :                 { ACB_SVRTRUST,  DCERPC_SCHANNEL | DCERPC_SEAL | DCERPC_SCHANNEL_128 },
     653             :                 { ACB_SVRTRUST,  DCERPC_SCHANNEL | DCERPC_SIGN | DCERPC_SCHANNEL_AES },
     654             :                 { ACB_SVRTRUST,  DCERPC_SCHANNEL | DCERPC_SEAL | DCERPC_SCHANNEL_AES }
     655             :         };
     656             :         int i;
     657             : 
     658         299 :         for (i=0;i<ARRAY_SIZE(tests);i++) {
     659         504 :                 torture_comment(torture, "Testing with acct_flags=0x%x dcerpc_flags=0x%x \n",
     660         276 :                        tests[i].acct_flags, tests[i].dcerpc_flags);
     661             : 
     662         456 :                 if (!test_schannel(torture,
     663         228 :                                    tests[i].acct_flags, tests[i].dcerpc_flags,
     664             :                                    i)) {
     665           0 :                         torture_comment(torture, "Failed with acct_flags=0x%x dcerpc_flags=0x%x \n",
     666           0 :                                tests[i].acct_flags, tests[i].dcerpc_flags);
     667           0 :                         ret = false;
     668             :                 }
     669             :         }
     670             : 
     671          23 :         return ret;
     672             : }
     673             : 
     674          10 : bool torture_rpc_schannel_anon_setpw(struct torture_context *torture)
     675             : {
     676          10 :         bool ret = true;
     677             :         bool ok;
     678          10 :         uint32_t dcerpc_flags = DCERPC_SCHANNEL | DCERPC_SIGN | DCERPC_SCHANNEL_AUTO;
     679             : 
     680          10 :         ok = test_schannel_anonymous_setPassword(torture,
     681             :                                                  dcerpc_flags,
     682             :                                                  true);
     683          10 :         if (!ok) {
     684           0 :                 torture_comment(torture,
     685             :                                 "Failed with dcerpc_flags=0x%x\n",
     686             :                                 dcerpc_flags);
     687           0 :                 ret = false;
     688             :         }
     689             : 
     690          10 :         ok = test_schannel_anonymous_setPassword(torture,
     691             :                                                  dcerpc_flags,
     692             :                                                  false);
     693          10 :         if (!ok) {
     694           0 :                 torture_comment(torture,
     695             :                                 "Failed with dcerpc_flags=0x%x\n",
     696             :                                 dcerpc_flags);
     697           0 :                 ret = false;
     698             :         }
     699             : 
     700          10 :         return ret;
     701             : }
     702             : 
     703             : /*
     704             :   test two schannel connections
     705             :  */
     706          23 : bool torture_rpc_schannel2(struct torture_context *torture)
     707             : {
     708             :         struct test_join *join_ctx;
     709             :         NTSTATUS status;
     710          23 :         const char *binding = torture_setting_string(torture, "binding", NULL);
     711             :         struct dcerpc_binding *b;
     712          23 :         struct dcerpc_pipe *p1 = NULL, *p2 = NULL;
     713             :         struct cli_credentials *credentials1, *credentials2;
     714          23 :         uint32_t dcerpc_flags = DCERPC_SCHANNEL | DCERPC_SCHANNEL_AUTO | DCERPC_SIGN;
     715             : 
     716          23 :         join_ctx = torture_join_domain(torture, talloc_asprintf(torture, "%s2", TEST_MACHINE_NAME),
     717             :                                        ACB_WSTRUST, &credentials1);
     718          23 :         torture_assert(torture, join_ctx != NULL,
     719             :                        "Failed to join domain with acct_flags=ACB_WSTRUST");
     720             : 
     721          23 :         credentials2 = cli_credentials_shallow_copy(torture, credentials1);
     722          23 :         cli_credentials_set_netlogon_creds(credentials1, NULL);
     723          23 :         cli_credentials_set_netlogon_creds(credentials2, NULL);
     724             : 
     725          23 :         status = dcerpc_parse_binding(torture, binding, &b);
     726          23 :         torture_assert_ntstatus_ok(torture, status, "Bad binding string");
     727             : 
     728          23 :         status = dcerpc_binding_set_flags(b, dcerpc_flags, DCERPC_AUTH_OPTIONS);
     729          23 :         torture_assert_ntstatus_ok(torture, status, "set flags");
     730             : 
     731          23 :         torture_comment(torture, "Opening first connection\n");
     732          23 :         status = dcerpc_pipe_connect_b(torture, &p1, b, &ndr_table_netlogon,
     733             :                                        credentials1, torture->ev, torture->lp_ctx);
     734          23 :         torture_assert_ntstatus_ok(torture, status, "Failed to connect with schannel");
     735             : 
     736          23 :         torture_comment(torture, "Opening second connection\n");
     737          23 :         status = dcerpc_pipe_connect_b(torture, &p2, b, &ndr_table_netlogon,
     738             :                                        credentials2, torture->ev, torture->lp_ctx);
     739          23 :         torture_assert_ntstatus_ok(torture, status, "Failed to connect with schannel");
     740             : 
     741          23 :         cli_credentials_set_netlogon_creds(credentials1, NULL);
     742          23 :         cli_credentials_set_netlogon_creds(credentials2, NULL);
     743             : 
     744          23 :         torture_comment(torture, "Testing logon on pipe1\n");
     745          23 :         if (!test_netlogon_ex_ops(p1, torture, credentials1, NULL))
     746           0 :                 return false;
     747             : 
     748          23 :         torture_comment(torture, "Testing logon on pipe2\n");
     749          23 :         if (!test_netlogon_ex_ops(p2, torture, credentials2, NULL))
     750           0 :                 return false;
     751             : 
     752          23 :         torture_comment(torture, "Again on pipe1\n");
     753          23 :         if (!test_netlogon_ex_ops(p1, torture, credentials1, NULL))
     754           0 :                 return false;
     755             : 
     756          23 :         torture_comment(torture, "Again on pipe2\n");
     757          23 :         if (!test_netlogon_ex_ops(p2, torture, credentials2, NULL))
     758           0 :                 return false;
     759             : 
     760          23 :         torture_leave_domain(torture, join_ctx);
     761          23 :         return true;
     762             : }
     763             : 
     764             : struct torture_schannel_bench;
     765             : 
     766             : struct torture_schannel_bench_conn {
     767             :         struct torture_schannel_bench *s;
     768             :         int index;
     769             :         struct cli_credentials *wks_creds;
     770             :         struct dcerpc_pipe *pipe;
     771             :         struct netr_LogonSamLogonEx r;
     772             :         struct netr_NetworkInfo ninfo;
     773             :         TALLOC_CTX *tmp;
     774             :         uint64_t total;
     775             :         uint32_t count;
     776             : };
     777             : 
     778             : struct torture_schannel_bench {
     779             :         struct torture_context *tctx;
     780             :         bool progress;
     781             :         int timelimit;
     782             :         int nprocs;
     783             :         int nconns;
     784             :         struct torture_schannel_bench_conn *conns;
     785             :         struct test_join *join_ctx1;
     786             :         struct cli_credentials *wks_creds1;
     787             :         struct test_join *join_ctx2;
     788             :         struct cli_credentials *wks_creds2;
     789             :         struct cli_credentials *user1_creds;
     790             :         struct cli_credentials *user2_creds;
     791             :         struct dcerpc_binding *b;
     792             :         NTSTATUS error;
     793             :         uint64_t total;
     794             :         uint32_t count;
     795             :         bool stopped;
     796             : };
     797             : 
     798             : #if 0
     799             : static void torture_schannel_bench_connected(struct composite_context *c)
     800             : {
     801             :         struct torture_schannel_bench_conn *conn =
     802             :                 (struct torture_schannel_bench_conn *)c->async.private_data;
     803             :         struct torture_schannel_bench *s = talloc_get_type(conn->s,
     804             :                                            struct torture_schannel_bench);
     805             : 
     806             :         s->error = dcerpc_pipe_connect_b_recv(c, s->conns, &conn->pipe);
     807             :         torture_comment(s->tctx, "conn[%u]: %s\n", conn->index, nt_errstr(s->error));
     808             :         if (NT_STATUS_IS_OK(s->error)) {
     809             :                 s->nconns++;
     810             :         }
     811             : }
     812             : #endif
     813             : 
     814             : static void torture_schannel_bench_recv(struct tevent_req *subreq);
     815             : 
     816           0 : static bool torture_schannel_bench_start(struct torture_schannel_bench_conn *conn)
     817             : {
     818           0 :         struct torture_schannel_bench *s = conn->s;
     819             :         NTSTATUS status;
     820             :         DATA_BLOB names_blob, chal, lm_resp, nt_resp;
     821           0 :         int flags = CLI_CRED_NTLM_AUTH;
     822             :         struct tevent_req *subreq;
     823             :         struct cli_credentials *user_creds;
     824             : 
     825           0 :         if (conn->total % 2) {
     826           0 :                 user_creds = s->user1_creds;
     827             :         } else {
     828           0 :                 user_creds = s->user2_creds;
     829             :         }
     830             : 
     831           0 :         if (lpcfg_client_lanman_auth(s->tctx->lp_ctx)) {
     832           0 :                 flags |= CLI_CRED_LANMAN_AUTH;
     833             :         }
     834             : 
     835           0 :         if (lpcfg_client_ntlmv2_auth(s->tctx->lp_ctx)) {
     836           0 :                 flags |= CLI_CRED_NTLMv2_AUTH;
     837             :         }
     838             : 
     839           0 :         talloc_free(conn->tmp);
     840           0 :         conn->tmp = talloc_new(s);
     841           0 :         ZERO_STRUCT(conn->ninfo);
     842           0 :         ZERO_STRUCT(conn->r);
     843             : 
     844           0 :         cli_credentials_get_ntlm_username_domain(user_creds, conn->tmp,
     845             :                                                  &conn->ninfo.identity_info.account_name.string,
     846             :                                                  &conn->ninfo.identity_info.domain_name.string);
     847             : 
     848           0 :         generate_random_buffer(conn->ninfo.challenge,
     849             :                                sizeof(conn->ninfo.challenge));
     850           0 :         chal = data_blob_const(conn->ninfo.challenge,
     851             :                                sizeof(conn->ninfo.challenge));
     852             : 
     853           0 :         names_blob = NTLMv2_generate_names_blob(conn->tmp,
     854             :                                                 cli_credentials_get_workstation(conn->wks_creds),
     855             :                                                 cli_credentials_get_domain(conn->wks_creds));
     856             : 
     857           0 :         status = cli_credentials_get_ntlm_response(user_creds, conn->tmp,
     858             :                                                    &flags,
     859             :                                                    chal,
     860             :                                                    NULL, /* server_timestamp */
     861             :                                                    names_blob,
     862             :                                                    &lm_resp, &nt_resp,
     863             :                                                    NULL, NULL);
     864           0 :         torture_assert_ntstatus_ok(s->tctx, status,
     865             :                                    "cli_credentials_get_ntlm_response failed");
     866             : 
     867           0 :         conn->ninfo.lm.data = lm_resp.data;
     868           0 :         conn->ninfo.lm.length = lm_resp.length;
     869             : 
     870           0 :         conn->ninfo.nt.data = nt_resp.data;
     871           0 :         conn->ninfo.nt.length = nt_resp.length;
     872             : 
     873           0 :         conn->ninfo.identity_info.parameter_control = 0;
     874           0 :         conn->ninfo.identity_info.logon_id = 0;
     875           0 :         conn->ninfo.identity_info.workstation.string = cli_credentials_get_workstation(conn->wks_creds);
     876             : 
     877           0 :         conn->r.in.server_name = talloc_asprintf(conn->tmp, "\\\\%s", dcerpc_server_name(conn->pipe));
     878           0 :         conn->r.in.computer_name = cli_credentials_get_workstation(conn->wks_creds);
     879           0 :         conn->r.in.logon_level = NetlogonNetworkInformation;
     880           0 :         conn->r.in.logon = talloc(conn->tmp, union netr_LogonLevel);
     881           0 :         conn->r.in.logon->network = &conn->ninfo;
     882           0 :         conn->r.in.flags = talloc(conn->tmp, uint32_t);
     883           0 :         conn->r.in.validation_level = 2;
     884           0 :         conn->r.out.validation = talloc(conn->tmp, union netr_Validation);
     885           0 :         conn->r.out.authoritative = talloc(conn->tmp, uint8_t);
     886           0 :         conn->r.out.flags = conn->r.in.flags;
     887             : 
     888           0 :         subreq = dcerpc_netr_LogonSamLogonEx_r_send(s, s->tctx->ev,
     889           0 :                                                     conn->pipe->binding_handle,
     890             :                                                     &conn->r);
     891           0 :         torture_assert(s->tctx, subreq, "Failed to setup LogonSamLogonEx request");
     892             : 
     893           0 :         tevent_req_set_callback(subreq, torture_schannel_bench_recv, conn);
     894             : 
     895           0 :         return true;
     896             : }
     897             : 
     898           0 : static void torture_schannel_bench_recv(struct tevent_req *subreq)
     899             : {
     900             :         bool ret;
     901           0 :         struct torture_schannel_bench_conn *conn =
     902           0 :                 (struct torture_schannel_bench_conn *)tevent_req_callback_data_void(subreq);
     903           0 :         struct torture_schannel_bench *s = talloc_get_type(conn->s,
     904             :                                            struct torture_schannel_bench);
     905             : 
     906           0 :         s->error = dcerpc_netr_LogonSamLogonEx_r_recv(subreq, subreq);
     907           0 :         TALLOC_FREE(subreq);
     908           0 :         if (!NT_STATUS_IS_OK(s->error)) {
     909           0 :                 return;
     910             :         }
     911             : 
     912           0 :         conn->total++;
     913           0 :         conn->count++;
     914             : 
     915           0 :         if (s->stopped) {
     916           0 :                 return;
     917             :         }
     918             : 
     919           0 :         ret = torture_schannel_bench_start(conn);
     920           0 :         if (!ret) {
     921           0 :                 s->error = NT_STATUS_INTERNAL_ERROR;
     922             :         }
     923             : }
     924             : 
     925             : /*
     926             :   test multiple schannel connection in parallel
     927             :  */
     928           0 : bool torture_rpc_schannel_bench1(struct torture_context *torture)
     929             : {
     930           0 :         bool ret = true;
     931             :         NTSTATUS status;
     932           0 :         const char *binding = torture_setting_string(torture, "binding", NULL);
     933             :         struct torture_schannel_bench *s;
     934             :         struct timeval start;
     935             :         struct timeval end;
     936             :         int i;
     937             :         const char *tmp;
     938             : 
     939           0 :         s = talloc_zero(torture, struct torture_schannel_bench);
     940           0 :         s->tctx = torture;
     941           0 :         s->progress = torture_setting_bool(torture, "progress", true);
     942           0 :         s->timelimit = torture_setting_int(torture, "timelimit", 10);
     943           0 :         s->nprocs = torture_setting_int(torture, "nprocs", 4);
     944           0 :         s->conns = talloc_zero_array(s, struct torture_schannel_bench_conn, s->nprocs);
     945             : 
     946           0 :         s->user1_creds = cli_credentials_shallow_copy(s,
     947             :                                 samba_cmdline_get_creds());
     948           0 :         tmp = torture_setting_string(s->tctx, "extra_user1", NULL);
     949           0 :         if (tmp) {
     950           0 :                 cli_credentials_parse_string(s->user1_creds, tmp, CRED_SPECIFIED);
     951             :         }
     952           0 :         s->user2_creds = cli_credentials_shallow_copy(s,
     953             :                                 samba_cmdline_get_creds());
     954           0 :         tmp = torture_setting_string(s->tctx, "extra_user2", NULL);
     955           0 :         if (tmp) {
     956           0 :                 cli_credentials_parse_string(s->user1_creds, tmp, CRED_SPECIFIED);
     957             :         }
     958             : 
     959           0 :         s->join_ctx1 = torture_join_domain(s->tctx, talloc_asprintf(s, "%sb", TEST_MACHINE_NAME),
     960             :                                            ACB_WSTRUST, &s->wks_creds1);
     961           0 :         torture_assert(torture, s->join_ctx1 != NULL,
     962             :                        "Failed to join domain with acct_flags=ACB_WSTRUST");
     963           0 :         s->join_ctx2 = torture_join_domain(s->tctx, talloc_asprintf(s, "%sc", TEST_MACHINE_NAME),
     964             :                                            ACB_WSTRUST, &s->wks_creds2);
     965           0 :         torture_assert(torture, s->join_ctx2 != NULL,
     966             :                        "Failed to join domain with acct_flags=ACB_WSTRUST");
     967             : 
     968           0 :         cli_credentials_set_kerberos_state(s->wks_creds1,
     969             :                                            CRED_USE_KERBEROS_DISABLED,
     970             :                                            CRED_SPECIFIED);
     971           0 :         cli_credentials_set_kerberos_state(s->wks_creds2,
     972             :                                            CRED_USE_KERBEROS_DISABLED,
     973             :                                            CRED_SPECIFIED);
     974             : 
     975           0 :         for (i=0; i < s->nprocs; i++) {
     976           0 :                 struct cli_credentials *wks = s->wks_creds1;
     977             : 
     978           0 :                 if ((i % 2) && (torture_setting_bool(torture, "multijoin", false))) {
     979           0 :                         wks = s->wks_creds2;
     980             :                 }
     981             : 
     982           0 :                 s->conns[i].s = s;
     983           0 :                 s->conns[i].index = i;
     984           0 :                 s->conns[i].wks_creds = cli_credentials_shallow_copy(s->conns, wks);
     985           0 :                 cli_credentials_set_netlogon_creds(s->conns[i].wks_creds, NULL);
     986             :         }
     987             : 
     988           0 :         status = dcerpc_parse_binding(s, binding, &s->b);
     989           0 :         torture_assert_ntstatus_ok(torture, status, "Bad binding string");
     990             : 
     991           0 :         status = dcerpc_binding_set_flags(s->b, DCERPC_SCHANNEL | DCERPC_SIGN,
     992             :                                           DCERPC_AUTH_OPTIONS);
     993           0 :         torture_assert_ntstatus_ok(torture, status, "set flags");
     994             : 
     995           0 :         torture_comment(torture, "Opening %d connections in parallel\n", s->nprocs);
     996           0 :         for (i=0; i < s->nprocs; i++) {
     997             : #if 1
     998           0 :                 s->error = dcerpc_pipe_connect_b(s->conns, &s->conns[i].pipe, s->b,
     999             :                                                  &ndr_table_netlogon,
    1000           0 :                                                  s->conns[i].wks_creds,
    1001             :                                                  torture->ev, torture->lp_ctx);
    1002           0 :                 torture_assert_ntstatus_ok(torture, s->error, "Failed to connect with schannel");
    1003             : #else
    1004             :                 /*
    1005             :                  * This path doesn't work against windows,
    1006             :                  * because of windows drops the connections
    1007             :                  * which haven't reached a session setup yet
    1008             :                  *
    1009             :                  * The same as the reset on zero vc stuff.
    1010             :                  */
    1011             :                 struct composite_context *c;
    1012             :                 c = dcerpc_pipe_connect_b_send(s->conns, s->b,
    1013             :                                                &ndr_table_netlogon,
    1014             :                                                s->conns[i].wks_creds,
    1015             :                                                torture->ev,
    1016             :                                                torture->lp_ctx);
    1017             :                 torture_assert(torture, c != NULL, "Failed to setup connect");
    1018             :                 c->async.fn = torture_schannel_bench_connected;
    1019             :                 c->async.private_data = &s->conns[i];
    1020             :         }
    1021             : 
    1022             :         while (NT_STATUS_IS_OK(s->error) && s->nprocs != s->nconns) {
    1023             :                 int ev_ret = tevent_loop_once(torture->ev);
    1024             :                 torture_assert(torture, ev_ret == 0, "tevent_loop_once failed");
    1025             : #endif
    1026             :         }
    1027           0 :         torture_assert_ntstatus_ok(torture, s->error, "Failed establish a connect");
    1028             : 
    1029             :         /*
    1030             :          * Change the workstation password after establishing the netlogon
    1031             :          * schannel connections to prove that existing connections are not
    1032             :          * affected by a wks pwchange.
    1033             :          */
    1034             : 
    1035             :         {
    1036             :                 struct netr_ServerPasswordSet pwset;
    1037           0 :                 char *password = generate_random_password(s->join_ctx1, 8, 255);
    1038             :                 struct netlogon_creds_CredentialState *creds_state;
    1039             :                 struct dcerpc_pipe *net_pipe;
    1040             :                 struct netr_Authenticator credential, return_authenticator;
    1041             :                 struct samr_Password new_password;
    1042             : 
    1043           0 :                 status = dcerpc_pipe_connect_b(s, &net_pipe, s->b,
    1044             :                                                &ndr_table_netlogon,
    1045             :                                                s->wks_creds1,
    1046             :                                                torture->ev, torture->lp_ctx);
    1047             : 
    1048           0 :                 torture_assert_ntstatus_ok(torture, status,
    1049             :                                            "dcerpc_pipe_connect_b failed");
    1050             : 
    1051           0 :                 pwset.in.server_name = talloc_asprintf(
    1052             :                         net_pipe, "\\\\%s", dcerpc_server_name(net_pipe));
    1053           0 :                 pwset.in.computer_name =
    1054           0 :                         cli_credentials_get_workstation(s->wks_creds1);
    1055           0 :                 pwset.in.account_name = talloc_asprintf(
    1056             :                         net_pipe, "%s$", pwset.in.computer_name);
    1057           0 :                 pwset.in.secure_channel_type = SEC_CHAN_WKSTA;
    1058           0 :                 pwset.in.credential = &credential;
    1059           0 :                 pwset.in.new_password = &new_password;
    1060           0 :                 pwset.out.return_authenticator = &return_authenticator;
    1061             : 
    1062           0 :                 E_md4hash(password, new_password.hash);
    1063             : 
    1064           0 :                 creds_state = cli_credentials_get_netlogon_creds(
    1065             :                         s->wks_creds1);
    1066           0 :                 netlogon_creds_des_encrypt(creds_state, &new_password);
    1067           0 :                 netlogon_creds_client_authenticator(creds_state, &credential);
    1068             : 
    1069           0 :                 torture_assert_ntstatus_ok(torture, dcerpc_netr_ServerPasswordSet_r(net_pipe->binding_handle, torture, &pwset),
    1070             :                         "ServerPasswordSet failed");
    1071           0 :                 torture_assert_ntstatus_ok(torture, pwset.out.result,
    1072             :                                            "ServerPasswordSet failed");
    1073             : 
    1074           0 :                 if (!netlogon_creds_client_check(creds_state,
    1075           0 :                                         &pwset.out.return_authenticator->cred)) {
    1076           0 :                         torture_comment(torture, "Credential chaining failed\n");
    1077             :                 }
    1078             : 
    1079           0 :                 cli_credentials_set_password(s->wks_creds1, password,
    1080             :                                              CRED_SPECIFIED);
    1081             : 
    1082           0 :                 talloc_free(net_pipe);
    1083             : 
    1084             :                 /* Just as a test, connect with the new creds */
    1085             : 
    1086           0 :                 cli_credentials_set_netlogon_creds(s->wks_creds1, NULL);
    1087             : 
    1088           0 :                 status = dcerpc_pipe_connect_b(s, &net_pipe, s->b,
    1089             :                                                &ndr_table_netlogon,
    1090             :                                                s->wks_creds1,
    1091             :                                                torture->ev, torture->lp_ctx);
    1092             : 
    1093           0 :                 torture_assert_ntstatus_ok(torture, status,
    1094             :                                            "dcerpc_pipe_connect_b failed");
    1095             : 
    1096           0 :                 talloc_free(net_pipe);
    1097             :         }
    1098             : 
    1099           0 :         torture_comment(torture, "Start looping LogonSamLogonEx on %d connections for %d secs\n",
    1100             :                         s->nprocs, s->timelimit);
    1101           0 :         for (i=0; i < s->nprocs; i++) {
    1102           0 :                 ret = torture_schannel_bench_start(&s->conns[i]);
    1103           0 :                 torture_assert(torture, ret, "Failed to setup LogonSamLogonEx");
    1104             :         }
    1105             : 
    1106           0 :         start = timeval_current();
    1107           0 :         end = timeval_add(&start, s->timelimit, 0);
    1108             : 
    1109           0 :         while (NT_STATUS_IS_OK(s->error) && !timeval_expired(&end)) {
    1110           0 :                 int ev_ret = tevent_loop_once(torture->ev);
    1111           0 :                 torture_assert(torture, ev_ret == 0, "tevent_loop_once failed");
    1112             :         }
    1113           0 :         torture_assert_ntstatus_ok(torture, s->error, "Failed some request");
    1114           0 :         s->stopped = true;
    1115           0 :         talloc_free(s->conns);
    1116             : 
    1117           0 :         for (i=0; i < s->nprocs; i++) {
    1118           0 :                 s->total += s->conns[i].total;
    1119             :         }
    1120             : 
    1121           0 :         torture_comment(torture,
    1122             :                         "Total ops[%llu] (%u ops/s)\n",
    1123           0 :                         (unsigned long long)s->total,
    1124           0 :                         (unsigned)s->total/s->timelimit);
    1125             : 
    1126           0 :         torture_leave_domain(torture, s->join_ctx1);
    1127           0 :         torture_leave_domain(torture, s->join_ctx2);
    1128           0 :         return true;
    1129             : }

Generated by: LCOV version 1.13