summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/lib/netapi/netlogon.c183
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;
}
/****************************************************************