summaryrefslogtreecommitdiff
path: root/libcli
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2015-07-20 14:00:05 +0200
committerGünther Deschner <gd@samba.org>2019-09-20 01:14:43 +0000
commit6e47f9ab37744d628cc6b723f4838e81202f2df6 (patch)
tree3612996ddd524b9b0f3afdf32ff9f13c515f95f1 /libcli
parent8f0751b8b7cd45fc7186b467d814eb5231821e34 (diff)
downloadsamba-6e47f9ab37744d628cc6b723f4838e81202f2df6.tar.gz
libcli/auth: add netlogon_creds_cli_LogonGetDomainInfo()
Signed-off-by: Stefan Metzmacher <metze@samba.org> Reviewed-by: Guenther Deschner <gd@samba.org>
Diffstat (limited to 'libcli')
-rw-r--r--libcli/auth/netlogon_creds_cli.c281
-rw-r--r--libcli/auth/netlogon_creds_cli.h17
2 files changed, 297 insertions, 1 deletions
diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c
index c5a100c3c0e..3cc18e7fa60 100644
--- a/libcli/auth/netlogon_creds_cli.c
+++ b/libcli/auth/netlogon_creds_cli.c
@@ -3528,7 +3528,6 @@ NTSTATUS netlogon_creds_cli_GetForestTrustInformation(
TALLOC_FREE(frame);
return status;
}
-
struct netlogon_creds_cli_SendToSam_state {
struct tevent_context *ev;
struct netlogon_creds_cli_context *context;
@@ -3793,3 +3792,283 @@ NTSTATUS netlogon_creds_cli_SendToSam(struct netlogon_creds_cli_context *context
TALLOC_FREE(frame);
return status;
}
+
+struct netlogon_creds_cli_LogonGetDomainInfo_state {
+ struct tevent_context *ev;
+ struct netlogon_creds_cli_context *context;
+ struct dcerpc_binding_handle *binding_handle;
+
+ char *srv_name_slash;
+ enum dcerpc_AuthType auth_type;
+ enum dcerpc_AuthLevel auth_level;
+
+ uint32_t level;
+ union netr_WorkstationInfo *query;
+ union netr_DomainInfo *info;
+
+ struct netlogon_creds_CredentialState *creds;
+ struct netlogon_creds_CredentialState tmp_creds;
+ struct netr_Authenticator req_auth;
+ struct netr_Authenticator rep_auth;
+};
+
+static void netlogon_creds_cli_LogonGetDomainInfo_cleanup(struct tevent_req *req,
+ NTSTATUS status);
+static void netlogon_creds_cli_LogonGetDomainInfo_locked(struct tevent_req *subreq);
+
+struct tevent_req *netlogon_creds_cli_LogonGetDomainInfo_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct netlogon_creds_cli_context *context,
+ struct dcerpc_binding_handle *b,
+ uint32_t level,
+ union netr_WorkstationInfo *query)
+{
+ struct tevent_req *req;
+ struct netlogon_creds_cli_LogonGetDomainInfo_state *state;
+ struct tevent_req *subreq;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct netlogon_creds_cli_LogonGetDomainInfo_state);
+ if (req == NULL) {
+ return NULL;
+ }
+
+ state->ev = ev;
+ state->context = context;
+ state->binding_handle = b;
+
+ state->srv_name_slash = talloc_asprintf(state, "\\\\%s",
+ context->server.computer);
+ if (tevent_req_nomem(state->srv_name_slash, req)) {
+ return tevent_req_post(req, ev);
+ }
+
+ state->level = level;
+ state->query = query;
+ state->info = talloc_zero(state, union netr_DomainInfo);
+ if (tevent_req_nomem(state->info, req)) {
+ return tevent_req_post(req, ev);
+ }
+
+ dcerpc_binding_handle_auth_info(state->binding_handle,
+ &state->auth_type,
+ &state->auth_level);
+
+ subreq = netlogon_creds_cli_lock_send(state, state->ev,
+ state->context);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+
+ tevent_req_set_callback(subreq,
+ netlogon_creds_cli_LogonGetDomainInfo_locked,
+ req);
+
+ return req;
+}
+
+static void netlogon_creds_cli_LogonGetDomainInfo_cleanup(struct tevent_req *req,
+ NTSTATUS status)
+{
+ struct netlogon_creds_cli_LogonGetDomainInfo_state *state =
+ tevent_req_data(req,
+ struct netlogon_creds_cli_LogonGetDomainInfo_state);
+
+ if (state->creds == NULL) {
+ return;
+ }
+
+ if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED) &&
+ !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) &&
+ !NT_STATUS_EQUAL(status, NT_STATUS_DOWNGRADE_DETECTED) &&
+ !NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
+ !NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
+ TALLOC_FREE(state->creds);
+ return;
+ }
+
+ netlogon_creds_cli_delete(state->context, state->creds);
+}
+
+static void netlogon_creds_cli_LogonGetDomainInfo_done(struct tevent_req *subreq);
+
+static void netlogon_creds_cli_LogonGetDomainInfo_locked(struct tevent_req *subreq)
+{
+ struct tevent_req *req =
+ tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct netlogon_creds_cli_LogonGetDomainInfo_state *state =
+ tevent_req_data(req,
+ struct netlogon_creds_cli_LogonGetDomainInfo_state);
+ NTSTATUS status;
+
+ status = netlogon_creds_cli_lock_recv(subreq, state,
+ &state->creds);
+ TALLOC_FREE(subreq);
+ if (tevent_req_nterror(req, status)) {
+ return;
+ }
+
+ if (state->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
+ switch (state->auth_level) {
+ case DCERPC_AUTH_LEVEL_INTEGRITY:
+ case DCERPC_AUTH_LEVEL_PRIVACY:
+ break;
+ default:
+ tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
+ return;
+ }
+ } else {
+ uint32_t tmp = state->creds->negotiate_flags;
+
+ if (tmp & NETLOGON_NEG_AUTHENTICATED_RPC) {
+ /*
+ * if DCERPC_AUTH_TYPE_SCHANNEL is supported
+ * it should be used, which means
+ * we had a chance to verify no downgrade
+ * happened.
+ *
+ * This relies on netlogon_creds_cli_check*
+ * being called before, as first request after
+ * the DCERPC bind.
+ */
+ tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
+ return;
+ }
+ }
+
+ /*
+ * we defer all callbacks in order to cleanup
+ * the database record.
+ */
+ tevent_req_defer_callback(req, state->ev);
+
+ state->tmp_creds = *state->creds;
+ netlogon_creds_client_authenticator(&state->tmp_creds,
+ &state->req_auth);
+ ZERO_STRUCT(state->rep_auth);
+
+ subreq = dcerpc_netr_LogonGetDomainInfo_send(state, state->ev,
+ state->binding_handle,
+ state->srv_name_slash,
+ state->tmp_creds.computer_name,
+ &state->req_auth,
+ &state->rep_auth,
+ state->level,
+ state->query,
+ state->info);
+ if (tevent_req_nomem(subreq, req)) {
+ status = NT_STATUS_NO_MEMORY;
+ netlogon_creds_cli_LogonGetDomainInfo_cleanup(req, status);
+ return;
+ }
+
+ tevent_req_set_callback(subreq,
+ netlogon_creds_cli_LogonGetDomainInfo_done,
+ req);
+}
+
+static void netlogon_creds_cli_LogonGetDomainInfo_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req =
+ tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct netlogon_creds_cli_LogonGetDomainInfo_state *state =
+ tevent_req_data(req,
+ struct netlogon_creds_cli_LogonGetDomainInfo_state);
+ NTSTATUS status;
+ NTSTATUS result;
+ bool ok;
+
+ /*
+ * We use state->dns_names as the memory context, as this is
+ * the only in/out variable and it has been overwritten by the
+ * out parameter from the server.
+ *
+ * We need to preserve the return value until the caller can use it.
+ */
+ status = dcerpc_netr_LogonGetDomainInfo_recv(subreq, state->info, &result);
+ TALLOC_FREE(subreq);
+ if (tevent_req_nterror(req, status)) {
+ netlogon_creds_cli_LogonGetDomainInfo_cleanup(req, status);
+ return;
+ }
+
+ ok = netlogon_creds_client_check(&state->tmp_creds,
+ &state->rep_auth.cred);
+ if (!ok) {
+ status = NT_STATUS_ACCESS_DENIED;
+ tevent_req_nterror(req, status);
+ netlogon_creds_cli_LogonGetDomainInfo_cleanup(req, status);
+ return;
+ }
+
+ if (tevent_req_nterror(req, result)) {
+ netlogon_creds_cli_LogonGetDomainInfo_cleanup(req, result);
+ return;
+ }
+
+ *state->creds = state->tmp_creds;
+ status = netlogon_creds_cli_store(state->context,
+ state->creds);
+ if (tevent_req_nterror(req, status)) {
+ netlogon_creds_cli_LogonGetDomainInfo_cleanup(req, status);
+ return;
+ }
+
+ tevent_req_done(req);
+}
+
+NTSTATUS netlogon_creds_cli_LogonGetDomainInfo_recv(struct tevent_req *req,
+ TALLOC_CTX *mem_ctx,
+ union netr_DomainInfo **info)
+{
+ struct netlogon_creds_cli_LogonGetDomainInfo_state *state =
+ tevent_req_data(req,
+ struct netlogon_creds_cli_LogonGetDomainInfo_state);
+ NTSTATUS status;
+
+ if (tevent_req_is_nterror(req, &status)) {
+ netlogon_creds_cli_LogonGetDomainInfo_cleanup(req, status);
+ tevent_req_received(req);
+ return status;
+ }
+
+ *info = talloc_move(mem_ctx, &state->info);
+
+ tevent_req_received(req);
+ return NT_STATUS_OK;
+}
+
+NTSTATUS netlogon_creds_cli_LogonGetDomainInfo(
+ struct netlogon_creds_cli_context *context,
+ struct dcerpc_binding_handle *b,
+ TALLOC_CTX *mem_ctx,
+ uint32_t level,
+ union netr_WorkstationInfo *query,
+ union netr_DomainInfo **info)
+{
+ TALLOC_CTX *frame = talloc_stackframe();
+ struct tevent_context *ev;
+ struct tevent_req *req;
+ NTSTATUS status = NT_STATUS_OK;
+
+ ev = samba_tevent_context_init(frame);
+ if (ev == NULL) {
+ goto fail;
+ }
+ req = netlogon_creds_cli_LogonGetDomainInfo_send(frame, ev, context, b,
+ level, query);
+ if (req == NULL) {
+ goto fail;
+ }
+ if (!tevent_req_poll_ntstatus(req, ev, &status)) {
+ goto fail;
+ }
+ status = netlogon_creds_cli_LogonGetDomainInfo_recv(req,
+ mem_ctx,
+ info);
+ fail:
+ TALLOC_FREE(frame);
+ return status;
+}
diff --git a/libcli/auth/netlogon_creds_cli.h b/libcli/auth/netlogon_creds_cli.h
index 56a2dd9bc77..7fb41872c36 100644
--- a/libcli/auth/netlogon_creds_cli.h
+++ b/libcli/auth/netlogon_creds_cli.h
@@ -214,4 +214,21 @@ NTSTATUS netlogon_creds_cli_SendToSam(
struct dcerpc_binding_handle *b,
struct netr_SendToSamBase *message);
+struct tevent_req *netlogon_creds_cli_LogonGetDomainInfo_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct netlogon_creds_cli_context *context,
+ struct dcerpc_binding_handle *b,
+ uint32_t level,
+ union netr_WorkstationInfo *query);
+NTSTATUS netlogon_creds_cli_LogonGetDomainInfo_recv(struct tevent_req *req,
+ TALLOC_CTX *mem_ctx,
+ union netr_DomainInfo **info);
+NTSTATUS netlogon_creds_cli_LogonGetDomainInfo(
+ struct netlogon_creds_cli_context *context,
+ struct dcerpc_binding_handle *b,
+ TALLOC_CTX *mem_ctx,
+ uint32_t level,
+ union netr_WorkstationInfo *query,
+ union netr_DomainInfo **info);
+
#endif /* NETLOGON_CREDS_CLI_H */