From a6852523d677f6c39a92e0e2b5d970211b29558b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 20 Nov 2005 17:34:56 +0000 Subject: r11812: Convert winbind to the async bind routines. Also remove tridge's hack for the winbind "bug" :-) Volker (This used to be commit fb9a3c7ef376f289288c71bc47d67f548ddb7194) --- source4/libcli/raw/clitransport.c | 4 -- source4/librpc/rpc/dcerpc_auth.c | 14 ++-- source4/winbind/wb_async_helpers.c | 127 +++++++++++++++++++++++-------------- source4/winbind/wb_connect_lsa.c | 65 +++++++++++++++---- source4/winbind/wb_connect_sam.c | 62 ++++++++++++++---- source4/winbind/wb_init_domain.c | 24 +++++-- 6 files changed, 203 insertions(+), 93 deletions(-) diff --git a/source4/libcli/raw/clitransport.c b/source4/libcli/raw/clitransport.c index 83b73f2e30..1cd0a3046e 100644 --- a/source4/libcli/raw/clitransport.c +++ b/source4/libcli/raw/clitransport.c @@ -122,11 +122,7 @@ struct smbcli_transport *smbcli_transport_init(struct smbcli_socket *sock, transport); packet_set_fde(transport->packet, transport->socket->event.fde); -#if 0 - /* winbind relies on non-serialised connections for dcerpc bind. Once that is - fixed we can go back to serialised connections */ packet_set_serialise(transport->packet); -#endif talloc_set_destructor(transport, transport_destructor); return transport; diff --git a/source4/librpc/rpc/dcerpc_auth.c b/source4/librpc/rpc/dcerpc_auth.c index 29ab80da7a..c0d4c55835 100644 --- a/source4/librpc/rpc/dcerpc_auth.c +++ b/source4/librpc/rpc/dcerpc_auth.c @@ -149,12 +149,12 @@ static void bind_auth_recv_bindreply(struct composite_context *creq) bind_auth_next_step(c); } -static struct composite_context *dcerpc_bind_auth_send(struct dcerpc_pipe *p, - TALLOC_CTX *mem_ctx, - const char *uuid, uint_t version, - struct cli_credentials *credentials, - uint8_t auth_type, - const char *service) +struct composite_context *dcerpc_bind_auth_send(TALLOC_CTX *mem_ctx, + struct dcerpc_pipe *p, + const char *uuid, uint_t version, + struct cli_credentials *credentials, + uint8_t auth_type, + const char *service) { struct composite_context *c, *creq; struct bind_auth_state *state; @@ -273,7 +273,7 @@ static struct composite_context *dcerpc_bind_auth_send(struct dcerpc_pipe *p, return c; } -static NTSTATUS dcerpc_bind_auth_recv(struct composite_context *creq) +NTSTATUS dcerpc_bind_auth_recv(struct composite_context *creq) { NTSTATUS result = composite_wait(creq); talloc_free(creq); diff --git a/source4/winbind/wb_async_helpers.c b/source4/winbind/wb_async_helpers.c index 51907c1350..cfbfe5f74f 100644 --- a/source4/winbind/wb_async_helpers.c +++ b/source4/winbind/wb_async_helpers.c @@ -175,7 +175,6 @@ NTSTATUS wb_finddcs(TALLOC_CTX *mem_ctx, } struct get_schannel_creds_state { - struct composite_context *ctx; struct cli_credentials *wks_creds; struct dcerpc_pipe *p; struct netr_ServerReqChallenge r; @@ -186,6 +185,7 @@ struct get_schannel_creds_state { struct netr_ServerAuthenticate2 a; }; +static void get_schannel_creds_recv_anonbind(struct composite_context *creq); static void get_schannel_creds_recv_auth(struct rpc_request *req); static void get_schannel_creds_recv_chal(struct rpc_request *req); static void get_schannel_creds_recv_pipe(struct composite_context *ctx); @@ -195,90 +195,117 @@ struct composite_context *wb_get_schannel_creds_send(TALLOC_CTX *mem_ctx, struct smbcli_tree *tree, struct event_context *ev) { - struct composite_context *result, *ctx; + struct composite_context *c, *creq; struct get_schannel_creds_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 = ev; + c = talloc_zero(mem_ctx, struct composite_context); + if (c == NULL) return NULL; - state = talloc(result, struct get_schannel_creds_state); - if (state == NULL) goto failed; - result->private_data = state; - state->ctx = result; + state = talloc(c, struct get_schannel_creds_state); + if (state == NULL) { + c->status = NT_STATUS_NO_MEMORY; + goto failed; + } + + c->state = COMPOSITE_STATE_IN_PROGRESS; + c->private_data = state; + c->event_ctx = ev; state->wks_creds = wks_creds; state->p = dcerpc_pipe_init(state, ev); - if (state->p == NULL) goto failed; + if (state->p == NULL) { + c->status = NT_STATUS_NO_MEMORY; + goto failed; + } - ctx = dcerpc_pipe_open_smb_send(state->p->conn, tree, "\\netlogon"); - if (ctx == NULL) goto failed; + creq = dcerpc_pipe_open_smb_send(state->p->conn, tree, "\\netlogon"); + if (creq == NULL) { + c->status = NT_STATUS_NO_MEMORY; + goto failed; + } - ctx->async.fn = get_schannel_creds_recv_pipe; - ctx->async.private_data = state; - return result; + creq->async.fn = get_schannel_creds_recv_pipe; + creq->async.private_data = c; + + return c; failed: - talloc_free(result); - return NULL; + composite_trigger_error(c); + return c; } -static void get_schannel_creds_recv_pipe(struct composite_context *ctx) +static void get_schannel_creds_recv_pipe(struct composite_context *creq) { + struct composite_context *c = + talloc_get_type(creq->async.private_data, + struct composite_context); struct get_schannel_creds_state *state = - talloc_get_type(ctx->async.private_data, + talloc_get_type(c->private_data, struct get_schannel_creds_state); - struct rpc_request *req; - state->ctx->status = dcerpc_pipe_open_smb_recv(ctx); - if (!composite_is_ok(state->ctx)) return; + c->status = dcerpc_pipe_open_smb_recv(creq); + if (!composite_is_ok(c)) return; - state->ctx->status = dcerpc_bind_auth_none(state->p, - DCERPC_NETLOGON_UUID, - DCERPC_NETLOGON_VERSION); - if (!composite_is_ok(state->ctx)) return; + creq = dcerpc_bind_auth_none_send(state, state->p, + DCERPC_NETLOGON_UUID, + DCERPC_NETLOGON_VERSION); + composite_continue(c, creq, get_schannel_creds_recv_anonbind, c); +} + +static void get_schannel_creds_recv_anonbind(struct composite_context *creq) +{ + struct composite_context *c = + talloc_get_type(creq->async.private_data, + struct composite_context); + struct get_schannel_creds_state *state = + talloc_get_type(c->private_data, + struct get_schannel_creds_state); + struct rpc_request *req; + + c->status = dcerpc_bind_auth_none_recv(creq); + if (!composite_is_ok(c)) 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 (composite_nomem(state->r.in.server_name, state->ctx)) return; + if (composite_nomem(state->r.in.server_name, c)) return; state->r.in.credentials = talloc(state, struct netr_Credential); - if (composite_nomem(state->r.in.credentials, state->ctx)) return; + if (composite_nomem(state->r.in.credentials, c)) return; state->r.out.credentials = talloc(state, struct netr_Credential); - if (composite_nomem(state->r.out.credentials, state->ctx)) return; + if (composite_nomem(state->r.out.credentials, c)) 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); - composite_continue_rpc(state->ctx, req, - get_schannel_creds_recv_chal, state); + composite_continue_rpc(c, req, get_schannel_creds_recv_chal, c); } static void get_schannel_creds_recv_chal(struct rpc_request *req) { - struct get_schannel_creds_state *state = + struct composite_context *c = talloc_get_type(req->async.private, + struct composite_context); + struct get_schannel_creds_state *state = + talloc_get_type(c->private_data, struct get_schannel_creds_state); const struct samr_Password *mach_pwd; - state->ctx->status = dcerpc_ndr_request_recv(req); - if (!composite_is_ok(state->ctx)) return; - state->ctx->status = state->r.out.result; - if (!composite_is_ok(state->ctx)) return; + c->status = dcerpc_ndr_request_recv(req); + if (!composite_is_ok(c)) return; + c->status = state->r.out.result; + if (!composite_is_ok(c)) return; state->creds_state = talloc(state, struct creds_CredentialState); - if (composite_nomem(state->creds_state, state->ctx)) return; + if (composite_nomem(state->creds_state, c)) return; mach_pwd = cli_credentials_get_nt_hash(state->wks_creds, state); - if (composite_nomem(mach_pwd, state->ctx)) return; + if (composite_nomem(mach_pwd, c)) return; state->negotiate_flags = NETLOGON_NEG_AUTH2_FLAGS; @@ -300,32 +327,34 @@ 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); - composite_continue_rpc(state->ctx, req, - get_schannel_creds_recv_auth, state); + composite_continue_rpc(c, req, get_schannel_creds_recv_auth, c); } static void get_schannel_creds_recv_auth(struct rpc_request *req) { - struct get_schannel_creds_state *state = + struct composite_context *c = talloc_get_type(req->async.private, + struct composite_context); + struct get_schannel_creds_state *state = + talloc_get_type(c->private_data, struct get_schannel_creds_state); - state->ctx->status = dcerpc_ndr_request_recv(req); - if (!composite_is_ok(state->ctx)) return; - state->ctx->status = state->a.out.result; - if (!composite_is_ok(state->ctx)) return; + c->status = dcerpc_ndr_request_recv(req); + if (!composite_is_ok(c)) return; + c->status = state->a.out.result; + if (!composite_is_ok(c)) return; if (!creds_client_check(state->creds_state, state->a.out.credentials)) { DEBUG(5, ("Server got us invalid creds\n")); - composite_error(state->ctx, NT_STATUS_UNSUCCESSFUL); + composite_error(c, NT_STATUS_UNSUCCESSFUL); return; } cli_credentials_set_netlogon_creds(state->wks_creds, state->creds_state); - composite_done(state->ctx); + composite_done(c); } NTSTATUS wb_get_schannel_creds_recv(struct composite_context *c, diff --git a/source4/winbind/wb_connect_lsa.c b/source4/winbind/wb_connect_lsa.c index d5222a6854..9443ef0dc7 100644 --- a/source4/winbind/wb_connect_lsa.c +++ b/source4/winbind/wb_connect_lsa.c @@ -43,6 +43,8 @@ struct init_lsa_state { }; static void init_lsa_recv_pipe(struct composite_context *ctx); +static void init_lsa_recv_anon_bind(struct composite_context *ctx); +static void init_lsa_recv_auth_bind(struct composite_context *ctx); static void init_lsa_recv_openpol(struct rpc_request *req); struct composite_context *wb_init_lsa_send(TALLOC_CTX *mem_ctx, @@ -86,17 +88,17 @@ 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); + ctx = dcerpc_bind_auth_none_send(state, state->lsa_pipe, + DCERPC_LSARPC_UUID, + DCERPC_LSARPC_VERSION); + composite_continue(state->ctx, ctx, init_lsa_recv_anon_bind, + state); break; case DCERPC_AUTH_TYPE_NTLMSSP: case DCERPC_AUTH_TYPE_SCHANNEL: @@ -105,17 +107,54 @@ static void init_lsa_recv_pipe(struct composite_context *ctx) return; } state->lsa_pipe->conn->flags |= (DCERPC_SIGN | DCERPC_SEAL); - state->ctx->status = - dcerpc_bind_auth(state->lsa_pipe, - DCERPC_LSARPC_UUID, - DCERPC_LSARPC_VERSION, - state->creds, state->auth_type, - NULL); + ctx = dcerpc_bind_auth_send(state, state->lsa_pipe, + DCERPC_LSARPC_UUID, + DCERPC_LSARPC_VERSION, + state->creds, state->auth_type, + NULL); + composite_continue(state->ctx, ctx, init_lsa_recv_auth_bind, + state); break; default: - state->ctx->status = NT_STATUS_INTERNAL_ERROR; - + composite_error(state->ctx, NT_STATUS_INTERNAL_ERROR); } +} + +static void init_lsa_recv_anon_bind(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_bind_auth_none_recv(ctx); + if (!composite_is_ok(state->ctx)) return; + + 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_auth_bind(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_bind_auth_recv(ctx); + if (!composite_is_ok(state->ctx)) return; state->handle = talloc(state, struct policy_handle); if (composite_nomem(state->handle, state->ctx)) return; diff --git a/source4/winbind/wb_connect_sam.c b/source4/winbind/wb_connect_sam.c index c806a6688b..b5511a1a12 100644 --- a/source4/winbind/wb_connect_sam.c +++ b/source4/winbind/wb_connect_sam.c @@ -46,6 +46,8 @@ struct connect_samr_state { }; static void connect_samr_recv_pipe(struct composite_context *ctx); +static void connect_samr_recv_anon_bind(struct composite_context *ctx); +static void connect_samr_recv_auth_bind(struct composite_context *ctx); static void connect_samr_recv_conn(struct rpc_request *req); static void connect_samr_recv_open(struct rpc_request *req); @@ -93,17 +95,17 @@ static void connect_samr_recv_pipe(struct composite_context *ctx) struct connect_samr_state *state = talloc_get_type(ctx->async.private_data, struct connect_samr_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->samr_pipe, - DCERPC_SAMR_UUID, - DCERPC_SAMR_VERSION); + ctx = dcerpc_bind_auth_none_send(state, state->samr_pipe, + DCERPC_SAMR_UUID, + DCERPC_SAMR_VERSION); + composite_continue(state->ctx, ctx, + connect_samr_recv_anon_bind, state); break; case DCERPC_AUTH_TYPE_NTLMSSP: case DCERPC_AUTH_TYPE_SCHANNEL: @@ -112,17 +114,51 @@ static void connect_samr_recv_pipe(struct composite_context *ctx) return; } state->samr_pipe->conn->flags |= (DCERPC_SIGN | DCERPC_SEAL); - state->ctx->status = - dcerpc_bind_auth(state->samr_pipe, - DCERPC_SAMR_UUID, - DCERPC_SAMR_VERSION, - state->creds, state->auth_type, - NULL); + ctx = dcerpc_bind_auth_send(state, state->samr_pipe, + DCERPC_SAMR_UUID, + DCERPC_SAMR_VERSION, + state->creds, state->auth_type, + NULL); + composite_continue(state->ctx, ctx, + connect_samr_recv_auth_bind, state); break; default: - state->ctx->status = NT_STATUS_INTERNAL_ERROR; - + composite_error(state->ctx, NT_STATUS_INTERNAL_ERROR); } +} + +static void connect_samr_recv_anon_bind(struct composite_context *ctx) +{ + struct connect_samr_state *state = + talloc_get_type(ctx->async.private_data, + struct connect_samr_state); + struct rpc_request *req; + + state->ctx->status = dcerpc_bind_auth_none_recv(ctx); + if (!composite_is_ok(state->ctx)) return; + + state->connect_handle = talloc(state, struct policy_handle); + if (composite_nomem(state->connect_handle, state->ctx)) return; + + state->c.in.system_name = + talloc_asprintf(state, "\\\\%s", + dcerpc_server_name(state->samr_pipe)); + state->c.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; + state->c.out.connect_handle = state->connect_handle; + + req = dcerpc_samr_Connect2_send(state->samr_pipe, state, &state->c); + composite_continue_rpc(state->ctx, req, connect_samr_recv_conn, state); +} + +static void connect_samr_recv_auth_bind(struct composite_context *ctx) +{ + struct connect_samr_state *state = + talloc_get_type(ctx->async.private_data, + struct connect_samr_state); + struct rpc_request *req; + + state->ctx->status = dcerpc_bind_auth_recv(ctx); + if (!composite_is_ok(state->ctx)) return; state->connect_handle = talloc(state, struct policy_handle); if (composite_nomem(state->connect_handle, state->ctx)) return; diff --git a/source4/winbind/wb_init_domain.c b/source4/winbind/wb_init_domain.c index fff3212cd9..07126dd04f 100644 --- a/source4/winbind/wb_init_domain.c +++ b/source4/winbind/wb_init_domain.c @@ -77,6 +77,7 @@ struct init_domain_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_schannel(struct composite_context *ctx); static void init_domain_recv_lsa(struct composite_context *ctx); static void init_domain_recv_queryinfo(struct rpc_request *req); static void init_domain_recv_ldapconn(struct composite_context *ctx); @@ -214,13 +215,22 @@ static void init_domain_recv_netlogonpipe(struct composite_context *ctx) state->domain->netlogon_pipe->conn->flags |= (DCERPC_SIGN | DCERPC_SEAL); - state->ctx->status = - dcerpc_bind_auth(state->domain->netlogon_pipe, - DCERPC_NETLOGON_UUID, - DCERPC_NETLOGON_VERSION, - state->domain->schannel_creds, - DCERPC_AUTH_TYPE_SCHANNEL, - NULL); + ctx = dcerpc_bind_auth_send(state, state->domain->netlogon_pipe, + DCERPC_NETLOGON_UUID, + DCERPC_NETLOGON_VERSION, + state->domain->schannel_creds, + DCERPC_AUTH_TYPE_SCHANNEL, + NULL); + composite_continue(state->ctx, ctx, init_domain_recv_schannel, state); +} + +static void init_domain_recv_schannel(struct composite_context *ctx) +{ + struct init_domain_state *state = + talloc_get_type(ctx->async.private_data, + struct init_domain_state); + + state->ctx->status = dcerpc_bind_auth_recv(ctx); if (!composite_is_ok(state->ctx)) return; ctx = wb_connect_lsa_send(state, state->conn.out.tree, -- cgit