LCOV - code coverage report
Current view: top level - source4/torture/rpc - schannel.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 432 624 69.2 %
Date: 2024-04-21 15:09:00 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         160 :         NTSTATUS status;
      49         160 :         struct netr_LogonSamLogonEx r;
      50         160 :         struct netr_NetworkInfo ninfo;
      51         160 :         union netr_LogonLevel logon;
      52         160 :         union netr_Validation validation;
      53         920 :         uint8_t authoritative = 1;
      54         920 :         uint32_t _flags = 0;
      55         160 :         DATA_BLOB names_blob, chal, lm_resp, nt_resp;
      56         160 :         int i;
      57         920 :         int flags = CLI_CRED_NTLM_AUTH;
      58         920 :         struct dcerpc_binding_handle *b = p->binding_handle;
      59             : 
      60         160 :         struct netr_UserSessionKey key;
      61         160 :         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,("decrypted 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 can't 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         632 :                 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         276 : static bool test_netlogon_ex_bug14932(struct dcerpc_pipe *p,
     245             :                                       struct torture_context *tctx,
     246             :                                       struct cli_credentials *credentials,
     247             :                                       struct netlogon_creds_CredentialState *creds)
     248             : {
     249          48 :         NTSTATUS status;
     250          48 :         struct netr_LogonSamLogonEx r;
     251          48 :         struct netr_NetworkInfo ninfo;
     252          48 :         union netr_LogonLevel logon;
     253          48 :         union netr_Validation validation;
     254         276 :         uint8_t authoritative = 1;
     255         276 :         uint32_t _flags = 0;
     256          48 :         static const char *netapp_magic =
     257             :                 "\x01\x01\x00\x00\x00\x00\x00\x00"
     258             :                 "\x3f\x3f\x3f\x3f\x3f\x3f\x3f\x3f"
     259             :                 "\xb8\x82\x3a\xf1\xb3\xdd\x08\x15"
     260             :                 "\x00\x00\x00\x00\x11\xa2\x08\x81"
     261             :                 "\x50\x38\x22\x78\x2b\x94\x47\xfe"
     262             :                 "\x54\x94\x7b\xff\x17\x27\x5a\xb4"
     263             :                 "\xf4\x18\xba\xdc\x2c\x38\xfd\x5b"
     264             :                 "\xfb\x0e\xc1\x85\x1e\xcc\x92\xbb"
     265             :                 "\x9b\xb1\xc4\xd5\x53\x14\xff\x8c"
     266             :                 "\x76\x49\xf5\x45\x90\x19\xa2";
     267         276 :         NTTIME timestamp = BVAL(netapp_magic, 8);
     268         276 :         DATA_BLOB names_blob = data_blob_string_const(netapp_magic + 28);
     269          48 :         DATA_BLOB chal, lm_resp, nt_resp;
     270          48 :         int i;
     271         276 :         int flags = CLI_CRED_NTLM_AUTH;
     272         276 :         struct dcerpc_binding_handle *b = p->binding_handle;
     273          48 :         struct netr_UserSessionKey key;
     274          48 :         struct netr_LMSessionKey LMSessKey;
     275         276 :         uint32_t validation_levels[] = { 2, 3 };
     276         276 :         struct netr_SamBaseInfo *base = NULL;
     277         276 :         const char *crypto_alg = "";
     278         276 :         bool can_do_validation_6 = true;
     279         276 :         enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
     280             : 
     281         276 :         flags |= CLI_CRED_NTLMv2_AUTH;
     282             : 
     283         276 :         cli_credentials_get_ntlm_username_domain(samba_cmdline_get_creds(),
     284             :                                 tctx,
     285             :                                 &ninfo.identity_info.account_name.string,
     286             :                                 &ninfo.identity_info.domain_name.string);
     287             : 
     288         276 :         generate_random_buffer(ninfo.challenge,
     289             :                                sizeof(ninfo.challenge));
     290             : 
     291         276 :         chal = data_blob_const(ninfo.challenge,
     292             :                                sizeof(ninfo.challenge));
     293             : 
     294         276 :         status = cli_credentials_get_ntlm_response(
     295             :                         samba_cmdline_get_creds(),
     296             :                         tctx,
     297             :                         &flags,
     298             :                         chal,
     299             :                         &timestamp,
     300             :                         names_blob,
     301             :                         &lm_resp, &nt_resp,
     302             :                         NULL, NULL);
     303         276 :         torture_assert_ntstatus_ok(tctx, status,
     304             :                                    "cli_credentials_get_ntlm_response failed");
     305             : 
     306         276 :         ninfo.lm.data = lm_resp.data;
     307         276 :         ninfo.lm.length = lm_resp.length;
     308             : 
     309         276 :         ninfo.nt.data = nt_resp.data;
     310         276 :         ninfo.nt.length = nt_resp.length;
     311             : 
     312         276 :         ninfo.identity_info.parameter_control = 0;
     313         276 :         ninfo.identity_info.logon_id = 0;
     314         276 :         ninfo.identity_info.workstation.string = cli_credentials_get_workstation(credentials);
     315             : 
     316         276 :         logon.network = &ninfo;
     317             : 
     318         276 :         r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
     319         276 :         r.in.computer_name = cli_credentials_get_workstation(credentials);
     320         276 :         r.in.logon_level = NetlogonNetworkInformation;
     321         276 :         r.in.logon= &logon;
     322         276 :         r.in.flags = &_flags;
     323         276 :         r.out.validation = &validation;
     324         276 :         r.out.authoritative = &authoritative;
     325         276 :         r.out.flags = &_flags;
     326             : 
     327             :         /*
     328             :         - retrieve level6
     329             :         - save usrsession and lmsession key
     330             :         - retrieve level 2
     331             :         - calculate, compare
     332             :         - retrieve level 3
     333             :         - calculate, compare
     334             :         */
     335             : 
     336         276 :         if (creds != NULL) {
     337         276 :                 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
     338         152 :                         crypto_alg = "AES";
     339          92 :                 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
     340          92 :                         crypto_alg = "ARCFOUR";
     341             :                 }
     342             :         }
     343             : 
     344         276 :         dcerpc_binding_handle_auth_info(b, NULL, &auth_level);
     345         276 :         if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
     346         138 :                 r.in.validation_level = 6;
     347             : 
     348         138 :                 torture_comment(tctx,
     349             :                                 "Testing LogonSamLogonEx with name %s using %s and validation_level: %d\n",
     350             :                                 ninfo.identity_info.account_name.string, crypto_alg,
     351         114 :                                 r.in.validation_level);
     352             : 
     353         138 :                 torture_assert_ntstatus_ok(tctx,
     354             :                         dcerpc_netr_LogonSamLogonEx_r(b, tctx, &r),
     355             :                         "LogonSamLogonEx failed");
     356             :         } else {
     357         138 :                 torture_comment(tctx,
     358             :                                 "Skip auth_level[%u] Testing LogonSamLogonEx with name %s using %s and validation_level: %d\n",
     359             :                                 auth_level, ninfo.identity_info.account_name.string, crypto_alg,
     360         138 :                                 r.in.validation_level);
     361         138 :                 r.out.result = NT_STATUS_INVALID_INFO_CLASS;
     362             :         }
     363             : 
     364         276 :         if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_INFO_CLASS)) {
     365         126 :                 can_do_validation_6 = false;
     366             :         } else {
     367         126 :                 torture_assert_ntstatus_ok(tctx, r.out.result,
     368             :                         "LogonSamLogonEx failed");
     369             : 
     370         126 :                 key = r.out.validation->sam6->base.key;
     371         126 :                 LMSessKey = r.out.validation->sam6->base.LMSessKey;
     372             : 
     373         126 :                 DEBUG(1,("unencrypted session keys from validation_level 6:\n"));
     374         126 :                 dump_data(1, r.out.validation->sam6->base.key.key, 16);
     375         126 :                 dump_data(1, r.out.validation->sam6->base.LMSessKey.key, 8);
     376             :         }
     377             : 
     378         828 :         for (i=0; i < ARRAY_SIZE(validation_levels); i++) {
     379             : 
     380         552 :                 r.in.validation_level = validation_levels[i];
     381             : 
     382         552 :                 torture_comment(tctx,
     383             :                         "Testing LogonSamLogonEx with name %s using %s and validation_level: %d\n",
     384             :                         ninfo.identity_info.account_name.string, crypto_alg,
     385         456 :                         r.in.validation_level);
     386             : 
     387         552 :                 torture_assert_ntstatus_ok(tctx,
     388             :                         dcerpc_netr_LogonSamLogonEx_r(b, tctx, &r),
     389             :                         "LogonSamLogonEx failed");
     390         552 :                 torture_assert_ntstatus_ok(tctx, r.out.result,
     391             :                         "LogonSamLogonEx failed");
     392             : 
     393         552 :                 if (creds == NULL) {
     394             :                         /* when this test is called without creds no point in
     395             :                          * testing the session keys */
     396           0 :                         continue;
     397             :                 }
     398             : 
     399         552 :                 switch (validation_levels[i]) {
     400         276 :                 case 2:
     401         276 :                         base = &r.out.validation->sam2->base;
     402         276 :                         break;
     403         276 :                 case 3:
     404         276 :                         base = &r.out.validation->sam3->base;
     405         276 :                         break;
     406           0 :                 default:
     407           0 :                         break;
     408             :                 }
     409             : 
     410         552 :                 DEBUG(1,("encrypted keys validation_level %d:\n",
     411             :                         validation_levels[i]));
     412         552 :                 dump_data(1, base->key.key, 16);
     413         552 :                 dump_data(1, base->LMSessKey.key, 8);
     414             : 
     415         552 :                 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
     416         368 :                         netlogon_creds_aes_decrypt(creds, base->key.key, 16);
     417         368 :                         netlogon_creds_aes_decrypt(creds, base->LMSessKey.key, 8);
     418         184 :                 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
     419         184 :                         netlogon_creds_arcfour_crypt(creds, base->key.key, 16);
     420         184 :                         netlogon_creds_arcfour_crypt(creds, base->LMSessKey.key, 8);
     421             :                 }
     422             : 
     423         552 :                 DEBUG(1,("decrypted keys validation_level %d\n",
     424             :                         validation_levels[i]));
     425             : 
     426         552 :                 dump_data(1, base->key.key, 16);
     427         552 :                 dump_data(1, base->LMSessKey.key, 8);
     428             : 
     429         552 :                 if (!can_do_validation_6) {
     430             :                         /* we can't compare against unencrypted keys */
     431         300 :                         continue;
     432             :                 }
     433             : 
     434         252 :                 torture_assert_mem_equal(tctx,
     435             :                                          base->key.key,
     436             :                                          key.key,
     437             :                                          16,
     438             :                                          "unexpected user session key\n");
     439         300 :                 torture_assert_mem_equal(tctx,
     440             :                                          base->LMSessKey.key,
     441             :                                          LMSessKey.key,
     442             :                                          8,
     443             :                                          "unexpected LM session key\n");
     444             :         }
     445             : 
     446         228 :         return true;
     447             : }
     448             : 
     449             : /*
     450             :   do some samr ops using the schannel connection
     451             :  */
     452         552 : static bool test_samr_ops(struct torture_context *tctx,
     453             :                           struct dcerpc_binding_handle *b)
     454             : {
     455          96 :         struct samr_GetDomPwInfo r;
     456          96 :         struct samr_PwInfo info;
     457          96 :         struct samr_Connect connect_r;
     458          96 :         struct samr_OpenDomain opendom;
     459          96 :         int i;
     460          96 :         struct lsa_String name;
     461          96 :         struct policy_handle handle;
     462          96 :         struct policy_handle domain_handle;
     463             : 
     464         552 :         name.string = lpcfg_workgroup(tctx->lp_ctx);
     465         552 :         r.in.domain_name = &name;
     466         552 :         r.out.info = &info;
     467             : 
     468         552 :         connect_r.in.system_name = 0;
     469         552 :         connect_r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
     470         552 :         connect_r.out.connect_handle = &handle;
     471             : 
     472         552 :         torture_comment(tctx, "Testing Connect and OpenDomain on BUILTIN\n");
     473             : 
     474         552 :         torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect_r(b, tctx, &connect_r),
     475             :                 "Connect failed");
     476         552 :         if (!NT_STATUS_IS_OK(connect_r.out.result)) {
     477           0 :                 if (NT_STATUS_EQUAL(connect_r.out.result, NT_STATUS_ACCESS_DENIED)) {
     478           0 :                         torture_comment(tctx, "Connect failed (expected, schannel mapped to anonymous): %s\n",
     479             :                                nt_errstr(connect_r.out.result));
     480             :                 } else {
     481           0 :                         torture_comment(tctx, "Connect failed - %s\n", nt_errstr(connect_r.out.result));
     482           0 :                         return false;
     483             :                 }
     484             :         } else {
     485         552 :                 opendom.in.connect_handle = &handle;
     486         552 :                 opendom.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
     487         552 :                 opendom.in.sid = dom_sid_parse_talloc(tctx, "S-1-5-32");
     488         552 :                 opendom.out.domain_handle = &domain_handle;
     489             : 
     490         552 :                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenDomain_r(b, tctx, &opendom),
     491             :                         "OpenDomain failed");
     492         552 :                 if (!NT_STATUS_IS_OK(opendom.out.result)) {
     493           0 :                         torture_comment(tctx, "OpenDomain failed - %s\n", nt_errstr(opendom.out.result));
     494           0 :                         return false;
     495             :                 }
     496             :         }
     497             : 
     498         552 :         torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
     499             : 
     500             :         /* do several ops to test credential chaining */
     501        3408 :         for (i=0;i<5;i++) {
     502        2760 :                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r),
     503             :                         "GetDomPwInfo failed");
     504        2760 :                 if (!NT_STATUS_IS_OK(r.out.result)) {
     505           0 :                         if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED)) {
     506           0 :                                 torture_comment(tctx, "GetDomPwInfo op %d failed - %s\n", i, nt_errstr(r.out.result));
     507           0 :                                 return false;
     508             :                         }
     509             :                 }
     510             :         }
     511             : 
     512         456 :         return true;
     513             : }
     514             : 
     515             : 
     516             : /*
     517             :   do some lsa ops using the schannel connection
     518             :  */
     519         276 : static bool test_lsa_ops(struct torture_context *tctx, struct dcerpc_pipe *p)
     520             : {
     521          48 :         struct lsa_GetUserName r;
     522         276 :         bool ret = true;
     523         276 :         struct lsa_String *account_name_p = NULL;
     524         276 :         struct lsa_String *authority_name_p = NULL;
     525         276 :         struct dcerpc_binding_handle *b = p->binding_handle;
     526             : 
     527         276 :         torture_comment(tctx, "\nTesting GetUserName\n");
     528             : 
     529         276 :         r.in.system_name = "\\";
     530         276 :         r.in.account_name = &account_name_p;
     531         276 :         r.in.authority_name = &authority_name_p;
     532         276 :         r.out.account_name = &account_name_p;
     533             : 
     534             :         /* do several ops to test credential chaining and various operations */
     535         276 :         torture_assert_ntstatus_ok(tctx, dcerpc_lsa_GetUserName_r(b, tctx, &r),
     536             :                 "lsa_GetUserName failed");
     537             : 
     538         276 :         authority_name_p = *r.out.authority_name;
     539             : 
     540         276 :         if (!NT_STATUS_IS_OK(r.out.result)) {
     541           0 :                 torture_comment(tctx, "GetUserName failed - %s\n", nt_errstr(r.out.result));
     542           0 :                 return false;
     543             :         } else {
     544         276 :                 if (!r.out.account_name) {
     545           0 :                         return false;
     546             :                 }
     547             : 
     548         276 :                 if (strcmp(account_name_p->string, "ANONYMOUS LOGON") != 0) {
     549          24 :                         torture_comment(tctx, "GetUserName returned wrong user: %s, expected %s\n",
     550          24 :                                account_name_p->string, "ANONYMOUS LOGON");
     551             :                         /* FIXME: gd */
     552          24 :                         if (!torture_setting_bool(tctx, "samba3", false)) {
     553           0 :                                 return false;
     554             :                         }
     555             :                 }
     556         276 :                 if (!authority_name_p || !authority_name_p->string) {
     557           0 :                         return false;
     558             :                 }
     559             : 
     560         276 :                 if (strcmp(authority_name_p->string, "NT AUTHORITY") != 0) {
     561          24 :                         torture_comment(tctx, "GetUserName returned wrong user: %s, expected %s\n",
     562          24 :                                authority_name_p->string, "NT AUTHORITY");
     563             :                         /* FIXME: gd */
     564          24 :                         if (!torture_setting_bool(tctx, "samba3", false)) {
     565           0 :                                 return false;
     566             :                         }
     567             :                 }
     568             :         }
     569             : 
     570         228 :         return ret;
     571             : }
     572             : 
     573             : 
     574             : /*
     575             :   test a schannel connection with the given flags
     576             :  */
     577         276 : static bool test_schannel(struct torture_context *tctx,
     578             :                           uint16_t acct_flags, uint32_t dcerpc_flags,
     579             :                           int i)
     580             : {
     581          48 :         struct test_join *join_ctx;
     582          48 :         NTSTATUS status;
     583         276 :         const char *binding = torture_setting_string(tctx, "binding", NULL);
     584          48 :         struct dcerpc_binding *b;
     585         276 :         struct dcerpc_pipe *p = NULL;
     586         276 :         struct dcerpc_pipe *p_netlogon = NULL;
     587         276 :         struct dcerpc_pipe *p_netlogon2 = NULL;
     588         276 :         struct dcerpc_pipe *p_netlogon3 = NULL;
     589         276 :         struct dcerpc_pipe *p_samr2 = NULL;
     590         276 :         struct dcerpc_pipe *p_lsa = NULL;
     591          48 :         struct netlogon_creds_CredentialState *creds;
     592          48 :         struct cli_credentials *credentials;
     593          48 :         enum dcerpc_transport_t transport;
     594             : 
     595         276 :         join_ctx = torture_join_domain(tctx,
     596         276 :                                        talloc_asprintf(tctx, "%s%d", TEST_MACHINE_NAME, i),
     597             :                                        acct_flags, &credentials);
     598         276 :         torture_assert(tctx, join_ctx != NULL, "Failed to join domain");
     599             : 
     600         276 :         status = dcerpc_parse_binding(tctx, binding, &b);
     601         276 :         torture_assert_ntstatus_ok(tctx, status, "Bad binding string");
     602             : 
     603         276 :         status = dcerpc_binding_set_flags(b, dcerpc_flags, DCERPC_AUTH_OPTIONS);
     604         276 :         torture_assert_ntstatus_ok(tctx, status, "set flags");
     605             : 
     606         276 :         status = dcerpc_pipe_connect_b(tctx, &p, b, &ndr_table_samr,
     607             :                                        credentials, tctx->ev, tctx->lp_ctx);
     608         276 :         torture_assert_ntstatus_ok(tctx, status,
     609             :                 "Failed to connect to samr with schannel");
     610             : 
     611         276 :         torture_assert(tctx, test_samr_ops(tctx, p->binding_handle),
     612             :                        "Failed to process schannel secured SAMR ops");
     613             : 
     614             :         /* Also test that when we connect to the netlogon pipe, that
     615             :          * the credentials we setup on the first pipe are valid for
     616             :          * the second */
     617             : 
     618             :         /* Swap the binding details from SAMR to NETLOGON */
     619         276 :         status = dcerpc_epm_map_binding(tctx, b, &ndr_table_netlogon, tctx->ev, tctx->lp_ctx);
     620         276 :         torture_assert_ntstatus_ok(tctx, status, "epm map");
     621             : 
     622         276 :         status = dcerpc_binding_set_flags(b, dcerpc_flags, DCERPC_AUTH_OPTIONS);
     623         276 :         torture_assert_ntstatus_ok(tctx, status, "set flags");
     624             : 
     625         276 :         status = dcerpc_secondary_auth_connection(p, b, &ndr_table_netlogon,
     626             :                                                   credentials, tctx->lp_ctx,
     627             :                                                   tctx, &p_netlogon);
     628         276 :         torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
     629             : 
     630         276 :         creds = cli_credentials_get_netlogon_creds(credentials);
     631         276 :         torture_assert(tctx, (creds != NULL), "schannel creds");
     632             : 
     633             :         /* checks the capabilities */
     634         276 :         torture_assert(tctx, test_netlogon_capabilities(p_netlogon, tctx, credentials, creds),
     635             :                        "Failed to process schannel secured capability ops (on fresh connection)");
     636             : 
     637             :         /* do a couple of logins */
     638         276 :         torture_assert(tctx, test_netlogon_ops(p_netlogon, tctx, credentials, creds),
     639             :                 "Failed to process schannel secured NETLOGON ops");
     640             : 
     641         276 :         torture_assert(tctx, test_netlogon_ex_ops(p_netlogon, tctx, credentials, creds),
     642             :                 "Failed to process schannel secured NETLOGON EX ops");
     643             : 
     644             :         /* regression test for https://bugzilla.samba.org/show_bug.cgi?id=14932 */
     645         276 :         torture_assert(tctx, test_netlogon_ex_bug14932(p_netlogon, tctx, credentials, creds),
     646             :                        "Failed to process schannel secured NETLOGON EX for BUG 14932");
     647             : 
     648             :         /* we *MUST* use ncacn_np for openpolicy etc. */
     649         276 :         transport = dcerpc_binding_get_transport(b);
     650         276 :         status = dcerpc_binding_set_transport(b, NCACN_NP);
     651         276 :         torture_assert_ntstatus_ok(tctx, status, "set transport");
     652             : 
     653             :         /* Swap the binding details from SAMR to LSARPC */
     654         276 :         status = dcerpc_epm_map_binding(tctx, b, &ndr_table_lsarpc, tctx->ev, tctx->lp_ctx);
     655         276 :         torture_assert_ntstatus_ok(tctx, status, "epm map");
     656             : 
     657         276 :         torture_assert_ntstatus_ok(tctx,
     658             :                 dcerpc_pipe_connect_b(tctx, &p_lsa, b, &ndr_table_lsarpc,
     659             :                                       credentials, tctx->ev, tctx->lp_ctx),
     660             :                 "failed to connect lsarpc with schannel");
     661             : 
     662         276 :         torture_assert(tctx, test_lsa_ops(tctx, p_lsa),
     663             :                 "Failed to process schannel secured LSA ops");
     664             : 
     665         276 :         talloc_free(p_lsa);
     666         276 :         p_lsa = NULL;
     667             : 
     668             :         /* we *MUST* use ncacn_ip_tcp for lookupsids3/lookupnames4 */
     669         276 :         status = dcerpc_binding_set_transport(b, NCACN_IP_TCP);
     670         276 :         torture_assert_ntstatus_ok(tctx, status, "set transport");
     671             : 
     672         276 :         torture_assert_ntstatus_ok(tctx,
     673             :                 dcerpc_epm_map_binding(tctx, b, &ndr_table_lsarpc, tctx->ev, tctx->lp_ctx),
     674             :                 "failed to call epm map");
     675             : 
     676         276 :         torture_assert_ntstatus_ok(tctx,
     677             :                 dcerpc_pipe_connect_b(tctx, &p_lsa, b, &ndr_table_lsarpc,
     678             :                                       credentials, tctx->ev, tctx->lp_ctx),
     679             :                 "failed to connect lsarpc with schannel");
     680             : 
     681         276 :         torture_assert(tctx,
     682             :                 test_many_LookupSids(p_lsa, tctx, NULL, LSA_LOOKUP_NAMES_ALL),
     683             :                 "LsaLookupSids3 failed!\n");
     684             : 
     685         276 :         status = dcerpc_binding_set_transport(b, transport);
     686         276 :         torture_assert_ntstatus_ok(tctx, status, "set transport");
     687             : 
     688             : 
     689             :         /* Drop the socket, we want to start from scratch */
     690         276 :         talloc_free(p);
     691         276 :         p = NULL;
     692             : 
     693             :         /* Now see what we are still allowed to do */
     694             : 
     695         276 :         status = dcerpc_parse_binding(tctx, binding, &b);
     696         276 :         torture_assert_ntstatus_ok(tctx, status, "Bad binding string");
     697             : 
     698         276 :         status = dcerpc_binding_set_flags(b, dcerpc_flags, DCERPC_AUTH_OPTIONS);
     699         276 :         torture_assert_ntstatus_ok(tctx, status, "set flags");
     700             : 
     701         276 :         status = dcerpc_pipe_connect_b(tctx, &p_samr2, b, &ndr_table_samr,
     702             :                                        credentials, tctx->ev, tctx->lp_ctx);
     703         276 :         torture_assert_ntstatus_ok(tctx, status,
     704             :                 "Failed to connect with schannel");
     705             : 
     706             :         /* do a some SAMR operations.  We have *not* done a new serverauthenticate */
     707         276 :         torture_assert (tctx, test_samr_ops(tctx, p_samr2->binding_handle),
     708             :                         "Failed to process schannel secured SAMR ops (on fresh connection)");
     709             : 
     710             :         /* Swap the binding details from SAMR to NETLOGON */
     711         276 :         status = dcerpc_epm_map_binding(tctx, b, &ndr_table_netlogon, tctx->ev, tctx->lp_ctx);
     712         276 :         torture_assert_ntstatus_ok(tctx, status, "epm");
     713             : 
     714         276 :         status = dcerpc_binding_set_flags(b, dcerpc_flags, DCERPC_AUTH_OPTIONS);
     715         276 :         torture_assert_ntstatus_ok(tctx, status, "set flags");
     716             : 
     717         276 :         status = dcerpc_secondary_auth_connection(p_samr2, b, &ndr_table_netlogon,
     718             :                                                   credentials, tctx->lp_ctx,
     719             :                                                   tctx, &p_netlogon2);
     720         276 :         torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
     721             : 
     722             :         /* checks the capabilities */
     723         276 :         torture_assert(tctx, test_netlogon_capabilities(p_netlogon2, tctx, credentials, creds),
     724             :                        "Failed to process schannel secured capability ops (on fresh connection)");
     725             : 
     726             :         /* Try the schannel-only SamLogonEx operation */
     727         276 :         torture_assert(tctx, test_netlogon_ex_ops(p_netlogon2, tctx, credentials, creds),
     728             :                        "Failed to process schannel secured NETLOGON EX ops (on fresh connection)");
     729             : 
     730             : 
     731             :         /* And the more traditional style, proving that the
     732             :          * credentials chaining state is fully present */
     733         276 :         torture_assert(tctx, test_netlogon_ops(p_netlogon2, tctx, credentials, creds),
     734             :                              "Failed to process schannel secured NETLOGON ops (on fresh connection)");
     735             : 
     736             :         /* Drop the socket, we want to start from scratch (again) */
     737         276 :         talloc_free(p_samr2);
     738             : 
     739             :         /* We don't want schannel for this test */
     740         276 :         status = dcerpc_binding_set_flags(b, 0, DCERPC_AUTH_OPTIONS);
     741         276 :         torture_assert_ntstatus_ok(tctx, status, "set flags");
     742             : 
     743         276 :         status = dcerpc_pipe_connect_b(tctx, &p_netlogon3, b, &ndr_table_netlogon,
     744             :                                        credentials, tctx->ev, tctx->lp_ctx);
     745         276 :         torture_assert_ntstatus_ok(tctx, status, "Failed to connect without schannel");
     746             : 
     747         276 :         torture_assert(tctx, !test_netlogon_ex_ops(p_netlogon3, tctx, credentials, creds),
     748             :                         "Processed NOT schannel secured NETLOGON EX ops without SCHANNEL (unsafe)");
     749             : 
     750             :         /* Required because the previous call will mark the current context as having failed */
     751         276 :         tctx->last_result = TORTURE_OK;
     752         276 :         tctx->last_reason = NULL;
     753             : 
     754         276 :         torture_assert(tctx, test_netlogon_ops(p_netlogon3, tctx, credentials, creds),
     755             :                         "Failed to processed NOT schannel secured NETLOGON ops without new ServerAuth");
     756             : 
     757         276 :         torture_leave_domain(tctx, join_ctx);
     758         276 :         return true;
     759             : }
     760             : 
     761             : /*
     762             :  * Purpose of this test is to demonstrate that a netlogon server carefully deals
     763             :  * with anonymous attempts to set passwords, in particular when the server
     764             :  * enforces the use of schannel. This test makes most sense to be run in an
     765             :  * environment where the netlogon server enforces use of schannel.
     766             :  */
     767             : 
     768          20 : static bool test_schannel_anonymous_setPassword(struct torture_context *tctx,
     769             :                                                 uint32_t dcerpc_flags,
     770             :                                                 bool use2)
     771             : {
     772           2 :         NTSTATUS status, result;
     773          20 :         const char *binding = torture_setting_string(tctx, "binding", NULL);
     774           2 :         struct dcerpc_binding *b;
     775          20 :         struct dcerpc_pipe *p = NULL;
     776           2 :         struct cli_credentials *credentials;
     777          20 :         bool ok = true;
     778             : 
     779          20 :         credentials = cli_credentials_init(NULL);
     780          20 :         torture_assert(tctx, credentials != NULL, "Bad credentials");
     781          20 :         cli_credentials_set_anonymous(credentials);
     782             : 
     783          20 :         status = dcerpc_parse_binding(tctx, binding, &b);
     784          20 :         torture_assert_ntstatus_ok(tctx, status, "Bad binding string");
     785             : 
     786          20 :         status = dcerpc_binding_set_flags(b, dcerpc_flags, DCERPC_AUTH_OPTIONS);
     787          20 :         torture_assert_ntstatus_ok(tctx, status, "set flags");
     788             : 
     789          20 :         status = dcerpc_pipe_connect_b(tctx,
     790             :                                        &p,
     791             :                                        b,
     792             :                                        &ndr_table_netlogon,
     793             :                                        credentials,
     794             :                                        tctx->ev,
     795             :                                        tctx->lp_ctx);
     796          20 :         torture_assert_ntstatus_ok(tctx, status, "Failed to connect without schannel");
     797             : 
     798          20 :         if (use2) {
     799          10 :                 struct netr_ServerPasswordSet2 r = {};
     800          10 :                 struct netr_Authenticator credential = {};
     801          10 :                 struct netr_Authenticator return_authenticator = {};
     802          10 :                 struct netr_CryptPassword new_password = {};
     803             : 
     804          10 :                 r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
     805          10 :                 r.in.account_name = talloc_asprintf(tctx, "%s$", TEST_MACHINE_NAME);
     806          10 :                 r.in.secure_channel_type = 0;
     807          10 :                 r.in.computer_name = TEST_MACHINE_NAME;
     808          10 :                 r.in.credential = &credential;
     809          10 :                 r.in.new_password = &new_password;
     810          10 :                 r.out.return_authenticator = &return_authenticator;
     811             : 
     812          10 :                 status = dcerpc_netr_ServerPasswordSet2_r(p->binding_handle, tctx, &r);
     813          10 :                 result = r.out.result;
     814             :         } else {
     815          10 :                 struct netr_ServerPasswordSet r = {};
     816          10 :                 struct netr_Authenticator credential = {};
     817          10 :                 struct netr_Authenticator return_authenticator = {};
     818          10 :                 struct samr_Password new_password = {};
     819             : 
     820          10 :                 r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
     821          10 :                 r.in.account_name = talloc_asprintf(tctx, "%s$", TEST_MACHINE_NAME);
     822          10 :                 r.in.secure_channel_type = 0;
     823          10 :                 r.in.computer_name = TEST_MACHINE_NAME;
     824          10 :                 r.in.credential = &credential;
     825          10 :                 r.in.new_password = &new_password;
     826          10 :                 r.out.return_authenticator = &return_authenticator;
     827             : 
     828          10 :                 status = dcerpc_netr_ServerPasswordSet_r(p->binding_handle, tctx, &r);
     829          10 :                 result = r.out.result;
     830             :         }
     831             : 
     832          20 :         torture_assert_ntstatus_ok(tctx, status, "ServerPasswordSet failed");
     833             : 
     834          20 :         if (NT_STATUS_IS_OK(result)) {
     835           0 :                 torture_fail(tctx, "unexpectedly received NT_STATUS_OK");
     836             :         }
     837             : 
     838          18 :         return ok;
     839             : }
     840             : 
     841             : 
     842             : /*
     843             :   a schannel test suite
     844             :  */
     845          23 : bool torture_rpc_schannel(struct torture_context *torture)
     846             : {
     847          23 :         bool ret = true;
     848           4 :         struct {
     849             :                 uint16_t acct_flags;
     850             :                 uint32_t dcerpc_flags;
     851          23 :         } tests[] = {
     852             :                 { ACB_WSTRUST,   DCERPC_SCHANNEL | DCERPC_SIGN | DCERPC_SCHANNEL_AUTO},
     853             :                 { ACB_WSTRUST,   DCERPC_SCHANNEL | DCERPC_SEAL | DCERPC_SCHANNEL_AUTO},
     854             :                 { ACB_WSTRUST,   DCERPC_SCHANNEL | DCERPC_SIGN | DCERPC_SCHANNEL_128},
     855             :                 { ACB_WSTRUST,   DCERPC_SCHANNEL | DCERPC_SEAL | DCERPC_SCHANNEL_128 },
     856             :                 { ACB_WSTRUST,   DCERPC_SCHANNEL | DCERPC_SIGN | DCERPC_SCHANNEL_AES},
     857             :                 { ACB_WSTRUST,   DCERPC_SCHANNEL | DCERPC_SEAL | DCERPC_SCHANNEL_AES },
     858             :                 { ACB_SVRTRUST,  DCERPC_SCHANNEL | DCERPC_SIGN | DCERPC_SCHANNEL_AUTO},
     859             :                 { ACB_SVRTRUST,  DCERPC_SCHANNEL | DCERPC_SEAL | DCERPC_SCHANNEL_AUTO},
     860             :                 { ACB_SVRTRUST,  DCERPC_SCHANNEL | DCERPC_SIGN | DCERPC_SCHANNEL_128 },
     861             :                 { ACB_SVRTRUST,  DCERPC_SCHANNEL | DCERPC_SEAL | DCERPC_SCHANNEL_128 },
     862             :                 { ACB_SVRTRUST,  DCERPC_SCHANNEL | DCERPC_SIGN | DCERPC_SCHANNEL_AES },
     863             :                 { ACB_SVRTRUST,  DCERPC_SCHANNEL | DCERPC_SEAL | DCERPC_SCHANNEL_AES }
     864             :         };
     865           4 :         int i;
     866             : 
     867         299 :         for (i=0;i<ARRAY_SIZE(tests);i++) {
     868         276 :                 torture_comment(torture, "Testing with acct_flags=0x%x dcerpc_flags=0x%x \n",
     869         276 :                        tests[i].acct_flags, tests[i].dcerpc_flags);
     870             : 
     871         276 :                 if (!test_schannel(torture,
     872         228 :                                    tests[i].acct_flags, tests[i].dcerpc_flags,
     873             :                                    i)) {
     874           0 :                         torture_comment(torture, "Failed with acct_flags=0x%x dcerpc_flags=0x%x \n",
     875           0 :                                tests[i].acct_flags, tests[i].dcerpc_flags);
     876           0 :                         ret = false;
     877             :                 }
     878             :         }
     879             : 
     880          23 :         return ret;
     881             : }
     882             : 
     883          10 : bool torture_rpc_schannel_anon_setpw(struct torture_context *torture)
     884             : {
     885          10 :         bool ret = true;
     886           1 :         bool ok;
     887          10 :         uint32_t dcerpc_flags = DCERPC_SCHANNEL | DCERPC_SIGN | DCERPC_SCHANNEL_AUTO;
     888             : 
     889          10 :         ok = test_schannel_anonymous_setPassword(torture,
     890             :                                                  dcerpc_flags,
     891             :                                                  true);
     892          10 :         if (!ok) {
     893           0 :                 torture_comment(torture,
     894             :                                 "Failed with dcerpc_flags=0x%x\n",
     895             :                                 dcerpc_flags);
     896           0 :                 ret = false;
     897             :         }
     898             : 
     899          10 :         ok = test_schannel_anonymous_setPassword(torture,
     900             :                                                  dcerpc_flags,
     901             :                                                  false);
     902          10 :         if (!ok) {
     903           0 :                 torture_comment(torture,
     904             :                                 "Failed with dcerpc_flags=0x%x\n",
     905             :                                 dcerpc_flags);
     906           0 :                 ret = false;
     907             :         }
     908             : 
     909          10 :         return ret;
     910             : }
     911             : 
     912             : /*
     913             :   test two schannel connections
     914             :  */
     915          23 : bool torture_rpc_schannel2(struct torture_context *torture)
     916             : {
     917           4 :         struct test_join *join_ctx;
     918           4 :         NTSTATUS status;
     919          23 :         const char *binding = torture_setting_string(torture, "binding", NULL);
     920           4 :         struct dcerpc_binding *b;
     921          23 :         struct dcerpc_pipe *p1 = NULL, *p2 = NULL;
     922           4 :         struct cli_credentials *credentials1, *credentials2;
     923          23 :         uint32_t dcerpc_flags = DCERPC_SCHANNEL | DCERPC_SCHANNEL_AUTO | DCERPC_SIGN;
     924             : 
     925          23 :         join_ctx = torture_join_domain(torture, talloc_asprintf(torture, "%s2", TEST_MACHINE_NAME),
     926             :                                        ACB_WSTRUST, &credentials1);
     927          23 :         torture_assert(torture, join_ctx != NULL,
     928             :                        "Failed to join domain with acct_flags=ACB_WSTRUST");
     929             : 
     930          23 :         credentials2 = cli_credentials_shallow_copy(torture, credentials1);
     931          23 :         cli_credentials_set_netlogon_creds(credentials1, NULL);
     932          23 :         cli_credentials_set_netlogon_creds(credentials2, NULL);
     933             : 
     934          23 :         status = dcerpc_parse_binding(torture, binding, &b);
     935          23 :         torture_assert_ntstatus_ok(torture, status, "Bad binding string");
     936             : 
     937          23 :         status = dcerpc_binding_set_flags(b, dcerpc_flags, DCERPC_AUTH_OPTIONS);
     938          23 :         torture_assert_ntstatus_ok(torture, status, "set flags");
     939             : 
     940          23 :         torture_comment(torture, "Opening first connection\n");
     941          23 :         status = dcerpc_pipe_connect_b(torture, &p1, b, &ndr_table_netlogon,
     942             :                                        credentials1, torture->ev, torture->lp_ctx);
     943          23 :         torture_assert_ntstatus_ok(torture, status, "Failed to connect with schannel");
     944             : 
     945          23 :         torture_comment(torture, "Opening second connection\n");
     946          23 :         status = dcerpc_pipe_connect_b(torture, &p2, b, &ndr_table_netlogon,
     947             :                                        credentials2, torture->ev, torture->lp_ctx);
     948          23 :         torture_assert_ntstatus_ok(torture, status, "Failed to connect with schannel");
     949             : 
     950          23 :         cli_credentials_set_netlogon_creds(credentials1, NULL);
     951          23 :         cli_credentials_set_netlogon_creds(credentials2, NULL);
     952             : 
     953          23 :         torture_comment(torture, "Testing logon on pipe1\n");
     954          23 :         if (!test_netlogon_ex_ops(p1, torture, credentials1, NULL))
     955           0 :                 return false;
     956             : 
     957          23 :         torture_comment(torture, "Testing logon on pipe2\n");
     958          23 :         if (!test_netlogon_ex_ops(p2, torture, credentials2, NULL))
     959           0 :                 return false;
     960             : 
     961          23 :         torture_comment(torture, "Again on pipe1\n");
     962          23 :         if (!test_netlogon_ex_ops(p1, torture, credentials1, NULL))
     963           0 :                 return false;
     964             : 
     965          23 :         torture_comment(torture, "Again on pipe2\n");
     966          23 :         if (!test_netlogon_ex_ops(p2, torture, credentials2, NULL))
     967           0 :                 return false;
     968             : 
     969          23 :         torture_leave_domain(torture, join_ctx);
     970          23 :         return true;
     971             : }
     972             : 
     973             : struct torture_schannel_bench;
     974             : 
     975             : struct torture_schannel_bench_conn {
     976             :         struct torture_schannel_bench *s;
     977             :         int index;
     978             :         struct cli_credentials *wks_creds;
     979             :         struct dcerpc_pipe *pipe;
     980             :         struct netr_LogonSamLogonEx r;
     981             :         struct netr_NetworkInfo ninfo;
     982             :         TALLOC_CTX *tmp;
     983             :         uint64_t total;
     984             :         uint32_t count;
     985             : };
     986             : 
     987             : struct torture_schannel_bench {
     988             :         struct torture_context *tctx;
     989             :         bool progress;
     990             :         int timelimit;
     991             :         int nprocs;
     992             :         int nconns;
     993             :         struct torture_schannel_bench_conn *conns;
     994             :         struct test_join *join_ctx1;
     995             :         struct cli_credentials *wks_creds1;
     996             :         struct test_join *join_ctx2;
     997             :         struct cli_credentials *wks_creds2;
     998             :         struct cli_credentials *user1_creds;
     999             :         struct cli_credentials *user2_creds;
    1000             :         struct dcerpc_binding *b;
    1001             :         NTSTATUS error;
    1002             :         uint64_t total;
    1003             :         uint32_t count;
    1004             :         bool stopped;
    1005             : };
    1006             : 
    1007             : #if 0
    1008             : static void torture_schannel_bench_connected(struct composite_context *c)
    1009             : {
    1010             :         struct torture_schannel_bench_conn *conn =
    1011             :                 (struct torture_schannel_bench_conn *)c->async.private_data;
    1012             :         struct torture_schannel_bench *s = talloc_get_type(conn->s,
    1013             :                                            struct torture_schannel_bench);
    1014             : 
    1015             :         s->error = dcerpc_pipe_connect_b_recv(c, s->conns, &conn->pipe);
    1016             :         torture_comment(s->tctx, "conn[%u]: %s\n", conn->index, nt_errstr(s->error));
    1017             :         if (NT_STATUS_IS_OK(s->error)) {
    1018             :                 s->nconns++;
    1019             :         }
    1020             : }
    1021             : #endif
    1022             : 
    1023             : static void torture_schannel_bench_recv(struct tevent_req *subreq);
    1024             : 
    1025           0 : static bool torture_schannel_bench_start(struct torture_schannel_bench_conn *conn)
    1026             : {
    1027           0 :         struct torture_schannel_bench *s = conn->s;
    1028           0 :         NTSTATUS status;
    1029           0 :         DATA_BLOB names_blob, chal, lm_resp, nt_resp;
    1030           0 :         int flags = CLI_CRED_NTLM_AUTH;
    1031           0 :         struct tevent_req *subreq;
    1032           0 :         struct cli_credentials *user_creds;
    1033             : 
    1034           0 :         if (conn->total % 2) {
    1035           0 :                 user_creds = s->user1_creds;
    1036             :         } else {
    1037           0 :                 user_creds = s->user2_creds;
    1038             :         }
    1039             : 
    1040           0 :         if (lpcfg_client_lanman_auth(s->tctx->lp_ctx)) {
    1041           0 :                 flags |= CLI_CRED_LANMAN_AUTH;
    1042             :         }
    1043             : 
    1044           0 :         if (lpcfg_client_ntlmv2_auth(s->tctx->lp_ctx)) {
    1045           0 :                 flags |= CLI_CRED_NTLMv2_AUTH;
    1046             :         }
    1047             : 
    1048           0 :         talloc_free(conn->tmp);
    1049           0 :         conn->tmp = talloc_new(s);
    1050           0 :         ZERO_STRUCT(conn->ninfo);
    1051           0 :         ZERO_STRUCT(conn->r);
    1052             : 
    1053           0 :         cli_credentials_get_ntlm_username_domain(user_creds, conn->tmp,
    1054             :                                                  &conn->ninfo.identity_info.account_name.string,
    1055             :                                                  &conn->ninfo.identity_info.domain_name.string);
    1056             : 
    1057           0 :         generate_random_buffer(conn->ninfo.challenge,
    1058             :                                sizeof(conn->ninfo.challenge));
    1059           0 :         chal = data_blob_const(conn->ninfo.challenge,
    1060             :                                sizeof(conn->ninfo.challenge));
    1061             : 
    1062           0 :         names_blob = NTLMv2_generate_names_blob(conn->tmp,
    1063             :                                                 cli_credentials_get_workstation(conn->wks_creds),
    1064             :                                                 cli_credentials_get_domain(conn->wks_creds));
    1065             : 
    1066           0 :         status = cli_credentials_get_ntlm_response(user_creds, conn->tmp,
    1067             :                                                    &flags,
    1068             :                                                    chal,
    1069             :                                                    NULL, /* server_timestamp */
    1070             :                                                    names_blob,
    1071             :                                                    &lm_resp, &nt_resp,
    1072             :                                                    NULL, NULL);
    1073           0 :         torture_assert_ntstatus_ok(s->tctx, status,
    1074             :                                    "cli_credentials_get_ntlm_response failed");
    1075             : 
    1076           0 :         conn->ninfo.lm.data = lm_resp.data;
    1077           0 :         conn->ninfo.lm.length = lm_resp.length;
    1078             : 
    1079           0 :         conn->ninfo.nt.data = nt_resp.data;
    1080           0 :         conn->ninfo.nt.length = nt_resp.length;
    1081             : 
    1082           0 :         conn->ninfo.identity_info.parameter_control = 0;
    1083           0 :         conn->ninfo.identity_info.logon_id = 0;
    1084           0 :         conn->ninfo.identity_info.workstation.string = cli_credentials_get_workstation(conn->wks_creds);
    1085             : 
    1086           0 :         conn->r.in.server_name = talloc_asprintf(conn->tmp, "\\\\%s", dcerpc_server_name(conn->pipe));
    1087           0 :         conn->r.in.computer_name = cli_credentials_get_workstation(conn->wks_creds);
    1088           0 :         conn->r.in.logon_level = NetlogonNetworkInformation;
    1089           0 :         conn->r.in.logon = talloc(conn->tmp, union netr_LogonLevel);
    1090           0 :         conn->r.in.logon->network = &conn->ninfo;
    1091           0 :         conn->r.in.flags = talloc(conn->tmp, uint32_t);
    1092           0 :         conn->r.in.validation_level = 2;
    1093           0 :         conn->r.out.validation = talloc(conn->tmp, union netr_Validation);
    1094           0 :         conn->r.out.authoritative = talloc(conn->tmp, uint8_t);
    1095           0 :         conn->r.out.flags = conn->r.in.flags;
    1096             : 
    1097           0 :         subreq = dcerpc_netr_LogonSamLogonEx_r_send(s, s->tctx->ev,
    1098           0 :                                                     conn->pipe->binding_handle,
    1099             :                                                     &conn->r);
    1100           0 :         torture_assert(s->tctx, subreq, "Failed to setup LogonSamLogonEx request");
    1101             : 
    1102           0 :         tevent_req_set_callback(subreq, torture_schannel_bench_recv, conn);
    1103             : 
    1104           0 :         return true;
    1105             : }
    1106             : 
    1107           0 : static void torture_schannel_bench_recv(struct tevent_req *subreq)
    1108             : {
    1109           0 :         bool ret;
    1110           0 :         struct torture_schannel_bench_conn *conn =
    1111           0 :                 (struct torture_schannel_bench_conn *)tevent_req_callback_data_void(subreq);
    1112           0 :         struct torture_schannel_bench *s = talloc_get_type(conn->s,
    1113             :                                            struct torture_schannel_bench);
    1114             : 
    1115           0 :         s->error = dcerpc_netr_LogonSamLogonEx_r_recv(subreq, subreq);
    1116           0 :         TALLOC_FREE(subreq);
    1117           0 :         if (!NT_STATUS_IS_OK(s->error)) {
    1118           0 :                 return;
    1119             :         }
    1120             : 
    1121           0 :         conn->total++;
    1122           0 :         conn->count++;
    1123             : 
    1124           0 :         if (s->stopped) {
    1125           0 :                 return;
    1126             :         }
    1127             : 
    1128           0 :         ret = torture_schannel_bench_start(conn);
    1129           0 :         if (!ret) {
    1130           0 :                 s->error = NT_STATUS_INTERNAL_ERROR;
    1131             :         }
    1132             : }
    1133             : 
    1134             : /*
    1135             :   test multiple schannel connection in parallel
    1136             :  */
    1137           0 : bool torture_rpc_schannel_bench1(struct torture_context *torture)
    1138             : {
    1139           0 :         bool ret = true;
    1140           0 :         NTSTATUS status;
    1141           0 :         const char *binding = torture_setting_string(torture, "binding", NULL);
    1142           0 :         struct torture_schannel_bench *s;
    1143           0 :         struct timeval start;
    1144           0 :         struct timeval end;
    1145           0 :         int i;
    1146           0 :         const char *tmp;
    1147             : 
    1148           0 :         s = talloc_zero(torture, struct torture_schannel_bench);
    1149           0 :         s->tctx = torture;
    1150           0 :         s->progress = torture_setting_bool(torture, "progress", true);
    1151           0 :         s->timelimit = torture_setting_int(torture, "timelimit", 10);
    1152           0 :         s->nprocs = torture_setting_int(torture, "nprocs", 4);
    1153           0 :         s->conns = talloc_zero_array(s, struct torture_schannel_bench_conn, s->nprocs);
    1154             : 
    1155           0 :         s->user1_creds = cli_credentials_shallow_copy(s,
    1156             :                                 samba_cmdline_get_creds());
    1157           0 :         tmp = torture_setting_string(s->tctx, "extra_user1", NULL);
    1158           0 :         if (tmp) {
    1159           0 :                 cli_credentials_parse_string(s->user1_creds, tmp, CRED_SPECIFIED);
    1160             :         }
    1161           0 :         s->user2_creds = cli_credentials_shallow_copy(s,
    1162             :                                 samba_cmdline_get_creds());
    1163           0 :         tmp = torture_setting_string(s->tctx, "extra_user2", NULL);
    1164           0 :         if (tmp) {
    1165           0 :                 cli_credentials_parse_string(s->user1_creds, tmp, CRED_SPECIFIED);
    1166             :         }
    1167             : 
    1168           0 :         s->join_ctx1 = torture_join_domain(s->tctx, talloc_asprintf(s, "%sb", TEST_MACHINE_NAME),
    1169             :                                            ACB_WSTRUST, &s->wks_creds1);
    1170           0 :         torture_assert(torture, s->join_ctx1 != NULL,
    1171             :                        "Failed to join domain with acct_flags=ACB_WSTRUST");
    1172           0 :         s->join_ctx2 = torture_join_domain(s->tctx, talloc_asprintf(s, "%sc", TEST_MACHINE_NAME),
    1173             :                                            ACB_WSTRUST, &s->wks_creds2);
    1174           0 :         torture_assert(torture, s->join_ctx2 != NULL,
    1175             :                        "Failed to join domain with acct_flags=ACB_WSTRUST");
    1176             : 
    1177           0 :         cli_credentials_set_kerberos_state(s->wks_creds1,
    1178             :                                            CRED_USE_KERBEROS_DISABLED,
    1179             :                                            CRED_SPECIFIED);
    1180           0 :         cli_credentials_set_kerberos_state(s->wks_creds2,
    1181             :                                            CRED_USE_KERBEROS_DISABLED,
    1182             :                                            CRED_SPECIFIED);
    1183             : 
    1184           0 :         for (i=0; i < s->nprocs; i++) {
    1185           0 :                 struct cli_credentials *wks = s->wks_creds1;
    1186             : 
    1187           0 :                 if ((i % 2) && (torture_setting_bool(torture, "multijoin", false))) {
    1188           0 :                         wks = s->wks_creds2;
    1189             :                 }
    1190             : 
    1191           0 :                 s->conns[i].s = s;
    1192           0 :                 s->conns[i].index = i;
    1193           0 :                 s->conns[i].wks_creds = cli_credentials_shallow_copy(s->conns, wks);
    1194           0 :                 cli_credentials_set_netlogon_creds(s->conns[i].wks_creds, NULL);
    1195             :         }
    1196             : 
    1197           0 :         status = dcerpc_parse_binding(s, binding, &s->b);
    1198           0 :         torture_assert_ntstatus_ok(torture, status, "Bad binding string");
    1199             : 
    1200           0 :         status = dcerpc_binding_set_flags(s->b, DCERPC_SCHANNEL | DCERPC_SIGN,
    1201             :                                           DCERPC_AUTH_OPTIONS);
    1202           0 :         torture_assert_ntstatus_ok(torture, status, "set flags");
    1203             : 
    1204           0 :         torture_comment(torture, "Opening %d connections in parallel\n", s->nprocs);
    1205           0 :         for (i=0; i < s->nprocs; i++) {
    1206             : #if 1
    1207           0 :                 s->error = dcerpc_pipe_connect_b(s->conns, &s->conns[i].pipe, s->b,
    1208             :                                                  &ndr_table_netlogon,
    1209           0 :                                                  s->conns[i].wks_creds,
    1210             :                                                  torture->ev, torture->lp_ctx);
    1211           0 :                 torture_assert_ntstatus_ok(torture, s->error, "Failed to connect with schannel");
    1212             : #else
    1213             :                 /*
    1214             :                  * This path doesn't work against windows,
    1215             :                  * because of windows drops the connections
    1216             :                  * which haven't reached a session setup yet
    1217             :                  *
    1218             :                  * The same as the reset on zero vc stuff.
    1219             :                  */
    1220             :                 struct composite_context *c;
    1221             :                 c = dcerpc_pipe_connect_b_send(s->conns, s->b,
    1222             :                                                &ndr_table_netlogon,
    1223             :                                                s->conns[i].wks_creds,
    1224             :                                                torture->ev,
    1225             :                                                torture->lp_ctx);
    1226             :                 torture_assert(torture, c != NULL, "Failed to setup connect");
    1227             :                 c->async.fn = torture_schannel_bench_connected;
    1228             :                 c->async.private_data = &s->conns[i];
    1229             :         }
    1230             : 
    1231             :         while (NT_STATUS_IS_OK(s->error) && s->nprocs != s->nconns) {
    1232             :                 int ev_ret = tevent_loop_once(torture->ev);
    1233             :                 torture_assert(torture, ev_ret == 0, "tevent_loop_once failed");
    1234             : #endif
    1235             :         }
    1236           0 :         torture_assert_ntstatus_ok(torture, s->error, "Failed establish a connect");
    1237             : 
    1238             :         /*
    1239             :          * Change the workstation password after establishing the netlogon
    1240             :          * schannel connections to prove that existing connections are not
    1241             :          * affected by a wks pwchange.
    1242             :          */
    1243             : 
    1244             :         {
    1245           0 :                 struct netr_ServerPasswordSet pwset;
    1246           0 :                 char *password = generate_random_password(s->join_ctx1, 8, 255);
    1247           0 :                 struct netlogon_creds_CredentialState *creds_state;
    1248           0 :                 struct dcerpc_pipe *net_pipe;
    1249           0 :                 struct netr_Authenticator credential, return_authenticator;
    1250           0 :                 struct samr_Password new_password;
    1251             : 
    1252           0 :                 status = dcerpc_pipe_connect_b(s, &net_pipe, s->b,
    1253             :                                                &ndr_table_netlogon,
    1254             :                                                s->wks_creds1,
    1255             :                                                torture->ev, torture->lp_ctx);
    1256             : 
    1257           0 :                 torture_assert_ntstatus_ok(torture, status,
    1258             :                                            "dcerpc_pipe_connect_b failed");
    1259             : 
    1260           0 :                 pwset.in.server_name = talloc_asprintf(
    1261             :                         net_pipe, "\\\\%s", dcerpc_server_name(net_pipe));
    1262           0 :                 pwset.in.computer_name =
    1263           0 :                         cli_credentials_get_workstation(s->wks_creds1);
    1264           0 :                 pwset.in.account_name = talloc_asprintf(
    1265             :                         net_pipe, "%s$", pwset.in.computer_name);
    1266           0 :                 pwset.in.secure_channel_type = SEC_CHAN_WKSTA;
    1267           0 :                 pwset.in.credential = &credential;
    1268           0 :                 pwset.in.new_password = &new_password;
    1269           0 :                 pwset.out.return_authenticator = &return_authenticator;
    1270             : 
    1271           0 :                 E_md4hash(password, new_password.hash);
    1272             : 
    1273           0 :                 creds_state = cli_credentials_get_netlogon_creds(
    1274             :                         s->wks_creds1);
    1275           0 :                 netlogon_creds_des_encrypt(creds_state, &new_password);
    1276           0 :                 netlogon_creds_client_authenticator(creds_state, &credential);
    1277             : 
    1278           0 :                 torture_assert_ntstatus_ok(torture, dcerpc_netr_ServerPasswordSet_r(net_pipe->binding_handle, torture, &pwset),
    1279             :                         "ServerPasswordSet failed");
    1280           0 :                 torture_assert_ntstatus_ok(torture, pwset.out.result,
    1281             :                                            "ServerPasswordSet failed");
    1282             : 
    1283           0 :                 if (!netlogon_creds_client_check(creds_state,
    1284           0 :                                         &pwset.out.return_authenticator->cred)) {
    1285           0 :                         torture_comment(torture, "Credential chaining failed\n");
    1286             :                 }
    1287             : 
    1288           0 :                 cli_credentials_set_password(s->wks_creds1, password,
    1289             :                                              CRED_SPECIFIED);
    1290             : 
    1291           0 :                 talloc_free(net_pipe);
    1292             : 
    1293             :                 /* Just as a test, connect with the new creds */
    1294             : 
    1295           0 :                 cli_credentials_set_netlogon_creds(s->wks_creds1, NULL);
    1296             : 
    1297           0 :                 status = dcerpc_pipe_connect_b(s, &net_pipe, s->b,
    1298             :                                                &ndr_table_netlogon,
    1299             :                                                s->wks_creds1,
    1300             :                                                torture->ev, torture->lp_ctx);
    1301             : 
    1302           0 :                 torture_assert_ntstatus_ok(torture, status,
    1303             :                                            "dcerpc_pipe_connect_b failed");
    1304             : 
    1305           0 :                 talloc_free(net_pipe);
    1306             :         }
    1307             : 
    1308           0 :         torture_comment(torture, "Start looping LogonSamLogonEx on %d connections for %d secs\n",
    1309             :                         s->nprocs, s->timelimit);
    1310           0 :         for (i=0; i < s->nprocs; i++) {
    1311           0 :                 ret = torture_schannel_bench_start(&s->conns[i]);
    1312           0 :                 torture_assert(torture, ret, "Failed to setup LogonSamLogonEx");
    1313             :         }
    1314             : 
    1315           0 :         start = timeval_current();
    1316           0 :         end = timeval_add(&start, s->timelimit, 0);
    1317             : 
    1318           0 :         while (NT_STATUS_IS_OK(s->error) && !timeval_expired(&end)) {
    1319           0 :                 int ev_ret = tevent_loop_once(torture->ev);
    1320           0 :                 torture_assert(torture, ev_ret == 0, "tevent_loop_once failed");
    1321             :         }
    1322           0 :         torture_assert_ntstatus_ok(torture, s->error, "Failed some request");
    1323           0 :         s->stopped = true;
    1324           0 :         talloc_free(s->conns);
    1325             : 
    1326           0 :         for (i=0; i < s->nprocs; i++) {
    1327           0 :                 s->total += s->conns[i].total;
    1328             :         }
    1329             : 
    1330           0 :         torture_comment(torture,
    1331             :                         "Total ops[%llu] (%u ops/s)\n",
    1332           0 :                         (unsigned long long)s->total,
    1333           0 :                         (unsigned)s->total/s->timelimit);
    1334             : 
    1335           0 :         torture_leave_domain(torture, s->join_ctx1);
    1336           0 :         torture_leave_domain(torture, s->join_ctx2);
    1337           0 :         return true;
    1338             : }

Generated by: LCOV version 1.14