summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2010-09-13 07:41:56 +1000
committerAndrew Tridgell <tridge@samba.org>2010-09-15 15:39:34 +1000
commit5b02cf1eb0b2e524cb58ec6ed6e766c252b06af9 (patch)
treeb3efcd5c6523dc88c1269099ac66054f1f029e82
parent890a33c99bc0a468984c456647311db0a19528aa (diff)
downloadsamba-5b02cf1eb0b2e524cb58ec6ed6e766c252b06af9.tar.gz
samba-5b02cf1eb0b2e524cb58ec6ed6e766c252b06af9.tar.bz2
samba-5b02cf1eb0b2e524cb58ec6ed6e766c252b06af9.zip
s4-auth: allow multiple active auth backends
when we are an RODC we need to be able to allow multiple auth backends to process a single auth request. First the sam backend will try to authenticate, using locally stored passwords. If this backend can't find local passwords then it will try the winbind backend and authenticate via a writeable DC Pair-Programmed-With: Andrew Bartlett <abartlet@samba.org>
-rw-r--r--source4/auth/ntlm/auth.c78
1 files changed, 43 insertions, 35 deletions
diff --git a/source4/auth/ntlm/auth.c b/source4/auth/ntlm/auth.c
index a977aa4c41..b34b8ac132 100644
--- a/source4/auth/ntlm/auth.c
+++ b/source4/auth/ntlm/auth.c
@@ -234,7 +234,6 @@ _PUBLIC_ struct tevent_req *auth_check_password_send(TALLOC_CTX *mem_ctx,
struct auth_check_password_state *state;
/* if all the modules say 'not for me' this is reasonable */
NTSTATUS nt_status;
- struct auth_method_context *method;
uint8_t chal[8];
struct auth_usersupplied_info *user_info_tmp;
struct tevent_immediate *im;
@@ -252,7 +251,6 @@ _PUBLIC_ struct tevent_req *auth_check_password_send(TALLOC_CTX *mem_ctx,
state->auth_ctx = auth_ctx;
state->user_info = user_info;
- state->method = NULL;
if (!user_info->mapped_state) {
nt_status = map_user_info(req, lpcfg_workgroup(auth_ctx->lp_ctx),
@@ -296,35 +294,11 @@ _PUBLIC_ struct tevent_req *auth_check_password_send(TALLOC_CTX *mem_ctx,
return tevent_req_post(req, ev);
}
- for (method = auth_ctx->methods; method; method = method->next) {
- NTSTATUS result;
-
- /* check if the module wants to chek the password */
- result = method->ops->want_check(method, req, user_info);
- if (NT_STATUS_EQUAL(result, NT_STATUS_NOT_IMPLEMENTED)) {
- DEBUG(11,("auth_check_password_send: "
- "%s had nothing to say\n",
- method->ops->name));
- continue;
- }
-
- state->method = method;
-
- if (tevent_req_nterror(req, result)) {
- return tevent_req_post(req, ev);
- }
-
- tevent_schedule_immediate(im,
- auth_ctx->event_ctx,
- auth_check_password_async_trigger,
- req);
-
- return req;
- }
-
- /* If all the modules say 'not for me', then this is reasonable */
- tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER);
- return tevent_req_post(req, ev);
+ tevent_schedule_immediate(im,
+ auth_ctx->event_ctx,
+ auth_check_password_async_trigger,
+ req);
+ return req;
}
static void auth_check_password_async_trigger(struct tevent_context *ev,
@@ -336,11 +310,45 @@ static void auth_check_password_async_trigger(struct tevent_context *ev,
struct auth_check_password_state *state =
tevent_req_data(req, struct auth_check_password_state);
NTSTATUS status;
+ struct auth_method_context *method;
+
+ status = NT_STATUS_OK;
+
+ for (method=state->auth_ctx->methods; method; method = method->next) {
+
+ /* we fill in state->method here so debug messages in
+ the callers know which method failed */
+ state->method = method;
+
+ /* check if the module wants to check the password */
+ status = method->ops->want_check(method, req, state->user_info);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
+ DEBUG(11,("auth_check_password_send: "
+ "%s had nothing to say\n",
+ method->ops->name));
+ continue;
+ }
+
+ if (tevent_req_nterror(req, status)) {
+ return;
+ }
+
+ status = method->ops->check_password(method,
+ state,
+ state->user_info,
+ &state->server_info);
+ if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
+ /* the backend has handled the request */
+ break;
+ }
+ }
+
+ if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
+ /* don't expose the NT_STATUS_NOT_IMPLEMENTED
+ internals */
+ status = NT_STATUS_NO_SUCH_USER;
+ }
- status = state->method->ops->check_password(state->method,
- state,
- state->user_info,
- &state->server_info);
if (tevent_req_nterror(req, status)) {
return;
}