libcli/auth: add netlogon_creds_cli_LogonGetDomainInfo()
authorStefan Metzmacher <metze@samba.org>
Mon, 20 Jul 2015 12:00:05 +0000 (14:00 +0200)
committerGünther Deschner <gd@samba.org>
Fri, 20 Sep 2019 01:14:43 +0000 (01:14 +0000)
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Guenther Deschner <gd@samba.org>
libcli/auth/netlogon_creds_cli.c
libcli/auth/netlogon_creds_cli.h

index c5a100c3c0ee0a7472b35009aa2cb2716cc0e8ea..3cc18e7fa60fbac4d7d547e6700c17fb796ad218 100644 (file)
@@ -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;
+}
index 56a2dd9bc77bf653dc5f7ff0eb97da210c39d8c6..7fb41872c36cbd5bb70aca750a0c5911a1084a14 100644 (file)
@@ -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 */