diff options
-rw-r--r-- | source4/libcli/composite/composite.c | 42 | ||||
-rw-r--r-- | source4/libcli/raw/clitree.c | 1 | ||||
-rw-r--r-- | source4/libcli/smb_composite/connect.c | 83 | ||||
-rw-r--r-- | source4/libcli/smb_composite/fetchfile.c | 1 | ||||
-rw-r--r-- | source4/libcli/smb_composite/fsinfo.c | 1 | ||||
-rw-r--r-- | source4/libcli/smb_composite/smb_composite.h | 2 | ||||
-rw-r--r-- | source4/ntvfs/cifs/vfs_cifs.c | 1 | ||||
-rw-r--r-- | source4/winbind/config.mk | 1 | ||||
-rw-r--r-- | source4/winbind/wb_async_helpers.c | 68 | ||||
-rw-r--r-- | source4/winbind/wb_connect_lsa.c | 323 | ||||
-rw-r--r-- | source4/winbind/wb_init_domain.c | 327 |
11 files changed, 520 insertions, 330 deletions
diff --git a/source4/libcli/composite/composite.c b/source4/libcli/composite/composite.c index 6458a971b4..f5eed77300 100644 --- a/source4/libcli/composite/composite.c +++ b/source4/libcli/composite/composite.c @@ -75,7 +75,7 @@ void composite_trigger_done(struct composite_context *c) * functions. */ -BOOL comp_is_ok(struct composite_context *ctx) +BOOL composite_is_ok(struct composite_context *ctx) { if (NT_STATUS_IS_OK(ctx->status)) { return True; @@ -87,22 +87,22 @@ BOOL comp_is_ok(struct composite_context *ctx) return False; } -void comp_error(struct composite_context *ctx, NTSTATUS status) +void composite_error(struct composite_context *ctx, NTSTATUS status) { ctx->status = status; - SMB_ASSERT(!comp_is_ok(ctx)); + SMB_ASSERT(!composite_is_ok(ctx)); } -BOOL comp_nomem(const void *p, struct composite_context *ctx) +BOOL composite_nomem(const void *p, struct composite_context *ctx) { if (p != NULL) { return False; } - comp_error(ctx, NT_STATUS_NO_MEMORY); + composite_error(ctx, NT_STATUS_NO_MEMORY); return True; } -void comp_done(struct composite_context *ctx) +void composite_done(struct composite_context *ctx) { ctx->state = COMPOSITE_STATE_DONE; if (ctx->async.fn != NULL) { @@ -110,32 +110,32 @@ void comp_done(struct composite_context *ctx) } } -void comp_cont(struct composite_context *ctx, - struct composite_context *new_ctx, - void (*continuation)(struct composite_context *), - void *private_data) +void composite_continue(struct composite_context *ctx, + struct composite_context *new_ctx, + void (*continuation)(struct composite_context *), + void *private_data) { - if (comp_nomem(new_ctx, ctx)) return; + if (composite_nomem(new_ctx, ctx)) return; new_ctx->async.fn = continuation; new_ctx->async.private_data = private_data; } -void rpc_cont(struct composite_context *ctx, - struct rpc_request *new_req, - void (*continuation)(struct rpc_request *), - void *private_data) +void composite_continue_rpc(struct composite_context *ctx, + struct rpc_request *new_req, + void (*continuation)(struct rpc_request *), + void *private_data) { - if (comp_nomem(new_req, ctx)) return; + if (composite_nomem(new_req, ctx)) return; new_req->async.callback = continuation; new_req->async.private = private_data; } -void irpc_cont(struct composite_context *ctx, - struct irpc_request *new_req, - void (*continuation)(struct irpc_request *), - void *private_data) +void composite_continue_irpc(struct composite_context *ctx, + struct irpc_request *new_req, + void (*continuation)(struct irpc_request *), + void *private_data) { - if (comp_nomem(new_req, ctx)) return; + if (composite_nomem(new_req, ctx)) return; new_req->async.fn = continuation; new_req->async.private = private_data; } diff --git a/source4/libcli/raw/clitree.c b/source4/libcli/raw/clitree.c index cae93bdbe2..990552d64f 100644 --- a/source4/libcli/raw/clitree.c +++ b/source4/libcli/raw/clitree.c @@ -179,6 +179,7 @@ NTSTATUS smbcli_tree_full_connection(TALLOC_CTX *parent_ctx, io.in.service = service; io.in.service_type = service_type; io.in.credentials = credentials; + io.in.fallback_to_anonymous = False; io.in.workgroup = lp_workgroup(); status = smb_composite_connect(&io, parent_ctx, ev); diff --git a/source4/libcli/smb_composite/connect.c b/source4/libcli/smb_composite/connect.c index 53cc8a9ac0..925d5ddb38 100644 --- a/source4/libcli/smb_composite/connect.c +++ b/source4/libcli/smb_composite/connect.c @@ -30,9 +30,10 @@ /* the stages of this call */ enum connect_stage {CONNECT_RESOLVE, CONNECT_SOCKET, - CONNECT_SESSION_REQUEST, + CONNECT_SESSION_REQUEST, CONNECT_NEGPROT, CONNECT_SESSION_SETUP, + CONNECT_SESSION_SETUP_ANON, CONNECT_TCON}; struct connect_state { @@ -101,7 +102,59 @@ static NTSTATUS connect_tcon(struct composite_context *c, /* - a session setup request has competed + a session setup request with anonymous fallback has completed +*/ +static NTSTATUS connect_session_setup_anon(struct composite_context *c, + struct smb_composite_connect *io) +{ + struct connect_state *state = talloc_get_type(c->private_data, struct connect_state); + NTSTATUS status; + + status = smb_composite_sesssetup_recv(state->creq); + NT_STATUS_NOT_OK_RETURN(status); + + io->out.anonymous_fallback_done = True; + + state->session->vuid = state->io_setup->out.vuid; + + /* setup for a tconx */ + io->out.tree = smbcli_tree_init(state->session, state, True); + NT_STATUS_HAVE_NO_MEMORY(io->out.tree); + + state->io_tcon = talloc(c, union smb_tcon); + NT_STATUS_HAVE_NO_MEMORY(state->io_tcon); + + /* connect to a share using a tree connect */ + state->io_tcon->generic.level = RAW_TCON_TCONX; + state->io_tcon->tconx.in.flags = 0; + state->io_tcon->tconx.in.password = data_blob(NULL, 0); + + state->io_tcon->tconx.in.path = talloc_asprintf(state->io_tcon, + "\\\\%s\\%s", + io->in.called_name, + io->in.service); + NT_STATUS_HAVE_NO_MEMORY(state->io_tcon->tconx.in.path); + if (!io->in.service_type) { + state->io_tcon->tconx.in.device = "?????"; + } else { + state->io_tcon->tconx.in.device = io->in.service_type; + } + + state->req = smb_raw_tcon_send(io->out.tree, state->io_tcon); + NT_STATUS_HAVE_NO_MEMORY(state->req); + if (state->req->state == SMBCLI_REQUEST_ERROR) { + return state->req->status; + } + + state->req->async.fn = request_handler; + state->req->async.private = c; + state->stage = CONNECT_TCON; + + return NT_STATUS_OK; +} + +/* + a session setup request has completed */ static NTSTATUS connect_session_setup(struct composite_context *c, struct smb_composite_connect *io) @@ -110,6 +163,29 @@ static NTSTATUS connect_session_setup(struct composite_context *c, NTSTATUS status; status = smb_composite_sesssetup_recv(state->creq); + + if (!NT_STATUS_IS_OK(status) && + !cli_credentials_is_anonymous(state->io->in.credentials) && + io->in.fallback_to_anonymous) { + + state->io_setup->in.credentials = cli_credentials_init(state); + NT_STATUS_HAVE_NO_MEMORY(state->io_setup->in.credentials); + cli_credentials_set_conf(state->io_setup->in.credentials); + cli_credentials_set_anonymous(state->io_setup->in.credentials); + + state->creq = smb_composite_sesssetup_send(state->session, + state->io_setup); + NT_STATUS_HAVE_NO_MEMORY(state->creq); + if (state->creq->state == COMPOSITE_STATE_ERROR) { + return state->creq->status; + } + state->creq->async.fn = composite_handler; + state->creq->async.private_data = c; + state->stage = CONNECT_SESSION_SETUP_ANON; + + return NT_STATUS_OK; + } + NT_STATUS_NOT_OK_RETURN(status); state->session->vuid = state->io_setup->out.vuid; @@ -318,6 +394,9 @@ static void state_handler(struct composite_context *c) case CONNECT_SESSION_SETUP: c->status = connect_session_setup(c, state->io); break; + case CONNECT_SESSION_SETUP_ANON: + c->status = connect_session_setup_anon(c, state->io); + break; case CONNECT_TCON: c->status = connect_tcon(c, state->io); break; diff --git a/source4/libcli/smb_composite/fetchfile.c b/source4/libcli/smb_composite/fetchfile.c index 8aa91bf3a9..1891ee956c 100644 --- a/source4/libcli/smb_composite/fetchfile.c +++ b/source4/libcli/smb_composite/fetchfile.c @@ -144,6 +144,7 @@ struct composite_context *smb_composite_fetchfile_send(struct smb_composite_fetc state->connect->in.service = io->in.service; state->connect->in.service_type = io->in.service_type; state->connect->in.credentials = io->in.credentials; + state->connect->in.fallback_to_anonymous = False; state->connect->in.workgroup = io->in.workgroup; state->creq = smb_composite_connect_send(state->connect, state, event_ctx); diff --git a/source4/libcli/smb_composite/fsinfo.c b/source4/libcli/smb_composite/fsinfo.c index fa9f18d132..1d3860e5c6 100644 --- a/source4/libcli/smb_composite/fsinfo.c +++ b/source4/libcli/smb_composite/fsinfo.c @@ -149,6 +149,7 @@ struct composite_context *smb_composite_fsinfo_send(struct smbcli_tree *tree, state->connect->in.service = io->in.service; state->connect->in.service_type = io->in.service_type; state->connect->in.credentials = io->in.credentials; + state->connect->in.fallback_to_anonymous = False; state->connect->in.workgroup = io->in.workgroup; c->state = COMPOSITE_STATE_IN_PROGRESS; diff --git a/source4/libcli/smb_composite/smb_composite.h b/source4/libcli/smb_composite/smb_composite.h index ec3a7af22d..7ab0127440 100644 --- a/source4/libcli/smb_composite/smb_composite.h +++ b/source4/libcli/smb_composite/smb_composite.h @@ -90,10 +90,12 @@ struct smb_composite_connect { const char *service; const char *service_type; struct cli_credentials *credentials; + BOOL fallback_to_anonymous; const char *workgroup; } in; struct { struct smbcli_tree *tree; + BOOL anonymous_fallback_done; } out; }; diff --git a/source4/ntvfs/cifs/vfs_cifs.c b/source4/ntvfs/cifs/vfs_cifs.c index 0ad0425415..cb6fbb3880 100644 --- a/source4/ntvfs/cifs/vfs_cifs.c +++ b/source4/ntvfs/cifs/vfs_cifs.c @@ -130,6 +130,7 @@ static NTSTATUS cvfs_connect(struct ntvfs_module_context *ntvfs, io.in.port = 0; io.in.called_name = host; io.in.credentials = credentials; + io.in.fallback_to_anonymous = False; io.in.workgroup = lp_workgroup(); io.in.service = remote_share; io.in.service_type = "?????"; 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; i<state->num_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) |