auth auth_log: csbuild unused parm unix_username
[Samba.git] / source4 / auth / ntlm / auth.c
blobead5326705e67ec071ab34fcfce968834ef96f53
1 /*
2 Unix SMB/CIFS implementation.
3 Password and authentication handling
4 Copyright (C) Andrew Bartlett 2001-2002
5 Copyright (C) Stefan Metzmacher 2005
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "includes.h"
22 #include <tevent.h>
23 #include "../lib/util/tevent_ntstatus.h"
24 #include "../lib/util/dlinklist.h"
25 #include "auth/auth.h"
26 #include "auth/ntlm/auth_proto.h"
27 #include "param/param.h"
28 #include "dsdb/samdb/samdb.h"
29 #include "libcli/wbclient/wbclient.h"
30 #include "lib/util/samba_modules.h"
31 #include "auth/credentials/credentials.h"
32 #include "system/kerberos.h"
33 #include "auth/kerberos/kerberos.h"
34 #include "auth/kerberos/kerberos_util.h"
35 #include "libds/common/roles.h"
37 #undef DBGC_CLASS
38 #define DBGC_CLASS DBGC_AUTH
40 static NTSTATUS auth_generate_session_info_wrapper(struct auth4_context *auth_context,
41 TALLOC_CTX *mem_ctx,
42 void *server_returned_info,
43 const char *original_user_name,
44 uint32_t session_info_flags,
45 struct auth_session_info **session_info);
47 /***************************************************************************
48 Set a fixed challenge
49 ***************************************************************************/
50 _PUBLIC_ NTSTATUS auth_context_set_challenge(struct auth4_context *auth_ctx, const uint8_t chal[8], const char *set_by)
52 auth_ctx->challenge.set_by = talloc_strdup(auth_ctx, set_by);
53 NT_STATUS_HAVE_NO_MEMORY(auth_ctx->challenge.set_by);
55 auth_ctx->challenge.data = data_blob_talloc(auth_ctx, chal, 8);
56 NT_STATUS_HAVE_NO_MEMORY(auth_ctx->challenge.data.data);
58 return NT_STATUS_OK;
61 /****************************************************************************
62 Try to get a challenge out of the various authentication modules.
63 Returns a const char of length 8 bytes.
64 ****************************************************************************/
65 _PUBLIC_ NTSTATUS auth_get_challenge(struct auth4_context *auth_ctx, uint8_t chal[8])
68 if (auth_ctx->challenge.data.length == 8) {
69 DEBUG(5, ("auth_get_challenge: returning previous challenge by module %s (normal)\n",
70 auth_ctx->challenge.set_by));
71 memcpy(chal, auth_ctx->challenge.data.data, 8);
72 return NT_STATUS_OK;
75 if (!auth_ctx->challenge.set_by) {
76 generate_random_buffer(chal, 8);
78 auth_ctx->challenge.data = data_blob_talloc(auth_ctx, chal, 8);
79 NT_STATUS_HAVE_NO_MEMORY(auth_ctx->challenge.data.data);
80 auth_ctx->challenge.set_by = "random";
83 DEBUG(10,("auth_get_challenge: challenge set by %s\n",
84 auth_ctx->challenge.set_by));
86 return NT_STATUS_OK;
89 /****************************************************************************
90 Used in the gensec_gssapi and gensec_krb5 server-side code, where the
91 PAC isn't available, and for tokenGroups in the DSDB stack.
93 Supply either a principal or a DN
94 ****************************************************************************/
95 static NTSTATUS auth_generate_session_info_principal(struct auth4_context *auth_ctx,
96 TALLOC_CTX *mem_ctx,
97 const char *principal,
98 struct ldb_dn *user_dn,
99 uint32_t session_info_flags,
100 struct auth_session_info **session_info)
102 NTSTATUS nt_status;
103 struct auth_method_context *method;
104 struct auth_user_info_dc *user_info_dc;
106 for (method = auth_ctx->methods; method; method = method->next) {
107 if (!method->ops->get_user_info_dc_principal) {
108 continue;
111 nt_status = method->ops->get_user_info_dc_principal(mem_ctx, auth_ctx, principal, user_dn, &user_info_dc);
112 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NOT_IMPLEMENTED)) {
113 continue;
115 if (!NT_STATUS_IS_OK(nt_status)) {
116 return nt_status;
119 nt_status = auth_generate_session_info_wrapper(auth_ctx, mem_ctx,
120 user_info_dc,
121 user_info_dc->info->account_name,
122 session_info_flags, session_info);
123 talloc_free(user_info_dc);
125 return nt_status;
128 return NT_STATUS_NOT_IMPLEMENTED;
132 * Check a user's Plaintext, LM or NTLM password.
133 * (sync version)
135 * Check a user's password, as given in the user_info struct and return various
136 * interesting details in the user_info_dc struct.
138 * The return value takes precedence over the contents of the user_info_dc
139 * struct. When the return is other than NT_STATUS_OK the contents
140 * of that structure is undefined.
142 * @param auth_ctx Supplies the challenges and some other data.
143 * Must be created with auth_context_create(), and the challenges should be
144 * filled in, either at creation or by calling the challenge geneation
145 * function auth_get_challenge().
147 * @param user_info Contains the user supplied components, including the passwords.
149 * @param mem_ctx The parent memory context for the user_info_dc structure
151 * @param user_info_dc If successful, contains information about the authentication,
152 * including a SAM_ACCOUNT struct describing the user.
154 * @return An NTSTATUS with NT_STATUS_OK or an appropriate error.
158 _PUBLIC_ NTSTATUS auth_check_password(struct auth4_context *auth_ctx,
159 TALLOC_CTX *mem_ctx,
160 const struct auth_usersupplied_info *user_info,
161 struct auth_user_info_dc **user_info_dc,
162 uint8_t *pauthoritative)
164 struct tevent_req *subreq;
165 struct tevent_context *ev;
166 bool ok;
167 NTSTATUS status;
169 /*TODO: create a new event context here! */
170 ev = auth_ctx->event_ctx;
172 subreq = auth_check_password_send(mem_ctx,
174 auth_ctx,
175 user_info);
176 if (subreq == NULL) {
177 return NT_STATUS_NO_MEMORY;
180 ok = tevent_req_poll(subreq, ev);
181 if (!ok) {
182 return NT_STATUS_INTERNAL_ERROR;
185 status = auth_check_password_recv(subreq, mem_ctx,
186 user_info_dc, pauthoritative);
187 TALLOC_FREE(subreq);
189 return status;
192 struct auth_check_password_state {
193 struct tevent_context *ev;
194 struct auth4_context *auth_ctx;
195 const struct auth_usersupplied_info *user_info;
196 struct auth_user_info_dc *user_info_dc;
197 struct auth_method_context *method;
198 uint8_t authoritative;
201 static void auth_check_password_next(struct tevent_req *req);
204 * Check a user's Plaintext, LM or NTLM password.
205 * async send hook
207 * Check a user's password, as given in the user_info struct and return various
208 * interesting details in the user_info_dc struct.
210 * The return value takes precedence over the contents of the user_info_dc
211 * struct. When the return is other than NT_STATUS_OK the contents
212 * of that structure is undefined.
214 * @param mem_ctx The memory context the request should operate on
216 * @param ev The tevent context the request should operate on
218 * @param auth_ctx Supplies the challenges and some other data.
219 * Must be created with make_auth_context(), and the challenges should be
220 * filled in, either at creation or by calling the challenge geneation
221 * function auth_get_challenge().
223 * @param user_info Contains the user supplied components, including the passwords.
225 * @return The request handle or NULL on no memory error.
229 _PUBLIC_ struct tevent_req *auth_check_password_send(TALLOC_CTX *mem_ctx,
230 struct tevent_context *ev,
231 struct auth4_context *auth_ctx,
232 const struct auth_usersupplied_info *user_info)
234 struct tevent_req *req;
235 struct auth_check_password_state *state;
236 /* if all the modules say 'not for me' this is reasonable */
237 NTSTATUS nt_status;
238 uint8_t chal[8];
240 DEBUG(3,("auth_check_password_send: "
241 "Checking password for unmapped user [%s]\\[%s]@[%s]\n",
242 user_info->client.domain_name, user_info->client.account_name,
243 user_info->workstation_name));
245 req = tevent_req_create(mem_ctx, &state,
246 struct auth_check_password_state);
247 if (req == NULL) {
248 return NULL;
252 * We are authoritative by default.
254 state->ev = ev;
255 state->auth_ctx = auth_ctx;
256 state->user_info = user_info;
257 state->authoritative = 1;
259 if (!user_info->mapped_state) {
260 struct auth_usersupplied_info *user_info_tmp;
263 * We don't really do any mapping here.
265 * So we don't set user_info->mapped_state,
266 * but we set mapped.domain_name and
267 * mapped.account_name to the client
268 * provided values.
270 * It's up to the backends to do mappings
271 * for their authentication.
273 user_info_tmp = talloc_zero(state, struct auth_usersupplied_info);
274 if (tevent_req_nomem(user_info_tmp, req)) {
275 return tevent_req_post(req, ev);;
279 * The lifetime of user_info is longer than
280 * user_info_tmp, so we don't need to copy the
281 * strings.
283 *user_info_tmp = *user_info;
284 user_info_tmp->mapped.domain_name = user_info->client.domain_name;
285 user_info_tmp->mapped.account_name = user_info->client.account_name;
287 user_info = user_info_tmp;
288 state->user_info = user_info_tmp;
291 DEBUGADD(3,("auth_check_password_send: "
292 "user is: [%s]\\[%s]@[%s]\n",
293 user_info->mapped.domain_name,
294 user_info->mapped.account_name,
295 user_info->workstation_name));
297 nt_status = auth_get_challenge(auth_ctx, chal);
298 if (tevent_req_nterror(req, nt_status)) {
299 DEBUG(0,("auth_check_password_send: "
300 "Invalid challenge (length %u) stored for "
301 "this auth context set_by %s - cannot continue: %s\n",
302 (unsigned)auth_ctx->challenge.data.length,
303 auth_ctx->challenge.set_by,
304 nt_errstr(nt_status)));
305 return tevent_req_post(req, ev);
308 if (auth_ctx->challenge.set_by) {
309 DEBUG(10,("auth_check_password_send: "
310 "auth_context challenge created by %s\n",
311 auth_ctx->challenge.set_by));
314 DEBUG(10, ("auth_check_password_send: challenge is: \n"));
315 dump_data(5, auth_ctx->challenge.data.data,
316 auth_ctx->challenge.data.length);
318 state->method = state->auth_ctx->methods;
319 auth_check_password_next(req);
320 if (!tevent_req_is_in_progress(req)) {
321 return tevent_req_post(req, ev);
324 return req;
327 static void auth_check_password_done(struct tevent_req *subreq);
329 static void auth_check_password_next(struct tevent_req *req)
331 struct auth_check_password_state *state =
332 tevent_req_data(req, struct auth_check_password_state);
333 struct tevent_req *subreq = NULL;
334 bool authoritative = true;
335 NTSTATUS status;
337 if (state->method == NULL) {
338 state->authoritative = 0;
339 tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER);
340 return;
343 /* check if the module wants to check the password */
344 status = state->method->ops->want_check(state->method, state,
345 state->user_info);
346 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
347 DEBUG(11,("auth_check_password_send: "
348 "%s doesn't want to check\n",
349 state->method->ops->name));
350 state->method = state->method->next;
351 auth_check_password_next(req);
352 return;
355 if (tevent_req_nterror(req, status)) {
356 return;
359 if (state->method->ops->check_password_send != NULL) {
360 subreq = state->method->ops->check_password_send(state,
361 state->ev,
362 state->method,
363 state->user_info);
364 if (tevent_req_nomem(subreq, req)) {
365 return;
367 tevent_req_set_callback(subreq,
368 auth_check_password_done,
369 req);
370 return;
373 if (state->method->ops->check_password == NULL) {
374 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
375 return;
378 status = state->method->ops->check_password(state->method,
379 state,
380 state->user_info,
381 &state->user_info_dc,
382 &authoritative);
383 if (!authoritative ||
384 NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
385 DEBUG(11,("auth_check_password_send: "
386 "%s passes to the next method\n",
387 state->method->ops->name));
388 state->method = state->method->next;
389 auth_check_password_next(req);
390 return;
393 /* the backend has handled the request */
395 if (tevent_req_nterror(req, status)) {
396 return;
399 tevent_req_done(req);
402 static void auth_check_password_done(struct tevent_req *subreq)
404 struct tevent_req *req =
405 tevent_req_callback_data(subreq,
406 struct tevent_req);
407 struct auth_check_password_state *state =
408 tevent_req_data(req,
409 struct auth_check_password_state);
410 bool authoritative = true;
411 NTSTATUS status;
413 status = state->method->ops->check_password_recv(subreq, state,
414 &state->user_info_dc,
415 &authoritative);
416 TALLOC_FREE(subreq);
417 if (!authoritative ||
418 NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
419 DEBUG(11,("auth_check_password_send: "
420 "%s passes to the next method\n",
421 state->method->ops->name));
422 state->method = state->method->next;
423 auth_check_password_next(req);
424 return;
427 /* the backend has handled the request */
429 if (tevent_req_nterror(req, status)) {
430 return;
433 tevent_req_done(req);
437 * Check a user's Plaintext, LM or NTLM password.
438 * async receive function
440 * The return value takes precedence over the contents of the user_info_dc
441 * struct. When the return is other than NT_STATUS_OK the contents
442 * of that structure is undefined.
445 * @param req The async request state
447 * @param mem_ctx The parent memory context for the user_info_dc structure
449 * @param user_info_dc If successful, contains information about the authentication,
450 * including a SAM_ACCOUNT struct describing the user.
452 * @return An NTSTATUS with NT_STATUS_OK or an appropriate error.
456 _PUBLIC_ NTSTATUS auth_check_password_recv(struct tevent_req *req,
457 TALLOC_CTX *mem_ctx,
458 struct auth_user_info_dc **user_info_dc,
459 uint8_t *pauthoritative)
461 struct auth_check_password_state *state =
462 tevent_req_data(req, struct auth_check_password_state);
463 NTSTATUS status = NT_STATUS_OK;
465 *pauthoritative = state->authoritative;
467 if (tevent_req_is_nterror(req, &status)) {
469 * Please try not to change this string, it is probably in use
470 * in audit logging tools
472 DEBUG(2,("auth_check_password_recv: "
473 "%s authentication for user [%s\\%s] "
474 "FAILED with error %s, authoritative=%u\n",
475 (state->method ? state->method->ops->name : "NO_METHOD"),
476 state->user_info->mapped.domain_name,
477 state->user_info->mapped.account_name,
478 nt_errstr(status), state->authoritative));
480 log_authentication_event(state->auth_ctx->msg_ctx,
481 state->auth_ctx->lp_ctx,
482 &state->auth_ctx->start_time,
483 state->user_info, status,
484 NULL, NULL, NULL);
485 tevent_req_received(req);
486 return status;
489 DEBUG(5,("auth_check_password_recv: "
490 "%s authentication for user [%s\\%s] succeeded\n",
491 state->method->ops->name,
492 state->user_info_dc->info->domain_name,
493 state->user_info_dc->info->account_name));
495 log_authentication_event(state->auth_ctx->msg_ctx,
496 state->auth_ctx->lp_ctx,
497 &state->auth_ctx->start_time,
498 state->user_info, status,
499 state->user_info_dc->info->domain_name,
500 state->user_info_dc->info->account_name,
501 &state->user_info_dc->sids[0]);
503 *user_info_dc = talloc_move(mem_ctx, &state->user_info_dc);
505 tevent_req_received(req);
506 return NT_STATUS_OK;
509 struct auth_check_password_wrapper_state {
510 uint8_t authoritative;
511 struct auth_user_info_dc *user_info_dc;
514 static void auth_check_password_wrapper_done(struct tevent_req *subreq);
516 static struct tevent_req *auth_check_password_wrapper_send(TALLOC_CTX *mem_ctx,
517 struct tevent_context *ev,
518 struct auth4_context *auth_ctx,
519 const struct auth_usersupplied_info *user_info)
521 struct tevent_req *req = NULL;
522 struct auth_check_password_wrapper *state = NULL;
523 struct tevent_req *subreq = NULL;
525 req = tevent_req_create(mem_ctx, &state,
526 struct auth_check_password_wrapper_state);
527 if (req == NULL) {
528 return NULL;
531 subreq = auth_check_password_send(state, ev, auth_ctx, user_info);
532 if (tevent_req_nomem(subreq, req)) {
533 return tevent_req_post(req, ev);
535 tevent_req_set_callback(subreq,
536 auth_check_password_wrapper_done,
537 req);
539 return req;
542 static void auth_check_password_wrapper_done(struct tevent_req *subreq)
544 struct tevent_req *req =
545 tevent_req_callback_data(subreq,
546 struct tevent_req);
547 struct auth_check_password_wrapper_state *state =
548 tevent_req_data(req,
549 struct auth_check_password_wrapper_state);
550 NTSTATUS status;
552 status = auth_check_password_recv(subreq, state,
553 &state->user_info_dc,
554 &state->authoritative);
555 TALLOC_FREE(subreq);
556 if (tevent_req_nterror(req, status)) {
557 return;
560 tevent_req_done(req);
563 static NTSTATUS auth_check_password_wrapper_recv(struct tevent_req *req,
564 TALLOC_CTX *mem_ctx,
565 uint8_t *pauthoritative,
566 void **server_returned_info,
567 DATA_BLOB *user_session_key,
568 DATA_BLOB *lm_session_key)
570 struct auth_check_password_wrapper_state *state =
571 tevent_req_data(req,
572 struct auth_check_password_wrapper_state);
573 struct auth_user_info_dc *user_info_dc = state->user_info_dc;
574 NTSTATUS status = NT_STATUS_OK;
576 *pauthoritative = state->authoritative;
578 if (tevent_req_is_nterror(req, &status)) {
579 tevent_req_received(req);
580 return status;
583 talloc_steal(mem_ctx, user_info_dc);
584 *server_returned_info = user_info_dc;
586 if (user_session_key) {
587 DEBUG(10, ("Got NT session key of length %u\n",
588 (unsigned)user_info_dc->user_session_key.length));
589 *user_session_key = user_info_dc->user_session_key;
590 talloc_steal(mem_ctx, user_session_key->data);
591 user_info_dc->user_session_key = data_blob_null;
594 if (lm_session_key) {
595 DEBUG(10, ("Got LM session key of length %u\n",
596 (unsigned)user_info_dc->lm_session_key.length));
597 *lm_session_key = user_info_dc->lm_session_key;
598 talloc_steal(mem_ctx, lm_session_key->data);
599 user_info_dc->lm_session_key = data_blob_null;
602 tevent_req_received(req);
603 return NT_STATUS_OK;
606 /* Wrapper because we don't want to expose all callers to needing to
607 * know that session_info is generated from the main ldb, and because
608 * we need to break a depenency loop between the DCE/RPC layer and the
609 * generation of unix tokens via IRPC */
610 static NTSTATUS auth_generate_session_info_wrapper(struct auth4_context *auth_context,
611 TALLOC_CTX *mem_ctx,
612 void *server_returned_info,
613 const char *original_user_name,
614 uint32_t session_info_flags,
615 struct auth_session_info **session_info)
617 NTSTATUS status;
618 struct auth_user_info_dc *user_info_dc = talloc_get_type_abort(server_returned_info, struct auth_user_info_dc);
620 if (user_info_dc->info->authenticated) {
621 session_info_flags |= AUTH_SESSION_INFO_AUTHENTICATED;
624 status = auth_generate_session_info(mem_ctx, auth_context->lp_ctx,
625 auth_context->sam_ctx, user_info_dc,
626 session_info_flags, session_info);
627 if (!NT_STATUS_IS_OK(status)) {
628 return status;
631 if ((session_info_flags & AUTH_SESSION_INFO_UNIX_TOKEN)
632 && NT_STATUS_IS_OK(status)) {
633 status = auth_session_info_fill_unix(auth_context->lp_ctx,
634 original_user_name,
635 *session_info);
636 if (!NT_STATUS_IS_OK(status)) {
637 TALLOC_FREE(*session_info);
640 return status;
643 /* Wrapper because we don't want to expose all callers to needing to
644 * know anything about the PAC or auth subsystem internal structures
645 * before we output a struct auth session_info */
646 static NTSTATUS auth_generate_session_info_pac(struct auth4_context *auth_ctx,
647 TALLOC_CTX *mem_ctx,
648 struct smb_krb5_context *smb_krb5_context,
649 DATA_BLOB *pac_blob,
650 const char *principal_name,
651 const struct tsocket_address *remote_address,
652 uint32_t session_info_flags,
653 struct auth_session_info **session_info)
655 NTSTATUS status;
656 struct auth_user_info_dc *user_info_dc;
657 TALLOC_CTX *tmp_ctx;
659 if (!pac_blob) {
660 return auth_generate_session_info_principal(auth_ctx, mem_ctx, principal_name,
661 NULL, session_info_flags, session_info);
664 tmp_ctx = talloc_named(mem_ctx, 0, "gensec_gssapi_session_info context");
665 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
667 status = kerberos_pac_blob_to_user_info_dc(tmp_ctx,
668 *pac_blob,
669 smb_krb5_context->krb5_context,
670 &user_info_dc, NULL, NULL);
671 if (!NT_STATUS_IS_OK(status)) {
672 talloc_free(tmp_ctx);
673 return status;
676 if (user_info_dc->info->authenticated) {
677 session_info_flags |= AUTH_SESSION_INFO_AUTHENTICATED;
680 status = auth_generate_session_info_wrapper(auth_ctx, mem_ctx,
681 user_info_dc,
682 user_info_dc->info->account_name,
683 session_info_flags, session_info);
684 talloc_free(tmp_ctx);
685 return status;
688 /***************************************************************************
689 Make a auth_info struct for the auth subsystem
690 - Allow the caller to specify the methods to use, including optionally the SAM to use
691 ***************************************************************************/
692 _PUBLIC_ NTSTATUS auth_context_create_methods(TALLOC_CTX *mem_ctx, const char * const *methods,
693 struct tevent_context *ev,
694 struct imessaging_context *msg,
695 struct loadparm_context *lp_ctx,
696 struct ldb_context *sam_ctx,
697 struct auth4_context **auth_ctx)
699 int i;
700 struct auth4_context *ctx;
702 auth4_init();
704 if (!ev) {
705 DEBUG(0,("auth_context_create: called with out event context\n"));
706 return NT_STATUS_INTERNAL_ERROR;
709 ctx = talloc_zero(mem_ctx, struct auth4_context);
710 NT_STATUS_HAVE_NO_MEMORY(ctx);
711 ctx->challenge.data = data_blob(NULL, 0);
712 ctx->methods = NULL;
713 ctx->event_ctx = ev;
714 ctx->msg_ctx = msg;
715 ctx->lp_ctx = lp_ctx;
716 ctx->start_time = timeval_current();
718 if (sam_ctx) {
719 ctx->sam_ctx = sam_ctx;
720 } else {
721 ctx->sam_ctx = samdb_connect(ctx,
722 ctx->event_ctx,
723 ctx->lp_ctx,
724 system_session(ctx->lp_ctx),
725 NULL,
729 for (i=0; methods && methods[i] ; i++) {
730 struct auth_method_context *method;
732 method = talloc(ctx, struct auth_method_context);
733 NT_STATUS_HAVE_NO_MEMORY(method);
735 method->ops = auth_backend_byname(methods[i]);
736 if (!method->ops) {
737 DEBUG(1,("auth_context_create: failed to find method=%s\n",
738 methods[i]));
739 return NT_STATUS_INTERNAL_ERROR;
741 method->auth_ctx = ctx;
742 method->depth = i;
743 DLIST_ADD_END(ctx->methods, method);
746 ctx->check_ntlm_password_send = auth_check_password_wrapper_send;
747 ctx->check_ntlm_password_recv = auth_check_password_wrapper_recv;
748 ctx->get_ntlm_challenge = auth_get_challenge;
749 ctx->set_ntlm_challenge = auth_context_set_challenge;
750 ctx->generate_session_info = auth_generate_session_info_wrapper;
751 ctx->generate_session_info_pac = auth_generate_session_info_pac;
753 *auth_ctx = ctx;
755 return NT_STATUS_OK;
758 const char **auth_methods_from_lp(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx)
760 char **auth_methods = NULL;
762 switch (lpcfg_server_role(lp_ctx)) {
763 case ROLE_STANDALONE:
764 auth_methods = str_list_make(mem_ctx, "anonymous sam_ignoredomain", NULL);
765 break;
766 case ROLE_DOMAIN_MEMBER:
767 case ROLE_DOMAIN_BDC:
768 case ROLE_DOMAIN_PDC:
769 case ROLE_ACTIVE_DIRECTORY_DC:
770 auth_methods = str_list_make(mem_ctx, "anonymous sam winbind sam_ignoredomain", NULL);
771 break;
773 return discard_const_p(const char *, auth_methods);
776 /***************************************************************************
777 Make a auth_info struct for the auth subsystem
778 - Uses default auth_methods, depending on server role and smb.conf settings
779 ***************************************************************************/
780 _PUBLIC_ NTSTATUS auth_context_create(TALLOC_CTX *mem_ctx,
781 struct tevent_context *ev,
782 struct imessaging_context *msg,
783 struct loadparm_context *lp_ctx,
784 struct auth4_context **auth_ctx)
786 NTSTATUS status;
787 const char **auth_methods;
788 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
789 if (!tmp_ctx) {
790 return NT_STATUS_NO_MEMORY;
793 auth_methods = auth_methods_from_lp(tmp_ctx, lp_ctx);
794 if (!auth_methods) {
795 return NT_STATUS_INVALID_PARAMETER;
797 status = auth_context_create_methods(mem_ctx, auth_methods, ev, msg, lp_ctx, NULL, auth_ctx);
798 talloc_free(tmp_ctx);
799 return status;
802 _PUBLIC_ NTSTATUS auth_context_create_for_netlogon(TALLOC_CTX *mem_ctx,
803 struct tevent_context *ev,
804 struct imessaging_context *msg,
805 struct loadparm_context *lp_ctx,
806 struct auth4_context **auth_ctx)
808 NTSTATUS status;
809 char **_auth_methods = NULL;
810 const char **auth_methods = NULL;
813 * Here we only allow 'sam winbind' instead of
814 * the 'anonymous sam winbind sam_ignoredomain'
815 * we typically use for authentication from clients.
817 _auth_methods = str_list_make(mem_ctx, "sam winbind", NULL);
818 if (_auth_methods == NULL) {
819 return NT_STATUS_NO_MEMORY;
821 auth_methods = discard_const_p(const char *, _auth_methods);
823 status = auth_context_create_methods(mem_ctx, auth_methods, ev, msg,
824 lp_ctx, NULL, auth_ctx);
825 talloc_free(_auth_methods);
826 return status;
829 /* the list of currently registered AUTH backends */
830 static struct auth_backend {
831 const struct auth_operations *ops;
832 } *backends = NULL;
833 static int num_backends;
836 register a AUTH backend.
838 The 'name' can be later used by other backends to find the operations
839 structure for this backend.
841 _PUBLIC_ NTSTATUS auth_register(TALLOC_CTX *mem_ctx,
842 const struct auth_operations *ops)
844 struct auth_operations *new_ops;
846 if (auth_backend_byname(ops->name) != NULL) {
847 /* its already registered! */
848 DEBUG(0,("AUTH backend '%s' already registered\n",
849 ops->name));
850 return NT_STATUS_OBJECT_NAME_COLLISION;
853 backends = talloc_realloc(mem_ctx, backends,
854 struct auth_backend, num_backends+1);
855 NT_STATUS_HAVE_NO_MEMORY(backends);
857 new_ops = (struct auth_operations *)talloc_memdup(backends, ops, sizeof(*ops));
858 NT_STATUS_HAVE_NO_MEMORY(new_ops);
859 new_ops->name = talloc_strdup(new_ops, ops->name);
860 NT_STATUS_HAVE_NO_MEMORY(new_ops->name);
862 backends[num_backends].ops = new_ops;
864 num_backends++;
866 DEBUG(3,("AUTH backend '%s' registered\n",
867 ops->name));
869 return NT_STATUS_OK;
873 return the operations structure for a named backend of the specified type
875 const struct auth_operations *auth_backend_byname(const char *name)
877 int i;
879 for (i=0;i<num_backends;i++) {
880 if (strcmp(backends[i].ops->name, name) == 0) {
881 return backends[i].ops;
885 return NULL;
889 return the AUTH interface version, and the size of some critical types
890 This can be used by backends to either detect compilation errors, or provide
891 multiple implementations for different smbd compilation options in one module
893 const struct auth_critical_sizes *auth_interface_version(void)
895 static const struct auth_critical_sizes critical_sizes = {
896 AUTH4_INTERFACE_VERSION,
897 sizeof(struct auth_operations),
898 sizeof(struct auth_method_context),
899 sizeof(struct auth4_context),
900 sizeof(struct auth_usersupplied_info),
901 sizeof(struct auth_user_info_dc)
904 return &critical_sizes;
907 _PUBLIC_ NTSTATUS auth4_init(void)
909 static bool initialized = false;
910 #define _MODULE_PROTO(init) extern NTSTATUS init(TALLOC_CTX *);
911 STATIC_auth4_MODULES_PROTO;
912 init_module_fn static_init[] = { STATIC_auth4_MODULES };
914 if (initialized) return NT_STATUS_OK;
915 initialized = true;
917 run_init_functions(NULL, static_init);
919 return NT_STATUS_OK;