Files
wmic/Samba/source/torture/dcom/dcom.c
T
2019-02-16 00:16:52 +01:00

400 lines
12 KiB
C

/*
DCOM torture tester
Copyright (C) Zenoss, Inc. 2008
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "includes.h"
#include "auth/credentials/credentials.h"
#include "lib/cmdline/popt_common.h"
#include "librpc/rpc/dcerpc.h"
#include "torture/rpc/rpc.h"
#include "torture/torture.h"
#include "librpc/rpc/dcerpc_table.h"
#include "lib/util/dlinklist.h"
#include "libcli/composite/composite.h"
#include "lib/com/com.h"
#include "librpc/gen_ndr/com_dcom.h"
#include "lib/com/dcom/dcom.h"
#include "wmi/wmi.h"
/*
* Test activating the IWbemLevel1Login interface synchronously.
*/
static BOOL torture_wbem_login(struct torture_context *torture)
{
BOOL ret = True;
TALLOC_CTX *mem_ctx = talloc_init("torture_wbem_login");
struct com_context *com_ctx = NULL;
const char *binding = NULL;
struct IUnknown **mqi = NULL;
struct GUID clsid;
struct GUID iid;
NTSTATUS status;
/*
* Initialize our COM and DCOM contexts.
*/
com_init_ctx(&com_ctx, NULL);
dcom_client_init(com_ctx, cmdline_credentials);
/*
* Pull our needed test arguments from the torture parameters subsystem.
*/
binding = torture_setting_string(torture, "binding", NULL);
/*
* Create the parameters needed for the activation call: we need the CLSID
* and IID for the specific interface we're after.
*/
GUID_from_string(CLSID_WBEMLEVEL1LOGIN, &clsid);
GUID_from_string(COM_IWBEMLEVEL1LOGIN_UUID, &iid);
/*
* Activate the interface using the DCOM synchronous method call.
*/
status = dcom_activate(com_ctx, mem_ctx, binding, &clsid, &iid, 1, &mqi);
ret = NT_STATUS_IS_OK(status);
if (ret)
{
/*
* Clean up by releasing the IUnknown interface on the remote server
* and also by releasing our allocated interface pointer.
*/
IUnknown_Release(mqi[0], mem_ctx);
talloc_free(mqi);
}
talloc_report_full(mem_ctx, stdout);
return ret;
}
/*
* Test activating the IWbemLevel1Login interface asynchronously.
*/
static void torture_wbem_login_async_cont(struct composite_context *ctx)
{
struct composite_context *c = NULL;
BOOL *pRet = NULL;
struct IUnknown **mqi = NULL;
NTSTATUS status;
/* retrieve the parent composite context */
c = talloc_get_type(ctx->async.private_data, struct composite_context);
if (!composite_is_ok(c)) return;
pRet = (BOOL *)c->private_data;
status = dcom_activate_recv(ctx, c, &mqi);
*pRet = NT_STATUS_IS_OK(status);
talloc_report_full(c, stdout);
if (*pRet)
{
/*
* Clean up by releasing the IUnknown interface on the remote server
* and also by releasing our allocated interface pointer.
*/
IUnknown_Release(mqi[0], c); /* really synchronous but eh */
talloc_free(mqi);
}
composite_done(c);
}
static BOOL torture_wbem_login_async(struct torture_context *torture)
{
BOOL ret = True;
TALLOC_CTX *mem_ctx = talloc_init("torture_wbem_login_async");
struct com_context *com_ctx = NULL;
const char *binding = NULL;
struct composite_context *c = NULL;
struct composite_context *new_ctx = NULL;
struct GUID clsid;
struct GUID iid;
/*
* Initialize our COM and DCOM contexts.
*/
com_init_ctx(&com_ctx, NULL);
dcom_client_init(com_ctx, cmdline_credentials);
/*
* Pull our needed test arguments from the torture parameters subsystem.
*/
binding = torture_setting_string(torture, "binding", NULL);
/*
* Create a new composite for our call sequence, with the private data being
* our return flag.
*/
c = composite_create(mem_ctx, com_ctx->event_ctx);
c->private_data = &ret;
/*
* Create the parameters needed for the activation call: we need the CLSID
* and IID for the specific interface we're after.
*/
GUID_from_string(CLSID_WBEMLEVEL1LOGIN, &clsid);
GUID_from_string(COM_IWBEMLEVEL1LOGIN_UUID, &iid);
/*
* Fire off the asynchronous activation request with all the needed
* input parameters. Then wait for the composite to be done within the
* context of this function, which allows all the asynchronous magic to
* still happen.
*/
new_ctx = dcom_activate_send(c, &clsid, binding, 1, &iid, com_ctx);
composite_continue(c, new_ctx, torture_wbem_login_async_cont, c);
composite_wait(new_ctx);
talloc_free(c);
talloc_report_full(mem_ctx, stdout);
return ret;
}
struct wbem_exec_query_state
{
NTSTATUS status;
struct IWbemServices *pServices;
struct IEnumWbemClassObject *pEnum;
};
static void wbem_enum_release_continue(struct composite_context *ctx)
{
struct composite_context *c = NULL;
/* retrieve the parent composite context */
c = talloc_get_type(ctx->async.private_data, struct composite_context);
(void)IUnknown_Release_recv(ctx);
composite_done(c);
}
static void wbem_enum_next_continue(struct composite_context *ctx)
{
struct composite_context *c = NULL;
struct composite_context *new_ctx = NULL;
struct wbem_exec_query_state *s = NULL;
struct WbemClassObject **apObjects = NULL;
uint32_t uReturned = 0;
WERROR result;
/* retrieve the parent composite context */
c = talloc_get_type(ctx->async.private_data, struct composite_context);
s = talloc_get_type(c->private_data, struct wbem_exec_query_state);
apObjects = talloc_array(c, struct WbemClassObject *, 7);
if (composite_nomem(apObjects, c)) return;
result = IEnumWbemClassObject_SmartNext_recv(ctx, c, apObjects, &uReturned);
if (W_ERROR_IS_OK(result))
{
DEBUG(1, ("wbem_enum_next_continue: %u objects returned\n", uReturned));
if (uReturned == 0)
{
new_ctx = IUnknown_Release_send((struct IUnknown *)s->pEnum, c);
if (composite_nomem(new_ctx, c)) return;
composite_continue(c, new_ctx, wbem_enum_release_continue, c);
}
else
{
new_ctx = IEnumWbemClassObject_SmartNext_send(s->pEnum,
c, 0xFFFFFFFF, 7); /* 0xffffffff = lTimeout, 7 = uCount */
if (composite_nomem(new_ctx, c)) return;
composite_continue(c, new_ctx, wbem_enum_next_continue, c);
}
}
else
{
DEBUG(1, ("wbem_enum_next_continue: %08x %s\n", W_ERROR_V(result),
wmi_errstr(result)));
composite_error(c, werror_to_ntstatus(result));
}
}
static void wbem_exec_query_continue3(struct composite_context *ctx)
{
struct composite_context *c = NULL;
struct composite_context *new_ctx = NULL;
struct wbem_exec_query_state *s = NULL;
WERROR result;
/* retrieve the parent composite context */
c = talloc_get_type(ctx->async.private_data, struct composite_context);
s = talloc_get_type(c->private_data, struct wbem_exec_query_state);
result = IEnumWbemClassObject_Reset_recv(ctx);
if (!W_ERROR_IS_OK(result))
{
s->status = werror_to_ntstatus(result);
composite_error(c, s->status);
return;
}
new_ctx = IEnumWbemClassObject_SmartNext_send(s->pEnum,
c, 0xFFFFFFFF, 7); /* 0xffffffff = lTimeout, 5 = uCount */
if (composite_nomem(new_ctx, c)) return;
composite_continue(c, new_ctx, wbem_enum_next_continue, c);
}
static void wbem_exec_query_continue2(struct composite_context *ctx)
{
struct composite_context *c = NULL;
struct wbem_exec_query_state *s = NULL;
struct composite_context *new_ctx = NULL;
WERROR result;
/* retrieve the parent composite context */
c = talloc_get_type(ctx->async.private_data, struct composite_context);
s = talloc_get_type(c->private_data, struct wbem_exec_query_state);
result = IWbemServices_ExecQuery_recv(ctx, &s->pEnum);
if (!W_ERROR_IS_OK(result))
{
s->status = werror_to_ntstatus(result);
composite_error(c, s->status);
return;
}
new_ctx = IEnumWbemClassObject_Reset_send(s->pEnum, c);
composite_continue(c, new_ctx, wbem_exec_query_continue3, c);
}
static void wbem_exec_query_continue(struct composite_context *ctx)
{
struct composite_context *c = NULL;
struct wbem_exec_query_state *s = NULL;
struct composite_context *new_ctx = NULL;
WERROR result;
/* retrieve the parent composite context */
c = talloc_get_type(ctx->async.private_data, struct composite_context);
s = talloc_get_type(c->private_data, struct wbem_exec_query_state);
result = WBEM_ConnectServer_recv(ctx, c, &s->pServices);
if (!W_ERROR_IS_OK(result))
{
s->status = werror_to_ntstatus(result);
composite_error(c, s->status);
return;
}
new_ctx = IWbemServices_ExecQuery_send(s->pServices, c, "WQL",
"SELECT * FROM Win32_NetworkAdapterConfiguration", 0, NULL);
composite_continue(c, new_ctx, wbem_exec_query_continue2, c);
}
static BOOL torture_wbem_exec_query_async(struct torture_context *torture)
{
BOOL ret = True;
TALLOC_CTX *mem_ctx = talloc_init("torture_wbem_login_async");
struct com_context *com_ctx = NULL;
struct composite_context *c = NULL;
struct composite_context *new_ctx = NULL;
const char *binding = NULL;
/*
* Initialize our COM and DCOM contexts.
*/
com_init_ctx(&com_ctx, NULL);
dcom_client_init(com_ctx, cmdline_credentials);
/*
* Pull our needed test arguments from the torture parameters subsystem.
*/
binding = torture_setting_string(torture, "binding", NULL);
/*
* Create a new composite for our call sequence, with the private data being
* our return flag.
*/
c = composite_create(mem_ctx, com_ctx->event_ctx);
c->private_data = talloc_zero(c, struct wbem_exec_query_state);
new_ctx = WBEM_ConnectServer_send(com_ctx,
mem_ctx, // parent_ctx
binding, // server
"root\\cimv2", // namespace
NULL, // user
NULL, // password
NULL, // locale
0, // flags
NULL, // authority
NULL); // wbem_ctx
composite_continue(c, new_ctx, wbem_exec_query_continue, c);
composite_wait(c);
ret = NT_STATUS_IS_OK(c->status);
talloc_free(c);
talloc_report_full(mem_ctx, stdout);
return ret;
}
NTSTATUS torture_dcom_init(void)
{
struct torture_suite *suite = torture_suite_create(
talloc_autofree_context(),
"DCOM");
/*
* Initialize all of the DCEPRC tables.
*/
dcerpc_init();
dcerpc_table_init();
/*
* Initialize all of the DCOM proxies.
*/
dcom_proxy_IUnknown_init();
dcom_proxy_IRemUnknown_init();
dcom_proxy_IWbemLevel1Login_init();
dcom_proxy_IWbemServices_init();
dcom_proxy_IEnumWbemClassObject_init();
dcom_proxy_IWbemFetchSmartEnum_init();
dcom_proxy_IWbemWCOSmartEnum_init();
/*
* Add all of the test cases in this suite.
*/
torture_suite_add_simple_test(suite, "WBEM-LOGIN", torture_wbem_login);
torture_suite_add_simple_test(suite, "WBEM-LOGIN-ASYNC",
torture_wbem_login_async);
torture_suite_add_simple_test(suite, "WBEM-EXEC-QUERY-ASYNC",
torture_wbem_exec_query_async);
/*
* Finish configuring our test suite and pass it back to the test subsystem.
*/
suite->description = talloc_strdup(suite,
"DCOM protocol and interface tests");
torture_register_suite(suite);
return NT_STATUS_OK;
}