diff options
-rw-r--r-- | source3/lib/netapi/netlogon.c | 183 |
1 files changed, 181 insertions, 2 deletions
diff --git a/source3/lib/netapi/netlogon.c b/source3/lib/netapi/netlogon.c index eb18a1edf6..082938cadc 100644 --- a/source3/lib/netapi/netlogon.c +++ b/source3/lib/netapi/netlogon.c @@ -24,13 +24,136 @@ #include "lib/netapi/netapi_private.h" #include "lib/netapi/libnetapi.h" +static WERROR construct_data(enum netr_LogonControlCode function_code, + const uint8_t *data_in, + union netr_CONTROL_DATA_INFORMATION *data_out) +{ + switch (function_code) { + case NETLOGON_CONTROL_QUERY: + case NETLOGON_CONTROL_REDISCOVER: + case NETLOGON_CONTROL_TC_QUERY: + case NETLOGON_CONTROL_CHANGE_PASSWORD: + case NETLOGON_CONTROL_TC_VERIFY: + data_out->domain = (const char *)data_in; + break; + case NETLOGON_CONTROL_FIND_USER: + data_out->user = (const char *)data_in; + break; + case NETLOGON_CONTROL_SET_DBFLAG: + data_out->debug_level = atoi((const char *)data_in); + break; + default: + return WERR_INVALID_PARAM; + } + + return WERR_OK; +} + +static WERROR construct_buffer(TALLOC_CTX *mem_ctx, + uint32_t level, + union netr_CONTROL_QUERY_INFORMATION *q, + uint8_t **buffer) +{ + struct NETLOGON_INFO_1 *i1; + struct NETLOGON_INFO_2 *i2; + struct NETLOGON_INFO_3 *i3; + struct NETLOGON_INFO_4 *i4; + + if (!q) { + return WERR_INVALID_PARAM; + } + + switch (level) { + case 1: + i1 = talloc(mem_ctx, struct NETLOGON_INFO_1); + W_ERROR_HAVE_NO_MEMORY(i1); + + i1->netlog1_flags = q->info1->flags; + i1->netlog1_pdc_connection_status = W_ERROR_V(q->info1->pdc_connection_status); + + *buffer = (uint8_t *)i1; + + break; + case 2: + i2 = talloc(mem_ctx, struct NETLOGON_INFO_2); + W_ERROR_HAVE_NO_MEMORY(i2); + + i2->netlog2_flags = q->info2->flags; + i2->netlog2_pdc_connection_status = W_ERROR_V(q->info2->pdc_connection_status); + i2->netlog2_trusted_dc_name = talloc_strdup(mem_ctx, q->info2->trusted_dc_name); + i2->netlog2_tc_connection_status = W_ERROR_V(q->info2->tc_connection_status); + + *buffer = (uint8_t *)i2; + + break; + case 3: + i3 = talloc(mem_ctx, struct NETLOGON_INFO_3); + W_ERROR_HAVE_NO_MEMORY(i3); + + i3->netlog1_flags = q->info3->flags; + i3->netlog3_logon_attempts = q->info3->logon_attempts; + i3->netlog3_reserved1 = q->info3->unknown1; + i3->netlog3_reserved2 = q->info3->unknown2; + i3->netlog3_reserved3 = q->info3->unknown3; + i3->netlog3_reserved4 = q->info3->unknown4; + i3->netlog3_reserved5 = q->info3->unknown5; + + *buffer = (uint8_t *)i3; + + break; + case 4: + i4 = talloc(mem_ctx, struct NETLOGON_INFO_4); + W_ERROR_HAVE_NO_MEMORY(i4); + + i4->netlog4_trusted_dc_name = talloc_strdup(mem_ctx, q->info4->trusted_dc_name); + i4->netlog4_trusted_domain_name = talloc_strdup(mem_ctx, q->info4->trusted_domain_name); + + *buffer = (uint8_t *)i4; + + break; + default: + return WERR_UNKNOWN_LEVEL; + } + return WERR_OK; +} + /**************************************************************** ****************************************************************/ WERROR I_NetLogonControl_r(struct libnetapi_ctx *ctx, struct I_NetLogonControl *r) { - return WERR_NOT_SUPPORTED; + WERROR werr; + NTSTATUS status; + struct rpc_pipe_client *pipe_cli = NULL; + union netr_CONTROL_QUERY_INFORMATION query; + + werr = libnetapi_open_pipe(ctx, r->in.server_name, + &ndr_table_netlogon.syntax_id, + &pipe_cli); + if (!W_ERROR_IS_OK(werr)) { + goto done; + } + + status = rpccli_netr_LogonControl(pipe_cli, ctx, + r->in.server_name, + r->in.function_code, + r->in.query_level, + &query, + &werr); + if (!NT_STATUS_IS_OK(status)) { + werr = ntstatus_to_werror(status); + goto done; + } + + werr = construct_buffer(ctx, r->in.query_level, &query, + r->out.buffer); + if (!W_ERROR_IS_OK(werr)) { + goto done; + } + + done: + return werr; } /**************************************************************** @@ -48,7 +171,63 @@ WERROR I_NetLogonControl_l(struct libnetapi_ctx *ctx, WERROR I_NetLogonControl2_r(struct libnetapi_ctx *ctx, struct I_NetLogonControl2 *r) { - return WERR_NOT_SUPPORTED; + WERROR werr; + NTSTATUS status; + struct rpc_pipe_client *pipe_cli = NULL; + union netr_CONTROL_DATA_INFORMATION data; + union netr_CONTROL_QUERY_INFORMATION query; + + werr = construct_data(r->in.function_code, r->in.data, &data); + if (!W_ERROR_IS_OK(werr)) { + goto done; + } + + werr = libnetapi_open_pipe(ctx, r->in.server_name, + &ndr_table_netlogon.syntax_id, + &pipe_cli); + if (!W_ERROR_IS_OK(werr)) { + goto done; + } + + switch (r->in.function_code) { + case NETLOGON_CONTROL_TC_VERIFY: + case NETLOGON_CONTROL_SET_DBFLAG: + status = rpccli_netr_LogonControl2Ex(pipe_cli, ctx, + r->in.server_name, + r->in.function_code, + r->in.query_level, + &data, + &query, + &werr); + break; + default: + status = rpccli_netr_LogonControl2(pipe_cli, ctx, + r->in.server_name, + r->in.function_code, + r->in.query_level, + &data, + &query, + &werr); + break; + } + + if (!W_ERROR_IS_OK(werr)) { + goto done; + } + + if (!NT_STATUS_IS_OK(status)) { + werr = ntstatus_to_werror(status); + goto done; + } + + werr = construct_buffer(ctx, r->in.query_level, &query, + r->out.buffer); + if (!W_ERROR_IS_OK(werr)) { + goto done; + } + + done: + return werr; } /**************************************************************** |