-
-/*
- * Connect to LSA using the credentials, try NTLMSSP and SCHANNEL using the
- * given credentials. If both fail or no credentials are available, fall back
- * to an anonymous bind.
- */
-
-struct connect_lsa_state {
- struct composite_context *ctx;
- struct smbcli_tree *tree;
- struct cli_credentials *credentials;
-
- uint8_t auth_type;
- struct dcerpc_pipe *lsa_pipe;
- struct policy_handle *lsa_policy;
-};
-
-static void connect_lsa_recv_ntlmssp(struct composite_context *ctx);
-static void connect_lsa_recv_schannel(struct composite_context *ctx);
-static void connect_lsa_recv_anon(struct composite_context *ctx);
-
-struct composite_context *wb_connect_lsa_send(TALLOC_CTX *mem_ctx,
- struct smbcli_tree *tree,
- struct cli_credentials *credentials)
-{
- struct composite_context *result, *ctx;
- struct connect_lsa_state *state;
-
- result = talloc(mem_ctx, struct composite_context);
- if (result == NULL) goto failed;
- result->state = COMPOSITE_STATE_IN_PROGRESS;
- result->async.fn = NULL;
- result->event_ctx = tree->session->transport->socket->event.ctx;
-
- state = talloc(result, struct connect_lsa_state);
- if (state == NULL) goto failed;
- state->ctx = result;
- result->private_data = state;
-
- state->tree = tree;
- state->credentials = credentials;
-
- if (credentials == NULL) {
- ctx = wb_init_lsa_send(state, tree, DCERPC_AUTH_TYPE_NONE,
- NULL);
- if (ctx == NULL) goto failed;
- ctx->async.fn = connect_lsa_recv_anon;
- ctx->async.private_data = state;
- return result;
- }
-
- ctx = wb_init_lsa_send(state, tree, DCERPC_AUTH_TYPE_NTLMSSP,
- credentials);
- if (ctx == NULL) goto failed;
- ctx->async.fn = connect_lsa_recv_ntlmssp;
- ctx->async.private_data = state;
- return result;
-
- failed:
- talloc_free(result);
- return NULL;
-}
-
-static void connect_lsa_recv_ntlmssp(struct composite_context *ctx)
-{
- struct connect_lsa_state *state =
- talloc_get_type(ctx->async.private_data,
- struct connect_lsa_state);
-
- state->ctx->status = wb_init_lsa_recv(ctx, state, &state->lsa_pipe,
- &state->lsa_policy);
-
- if (NT_STATUS_IS_OK(state->ctx->status)) {
- state->auth_type = DCERPC_AUTH_TYPE_NTLMSSP;
- composite_done(state->ctx);
- return;
- }
-
- ctx = wb_init_lsa_send(state, state->tree, DCERPC_AUTH_TYPE_SCHANNEL,
- state->credentials);
- composite_continue(state->ctx, ctx,
- connect_lsa_recv_schannel, state);
-}
-
-static void connect_lsa_recv_schannel(struct composite_context *ctx)
-{
- struct connect_lsa_state *state =
- talloc_get_type(ctx->async.private_data,
- struct connect_lsa_state);
-
- state->ctx->status = wb_init_lsa_recv(ctx, state, &state->lsa_pipe,
- &state->lsa_policy);
-
- if (NT_STATUS_IS_OK(state->ctx->status)) {
- state->auth_type = DCERPC_AUTH_TYPE_SCHANNEL;
- composite_done(state->ctx);
- return;
- }
-
- ctx = wb_init_lsa_send(state, state->tree, DCERPC_AUTH_TYPE_NONE,
- state->credentials);
- composite_continue(state->ctx, ctx,
- connect_lsa_recv_anon, state);
-}
-
-static void connect_lsa_recv_anon(struct composite_context *ctx)
-{
- struct connect_lsa_state *state =
- talloc_get_type(ctx->async.private_data,
- struct connect_lsa_state);
-
- state->ctx->status = wb_init_lsa_recv(ctx, state, &state->lsa_pipe,
- &state->lsa_policy);
- if (!composite_is_ok(state->ctx)) return;
-
- state->auth_type = DCERPC_AUTH_TYPE_NONE;
- composite_done(state->ctx);
-}
-
-NTSTATUS wb_connect_lsa_recv(struct composite_context *c,
- TALLOC_CTX *mem_ctx,
- uint8_t *auth_type,
- struct dcerpc_pipe **lsa_pipe,
- struct policy_handle **lsa_policy)
-{
- NTSTATUS status = composite_wait(c);
- if (NT_STATUS_IS_OK(status)) {
- struct connect_lsa_state *state =
- talloc_get_type(c->private_data,
- struct connect_lsa_state);
- *auth_type = state->auth_type;
- *lsa_pipe = talloc_steal(mem_ctx, state->lsa_pipe);
- *lsa_policy = talloc_steal(mem_ctx, state->lsa_policy);
- }
- talloc_free(c);
- return status;
-}
-
-NTSTATUS wb_connect_lsa(TALLOC_CTX *mem_ctx,
- struct smbcli_tree *tree,
- struct cli_credentials *credentials,
- uint8_t *auth_type,
- struct dcerpc_pipe **lsa_pipe,
- struct policy_handle **lsa_policy)
-{
- struct composite_context *c;
- c = wb_connect_lsa_send(mem_ctx, tree, credentials);
- return wb_connect_lsa_recv(c, mem_ctx, auth_type, lsa_pipe,
- lsa_policy);
-}