summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVolker Lendecke <vlendec@samba.org>2005-10-15 19:18:05 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:44:48 -0500
commit42ececdfae15a34205638cc6e3ec53d6f3ac2148 (patch)
treeca9b6b82f861b11c3f0362e5bb863d7efa62f953
parent9259f9ecc0ab6fa3faeb582796d59420e71fc069 (diff)
downloadsamba-42ececdfae15a34205638cc6e3ec53d6f3ac2148.tar.gz
samba-42ececdfae15a34205638cc6e3ec53d6f3ac2148.tar.bz2
samba-42ececdfae15a34205638cc6e3ec53d6f3ac2148.zip
r11093: Implement wb_queue_domain_send: If the domain is not yet initialized, do that
first. And if a request is being processed, queue it. This correctly survived 3 endless loops with wbinfo's doing different things while starting up smbd. The number of indirections starts to become a bit scary, but what can you do without a decent programming language that provides closures :-) One thing that we might consider is to auto-generate async rpc requests that return composite_context structs instead of rpc_requests. Otherwise I'd have to write a lot of wrappers like composite_netr_LogonSamLogon_send. The alternative would be to write two versions of wb_queue_domain_send which I would like to avoid. This is cluttered enough already. Volker (This used to be commit 66c1b674f9870de73cce0e611909caf9eff34baa)
-rw-r--r--source4/include/structs.h1
-rw-r--r--source4/winbind/wb_async_helpers.c135
-rw-r--r--source4/winbind/wb_connect_lsa.c16
-rw-r--r--source4/winbind/wb_init_domain.c112
-rw-r--r--source4/winbind/wb_pam_auth.c100
-rw-r--r--source4/winbind/wb_server.h3
6 files changed, 235 insertions, 132 deletions
diff --git a/source4/include/structs.h b/source4/include/structs.h
index 68cae5d256..2925d4fec9 100644
--- a/source4/include/structs.h
+++ b/source4/include/structs.h
@@ -108,6 +108,7 @@ union netr_Validation;
struct netr_SamBaseInfo;
struct netr_SamInfo3;
struct netr_UserSessionKey;
+struct netr_LogonSamLogon;
struct iface_struct;
diff --git a/source4/winbind/wb_async_helpers.c b/source4/winbind/wb_async_helpers.c
index 0480304abe..146a957727 100644
--- a/source4/winbind/wb_async_helpers.c
+++ b/source4/winbind/wb_async_helpers.c
@@ -66,6 +66,7 @@ struct composite_context *wb_finddcs_send(const char *domain_name,
result = talloc_zero(NULL, struct composite_context);
if (result == NULL) goto failed;
result->state = COMPOSITE_STATE_IN_PROGRESS;
+ result->async.fn = NULL;
result->event_ctx = event_ctx;
state = talloc(result, struct finddcs_state);
@@ -197,6 +198,7 @@ struct composite_context *wb_get_schannel_creds_send(struct cli_credentials *wks
result = talloc_zero(NULL, struct composite_context);
if (result == NULL) goto failed;
result->state = COMPOSITE_STATE_IN_PROGRESS;
+ result->async.fn = NULL;
result->event_ctx = ev;
state = talloc(result, struct get_schannel_creds_state);
@@ -384,6 +386,7 @@ struct composite_context *wb_lsa_lookupnames_send(struct dcerpc_pipe *lsa_pipe,
result = talloc_zero(NULL, struct composite_context);
if (result == NULL) goto failed;
result->state = COMPOSITE_STATE_IN_PROGRESS;
+ result->async.fn = NULL;
result->event_ctx = lsa_pipe->conn->event_ctx;
state = talloc(result, struct lsa_lookupnames_state);
@@ -506,94 +509,68 @@ struct cmd_lookupname_state {
struct wb_sid_object *result;
};
-static void cmd_lookupname_recv_init(struct composite_context *ctx);
-static void cmd_lookupname_recv_sid(struct composite_context *ctx);
+static struct composite_context *lookupname_send_req(void *p);
+static NTSTATUS lookupname_recv_req(struct composite_context *ctx, void *p);
struct composite_context *wb_cmd_lookupname_send(struct wbsrv_call *call,
const char *name)
{
- struct composite_context *result, *ctx;
struct cmd_lookupname_state *state;
struct wbsrv_service *service = call->wbconn->listen_socket->service;
- result = talloc_zero(call, struct composite_context);
- if (result == NULL) goto failed;
- result->state = COMPOSITE_STATE_IN_PROGRESS;
- result->event_ctx = call->event_ctx;
-
- state = talloc(result, struct cmd_lookupname_state);
- if (state == NULL) goto failed;
- state->ctx = result;
- result->private_data = state;
-
+ state = talloc(NULL, struct cmd_lookupname_state);
+ state->domain = service->domains;
state->call = call;
state->name = talloc_strdup(state, name);
-
- state->domain = service->domains;
-
- if (state->domain->initialized) {
- ctx = wb_lsa_lookupnames_send(state->domain->lsa_pipe,
- state->domain->lsa_policy,
- 1, &state->name);
- if (ctx == NULL) goto failed;
- ctx->async.fn = cmd_lookupname_recv_sid;
- ctx->async.private_data = state;
- return result;
+ state->ctx = wb_queue_domain_send(state, state->domain,
+ call->event_ctx,
+ call->wbconn->conn->msg_ctx,
+ lookupname_send_req,
+ lookupname_recv_req,
+ state);
+ if (state->ctx == NULL) {
+ talloc_free(state);
+ return NULL;
}
-
- ctx = wb_init_domain_send(state->domain,
- result->event_ctx,
- call->wbconn->conn->msg_ctx);
- if (ctx == NULL) goto failed;
- ctx->async.fn = cmd_lookupname_recv_init;
- ctx->async.private_data = state;
- return result;
-
- failed:
- talloc_free(result);
- return NULL;
+ state->ctx->private_data = state;
+ return state->ctx;
}
-static void cmd_lookupname_recv_init(struct composite_context *ctx)
+static struct composite_context *lookupname_send_req(void *p)
{
struct cmd_lookupname_state *state =
- talloc_get_type(ctx->async.private_data,
- struct cmd_lookupname_state);
+ talloc_get_type(p, struct cmd_lookupname_state);
- state->ctx->status = wb_init_domain_recv(ctx);
- if (!composite_is_ok(state->ctx)) return;
-
- ctx = wb_lsa_lookupnames_send(state->domain->lsa_pipe,
- state->domain->lsa_policy,
- 1, &state->name);
- composite_continue(state->ctx, ctx, cmd_lookupname_recv_sid, state);
+ return wb_lsa_lookupnames_send(state->domain->lsa_pipe,
+ state->domain->lsa_policy,
+ 1, &state->name);
}
-static void cmd_lookupname_recv_sid(struct composite_context *ctx)
+static NTSTATUS lookupname_recv_req(struct composite_context *ctx, void *p)
{
struct cmd_lookupname_state *state =
- talloc_get_type(ctx->async.private_data,
- struct cmd_lookupname_state);
+ talloc_get_type(p, struct cmd_lookupname_state);
struct wb_sid_object **sids;
+ NTSTATUS status;
- state->ctx->status = wb_lsa_lookupnames_recv(ctx, state, &sids);
- if (!composite_is_ok(state->ctx)) return;
- state->result = sids[0];
- composite_done(state->ctx);
+ status = wb_lsa_lookupnames_recv(ctx, state, &sids);
+ if (NT_STATUS_IS_OK(status)) {
+ state->result = sids[0];
+ }
+ return status;
}
NTSTATUS wb_cmd_lookupname_recv(struct composite_context *c,
TALLOC_CTX *mem_ctx,
struct wb_sid_object **sid)
{
+ struct cmd_lookupname_state *state =
+ talloc_get_type(c->private_data, struct cmd_lookupname_state);
NTSTATUS status = composite_wait(c);
if (NT_STATUS_IS_OK(status)) {
- struct cmd_lookupname_state *state =
- talloc_get_type(c->private_data,
- struct cmd_lookupname_state);
*sid = talloc_steal(mem_ctx, state->result);
}
- talloc_free(c);
+ talloc_free(state);
return status;
}
@@ -622,6 +599,7 @@ struct composite_context *wb_cmd_checkmachacc_send(struct wbsrv_call *call)
result = talloc(call, struct composite_context);
if (result == NULL) goto failed;
result->state = COMPOSITE_STATE_IN_PROGRESS;
+ result->async.fn = NULL;
result->event_ctx = call->event_ctx;
state = talloc(result, struct cmd_checkmachacc_state);
@@ -669,3 +647,46 @@ NTSTATUS wb_cmd_checkmachacc(struct wbsrv_call *call)
struct composite_context *c = wb_cmd_checkmachacc_send(call);
return wb_cmd_checkmachacc_recv(c);
}
+
+static void composite_netr_LogonSamLogon_recv_rpc(struct rpc_request *req);
+
+struct composite_context *composite_netr_LogonSamLogon_send(struct dcerpc_pipe *p,
+ TALLOC_CTX *mem_ctx,
+ struct netr_LogonSamLogon *r)
+{
+ struct composite_context *result;
+ struct rpc_request *req;
+
+ 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 = p->conn->event_ctx;
+
+ req = dcerpc_netr_LogonSamLogon_send(p, mem_ctx, r);
+ if (req == NULL) goto failed;
+ req->async.callback = composite_netr_LogonSamLogon_recv_rpc;
+ req->async.private = result;
+ return result;
+
+ failed:
+ talloc_free(result);
+ return NULL;
+}
+
+static void composite_netr_LogonSamLogon_recv_rpc(struct rpc_request *req)
+{
+ struct composite_context *ctx =
+ talloc_get_type(req->async.private, struct composite_context);
+
+ ctx->status = dcerpc_ndr_request_recv(req);
+ if (!composite_is_ok(ctx)) return;
+ composite_done(ctx);
+}
+
+NTSTATUS composite_netr_LogonSamLogon_recv(struct composite_context *ctx)
+{
+ NTSTATUS status = composite_wait(ctx);
+ talloc_free(ctx);
+ return status;
+}
diff --git a/source4/winbind/wb_connect_lsa.c b/source4/winbind/wb_connect_lsa.c
index ef7b525c2a..82fe3b2e74 100644
--- a/source4/winbind/wb_connect_lsa.c
+++ b/source4/winbind/wb_connect_lsa.c
@@ -23,21 +23,9 @@
#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. */
@@ -67,6 +55,7 @@ static struct composite_context *wb_init_lsa_send(struct smbcli_tree *tree,
result = talloc(NULL, struct composite_context);
if (result == NULL) goto failed;
result->state = COMPOSITE_STATE_IN_PROGRESS;
+ result->async.fn = NULL;
result->event_ctx = tree->session->transport->socket->event.ctx;
state = talloc(result, struct init_lsa_state);
@@ -205,6 +194,7 @@ struct composite_context *wb_connect_lsa_send(struct smbcli_tree *tree,
result = talloc(NULL, struct composite_context);
if (result == NULL) goto failed;
result->state = COMPOSITE_STATE_IN_PROGRESS;
+ result->async.fn = NULL;
result->event_ctx = tree->session->transport->socket->event.ctx;
state = talloc(result, struct connect_lsa_state);
diff --git a/source4/winbind/wb_init_domain.c b/source4/winbind/wb_init_domain.c
index c9389ea7dd..fbe44244f4 100644
--- a/source4/winbind/wb_init_domain.c
+++ b/source4/winbind/wb_init_domain.c
@@ -26,6 +26,7 @@
#include "winbind/wb_async_helpers.h"
#include "winbind/wb_server.h"
#include "smbd/service_stream.h"
+#include "dlinklist.h"
#include "librpc/gen_ndr/nbt.h"
#include "librpc/gen_ndr/samr.h"
@@ -350,3 +351,114 @@ NTSTATUS wb_init_domain(struct wbsrv_domain *domain,
wb_init_domain_send(domain, event_ctx, messaging_ctx);
return wb_init_domain_recv(c);
}
+
+struct queue_domain_state {
+ struct queue_domain_state *prev, *next;
+ struct composite_context *ctx;
+ struct wbsrv_domain *domain;
+ struct composite_context *(*send_fn)(void *p);
+ NTSTATUS (*recv_fn)(struct composite_context *c,
+ void *p);
+ void *private_data;
+};
+
+static void queue_domain_recv_init(struct composite_context *ctx);
+static void queue_domain_recv_sub(struct composite_context *ctx);
+
+struct composite_context *wb_queue_domain_send(TALLOC_CTX *mem_ctx,
+ struct wbsrv_domain *domain,
+ struct event_context *event_ctx,
+ struct messaging_context *msg_ctx,
+ struct composite_context *(*send_fn)(void *p),
+ NTSTATUS (*recv_fn)(struct composite_context *c,
+ void *p),
+ void *private_data)
+{
+ struct composite_context *result, *ctx;
+ struct queue_domain_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 = event_ctx;
+
+ state = talloc(result, struct queue_domain_state);
+ if (state == NULL) goto failed;
+ state->ctx = result;
+ result->private_data = state;
+
+ state->send_fn = send_fn;
+ state->recv_fn = recv_fn;
+ state->private_data = private_data;
+ state->domain = domain;
+
+ if (domain->busy) {
+ DEBUG(0, ("Domain %s busy\n", domain->name));
+ DLIST_ADD_END(domain->request_queue, state,
+ struct queue_domain_state *);
+ return result;
+ }
+
+ domain->busy = True;
+
+ if (!domain->initialized) {
+ ctx = wb_init_domain_send(domain, result->event_ctx, msg_ctx);
+ if (ctx == NULL) goto failed;
+ ctx->async.fn = queue_domain_recv_init;
+ ctx->async.private_data = state;
+ return result;
+ }
+
+ ctx = state->send_fn(state->private_data);
+ if (ctx == NULL) goto failed;
+ ctx->async.fn = queue_domain_recv_sub;
+ ctx->async.private_data = state;
+ return result;
+
+ failed:
+ talloc_free(result);
+ return NULL;
+}
+
+static void queue_domain_recv_init(struct composite_context *ctx)
+{
+ struct queue_domain_state *state =
+ talloc_get_type(ctx->async.private_data,
+ struct queue_domain_state);
+
+ state->ctx->status = wb_init_domain_recv(ctx);
+ if (!composite_is_ok(state->ctx)) return;
+
+ ctx = state->send_fn(state->private_data);
+ composite_continue(state->ctx, ctx, queue_domain_recv_sub, state);
+}
+
+static void queue_domain_recv_sub(struct composite_context *ctx)
+{
+ struct queue_domain_state *state =
+ talloc_get_type(ctx->async.private_data,
+ struct queue_domain_state);
+
+ state->ctx->status = state->recv_fn(ctx, state->private_data);
+ state->domain->busy = False;
+
+ if (state->domain->request_queue != NULL) {
+ struct queue_domain_state *s2;
+ s2 = state->domain->request_queue;
+ DLIST_REMOVE(state->domain->request_queue, s2);
+ ctx = s2->send_fn(s2->private_data);
+ composite_continue(s2->ctx, ctx, queue_domain_recv_sub, s2);
+ state->domain->busy = True;
+ }
+
+ if (!composite_is_ok(state->ctx)) return;
+ composite_done(state->ctx);
+}
+
+NTSTATUS wb_queue_domain_recv(struct composite_context *ctx)
+{
+ NTSTATUS status = composite_wait(ctx);
+ talloc_free(ctx);
+ return status;
+}
diff --git a/source4/winbind/wb_pam_auth.c b/source4/winbind/wb_pam_auth.c
index f35ff4703d..ef43aededd 100644
--- a/source4/winbind/wb_pam_auth.c
+++ b/source4/winbind/wb_pam_auth.c
@@ -29,6 +29,7 @@
struct pam_auth_crap_state {
struct composite_context *ctx;
+ struct event_context *event_ctx;
struct wbsrv_domain *domain;
const char *domain_name;
const char *user_name;
@@ -45,9 +46,8 @@ struct pam_auth_crap_state {
DATA_BLOB info3;
};
-static struct rpc_request *send_samlogon(struct pam_auth_crap_state *state);
-static void pam_auth_crap_recv_init(struct composite_context *ctx);
-static void pam_auth_crap_recv_samlogon(struct rpc_request *req);
+static struct composite_context *crap_samlogon_send_req(void *p);
+static NTSTATUS crap_samlogon_recv_req(struct composite_context *ctx, void *p);
struct composite_context *wb_cmd_pam_auth_crap_send(struct wbsrv_call *call,
const char *domain,
@@ -57,22 +57,14 @@ struct composite_context *wb_cmd_pam_auth_crap_send(struct wbsrv_call *call,
DATA_BLOB nt_resp,
DATA_BLOB lm_resp)
{
- struct composite_context *result, *ctx;
struct pam_auth_crap_state *state;
struct wbsrv_service *service = call->wbconn->listen_socket->service;
- result = talloc(NULL, struct composite_context);
- if (result == NULL) goto failed;
- result->state = COMPOSITE_STATE_IN_PROGRESS;
- result->event_ctx = call->event_ctx;
- result->async.fn = NULL;
-
- state = talloc(result, struct pam_auth_crap_state);
+ state = talloc(NULL, struct pam_auth_crap_state);
if (state == NULL) goto failed;
- state->ctx = result;
- result->private_data = state;
state->domain = service->domains;
+ state->event_ctx = call->event_ctx;
state->domain_name = talloc_strdup(state, domain);
if (state->domain_name == NULL) goto failed;
@@ -94,45 +86,28 @@ struct composite_context *wb_cmd_pam_auth_crap_send(struct wbsrv_call *call,
if ((lm_resp.data != NULL) &&
(state->lm_resp.data == NULL)) goto failed;
- if (state->domain->initialized) {
- struct rpc_request *req = send_samlogon(state);
- if (req == NULL) goto failed;
- req->async.callback = pam_auth_crap_recv_samlogon;
- req->async.private = state;
- return result;
- }
-
- ctx = wb_init_domain_send(state->domain, result->event_ctx,
- call->wbconn->conn->msg_ctx);
- if (ctx == NULL) goto failed;
- ctx->async.fn = pam_auth_crap_recv_init;
- ctx->async.private_data = state;
- return result;
+ state->ctx = wb_queue_domain_send(state, state->domain,
+ call->event_ctx,
+ call->wbconn->conn->msg_ctx,
+ crap_samlogon_send_req,
+ crap_samlogon_recv_req,
+ state);
+ if (state->ctx == NULL) goto failed;
+ state->ctx->private_data = state;
+ return state->ctx;
failed:
- talloc_free(result);
+ talloc_free(state);
return NULL;
}
-static void pam_auth_crap_recv_init(struct composite_context *ctx)
+static struct composite_context *crap_samlogon_send_req(void *p)
{
struct pam_auth_crap_state *state =
- talloc_get_type(ctx->async.private_data,
- struct pam_auth_crap_state);
- struct rpc_request *req;
-
- state->ctx->status = wb_init_domain_recv(ctx);
- if (!composite_is_ok(state->ctx)) return;
-
- req = send_samlogon(state);
- composite_continue_rpc(state->ctx, req,
- pam_auth_crap_recv_samlogon, state);
-}
-
-static struct rpc_request *send_samlogon(struct pam_auth_crap_state *state)
-{
+ talloc_get_type(p, struct pam_auth_crap_state);
state->creds_state = cli_credentials_get_netlogon_creds(
state->domain->schannel_creds);
+
creds_client_authenticator(state->creds_state, &state->auth);
state->ninfo.identity_info.account_name.string = state->user_name;
@@ -165,42 +140,44 @@ static struct rpc_request *send_samlogon(struct pam_auth_crap_state *state)
state->r.in.logon.network = &state->ninfo;
state->r.out.return_authenticator = NULL;
- return dcerpc_netr_LogonSamLogon_send(state->domain->netlogon_pipe,
- state, &state->r);
+ return composite_netr_LogonSamLogon_send(state->domain->netlogon_pipe,
+ state, &state->r);
}
-static void pam_auth_crap_recv_samlogon(struct rpc_request *req)
+static NTSTATUS crap_samlogon_recv_req(struct composite_context *ctx,
+ void *p)
{
struct pam_auth_crap_state *state =
- talloc_get_type(req->async.private,
- struct pam_auth_crap_state);
+ talloc_get_type(p, struct pam_auth_crap_state);
struct netr_SamBaseInfo *base;
DATA_BLOB tmp_blob;
+ NTSTATUS status;
- 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;
+ status = composite_netr_LogonSamLogon_recv(ctx);
+ if (!NT_STATUS_IS_OK(status)) return status;
+
+ status = state->r.out.result;
+ if (!NT_STATUS_IS_OK(status)) return status;
if ((state->r.out.return_authenticator == NULL) ||
(!creds_client_check(state->creds_state,
&state->r.out.return_authenticator->cred))) {
DEBUG(0, ("Credentials check failed!\n"));
- composite_error(state->ctx, NT_STATUS_ACCESS_DENIED);
- return;
+ return NT_STATUS_ACCESS_DENIED;
}
creds_decrypt_samlogon(state->creds_state,
state->r.in.validation_level,
&state->r.out.validation);
- state->ctx->status = ndr_push_struct_blob(
- &tmp_blob, state, state->r.out.validation.sam3,
+ status = ndr_push_struct_blob(
+ &tmp_blob, state,
+ state->r.out.validation.sam3,
(ndr_push_flags_fn_t)ndr_push_netr_SamInfo3);
- if (!composite_is_ok(state->ctx)) return;
-
+ NT_STATUS_NOT_OK_RETURN(status);
+
state->info3 = data_blob_talloc(state, NULL, tmp_blob.length+4);
- if (composite_nomem(state->info3.data, state->ctx)) return;
+ NT_STATUS_HAVE_NO_MEMORY(state->info3.data);
SIVAL(state->info3.data, 0, 1);
memcpy(state->info3.data+4, tmp_blob.data, tmp_blob.length);
@@ -218,14 +195,13 @@ static void pam_auth_crap_recv_samlogon(struct rpc_request *req)
break;
}
if (base == NULL) {
- composite_error(state->ctx, NT_STATUS_INTERNAL_ERROR);
- return;
+ return NT_STATUS_INTERNAL_ERROR;
}
state->user_session_key = base->key;
state->lm_key = base->LMSessKey;
- composite_done(state->ctx);
+ return NT_STATUS_OK;
}
NTSTATUS wb_cmd_pam_auth_crap_recv(struct composite_context *c,
diff --git a/source4/winbind/wb_server.h b/source4/winbind/wb_server.h
index df871f4c25..52e7256570 100644
--- a/source4/winbind/wb_server.h
+++ b/source4/winbind/wb_server.h
@@ -58,6 +58,9 @@ struct wbsrv_domain {
struct dcerpc_pipe *netlogon_auth2_pipe;
struct dcerpc_pipe *netlogon_pipe;
struct cli_credentials *schannel_creds;
+
+ BOOL busy;
+ struct queue_domain_state *request_queue;
};
/*