From d617556ef50863d6a03c81a04f0f6b05848a250e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 10 Oct 2005 19:57:55 +0000 Subject: r10878: Reply to some comments by tridge and metze: * rename the composite helper functions from comp_* to composite_* * Move the lsa initialization to wb_connect_lsa.c * Equip smb_composite_connect with a fallback_to_anonymous The latter two simplify wb_init_domain.c quite a bit. Volker (This used to be commit deb127e04ea01ae93394da5ebffb39d81caeb6d9) --- source4/winbind/config.mk | 1 + source4/winbind/wb_async_helpers.c | 68 ++++---- source4/winbind/wb_connect_lsa.c | 323 ++++++++++++++++++++++++++++++++++++ source4/winbind/wb_init_domain.c | 327 ++++++------------------------------- 4 files changed, 412 insertions(+), 307 deletions(-) create mode 100644 source4/winbind/wb_connect_lsa.c (limited to 'source4/winbind') diff --git a/source4/winbind/config.mk b/source4/winbind/config.mk index 991cce198a..f949f87106 100644 --- a/source4/winbind/config.mk +++ b/source4/winbind/config.mk @@ -10,6 +10,7 @@ INIT_OBJ_FILES = \ winbind/wb_samba3_protocol.o \ winbind/wb_samba3_cmd.o \ winbind/wb_init_domain.o \ + winbind/wb_connect_lsa.o \ winbind/wb_async_helpers.o REQUIRED_SUBSYSTEMS = RPC_NDR_LSA # End MODULE server_service_winbind diff --git a/source4/winbind/wb_async_helpers.c b/source4/winbind/wb_async_helpers.c index 001b147307..d7cbd702ea 100644 --- a/source4/winbind/wb_async_helpers.c +++ b/source4/winbind/wb_async_helpers.c @@ -103,17 +103,17 @@ static void finddcs_resolve(struct composite_context *ctx) const char *address; state->ctx->status = resolve_name_recv(ctx, state, &address); - if (!comp_is_ok(state->ctx)) return; + if (!composite_is_ok(state->ctx)) return; state->num_dcs = 1; state->dcs = talloc_array(state, struct nbt_dc_name, state->num_dcs); - if (comp_nomem(state->dcs, state->ctx)) return; + if (composite_nomem(state->dcs, state->ctx)) return; state->dcs[0].address = talloc_steal(state->dcs, address); nbt_servers = irpc_servers_byname(state->msg_ctx, "nbt_server"); if ((nbt_servers == NULL) || (nbt_servers[0] == 0)) { - comp_error(state->ctx, NT_STATUS_NO_LOGON_SERVERS); + composite_error(state->ctx, NT_STATUS_NO_LOGON_SERVERS); return; } @@ -122,15 +122,15 @@ static void finddcs_resolve(struct composite_context *ctx) state->r.in.my_computername = lp_netbios_name(); state->r.in.my_accountname = talloc_asprintf(state, "%s$", lp_netbios_name()); - if (comp_nomem(state->r.in.my_accountname, state->ctx)) return; + if (composite_nomem(state->r.in.my_accountname, state->ctx)) return; state->r.in.account_control = ACB_WSTRUST; state->r.in.domain_sid = dom_sid_dup(state, state->domain_sid); - if (comp_nomem(state->r.in.domain_sid, state->ctx)) return; + if (composite_nomem(state->r.in.domain_sid, state->ctx)) return; ireq = irpc_call_send(state->msg_ctx, nbt_servers[0], &dcerpc_table_irpc, DCERPC_NBTD_GETDCNAME, &state->r, state); - irpc_cont(state->ctx, ireq, finddcs_getdc, state); + composite_continue_irpc(state->ctx, ireq, finddcs_getdc, state); } static void finddcs_getdc(struct irpc_request *ireq) @@ -139,10 +139,10 @@ static void finddcs_getdc(struct irpc_request *ireq) talloc_get_type(ireq->async.private, struct finddcs_state); state->ctx->status = irpc_call_recv(ireq); - if (!comp_is_ok(state->ctx)) return; + if (!composite_is_ok(state->ctx)) return; state->dcs[0].name = talloc_steal(state->dcs, state->r.out.dcname); - comp_done(state->ctx); + composite_done(state->ctx); } NTSTATUS wb_finddcs_recv(struct composite_context *c, TALLOC_CTX *mem_ctx, @@ -228,31 +228,32 @@ static void get_schannel_creds_recv_pipe(struct composite_context *ctx) struct rpc_request *req; state->ctx->status = dcerpc_pipe_open_smb_recv(ctx); - if (!comp_is_ok(state->ctx)) return; + if (!composite_is_ok(state->ctx)) return; state->ctx->status = dcerpc_bind_auth_none(state->p, DCERPC_NETLOGON_UUID, DCERPC_NETLOGON_VERSION); - if (!comp_is_ok(state->ctx)) return; + if (!composite_is_ok(state->ctx)) return; state->r.in.computer_name = cli_credentials_get_workstation(state->wks_creds); state->r.in.server_name = talloc_asprintf(state, "\\\\%s", dcerpc_server_name(state->p)); - if (comp_nomem(state->r.in.server_name, state->ctx)) return; + if (composite_nomem(state->r.in.server_name, state->ctx)) return; state->r.in.credentials = talloc(state, struct netr_Credential); - if (comp_nomem(state->r.in.credentials, state->ctx)) return; + if (composite_nomem(state->r.in.credentials, state->ctx)) return; state->r.out.credentials = talloc(state, struct netr_Credential); - if (comp_nomem(state->r.out.credentials, state->ctx)) return; + if (composite_nomem(state->r.out.credentials, state->ctx)) return; generate_random_buffer(state->r.in.credentials->data, sizeof(state->r.in.credentials->data)); req = dcerpc_netr_ServerReqChallenge_send(state->p, state, &state->r); - rpc_cont(state->ctx, req, get_schannel_creds_recv_chal, state); + composite_continue_rpc(state->ctx, req, + get_schannel_creds_recv_chal, state); } static void get_schannel_creds_recv_chal(struct rpc_request *req) @@ -263,15 +264,15 @@ static void get_schannel_creds_recv_chal(struct rpc_request *req) const struct samr_Password *mach_pwd; state->ctx->status = dcerpc_ndr_request_recv(req); - if (!comp_is_ok(state->ctx)) return; + if (!composite_is_ok(state->ctx)) return; state->ctx->status = state->r.out.result; - if (!comp_is_ok(state->ctx)) return; + if (!composite_is_ok(state->ctx)) return; state->creds_state = talloc(state, struct creds_CredentialState); - if (comp_nomem(state->creds_state, state->ctx)) return; + if (composite_nomem(state->creds_state, state->ctx)) return; mach_pwd = cli_credentials_get_nt_hash(state->wks_creds, state); - if (comp_nomem(mach_pwd, state->ctx)) return; + if (composite_nomem(mach_pwd, state->ctx)) return; state->negotiate_flags = NETLOGON_NEG_AUTH2_FLAGS; @@ -293,7 +294,8 @@ static void get_schannel_creds_recv_chal(struct rpc_request *req) state->a.out.credentials = &state->netr_cred; req = dcerpc_netr_ServerAuthenticate2_send(state->p, state, &state->a); - rpc_cont(state->ctx, req, get_schannel_creds_recv_auth, state); + composite_continue_rpc(state->ctx, req, + get_schannel_creds_recv_auth, state); } static void get_schannel_creds_recv_auth(struct rpc_request *req) @@ -314,7 +316,8 @@ static void get_schannel_creds_recv_auth(struct rpc_request *req) goto done; } - cli_credentials_set_netlogon_creds(state->wks_creds, state->creds_state); + cli_credentials_set_netlogon_creds(state->wks_creds, + state->creds_state); state->ctx->state = COMPOSITE_STATE_DONE; @@ -428,17 +431,17 @@ static void lsa_lookupnames_recv_sids(struct rpc_request *req) int i; state->ctx->status = dcerpc_ndr_request_recv(req); - if (!comp_is_ok(state->ctx)) return; + if (!composite_is_ok(state->ctx)) return; state->ctx->status = state->r.out.result; if (!NT_STATUS_IS_OK(state->ctx->status) && !NT_STATUS_EQUAL(state->ctx->status, STATUS_SOME_UNMAPPED)) { - comp_error(state->ctx, state->ctx->status); + composite_error(state->ctx, state->ctx->status); return; } state->result = talloc_array(state, struct wb_sid_object *, state->num_names); - if (comp_nomem(state->result, state->ctx)) return; + if (composite_nomem(state->result, state->ctx)) return; for (i=0; inum_names; i++) { struct lsa_TranslatedSid *sid = &state->r.out.sids->sids[i]; @@ -446,7 +449,7 @@ static void lsa_lookupnames_recv_sids(struct rpc_request *req) state->result[i] = talloc_zero(state->result, struct wb_sid_object); - if (comp_nomem(state->result[i], state->ctx)) return; + if (composite_nomem(state->result[i], state->ctx)) return; state->result[i]->type = sid->sid_type; if (state->result[i]->type == SID_NAME_UNKNOWN) { @@ -454,7 +457,8 @@ static void lsa_lookupnames_recv_sids(struct rpc_request *req) } if (sid->sid_index >= state->r.out.domains->count) { - comp_error(state->ctx, NT_STATUS_INVALID_PARAMETER); + composite_error(state->ctx, + NT_STATUS_INVALID_PARAMETER); return; } @@ -464,7 +468,7 @@ static void lsa_lookupnames_recv_sids(struct rpc_request *req) dom->sid, sid->rid); } - comp_done(state->ctx); + composite_done(state->ctx); } NTSTATUS wb_lsa_lookupnames_recv(struct composite_context *c, @@ -556,12 +560,12 @@ static void cmd_lookupname_recv_init(struct composite_context *ctx) struct cmd_lookupname_state); state->ctx->status = wb_init_domain_recv(ctx); - if (!comp_is_ok(state->ctx)) return; + if (!composite_is_ok(state->ctx)) return; ctx = wb_lsa_lookupnames_send(state->domain->lsa_pipe, state->domain->lsa_policy, 1, &state->name); - comp_cont(state->ctx, ctx, cmd_lookupname_recv_sid, state); + composite_continue(state->ctx, ctx, cmd_lookupname_recv_sid, state); } static void cmd_lookupname_recv_sid(struct composite_context *ctx) @@ -574,9 +578,9 @@ static void cmd_lookupname_recv_sid(struct composite_context *ctx) state->ctx->status = wb_lsa_lookupnames_recv(ctx, state, &sids); state->result = sids[0]; - if (!comp_is_ok(state->ctx)) return; + if (!composite_is_ok(state->ctx)) return; - comp_done(state->ctx); + composite_done(state->ctx); } NTSTATUS wb_cmd_lookupname_recv(struct composite_context *c, @@ -649,9 +653,9 @@ static void cmd_checkmachacc_recv_init(struct composite_context *ctx) struct cmd_checkmachacc_state); state->ctx->status = wb_init_domain_recv(ctx); - if (!comp_is_ok(state->ctx)) return; + if (!composite_is_ok(state->ctx)) return; - comp_done(state->ctx); + composite_done(state->ctx); } NTSTATUS wb_cmd_checkmachacc_recv(struct composite_context *c) diff --git a/source4/winbind/wb_connect_lsa.c b/source4/winbind/wb_connect_lsa.c new file mode 100644 index 0000000000..ef7b525c2a --- /dev/null +++ b/source4/winbind/wb_connect_lsa.c @@ -0,0 +1,323 @@ +/* + Unix SMB/CIFS implementation. + + Connect to the LSA pipe, given an smbcli_tree and possibly some + credentials. Try ntlmssp, schannel and anon in that order. + + Copyright (C) Volker Lendecke 2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "libcli/composite/composite.h" +#include "libcli/smb_composite/smb_composite.h" +#include "winbind/wb_async_helpers.h" +#include "winbind/wb_server.h" +#include "smbd/service_stream.h" + +#include "librpc/gen_ndr/nbt.h" +#include "librpc/gen_ndr/samr.h" +#include "lib/messaging/irpc.h" +#include "librpc/gen_ndr/irpc.h" +#include "librpc/gen_ndr/ndr_irpc.h" +#include "libcli/raw/libcliraw.h" +#include "librpc/gen_ndr/ndr_netlogon.h" +#include "librpc/gen_ndr/ndr_lsa.h" +#include "libcli/auth/credentials.h" + + +/* Helper to initialize LSA with a specific auth methods. Verify by opening + * the LSA policy. */ + +struct init_lsa_state { + struct composite_context *ctx; + struct dcerpc_pipe *lsa_pipe; + + uint8_t auth_type; + struct cli_credentials *creds; + + struct lsa_ObjectAttribute objectattr; + struct lsa_OpenPolicy2 openpolicy; + struct policy_handle *handle; +}; + +static void init_lsa_recv_pipe(struct composite_context *ctx); +static void init_lsa_recv_openpol(struct rpc_request *req); + +static struct composite_context *wb_init_lsa_send(struct smbcli_tree *tree, + uint8_t auth_type, + struct cli_credentials *creds) +{ + struct composite_context *result, *ctx; + struct init_lsa_state *state; + + result = talloc(NULL, struct composite_context); + if (result == NULL) goto failed; + result->state = COMPOSITE_STATE_IN_PROGRESS; + result->event_ctx = tree->session->transport->socket->event.ctx; + + state = talloc(result, struct init_lsa_state); + if (state == NULL) goto failed; + state->ctx = result; + result->private_data = state; + + state->auth_type = auth_type; + state->creds = creds; + + state->lsa_pipe = dcerpc_pipe_init(state, result->event_ctx); + if (state->lsa_pipe == NULL) goto failed; + + ctx = dcerpc_pipe_open_smb_send(state->lsa_pipe->conn, tree, + "\\lsarpc"); + ctx->async.fn = init_lsa_recv_pipe; + ctx->async.private_data = state; + return result; + + failed: + talloc_free(result); + return NULL; +} + +static void init_lsa_recv_pipe(struct composite_context *ctx) +{ + struct init_lsa_state *state = + talloc_get_type(ctx->async.private_data, + struct init_lsa_state); + struct rpc_request *req; + + state->ctx->status = dcerpc_pipe_open_smb_recv(ctx); + if (!composite_is_ok(state->ctx)) return; + + switch (state->auth_type) { + case DCERPC_AUTH_TYPE_NONE: + state->ctx->status = + dcerpc_bind_auth_none(state->lsa_pipe, + DCERPC_LSARPC_UUID, + DCERPC_LSARPC_VERSION); + break; + case DCERPC_AUTH_TYPE_NTLMSSP: + case DCERPC_AUTH_TYPE_SCHANNEL: + if (state->creds == NULL) { + composite_error(state->ctx, NT_STATUS_INTERNAL_ERROR); + return; + } + state->lsa_pipe->conn->flags |= (DCERPC_SIGN | DCERPC_SEAL); + state->ctx->status = + dcerpc_bind_auth_password(state->lsa_pipe, + DCERPC_LSARPC_UUID, + DCERPC_LSARPC_VERSION, + state->creds, + state->auth_type, + NULL); + break; + default: + state->ctx->status = NT_STATUS_INTERNAL_ERROR; + + } + + state->handle = talloc(state, struct policy_handle); + if (composite_nomem(state->handle, state->ctx)) return; + + state->openpolicy.in.system_name = + talloc_asprintf(state, "\\\\%s", + dcerpc_server_name(state->lsa_pipe)); + ZERO_STRUCT(state->objectattr); + state->openpolicy.in.attr = &state->objectattr; + state->openpolicy.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; + state->openpolicy.out.handle = state->handle; + + req = dcerpc_lsa_OpenPolicy2_send(state->lsa_pipe, state, + &state->openpolicy); + composite_continue_rpc(state->ctx, req, init_lsa_recv_openpol, state); +} + +static void init_lsa_recv_openpol(struct rpc_request *req) +{ + struct init_lsa_state *state = + talloc_get_type(req->async.private, + struct init_lsa_state); + + state->ctx->status = dcerpc_ndr_request_recv(req); + if (!composite_is_ok(state->ctx)) return; + state->ctx->status = state->openpolicy.out.result; + if (!composite_is_ok(state->ctx)) return; + + composite_done(state->ctx); +} + +static NTSTATUS wb_init_lsa_recv(struct composite_context *c, + TALLOC_CTX *mem_ctx, + struct dcerpc_pipe **lsa_pipe, + struct policy_handle **lsa_policy) +{ + NTSTATUS status = composite_wait(c); + if (NT_STATUS_IS_OK(status)) { + struct init_lsa_state *state = + talloc_get_type(c->private_data, + struct init_lsa_state); + *lsa_pipe = talloc_steal(mem_ctx, state->lsa_pipe); + *lsa_policy = talloc_steal(mem_ctx, state->handle); + } + talloc_free(c); + return status; +} + + +/* + * 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(struct smbcli_tree *tree, + struct cli_credentials *credentials) +{ + struct composite_context *result, *ctx; + struct connect_lsa_state *state; + + result = talloc(NULL, struct composite_context); + if (result == NULL) goto failed; + result->state = COMPOSITE_STATE_IN_PROGRESS; + 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(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(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->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->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(struct smbcli_tree *tree, + struct cli_credentials *credentials, + TALLOC_CTX *mem_ctx, + uint8_t *auth_type, + struct dcerpc_pipe **lsa_pipe, + struct policy_handle **lsa_policy) +{ + struct composite_context *c; + c = wb_connect_lsa_send(tree, credentials); + return wb_connect_lsa_recv(c, mem_ctx, auth_type, lsa_pipe, + lsa_policy); +} diff --git a/source4/winbind/wb_init_domain.c b/source4/winbind/wb_init_domain.c index 0ac7d11d64..c9389ea7dd 100644 --- a/source4/winbind/wb_init_domain.c +++ b/source4/winbind/wb_init_domain.c @@ -1,6 +1,8 @@ /* Unix SMB/CIFS implementation. + A composite API for initializing a domain + Copyright (C) Volker Lendecke 2005 This program is free software; you can redistribute it and/or modify @@ -17,9 +19,6 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* - a composite API for initializing a domain -*/ #include "includes.h" #include "libcli/composite/composite.h" @@ -39,147 +38,12 @@ #include "libcli/auth/credentials.h" -/* Helper to initialize LSA with different auth methods and opening the lsa - * policy */ - -struct init_lsa_state { - struct composite_context *ctx; - struct dcerpc_pipe *lsa_pipe; - - uint8_t auth_type; - struct cli_credentials *creds; - - struct lsa_ObjectAttribute objectattr; - struct lsa_OpenPolicy2 openpolicy; - struct policy_handle *handle; -}; - -static void init_lsa_recv_pipe(struct composite_context *ctx); -static void init_lsa_recv_openpol(struct rpc_request *req); - -static struct composite_context *wb_init_lsa_send(struct smbcli_tree *tree, - uint8_t auth_type, - struct cli_credentials *creds) -{ - struct composite_context *result, *ctx; - struct init_lsa_state *state; - - result = talloc(NULL, struct composite_context); - if (result == NULL) goto failed; - result->state = COMPOSITE_STATE_IN_PROGRESS; - result->event_ctx = tree->session->transport->socket->event.ctx; - - state = talloc(result, struct init_lsa_state); - if (state == NULL) goto failed; - state->ctx = result; - result->private_data = state; - - state->auth_type = auth_type; - state->creds = creds; - - state->lsa_pipe = dcerpc_pipe_init(state, result->event_ctx); - if (state->lsa_pipe == NULL) goto failed; - - ctx = dcerpc_pipe_open_smb_send(state->lsa_pipe->conn, tree, - "\\lsarpc"); - ctx->async.fn = init_lsa_recv_pipe; - ctx->async.private_data = state; - return result; - - failed: - talloc_free(result); - return NULL; -} - -static void init_lsa_recv_pipe(struct composite_context *ctx) -{ - struct init_lsa_state *state = - talloc_get_type(ctx->async.private_data, - struct init_lsa_state); - struct rpc_request *req; - - state->ctx->status = dcerpc_pipe_open_smb_recv(ctx); - if (!comp_is_ok(state->ctx)) return; - - switch (state->auth_type) { - case DCERPC_AUTH_TYPE_NONE: - state->ctx->status = - dcerpc_bind_auth_none(state->lsa_pipe, - DCERPC_LSARPC_UUID, - DCERPC_LSARPC_VERSION); - break; - case DCERPC_AUTH_TYPE_NTLMSSP: - case DCERPC_AUTH_TYPE_SCHANNEL: - if (state->creds == NULL) { - comp_error(state->ctx, NT_STATUS_INTERNAL_ERROR); - return; - } - state->lsa_pipe->conn->flags |= (DCERPC_SIGN | DCERPC_SEAL); - state->ctx->status = - dcerpc_bind_auth_password(state->lsa_pipe, - DCERPC_LSARPC_UUID, - DCERPC_LSARPC_VERSION, - state->creds, - state->auth_type, - NULL); - break; - default: - state->ctx->status = NT_STATUS_INTERNAL_ERROR; - - } - - state->handle = talloc(state, struct policy_handle); - if (comp_nomem(state->handle, state->ctx)) return; - - state->openpolicy.in.system_name = - talloc_asprintf(state, "\\\\%s", - dcerpc_server_name(state->lsa_pipe)); - ZERO_STRUCT(state->objectattr); - state->openpolicy.in.attr = &state->objectattr; - state->openpolicy.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; - state->openpolicy.out.handle = state->handle; - - req = dcerpc_lsa_OpenPolicy2_send(state->lsa_pipe, state, - &state->openpolicy); - rpc_cont(state->ctx, req, init_lsa_recv_openpol, state); -} - -static void init_lsa_recv_openpol(struct rpc_request *req) -{ - struct init_lsa_state *state = - talloc_get_type(req->async.private, - struct init_lsa_state); - - state->ctx->status = dcerpc_ndr_request_recv(req); - if (!comp_is_ok(state->ctx)) return; - state->ctx->status = state->openpolicy.out.result; - if (!comp_is_ok(state->ctx)) return; - - comp_done(state->ctx); -} - -static NTSTATUS wb_init_lsa_recv(struct composite_context *c, - TALLOC_CTX *mem_ctx, - struct dcerpc_pipe **lsa_pipe, - struct policy_handle **lsa_policy) -{ - NTSTATUS status = composite_wait(c); - if (NT_STATUS_IS_OK(status)) { - struct init_lsa_state *state = - talloc_get_type(c->private_data, - struct init_lsa_state); - *lsa_pipe = talloc_steal(mem_ctx, state->lsa_pipe); - *lsa_policy = talloc_steal(mem_ctx, state->handle); - } - talloc_free(c); - return status; -} - /* * Initialize a domain: * - * - With schannel credentials, try to open the SMB connection with the machine - * creds. Fall back to anonymous. + * - With schannel credentials, try to open the SMB connection with the + * machine creds. This works against W2k3SP1 with an NTLMSSP session + * setup. Fall back to anonymous. * * - If we have schannel creds, do the auth2 and open the schannel'ed netlogon * pipe. @@ -215,17 +79,10 @@ struct init_domain_state { }; static void init_domain_recv_dcs(struct composite_context *ctx); -static void init_domain_recv_authsmb(struct composite_context *ctx); -static void init_domain_anonsmb(struct init_domain_state *state); -static void init_domain_recv_anonsmb(struct composite_context *ctx); -static void init_domain_openpipes(struct init_domain_state *state); -static void init_domain_openlsa(struct init_domain_state *state); +static void init_domain_recv_tree(struct composite_context *ctx); static void init_domain_recv_netlogoncreds(struct composite_context *ctx); static void init_domain_recv_netlogonpipe(struct composite_context *ctx); -static void init_domain_recv_lsa_ntlmssp(struct composite_context *ctx); -static void init_domain_recv_lsa_schannel(struct composite_context *ctx); -static void init_domain_recv_lsa_none(struct composite_context *ctx); -static void init_domain_check_lsa(struct init_domain_state *state); +static void init_domain_recv_lsa(struct composite_context *ctx); static void init_domain_recv_queryinfo(struct rpc_request *req); struct composite_context *wb_init_domain_send(struct wbsrv_domain *domain, @@ -280,10 +137,10 @@ static void init_domain_recv_dcs(struct composite_context *ctx) state->ctx->status = wb_finddcs_recv(ctx, state, &state->num_dcs, &state->dcs); - if (!comp_is_ok(state->ctx)) return; + if (!composite_is_ok(state->ctx)) return; if (state->num_dcs < 1) { - comp_error(state->ctx, NT_STATUS_NO_LOGON_SERVERS); + composite_error(state->ctx, NT_STATUS_NO_LOGON_SERVERS); return; } @@ -294,72 +151,46 @@ static void init_domain_recv_dcs(struct composite_context *ctx) state->conn.in.service_type = "IPC"; state->conn.in.workgroup = state->domain->name; - if (state->domain->schannel_creds != NULL) { - /* Try to connect as workstation */ - state->conn.in.credentials = state->domain->schannel_creds; - ctx = smb_composite_connect_send(&state->conn, state, - state->ctx->event_ctx); - comp_cont(state->ctx, ctx, init_domain_recv_authsmb, state); - return; - } - - init_domain_anonsmb(state); -} - -static void init_domain_recv_authsmb(struct composite_context *ctx) -{ - struct init_domain_state *state = - talloc_get_type(ctx->async.private_data, - struct init_domain_state); + state->conn.in.credentials = state->domain->schannel_creds; - state->ctx->status = smb_composite_connect_recv(ctx, state); - if (NT_STATUS_IS_OK(state->ctx->status)) { - init_domain_openpipes(state); - return; + if (state->conn.in.credentials == NULL) { + state->conn.in.credentials = cli_credentials_init(state); + if (composite_nomem(state->conn.in.credentials, state->ctx)) { + return; + } + cli_credentials_set_conf(state->conn.in.credentials); + cli_credentials_set_anonymous(state->conn.in.credentials); } + + state->conn.in.fallback_to_anonymous = True; - init_domain_anonsmb(state); -} - -static void init_domain_anonsmb(struct init_domain_state *state) -{ - struct composite_context *ctx; - - state->conn.in.credentials = cli_credentials_init(state); - if (comp_nomem(state->conn.in.credentials, state->ctx)) return; - cli_credentials_set_conf(state->conn.in.credentials); - cli_credentials_set_anonymous(state->conn.in.credentials); ctx = smb_composite_connect_send(&state->conn, state, state->ctx->event_ctx); - comp_cont(state->ctx, ctx, init_domain_recv_anonsmb, state); + composite_continue(state->ctx, ctx, init_domain_recv_tree, state); } -static void init_domain_recv_anonsmb(struct composite_context *ctx) +static void init_domain_recv_tree(struct composite_context *ctx) { struct init_domain_state *state = talloc_get_type(ctx->async.private_data, struct init_domain_state); state->ctx->status = smb_composite_connect_recv(ctx, state); - if (!comp_is_ok(state->ctx)) return; - - init_domain_openpipes(state); -} - -static void init_domain_openpipes(struct init_domain_state *state) -{ - struct composite_context *ctx; + if (!composite_is_ok(state->ctx)) return; if (state->domain->schannel_creds == NULL) { /* No chance to open netlogon */ - init_domain_openlsa(state); + ctx = wb_connect_lsa_send(state->conn.out.tree, NULL); + composite_continue(state->ctx, ctx, + init_domain_recv_lsa, state); return; } ctx = wb_get_schannel_creds_send(state->domain->schannel_creds, state->conn.out.tree, state->ctx->event_ctx); - comp_cont(state->ctx, ctx, init_domain_recv_netlogoncreds, state); + composite_continue(state->ctx, ctx, + init_domain_recv_netlogoncreds, state); } static void init_domain_recv_netlogoncreds(struct composite_context *ctx) @@ -371,25 +202,26 @@ static void init_domain_recv_netlogoncreds(struct composite_context *ctx) state->ctx->status = wb_get_schannel_creds_recv(ctx, state, &state->auth2_pipe); - if (!comp_is_ok(state->ctx)) return; + if (!composite_is_ok(state->ctx)) return; talloc_unlink(state, state->conn.out.tree); /* The pipe owns it now */ state->netlogon_pipe = dcerpc_pipe_init(state, state->ctx->event_ctx); - if (comp_nomem(state->netlogon_pipe, state->ctx)) return; + if (composite_nomem(state->netlogon_pipe, state->ctx)) return; if (state->auth2_pipe != NULL) { tree = dcerpc_smb_tree(state->auth2_pipe->conn); } if (tree == NULL) { - comp_error(state->ctx, NT_STATUS_INTERNAL_ERROR); + composite_error(state->ctx, NT_STATUS_INTERNAL_ERROR); return; } ctx = dcerpc_pipe_open_smb_send(state->netlogon_pipe->conn, tree, "\\netlogon"); - comp_cont(state->ctx, ctx, init_domain_recv_netlogonpipe, state); + composite_continue(state->ctx, ctx, + init_domain_recv_netlogonpipe, state); } static void init_domain_recv_netlogonpipe(struct composite_context *ctx) @@ -399,7 +231,7 @@ static void init_domain_recv_netlogonpipe(struct composite_context *ctx) struct init_domain_state); state->ctx->status = dcerpc_pipe_open_smb_recv(ctx); - if (!comp_is_ok(state->ctx)) return; + if (!composite_is_ok(state->ctx)) return; state->netlogon_pipe->conn->flags |= (DCERPC_SIGN | DCERPC_SEAL); state->ctx->status = @@ -409,85 +241,29 @@ static void init_domain_recv_netlogonpipe(struct composite_context *ctx) state->domain->schannel_creds, DCERPC_AUTH_TYPE_SCHANNEL, NULL); - if (!comp_is_ok(state->ctx)) return; - - init_domain_openlsa(state); -} - -static void init_domain_openlsa(struct init_domain_state *state) -{ - struct composite_context *ctx; - - if (state->domain->schannel_creds == NULL) { - ctx = wb_init_lsa_send(state->conn.out.tree, - DCERPC_AUTH_TYPE_NONE, - NULL); - comp_cont(state->ctx, ctx, init_domain_recv_lsa_none, state); - return; - } - ctx = wb_init_lsa_send(state->conn.out.tree, DCERPC_AUTH_TYPE_NTLMSSP, - state->domain->schannel_creds); - comp_cont(state->ctx, ctx, init_domain_recv_lsa_ntlmssp, state); + ctx = wb_connect_lsa_send(state->conn.out.tree, + state->domain->schannel_creds); + composite_continue(state->ctx, ctx, init_domain_recv_lsa, state); } -static void init_domain_recv_lsa_ntlmssp(struct composite_context *ctx) +static void init_domain_recv_lsa(struct composite_context *ctx) { struct init_domain_state *state = talloc_get_type(ctx->async.private_data, struct init_domain_state); - state->ctx->status = wb_init_lsa_recv(ctx, state, &state->lsa_pipe, - &state->lsa_policy); - if (NT_STATUS_IS_OK(state->ctx->status)) { - init_domain_check_lsa(state); - return; - } - - ctx = wb_init_lsa_send(state->conn.out.tree, - DCERPC_AUTH_TYPE_SCHANNEL, - state->domain->schannel_creds); - comp_cont(state->ctx, ctx, init_domain_recv_lsa_schannel, state); -} - -static void init_domain_recv_lsa_schannel(struct composite_context *ctx) -{ - struct init_domain_state *state = - talloc_get_type(ctx->async.private_data, - struct init_domain_state); - - state->ctx->status = wb_init_lsa_recv(ctx, state, &state->lsa_pipe, - &state->lsa_policy); - if (NT_STATUS_IS_OK(state->ctx->status)) { - init_domain_check_lsa(state); - return; - } - - ctx = wb_init_lsa_send(state->conn.out.tree, - DCERPC_AUTH_TYPE_NONE, NULL); - comp_cont(state->ctx, ctx, init_domain_recv_lsa_none, state); -} - -static void init_domain_recv_lsa_none(struct composite_context *ctx) -{ - struct init_domain_state *state = - talloc_get_type(ctx->async.private_data, - struct init_domain_state); - - state->ctx->status = wb_init_lsa_recv(ctx, state, &state->lsa_pipe, - &state->lsa_policy); - if (!comp_is_ok(state->ctx)) return; - - init_domain_check_lsa(state); -} - -static void init_domain_check_lsa(struct init_domain_state *state) -{ struct rpc_request *req; + uint8_t auth_type; + + state->ctx->status = wb_connect_lsa_recv(ctx, state, &auth_type, + &state->lsa_pipe, + &state->lsa_policy); + if (!composite_is_ok(state->ctx)) return; if (state->auth2_pipe == NULL) { - /* Give the tree to the LSA pipe, otherwise it has been given - * to the auth2 pipe already */ + /* Give the tree to the LSA pipe. If auth2_pipe exists we have + * given it to that already */ talloc_unlink(state, state->conn.out.tree); state->conn.out.tree = NULL; } @@ -497,7 +273,8 @@ static void init_domain_check_lsa(struct init_domain_state *state) req = dcerpc_lsa_QueryInfoPolicy_send(state->lsa_pipe, state, &state->queryinfo); - rpc_cont(state->ctx, req, init_domain_recv_queryinfo, state); + composite_continue_rpc(state->ctx, req, + init_domain_recv_queryinfo, state); } static void init_domain_recv_queryinfo(struct rpc_request *req) @@ -507,9 +284,9 @@ static void init_domain_recv_queryinfo(struct rpc_request *req) struct lsa_DomainInfo *dominfo; state->ctx->status = dcerpc_ndr_request_recv(req); - if (!comp_is_ok(state->ctx)) return; + if (!composite_is_ok(state->ctx)) return; state->ctx->status = state->queryinfo.out.result; - if (!comp_is_ok(state->ctx)) return; + if (!composite_is_ok(state->ctx)) return; dominfo = &state->queryinfo.out.info->account_domain; @@ -518,7 +295,7 @@ static void init_domain_recv_queryinfo(struct rpc_request *req) state->domain->name, dcerpc_server_name(state->lsa_pipe), dominfo->name.string)); - comp_error(state->ctx, NT_STATUS_INVALID_DOMAIN_STATE); + composite_error(state->ctx, NT_STATUS_INVALID_DOMAIN_STATE); return; } @@ -527,11 +304,11 @@ static void init_domain_recv_queryinfo(struct rpc_request *req) dom_sid_string(state, state->domain->sid), dcerpc_server_name(state->lsa_pipe), dom_sid_string(state, dominfo->sid))); - comp_error(state->ctx, NT_STATUS_INVALID_DOMAIN_STATE); + composite_error(state->ctx, NT_STATUS_INVALID_DOMAIN_STATE); return; } - comp_done(state->ctx); + composite_done(state->ctx); } NTSTATUS wb_init_domain_recv(struct composite_context *c) -- cgit