LCOV - code coverage report
Current view: top level - source4/torture/rpc - witness.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 13 325 4.0 %
Date: 2024-04-21 15:09:00 Functions: 1 17 5.9 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    test suite for rpc witness operations
       4             : 
       5             :    Copyright (C) Guenther Deschner 2015
       6             : 
       7             :    This program is free software; you can redistribute it and/or modify
       8             :    it under the terms of the GNU General Public License as published by
       9             :    the Free Software Foundation; either version 3 of the License, or
      10             :    (at your option) any later version.
      11             : 
      12             :    This program is distributed in the hope that it will be useful,
      13             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :    GNU General Public License for more details.
      16             : 
      17             :    You should have received a copy of the GNU General Public License
      18             :    along with this program; if not, write to the Free Software
      19             :    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
      20             : */
      21             : 
      22             : #include "includes.h"
      23             : #include "torture/rpc/torture_rpc.h"
      24             : #include "librpc/gen_ndr/ndr_witness_c.h"
      25             : #include "librpc/gen_ndr/ndr_srvsvc_c.h"
      26             : #include "librpc/gen_ndr/ndr_clusapi_c.h"
      27             : #include "param/param.h"
      28             : #include <tevent.h>
      29             : #include "lib/cmdline/cmdline.h"
      30             : 
      31             : struct torture_test_clusapi_state {
      32             :         struct dcerpc_pipe *p;
      33             : };
      34             : 
      35             : struct torture_test_witness_state {
      36             :         const char *net_name;
      37             :         const char *share_name;
      38             :         struct witness_interfaceList *list;
      39             :         struct policy_handle context_handle;
      40             :         struct torture_test_clusapi_state clusapi;
      41             : };
      42             : 
      43           0 : static bool test_witness_GetInterfaceList(struct torture_context *tctx,
      44             :                                           struct dcerpc_pipe *p,
      45             :                                           void *data)
      46             : {
      47           0 :         struct dcerpc_binding_handle *b = p->binding_handle;
      48           0 :         struct witness_GetInterfaceList r;
      49           0 :         struct witness_interfaceList *l;
      50           0 :         struct torture_test_witness_state *state =
      51             :                 (struct torture_test_witness_state *)data;
      52             : 
      53           0 :         r.out.interface_list = &l;
      54             : 
      55           0 :         torture_assert_ntstatus_ok(tctx,
      56             :                 dcerpc_witness_GetInterfaceList_r(b, tctx, &r),
      57             :                 "GetInterfaceList failed");
      58             : 
      59           0 :         torture_assert_werr_ok(tctx,
      60             :                 r.out.result,
      61             :                 "GetInterfaceList failed");
      62             : 
      63           0 :         state->list = l;
      64             : 
      65           0 :         return true;
      66             : }
      67             : 
      68           0 : static bool find_sofs_share(struct torture_context *tctx,
      69             :                             const char **sofs_sharename)
      70             : {
      71           0 :         struct dcerpc_pipe *p;
      72           0 :         struct dcerpc_binding_handle *b;
      73           0 :         struct srvsvc_NetShareEnumAll r;
      74           0 :         struct srvsvc_NetShareInfoCtr info_ctr;
      75           0 :         struct srvsvc_NetShareCtr1 ctr1;
      76           0 :         uint32_t resume_handle = 0;
      77           0 :         uint32_t totalentries = 0;
      78           0 :         int i;
      79             : 
      80           0 :         torture_assert_ntstatus_ok(tctx,
      81             :                 torture_rpc_connection_transport(tctx, &p, &ndr_table_srvsvc,
      82             :                                                  NCACN_NP, 0, 0),
      83             :                 "failed to setup srvsvc connection");
      84             : 
      85           0 :         b = p->binding_handle;
      86             : 
      87           0 :         ZERO_STRUCT(ctr1);
      88             : 
      89           0 :         info_ctr.level = 1;
      90           0 :         info_ctr.ctr.ctr1 = &ctr1;
      91             : 
      92           0 :         r.in.server_unc = dcerpc_server_name(p);
      93           0 :         r.in.max_buffer = -1;
      94           0 :         r.in.info_ctr = &info_ctr;
      95           0 :         r.in.resume_handle = &resume_handle;
      96           0 :         r.out.totalentries = &totalentries;
      97           0 :         r.out.info_ctr = &info_ctr;
      98           0 :         r.out.resume_handle = &resume_handle;
      99             : 
     100           0 :         torture_assert_ntstatus_ok(tctx,
     101             :                 dcerpc_srvsvc_NetShareEnumAll_r(b, tctx, &r),
     102             :                 "failed to call srvsvc_NetShareEnumAll");
     103             : 
     104           0 :         torture_assert_werr_ok(tctx,
     105             :                 r.out.result,
     106             :                 "failed to call srvsvc_NetShareEnumAll");
     107             : 
     108           0 :         for (i=0; i < r.out.info_ctr->ctr.ctr1->count; i++) {
     109             : 
     110           0 :                 if (r.out.info_ctr->ctr.ctr1->array[i].type == STYPE_CLUSTER_SOFS) {
     111           0 :                         *sofs_sharename = talloc_strdup(tctx, r.out.info_ctr->ctr.ctr1->array[i].name);
     112           0 :                         if (*sofs_sharename == NULL) {
     113           0 :                                 return false;
     114             :                         }
     115           0 :                         torture_comment(tctx, "using SOFS share: %s\n", *sofs_sharename);
     116           0 :                         return true;
     117             :                 }
     118           0 :                 if (r.out.info_ctr->ctr.ctr1->array[i].type == STYPE_DISKTREE) {
     119           0 :                         *sofs_sharename = talloc_strdup(tctx, r.out.info_ctr->ctr.ctr1->array[i].name);
     120           0 :                         if (*sofs_sharename == NULL) {
     121           0 :                                 return false;
     122             :                         }
     123           0 :                         torture_comment(tctx, "assuming SOFS share: %s\n", *sofs_sharename);
     124           0 :                         return true;
     125             :                 }
     126             :         }
     127             : 
     128           0 :         return false;
     129             : }
     130             : 
     131           0 : static bool init_witness_test_state(struct torture_context *tctx,
     132             :                                     struct dcerpc_pipe *p,
     133             :                                     struct torture_test_witness_state *state)
     134             : {
     135           0 :         if (state->net_name == NULL) {
     136           0 :                 state->net_name = lpcfg_parm_string(tctx->lp_ctx, NULL, "torture", "net_name");
     137             :         }
     138             : 
     139           0 :         if (state->list == NULL) {
     140           0 :                 torture_assert(tctx,
     141             :                         test_witness_GetInterfaceList(tctx, p, state),
     142             :                         "failed to retrieve GetInterfaceList");
     143             :         }
     144             : 
     145           0 :         if (state->share_name == NULL) {
     146           0 :                 find_sofs_share(tctx, &state->share_name);
     147             :         }
     148             : 
     149           0 :         return true;
     150             : }
     151             : 
     152           0 : static bool test_witness_UnRegister_with_handle(struct torture_context *tctx,
     153             :                                                 struct dcerpc_pipe *p,
     154             :                                                 struct policy_handle *context_handle)
     155             : {
     156           0 :         struct dcerpc_binding_handle *b = p->binding_handle;
     157           0 :         struct witness_UnRegister r;
     158             : 
     159           0 :         r.in.context_handle = *context_handle;
     160             : 
     161           0 :         torture_assert_ntstatus_ok(tctx,
     162             :                 dcerpc_witness_UnRegister_r(b, tctx, &r),
     163             :                 "UnRegister failed");
     164             : 
     165           0 :         torture_assert_werr_ok(tctx,
     166             :                 r.out.result,
     167             :                 "UnRegister failed");
     168             : 
     169             :         /* make sure we are not able/allowed to reuse context handles after they
     170             :          * have been unregistered */
     171             : 
     172           0 :         torture_assert_ntstatus_ok(tctx,
     173             :                 dcerpc_witness_UnRegister_r(b, tctx, &r),
     174             :                 "UnRegister failed");
     175             : 
     176           0 :         torture_assert_werr_equal(tctx,
     177             :                 r.out.result,
     178             :                 WERR_INVALID_PARAMETER,
     179             :                 "UnRegister failed");
     180             : 
     181           0 :         return true;
     182             : }
     183             : 
     184           0 : static bool test_witness_UnRegister(struct torture_context *tctx,
     185             :                                     struct dcerpc_pipe *p,
     186             :                                     void *data)
     187             : {
     188             :         /* acquire handle and free afterwards */
     189           0 :         return true;
     190             : }
     191             : 
     192           0 : static bool get_ip_address_from_interface(struct torture_context *tctx,
     193             :                                           struct witness_interfaceInfo *i,
     194             :                                           const char **ip_address)
     195             : {
     196           0 :         if (i->flags & WITNESS_INFO_IPv4_VALID) {
     197           0 :                 *ip_address = talloc_strdup(tctx, i->ipv4);
     198           0 :                 torture_assert(tctx, *ip_address, "talloc_strdup failed");
     199           0 :                 return true;
     200             :         }
     201             : 
     202           0 :         if (i->flags & WITNESS_INFO_IPv6_VALID) {
     203           0 :                 *ip_address = talloc_strdup(tctx, i->ipv6);
     204           0 :                 torture_assert(tctx, *ip_address, "talloc_strdup failed");
     205           0 :                 return true;
     206             :         }
     207             : 
     208           0 :         return false;
     209             : }
     210             : 
     211           0 : static bool check_valid_interface(struct torture_context *tctx,
     212             :                                   struct witness_interfaceInfo *i)
     213             : {
     214             :         /* continue looking for an interface that allows witness
     215             :          * registration */
     216           0 :         if (!(i->flags & WITNESS_INFO_WITNESS_IF)) {
     217           0 :                 return false;
     218             :         }
     219             : 
     220             :         /* witness should be available of course */
     221           0 :         if (i->state != WITNESS_STATE_AVAILABLE) {
     222           0 :                 return false;
     223             :         }
     224             : 
     225           0 :         return true;
     226             : }
     227             : 
     228           0 : static bool test_witness_Register(struct torture_context *tctx,
     229             :                                   struct dcerpc_pipe *p,
     230             :                                   void *data)
     231             : {
     232           0 :         struct dcerpc_binding_handle *b = p->binding_handle;
     233           0 :         struct witness_Register r;
     234           0 :         struct policy_handle context_handle;
     235           0 :         struct torture_test_witness_state *state =
     236             :                 (struct torture_test_witness_state *)data;
     237           0 :         int i;
     238             : 
     239           0 :         struct {
     240             :                 enum witness_version version;
     241             :                 const char *net_name;
     242             :                 const char *ip_address;
     243             :                 const char *client_computer_name;
     244             :                 NTSTATUS expected_status;
     245             :                 WERROR expected_result;
     246           0 :         } tests[] = {
     247             :                 {
     248             :                         .version                = 0,
     249             :                         .expected_status        = NT_STATUS_OK,
     250             :                         .expected_result        = WERR_REVISION_MISMATCH
     251             :                 },{
     252             :                         .version                = 1,
     253             :                         .expected_status        = NT_STATUS_OK,
     254             :                         .expected_result        = WERR_REVISION_MISMATCH
     255             :                 },{
     256             :                         .version                = 123456,
     257             :                         .expected_status        = NT_STATUS_OK,
     258             :                         .expected_result        = WERR_REVISION_MISMATCH
     259             :                 },{
     260             :                         .version                = -1,
     261             :                         .expected_status        = NT_STATUS_OK,
     262             :                         .expected_result        = WERR_REVISION_MISMATCH
     263             :                 },{
     264             :                         .version                = WITNESS_V2,
     265             :                         .expected_status        = NT_STATUS_OK,
     266             :                         .expected_result        = WERR_REVISION_MISMATCH
     267             :                 },{
     268             :                         .version                = WITNESS_V1,
     269             :                         .net_name               = "",
     270             :                         .ip_address             = "",
     271             :                         .client_computer_name   = "",
     272             :                         .expected_status        = NT_STATUS_OK,
     273             :                         .expected_result        = WERR_INVALID_PARAMETER
     274             :                 },{
     275             :                         .version                = WITNESS_V1,
     276             :                         .net_name               = NULL,
     277             :                         .ip_address             = NULL,
     278           0 :                         .client_computer_name   = lpcfg_netbios_name(tctx->lp_ctx),
     279             :                         .expected_status        = NT_STATUS_OK,
     280             :                         .expected_result        = WERR_INVALID_PARAMETER
     281             :                 },{
     282             :                         .version                = WITNESS_V2,
     283             :                         .net_name               = NULL,
     284             :                         .ip_address             = NULL,
     285           0 :                         .client_computer_name   = lpcfg_netbios_name(tctx->lp_ctx),
     286             :                         .expected_status        = NT_STATUS_OK,
     287             :                         .expected_result        = WERR_REVISION_MISMATCH
     288             :                 },{
     289             :                         .version                = WITNESS_V1,
     290           0 :                         .net_name               = dcerpc_server_name(p),
     291             :                         .ip_address             = NULL,
     292           0 :                         .client_computer_name   = lpcfg_netbios_name(tctx->lp_ctx),
     293             :                         .expected_status        = NT_STATUS_OK,
     294             :                         .expected_result        = WERR_INVALID_PARAMETER
     295             :                 }
     296             : 
     297             :         };
     298             : 
     299           0 :         for (i=0; i < ARRAY_SIZE(tests); i++) {
     300             : 
     301           0 :                 ZERO_STRUCT(r);
     302             : 
     303           0 :                 r.out.context_handle = &context_handle;
     304             : 
     305           0 :                 r.in.version = tests[i].version;
     306           0 :                 r.in.net_name = tests[i].net_name;
     307           0 :                 r.in.ip_address = tests[i].ip_address;
     308           0 :                 r.in.client_computer_name = tests[i].client_computer_name;
     309             : 
     310           0 :                 torture_assert_ntstatus_equal(tctx,
     311             :                         dcerpc_witness_Register_r(b, tctx, &r),
     312             :                         tests[i].expected_status,
     313             :                         "Register failed");
     314             : 
     315           0 :                 torture_assert_werr_equal(tctx,
     316             :                         r.out.result,
     317             :                         tests[i].expected_result,
     318             :                         "Register failed");
     319             : 
     320           0 :                 if (W_ERROR_IS_OK(r.out.result)) {
     321             : 
     322             :                         /* we have a handle, make sure to unregister it */
     323           0 :                         torture_assert(tctx,
     324             :                                 test_witness_UnRegister_with_handle(tctx, p, r.out.context_handle),
     325             :                                 "Failed to unregister");
     326             :                 }
     327             :         }
     328             : 
     329           0 :         init_witness_test_state(tctx, p, state);
     330             : 
     331           0 :         for (i=0; state->list && i < state->list->num_interfaces; i++) {
     332             : 
     333           0 :                 const char *ip_address;
     334           0 :                 struct witness_interfaceInfo interface = state->list->interfaces[i];
     335             : 
     336           0 :                 if (!check_valid_interface(tctx, &interface)) {
     337           0 :                         continue;
     338             :                 }
     339             : 
     340           0 :                 torture_assert(tctx,
     341             :                         get_ip_address_from_interface(tctx, &interface, &ip_address),
     342             :                         "failed to get ip_address from interface");
     343             : 
     344           0 :                 r.in.version = WITNESS_V1;
     345           0 :                 r.in.net_name = state->net_name;
     346           0 :                 r.in.ip_address = ip_address;
     347             : 
     348           0 :                 torture_assert_ntstatus_ok(tctx,
     349             :                         dcerpc_witness_Register_r(b, tctx, &r),
     350             :                         "Register failed");
     351             : 
     352           0 :                 torture_assert_werr_ok(tctx,
     353             :                         r.out.result,
     354             :                         "Register failed");
     355             : 
     356           0 :                 torture_assert(tctx,
     357             :                         test_witness_UnRegister_with_handle(tctx, p, r.out.context_handle),
     358             :                         "Failed to unregister");
     359             :         }
     360             : 
     361           0 :         return true;
     362             : }
     363             : 
     364           0 : static bool test_witness_RegisterEx(struct torture_context *tctx,
     365             :                                     struct dcerpc_pipe *p,
     366             :                                     void *data)
     367             : {
     368           0 :         struct dcerpc_binding_handle *b = p->binding_handle;
     369           0 :         struct witness_RegisterEx r;
     370           0 :         struct policy_handle context_handle;
     371           0 :         struct torture_test_witness_state *state =
     372             :                 (struct torture_test_witness_state *)data;
     373           0 :         int i;
     374             : 
     375           0 :         struct {
     376             :                 enum witness_version version;
     377             :                 const char *net_name;
     378             :                 const char *ip_address;
     379             :                 const char *client_computer_name;
     380             :                 NTSTATUS expected_status;
     381             :                 WERROR expected_result;
     382           0 :         } tests[] = {
     383             :                 {
     384             :                         .version                = 0,
     385             :                         .expected_status        = NT_STATUS_OK,
     386             :                         .expected_result        = WERR_REVISION_MISMATCH
     387             :                 },{
     388             :                         .version                = 1,
     389             :                         .expected_status        = NT_STATUS_OK,
     390             :                         .expected_result        = WERR_REVISION_MISMATCH
     391             :                 },{
     392             :                         .version                = 123456,
     393             :                         .expected_status        = NT_STATUS_OK,
     394             :                         .expected_result        = WERR_REVISION_MISMATCH
     395             :                 },{
     396             :                         .version                = -1,
     397             :                         .expected_status        = NT_STATUS_OK,
     398             :                         .expected_result        = WERR_REVISION_MISMATCH
     399             :                 },{
     400             :                         .version                = WITNESS_V1,
     401             :                         .expected_status        = NT_STATUS_OK,
     402             :                         .expected_result        = WERR_REVISION_MISMATCH
     403             :                 },{
     404             :                         .version                = WITNESS_V2,
     405             :                         .net_name               = "",
     406             :                         .ip_address             = "",
     407             :                         .client_computer_name   = "",
     408             :                         .expected_status        = NT_STATUS_OK,
     409             :                         .expected_result        = WERR_INVALID_PARAMETER
     410             :                 },{
     411             :                         .version                = WITNESS_V2,
     412             :                         .net_name               = NULL,
     413             :                         .ip_address             = NULL,
     414           0 :                         .client_computer_name   = lpcfg_netbios_name(tctx->lp_ctx),
     415             :                         .expected_status        = NT_STATUS_OK,
     416             :                         .expected_result        = WERR_INVALID_PARAMETER
     417             :                 },{
     418             :                         .version                = WITNESS_V1,
     419             :                         .net_name               = NULL,
     420             :                         .ip_address             = NULL,
     421           0 :                         .client_computer_name   = lpcfg_netbios_name(tctx->lp_ctx),
     422             :                         .expected_status        = NT_STATUS_OK,
     423             :                         .expected_result        = WERR_REVISION_MISMATCH
     424             :                 },{
     425             :                         .version                = WITNESS_V2,
     426           0 :                         .net_name               = dcerpc_server_name(p),
     427             :                         .ip_address             = NULL,
     428           0 :                         .client_computer_name   = lpcfg_netbios_name(tctx->lp_ctx),
     429             :                         .expected_status        = NT_STATUS_OK,
     430             :                         .expected_result        = WERR_INVALID_PARAMETER
     431             :                 }
     432             : 
     433             :         };
     434             : 
     435           0 :         for (i=0; i < ARRAY_SIZE(tests); i++) {
     436             : 
     437           0 :                 ZERO_STRUCT(r);
     438             : 
     439           0 :                 r.out.context_handle = &context_handle;
     440             : 
     441           0 :                 r.in.version = tests[i].version;
     442           0 :                 r.in.net_name = tests[i].net_name;
     443           0 :                 r.in.ip_address = tests[i].ip_address;
     444           0 :                 r.in.client_computer_name = tests[i].client_computer_name;
     445             : 
     446           0 :                 torture_assert_ntstatus_equal(tctx,
     447             :                         dcerpc_witness_RegisterEx_r(b, tctx, &r),
     448             :                         tests[i].expected_status,
     449             :                         "RegisterEx failed");
     450             : 
     451           0 :                 torture_assert_werr_equal(tctx,
     452             :                         r.out.result,
     453             :                         tests[i].expected_result,
     454             :                         "RegisterEx failed");
     455             : 
     456           0 :                 if (W_ERROR_IS_OK(r.out.result)) {
     457             : 
     458             :                         /* we have a handle, make sure to unregister it */
     459           0 :                         torture_assert(tctx,
     460             :                                 test_witness_UnRegister_with_handle(tctx, p, r.out.context_handle),
     461             :                                 "Failed to unregister");
     462             :                 }
     463             :         }
     464             : 
     465           0 :         init_witness_test_state(tctx, p, state);
     466             : 
     467           0 :         for (i=0; state->list && i < state->list->num_interfaces; i++) {
     468             : 
     469           0 :                 const char *ip_address;
     470           0 :                 struct witness_interfaceInfo interface = state->list->interfaces[i];
     471             : 
     472           0 :                 if (!check_valid_interface(tctx, &interface)) {
     473           0 :                         continue;
     474             :                 }
     475             : 
     476           0 :                 torture_assert(tctx,
     477             :                         get_ip_address_from_interface(tctx, &interface, &ip_address),
     478             :                         "failed to get ip_address from interface");
     479             : 
     480           0 :                 r.in.version = WITNESS_V2;
     481           0 :                 r.in.net_name = state->net_name;
     482           0 :                 r.in.ip_address = ip_address;
     483             : 
     484             :                 /*
     485             :                  * a valid request with an invalid sharename fails with
     486             :                  * WERR_INVALID_STATE
     487             :                  */
     488           0 :                 r.in.share_name = "any_invalid_share_name";
     489             : 
     490           0 :                 torture_assert_ntstatus_ok(tctx,
     491             :                         dcerpc_witness_RegisterEx_r(b, tctx, &r),
     492             :                         "RegisterEx failed");
     493             : 
     494           0 :                 torture_assert_werr_equal(tctx,
     495             :                         r.out.result,
     496             :                         WERR_INVALID_STATE,
     497             :                         "RegisterEx failed");
     498             : 
     499           0 :                 r.in.share_name = NULL;
     500             : 
     501           0 :                 torture_assert_ntstatus_ok(tctx,
     502             :                         dcerpc_witness_RegisterEx_r(b, tctx, &r),
     503             :                         "RegisterEx failed");
     504             : 
     505           0 :                 torture_assert_werr_ok(tctx,
     506             :                         r.out.result,
     507             :                         "RegisterEx failed");
     508             : 
     509           0 :                 torture_assert(tctx,
     510             :                         test_witness_UnRegister_with_handle(tctx, p, r.out.context_handle),
     511             :                         "Failed to unregister");
     512             :         }
     513             : 
     514           0 :         return true;
     515             : }
     516             : 
     517           0 : static bool setup_clusapi_connection(struct torture_context *tctx,
     518             :                                      struct torture_test_witness_state *s)
     519             : {
     520           0 :         struct dcerpc_binding *binding;
     521             : 
     522           0 :         if (s->clusapi.p) {
     523           0 :                 return true;
     524             :         }
     525             : 
     526           0 :         torture_assert_ntstatus_ok(tctx,
     527             :                 torture_rpc_binding(tctx, &binding),
     528             :                 "failed to retrieve torture binding");
     529             : 
     530           0 :         torture_assert_ntstatus_ok(tctx,
     531             :                 dcerpc_binding_set_transport(binding, NCACN_IP_TCP),
     532             :                 "failed to set transport");
     533             : 
     534           0 :         torture_assert_ntstatus_ok(tctx,
     535             :                 dcerpc_binding_set_flags(binding, DCERPC_SEAL, 0),
     536             :                 "failed to set dcerpc flags");
     537             : 
     538           0 :         torture_assert_ntstatus_ok(tctx,
     539             :                 dcerpc_pipe_connect_b(tctx, &s->clusapi.p, binding,
     540             :                                       &ndr_table_clusapi,
     541             :                                       samba_cmdline_get_creds(),
     542             :                                       tctx->ev, tctx->lp_ctx),
     543             :                 "failed to connect dcerpc pipe");
     544             : 
     545           0 :         return true;
     546             : }
     547             : 
     548             : #if 0
     549             : static bool cluster_get_nodes(struct torture_context *tctx,
     550             :                               struct torture_test_witness_state *s)
     551             : {
     552             :         struct clusapi_CreateEnum r;
     553             :         struct ENUM_LIST *ReturnEnum;
     554             :         WERROR rpc_status;
     555             :         struct dcerpc_binding_handle *b;
     556             : 
     557             :         torture_assert(tctx,
     558             :                 setup_clusapi_connection(tctx, s),
     559             :                 "failed to setup clusapi connection");
     560             : 
     561             :         b = s->clusapi.p->binding_handle;
     562             : 
     563             :         r.in.dwType = CLUSTER_ENUM_NODE;
     564             :         r.out.ReturnEnum = &ReturnEnum;
     565             :         r.out.rpc_status = &rpc_status;
     566             : 
     567             :         torture_assert_ntstatus_ok(tctx,
     568             :                 dcerpc_clusapi_CreateEnum_r(b, tctx, &r),
     569             :                 "failed to enumerate nodes");
     570             : 
     571             :         return true;
     572             : }
     573             : #endif
     574             : 
     575           0 : static bool test_GetResourceState_int(struct torture_context *tctx,
     576             :                                       struct dcerpc_pipe *p,
     577             :                                       struct policy_handle *hResource,
     578             :                                       enum clusapi_ClusterResourceState *State)
     579             : {
     580           0 :         struct dcerpc_binding_handle *b = p->binding_handle;
     581           0 :         struct clusapi_GetResourceState r;
     582           0 :         const char *NodeName;
     583           0 :         const char *GroupName;
     584           0 :         WERROR rpc_status;
     585             : 
     586           0 :         r.in.hResource = *hResource;
     587           0 :         r.out.State = State;
     588           0 :         r.out.NodeName = &NodeName;
     589           0 :         r.out.GroupName = &GroupName;
     590           0 :         r.out.rpc_status = &rpc_status;
     591             : 
     592           0 :         torture_assert_ntstatus_ok(tctx,
     593             :                 dcerpc_clusapi_GetResourceState_r(b, tctx, &r),
     594             :                 "GetResourceState failed");
     595           0 :         torture_assert_werr_ok(tctx,
     596             :                 r.out.result,
     597             :                 "GetResourceState failed");
     598             : 
     599           0 :         return true;
     600             : }
     601             : 
     602           0 : static bool toggle_cluster_resource_state(struct torture_context *tctx,
     603             :                                           struct dcerpc_pipe *p,
     604             :                                           const char *resource_name,
     605             :                                           enum clusapi_ClusterResourceState *old_state,
     606             :                                           enum clusapi_ClusterResourceState *new_state)
     607             : {
     608           0 :         struct policy_handle hResource;
     609           0 :         enum clusapi_ClusterResourceState State;
     610             : 
     611           0 :         torture_assert(tctx,
     612             :                 test_OpenResource_int(tctx, p, resource_name, &hResource),
     613             :                 "failed to open resource");
     614           0 :         torture_assert(tctx,
     615             :                 test_GetResourceState_int(tctx, p, &hResource, &State),
     616             :                 "failed to query resource state");
     617             : 
     618           0 :         if (old_state) {
     619           0 :                 *old_state = State;
     620             :         }
     621             : 
     622           0 :         switch (State) {
     623           0 :         case ClusterResourceOffline:
     624           0 :                 if (!test_OnlineResource_int(tctx, p, &hResource)) {
     625           0 :                         test_CloseResource_int(tctx, p, &hResource);
     626           0 :                         torture_warning(tctx, "failed to set resource online");
     627           0 :                         return false;
     628             :                 }
     629           0 :                 break;
     630           0 :         case ClusterResourceOnline:
     631           0 :                 if (!test_OfflineResource_int(tctx, p, &hResource)) {
     632           0 :                         test_CloseResource_int(tctx, p, &hResource);
     633           0 :                         torture_warning(tctx, "failed to set resource offline");
     634           0 :                         return false;
     635             :                 }
     636           0 :                 break;
     637             : 
     638           0 :         default:
     639           0 :                 break;
     640             :         }
     641             : 
     642           0 :         torture_assert(tctx,
     643             :                 test_GetResourceState_int(tctx, p, &hResource, &State),
     644             :                 "failed to query resource state");
     645             : 
     646           0 :         if (new_state) {
     647           0 :                 *new_state = State;
     648             :         }
     649             : 
     650           0 :         test_CloseResource_int(tctx, p, &hResource);
     651             : 
     652           0 :         return true;
     653             : }
     654             : 
     655           0 : static bool test_witness_AsyncNotify(struct torture_context *tctx,
     656             :                                      struct dcerpc_pipe *p,
     657             :                                      void *data)
     658             : {
     659           0 :         struct dcerpc_binding_handle *b = p->binding_handle;
     660           0 :         struct witness_AsyncNotify r;
     661           0 :         struct witness_notifyResponse *response;
     662           0 :         struct torture_test_witness_state *state =
     663             :                 (struct torture_test_witness_state *)data;
     664           0 :         int i;
     665             : 
     666           0 :         init_witness_test_state(tctx, p, state);
     667             : 
     668           0 :         setup_clusapi_connection(tctx, state);
     669             : 
     670           0 :         for (i=0; state->list && i < state->list->num_interfaces; i++) {
     671             : 
     672           0 :                 const char *ip_address;
     673           0 :                 struct witness_interfaceInfo interface = state->list->interfaces[i];
     674           0 :                 struct witness_Register reg;
     675           0 :                 struct tevent_req *req;
     676           0 :                 enum clusapi_ClusterResourceState old_state, new_state;
     677             : 
     678           0 :                 if (!check_valid_interface(tctx, &interface)) {
     679           0 :                         continue;
     680             :                 }
     681             : 
     682           0 :                 torture_assert(tctx,
     683             :                         get_ip_address_from_interface(tctx, &interface, &ip_address),
     684             :                         "failed to get ip_address from interface");
     685             : 
     686           0 :                 reg.in.version = WITNESS_V1;
     687           0 :                 reg.in.net_name = state->net_name;
     688           0 :                 reg.in.ip_address = ip_address;
     689           0 :                 reg.in.client_computer_name = lpcfg_netbios_name(tctx->lp_ctx);
     690           0 :                 reg.out.context_handle = &state->context_handle;
     691             : 
     692           0 :                 torture_assert_ntstatus_ok(tctx,
     693             :                         dcerpc_witness_Register_r(b, tctx, &reg),
     694             :                         "Register failed");
     695             : 
     696           0 :                 torture_assert_werr_ok(tctx,
     697             :                         reg.out.result,
     698             :                         "Register failed");
     699             : 
     700           0 :                 r.in.context_handle = state->context_handle;
     701           0 :                 r.out.response = &response;
     702             : 
     703           0 :                 req = dcerpc_witness_AsyncNotify_r_send(tctx, tctx->ev, b, &r);
     704           0 :                 torture_assert(tctx, req, "failed to create request");
     705             : 
     706           0 :                 torture_assert(tctx,
     707             :                         toggle_cluster_resource_state(tctx, state->clusapi.p, state->net_name, &old_state, &new_state),
     708             :                         "failed to toggle cluster resource state");
     709           0 :                 torture_assert(tctx, old_state != new_state, "failed to change cluster resource state");
     710             : 
     711           0 :                 torture_assert(tctx,
     712             :                         tevent_req_poll(req, tctx->ev),
     713             :                         "failed to call event loop");
     714             : 
     715           0 :                 torture_assert_ntstatus_ok(tctx,
     716             :                         dcerpc_witness_AsyncNotify_r_recv(req, tctx),
     717             :                         "failed to receive reply");
     718             : 
     719           0 :                 torture_assert_int_equal(tctx, response->num, 1, "num");
     720           0 :                 torture_assert_int_equal(tctx, response->type, WITNESS_NOTIFY_RESOURCE_CHANGE, "type");
     721             : 
     722             :                 /*
     723             :                  * TODO: find out how ClusterResourceOfflinePending and
     724             :                  * ClusterResourceOnlinePending are represented as witness
     725             :                  * types.
     726             :                  */
     727             : 
     728           0 :                 if (new_state == ClusterResourceOffline) {
     729           0 :                         torture_assert_int_equal(tctx, response->messages[0].resource_change.type, WITNESS_RESOURCE_STATE_UNAVAILABLE, "resource_change.type");
     730             :                 }
     731           0 :                 if (new_state == ClusterResourceOnline) {
     732           0 :                         torture_assert_int_equal(tctx, response->messages[0].resource_change.type, WITNESS_RESOURCE_STATE_AVAILABLE, "resource_change.type");
     733             :                 }
     734           0 :                 torture_assert(tctx,
     735             :                         test_witness_UnRegister_with_handle(tctx, p, &state->context_handle),
     736             :                         "Failed to unregister");
     737             : 
     738           0 :                 ZERO_STRUCT(state->context_handle);
     739             : 
     740           0 :                 torture_assert(tctx,
     741             :                         toggle_cluster_resource_state(tctx, state->clusapi.p, state->net_name, &old_state, &new_state),
     742             :                         "failed to toggle cluster resource state");
     743           0 :                 torture_assert(tctx, old_state != new_state, "failed to change cluster resource state");
     744             :         }
     745             : 
     746           0 :         return true;
     747             : }
     748             : 
     749           0 : static bool test_do_witness_RegisterEx(struct torture_context *tctx,
     750             :                                        struct dcerpc_binding_handle *b,
     751             :                                        uint32_t version,
     752             :                                        const char *net_name,
     753             :                                        const char *share_name,
     754             :                                        const char *ip_address,
     755             :                                        const char *client_computer_name,
     756             :                                        uint32_t flags,
     757             :                                        uint32_t timeout,
     758             :                                        struct policy_handle *context_handle)
     759             : {
     760           0 :         struct witness_RegisterEx r;
     761             : 
     762           0 :         r.in.version = version;
     763           0 :         r.in.net_name = net_name;
     764           0 :         r.in.share_name = NULL;
     765           0 :         r.in.ip_address = ip_address;
     766           0 :         r.in.client_computer_name = client_computer_name;
     767           0 :         r.in.flags = flags;
     768           0 :         r.in.timeout = timeout;
     769           0 :         r.out.context_handle = context_handle;
     770             : 
     771           0 :         torture_assert_ntstatus_ok(tctx,
     772             :                 dcerpc_witness_RegisterEx_r(b, tctx, &r),
     773             :                 "RegisterEx failed");
     774             : 
     775           0 :         torture_assert_werr_ok(tctx,
     776             :                 r.out.result,
     777             :                 "RegisterEx failed");
     778             : 
     779           0 :         return true;
     780             : }
     781             : 
     782           0 : static void torture_subunit_report_time(struct torture_context *tctx)
     783             : {
     784           0 :         struct timespec tp;
     785           0 :         struct tm *tmp;
     786           0 :         char timestr[200];
     787             : 
     788           0 :         if (clock_gettime(CLOCK_REALTIME, &tp) != 0) {
     789           0 :                 torture_comment(tctx, "failed to call clock_gettime");
     790           0 :                 return;
     791             :         }
     792             : 
     793           0 :         tmp = gmtime(&tp.tv_sec);
     794           0 :         if (!tmp) {
     795           0 :                 torture_comment(tctx, "failed to call gmtime");
     796           0 :                 return;
     797             :         }
     798             : 
     799           0 :         if (strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S", tmp) <= 0) {
     800           0 :                 torture_comment(tctx, "failed to call strftime");
     801           0 :                 return;
     802             :         }
     803             : 
     804           0 :         torture_comment(tctx, "time: %s.%06ld\n", timestr, tp.tv_nsec / 1000);
     805             : }
     806             : 
     807           0 : static bool test_witness_AsyncNotify_timeouts(struct torture_context *tctx,
     808             :                                               struct dcerpc_pipe *p,
     809             :                                               void *data)
     810             : {
     811           0 :         struct dcerpc_binding_handle *b = p->binding_handle;
     812           0 :         struct witness_AsyncNotify r;
     813           0 :         struct witness_notifyResponse *response;
     814           0 :         struct torture_test_witness_state *state =
     815             :                 (struct torture_test_witness_state *)data;
     816           0 :         int i;
     817             : 
     818           0 :         init_witness_test_state(tctx, p, state);
     819             : 
     820           0 :         setup_clusapi_connection(tctx, state);
     821             : 
     822           0 :         for (i=0; state->list && i < state->list->num_interfaces; i++) {
     823             : 
     824           0 :                 const char *ip_address;
     825           0 :                 struct witness_interfaceInfo interface = state->list->interfaces[i];
     826           0 :                 uint32_t timeouts[] = {
     827             :                         0, 1, 10, 100, 120
     828             :                 };
     829           0 :                 int t;
     830           0 :                 uint32_t old_timeout;
     831             : 
     832           0 :                 if (!check_valid_interface(tctx, &interface)) {
     833           0 :                         continue;
     834             :                 }
     835             : 
     836           0 :                 torture_assert(tctx,
     837             :                         get_ip_address_from_interface(tctx, &interface, &ip_address),
     838             :                         "failed to get ip_address from interface");
     839             : 
     840           0 :                 for (t=0; t < ARRAY_SIZE(timeouts); t++) {
     841             : 
     842           0 :                         torture_comment(tctx, "Testing Async Notify with timeout of %d milliseconds", timeouts[t]);
     843             : 
     844           0 :                         torture_assert(tctx,
     845             :                                 test_do_witness_RegisterEx(tctx, b,
     846             :                                                            WITNESS_V2,
     847             :                                                            state->net_name,
     848             :                                                            NULL,
     849             :                                                            ip_address,
     850             :                                                            lpcfg_netbios_name(tctx->lp_ctx),
     851             :                                                            0,
     852             :                                                            timeouts[t],
     853             :                                                            &state->context_handle),
     854             :                                 "failed to RegisterEx");
     855             : 
     856           0 :                         r.in.context_handle = state->context_handle;
     857           0 :                         r.out.response = &response;
     858             : 
     859           0 :                         old_timeout = dcerpc_binding_handle_set_timeout(b, UINT_MAX);
     860             : 
     861           0 :                         torture_subunit_report_time(tctx);
     862             : 
     863           0 :                         torture_assert_ntstatus_ok(tctx,
     864             :                                 dcerpc_witness_AsyncNotify_r(b, tctx, &r),
     865             :                                 "AsyncNotify failed");
     866           0 :                         torture_assert_werr_equal(tctx,
     867             :                                 r.out.result,
     868             :                                 WERR_TIMEOUT,
     869             :                                 "AsyncNotify failed");
     870             : 
     871           0 :                         torture_subunit_report_time(tctx);
     872             : 
     873           0 :                         dcerpc_binding_handle_set_timeout(b, old_timeout);
     874             : 
     875           0 :                         torture_assert(tctx,
     876             :                                 test_witness_UnRegister_with_handle(tctx, p, &state->context_handle),
     877             :                                 "Failed to unregister");
     878             : 
     879           0 :                         ZERO_STRUCT(state->context_handle);
     880             :                 }
     881             :         }
     882             : 
     883           0 :         return true;
     884             : }
     885             : 
     886        2354 : struct torture_suite *torture_rpc_witness(TALLOC_CTX *mem_ctx)
     887             : {
     888         125 :         struct torture_rpc_tcase *tcase;
     889        2354 :         struct torture_suite *suite = torture_suite_create(mem_ctx, "witness");
     890         125 :         struct torture_test_witness_state *state;
     891             : 
     892        2354 :         tcase = torture_suite_add_rpc_iface_tcase(suite, "witness",
     893             :                                                   &ndr_table_witness);
     894             : 
     895        2354 :         state = talloc_zero(tcase, struct torture_test_witness_state);
     896             : 
     897        2354 :         torture_rpc_tcase_add_test_ex(tcase, "GetInterfaceList",
     898             :                                       test_witness_GetInterfaceList, state);
     899        2354 :         torture_rpc_tcase_add_test_ex(tcase, "Register",
     900             :                                       test_witness_Register, state);
     901        2354 :         torture_rpc_tcase_add_test_ex(tcase, "UnRegister",
     902             :                                       test_witness_UnRegister, state);
     903        2354 :         torture_rpc_tcase_add_test_ex(tcase, "RegisterEx",
     904             :                                       test_witness_RegisterEx, state);
     905        2354 :         torture_rpc_tcase_add_test_ex(tcase, "AsyncNotify",
     906             :                                       test_witness_AsyncNotify, state);
     907        2354 :         torture_rpc_tcase_add_test_ex(tcase, "AsyncNotify_timeouts",
     908             :                                       test_witness_AsyncNotify_timeouts, state);
     909             : 
     910        2354 :         return suite;
     911             : }

Generated by: LCOV version 1.14