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/>.
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 static NTSTATUS
auth_generate_session_info_wrapper(struct auth4_context
*auth_context
,
39 void *server_returned_info
,
40 const char *original_user_name
,
41 uint32_t session_info_flags
,
42 struct auth_session_info
**session_info
);
44 /***************************************************************************
46 ***************************************************************************/
47 _PUBLIC_ NTSTATUS
auth_context_set_challenge(struct auth4_context
*auth_ctx
, const uint8_t chal
[8], const char *set_by
)
49 auth_ctx
->challenge
.set_by
= talloc_strdup(auth_ctx
, set_by
);
50 NT_STATUS_HAVE_NO_MEMORY(auth_ctx
->challenge
.set_by
);
52 auth_ctx
->challenge
.data
= data_blob_talloc(auth_ctx
, chal
, 8);
53 NT_STATUS_HAVE_NO_MEMORY(auth_ctx
->challenge
.data
.data
);
58 /****************************************************************************
59 Try to get a challenge out of the various authentication modules.
60 Returns a const char of length 8 bytes.
61 ****************************************************************************/
62 _PUBLIC_ NTSTATUS
auth_get_challenge(struct auth4_context
*auth_ctx
, uint8_t chal
[8])
65 if (auth_ctx
->challenge
.data
.length
== 8) {
66 DEBUG(5, ("auth_get_challenge: returning previous challenge by module %s (normal)\n",
67 auth_ctx
->challenge
.set_by
));
68 memcpy(chal
, auth_ctx
->challenge
.data
.data
, 8);
72 if (!auth_ctx
->challenge
.set_by
) {
73 generate_random_buffer(chal
, 8);
75 auth_ctx
->challenge
.data
= data_blob_talloc(auth_ctx
, chal
, 8);
76 NT_STATUS_HAVE_NO_MEMORY(auth_ctx
->challenge
.data
.data
);
77 auth_ctx
->challenge
.set_by
= "random";
80 DEBUG(10,("auth_get_challenge: challenge set by %s\n",
81 auth_ctx
->challenge
.set_by
));
86 /****************************************************************************
87 Used in the gensec_gssapi and gensec_krb5 server-side code, where the
88 PAC isn't available, and for tokenGroups in the DSDB stack.
90 Supply either a principal or a DN
91 ****************************************************************************/
92 static NTSTATUS
auth_generate_session_info_principal(struct auth4_context
*auth_ctx
,
94 const char *principal
,
95 struct ldb_dn
*user_dn
,
96 uint32_t session_info_flags
,
97 struct auth_session_info
**session_info
)
100 struct auth_method_context
*method
;
101 struct auth_user_info_dc
*user_info_dc
;
103 for (method
= auth_ctx
->methods
; method
; method
= method
->next
) {
104 if (!method
->ops
->get_user_info_dc_principal
) {
108 nt_status
= method
->ops
->get_user_info_dc_principal(mem_ctx
, auth_ctx
, principal
, user_dn
, &user_info_dc
);
109 if (NT_STATUS_EQUAL(nt_status
, NT_STATUS_NOT_IMPLEMENTED
)) {
112 if (!NT_STATUS_IS_OK(nt_status
)) {
116 nt_status
= auth_generate_session_info_wrapper(auth_ctx
, mem_ctx
,
118 user_info_dc
->info
->account_name
,
119 session_info_flags
, session_info
);
120 talloc_free(user_info_dc
);
125 return NT_STATUS_NOT_IMPLEMENTED
;
129 * Check a user's Plaintext, LM or NTLM password.
132 * Check a user's password, as given in the user_info struct and return various
133 * interesting details in the user_info_dc struct.
135 * The return value takes precedence over the contents of the user_info_dc
136 * struct. When the return is other than NT_STATUS_OK the contents
137 * of that structure is undefined.
139 * @param auth_ctx Supplies the challenges and some other data.
140 * Must be created with auth_context_create(), and the challenges should be
141 * filled in, either at creation or by calling the challenge geneation
142 * function auth_get_challenge().
144 * @param user_info Contains the user supplied components, including the passwords.
146 * @param mem_ctx The parent memory context for the user_info_dc structure
148 * @param user_info_dc If successful, contains information about the authentication,
149 * including a SAM_ACCOUNT struct describing the user.
151 * @return An NTSTATUS with NT_STATUS_OK or an appropriate error.
155 _PUBLIC_ NTSTATUS
auth_check_password(struct auth4_context
*auth_ctx
,
157 const struct auth_usersupplied_info
*user_info
,
158 struct auth_user_info_dc
**user_info_dc
,
159 uint8_t *pauthoritative
)
161 struct tevent_req
*subreq
;
162 struct tevent_context
*ev
;
166 /*TODO: create a new event context here! */
167 ev
= auth_ctx
->event_ctx
;
169 subreq
= auth_check_password_send(mem_ctx
,
173 if (subreq
== NULL
) {
174 return NT_STATUS_NO_MEMORY
;
177 ok
= tevent_req_poll(subreq
, ev
);
179 return NT_STATUS_INTERNAL_ERROR
;
182 status
= auth_check_password_recv(subreq
, mem_ctx
,
183 user_info_dc
, pauthoritative
);
189 struct auth_check_password_state
{
190 struct tevent_context
*ev
;
191 struct auth4_context
*auth_ctx
;
192 const struct auth_usersupplied_info
*user_info
;
193 struct auth_user_info_dc
*user_info_dc
;
194 struct auth_method_context
*method
;
195 uint8_t authoritative
;
198 static void auth_check_password_next(struct tevent_req
*req
);
201 * Check a user's Plaintext, LM or NTLM password.
204 * Check a user's password, as given in the user_info struct and return various
205 * interesting details in the user_info_dc struct.
207 * The return value takes precedence over the contents of the user_info_dc
208 * struct. When the return is other than NT_STATUS_OK the contents
209 * of that structure is undefined.
211 * @param mem_ctx The memory context the request should operate on
213 * @param ev The tevent context the request should operate on
215 * @param auth_ctx Supplies the challenges and some other data.
216 * Must be created with make_auth_context(), and the challenges should be
217 * filled in, either at creation or by calling the challenge geneation
218 * function auth_get_challenge().
220 * @param user_info Contains the user supplied components, including the passwords.
222 * @return The request handle or NULL on no memory error.
226 _PUBLIC_
struct tevent_req
*auth_check_password_send(TALLOC_CTX
*mem_ctx
,
227 struct tevent_context
*ev
,
228 struct auth4_context
*auth_ctx
,
229 const struct auth_usersupplied_info
*user_info
)
231 struct tevent_req
*req
;
232 struct auth_check_password_state
*state
;
233 /* if all the modules say 'not for me' this is reasonable */
237 DEBUG(3,("auth_check_password_send: "
238 "Checking password for unmapped user [%s]\\[%s]@[%s]\n",
239 user_info
->client
.domain_name
, user_info
->client
.account_name
,
240 user_info
->workstation_name
));
242 req
= tevent_req_create(mem_ctx
, &state
,
243 struct auth_check_password_state
);
249 * We are authoritative by default.
252 state
->auth_ctx
= auth_ctx
;
253 state
->user_info
= user_info
;
254 state
->authoritative
= 1;
256 if (!user_info
->mapped_state
) {
257 struct auth_usersupplied_info
*user_info_tmp
;
260 * We don't really do any mapping here.
262 * So we don't set user_info->mapped_state,
263 * but we set mapped.domain_name and
264 * mapped.account_name to the client
267 * It's up to the backends to do mappings
268 * for their authentication.
270 user_info_tmp
= talloc_zero(state
, struct auth_usersupplied_info
);
271 if (tevent_req_nomem(user_info_tmp
, req
)) {
272 return tevent_req_post(req
, ev
);;
276 * The lifetime of user_info is longer than
277 * user_info_tmp, so we don't need to copy the
280 *user_info_tmp
= *user_info
;
281 user_info_tmp
->mapped
.domain_name
= user_info
->client
.domain_name
;
282 user_info_tmp
->mapped
.account_name
= user_info
->client
.account_name
;
284 user_info
= user_info_tmp
;
285 state
->user_info
= user_info_tmp
;
288 DEBUGADD(3,("auth_check_password_send: "
289 "user is: [%s]\\[%s]@[%s]\n",
290 user_info
->mapped
.domain_name
,
291 user_info
->mapped
.account_name
,
292 user_info
->workstation_name
));
294 nt_status
= auth_get_challenge(auth_ctx
, chal
);
295 if (tevent_req_nterror(req
, nt_status
)) {
296 DEBUG(0,("auth_check_password_send: "
297 "Invalid challenge (length %u) stored for "
298 "this auth context set_by %s - cannot continue: %s\n",
299 (unsigned)auth_ctx
->challenge
.data
.length
,
300 auth_ctx
->challenge
.set_by
,
301 nt_errstr(nt_status
)));
302 return tevent_req_post(req
, ev
);
305 if (auth_ctx
->challenge
.set_by
) {
306 DEBUG(10,("auth_check_password_send: "
307 "auth_context challenge created by %s\n",
308 auth_ctx
->challenge
.set_by
));
311 DEBUG(10, ("auth_check_password_send: challenge is: \n"));
312 dump_data(5, auth_ctx
->challenge
.data
.data
,
313 auth_ctx
->challenge
.data
.length
);
315 state
->method
= state
->auth_ctx
->methods
;
316 auth_check_password_next(req
);
317 if (!tevent_req_is_in_progress(req
)) {
318 return tevent_req_post(req
, ev
);
324 static void auth_check_password_done(struct tevent_req
*subreq
);
326 static void auth_check_password_next(struct tevent_req
*req
)
328 struct auth_check_password_state
*state
=
329 tevent_req_data(req
, struct auth_check_password_state
);
330 struct tevent_req
*subreq
= NULL
;
331 bool authoritative
= true;
334 if (state
->method
== NULL
) {
335 state
->authoritative
= 0;
336 tevent_req_nterror(req
, NT_STATUS_NO_SUCH_USER
);
340 /* check if the module wants to check the password */
341 status
= state
->method
->ops
->want_check(state
->method
, state
,
343 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_IMPLEMENTED
)) {
344 DEBUG(11,("auth_check_password_send: "
345 "%s doesn't want to check\n",
346 state
->method
->ops
->name
));
347 state
->method
= state
->method
->next
;
348 auth_check_password_next(req
);
352 if (tevent_req_nterror(req
, status
)) {
356 if (state
->method
->ops
->check_password_send
!= NULL
) {
357 subreq
= state
->method
->ops
->check_password_send(state
,
361 if (tevent_req_nomem(subreq
, req
)) {
364 tevent_req_set_callback(subreq
,
365 auth_check_password_done
,
370 if (state
->method
->ops
->check_password
== NULL
) {
371 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
375 status
= state
->method
->ops
->check_password(state
->method
,
378 &state
->user_info_dc
,
380 if (!authoritative
||
381 NT_STATUS_EQUAL(status
, NT_STATUS_NOT_IMPLEMENTED
)) {
382 DEBUG(11,("auth_check_password_send: "
383 "%s passes to the next method\n",
384 state
->method
->ops
->name
));
385 state
->method
= state
->method
->next
;
386 auth_check_password_next(req
);
390 /* the backend has handled the request */
392 if (tevent_req_nterror(req
, status
)) {
396 tevent_req_done(req
);
399 static void auth_check_password_done(struct tevent_req
*subreq
)
401 struct tevent_req
*req
=
402 tevent_req_callback_data(subreq
,
404 struct auth_check_password_state
*state
=
406 struct auth_check_password_state
);
407 bool authoritative
= true;
410 status
= state
->method
->ops
->check_password_recv(subreq
, state
,
411 &state
->user_info_dc
,
414 if (!authoritative
||
415 NT_STATUS_EQUAL(status
, NT_STATUS_NOT_IMPLEMENTED
)) {
416 DEBUG(11,("auth_check_password_send: "
417 "%s passes to the next method\n",
418 state
->method
->ops
->name
));
419 state
->method
= state
->method
->next
;
420 auth_check_password_next(req
);
424 /* the backend has handled the request */
426 if (tevent_req_nterror(req
, status
)) {
430 tevent_req_done(req
);
434 * Check a user's Plaintext, LM or NTLM password.
435 * async receive function
437 * The return value takes precedence over the contents of the user_info_dc
438 * struct. When the return is other than NT_STATUS_OK the contents
439 * of that structure is undefined.
442 * @param req The async request state
444 * @param mem_ctx The parent memory context for the user_info_dc structure
446 * @param user_info_dc If successful, contains information about the authentication,
447 * including a SAM_ACCOUNT struct describing the user.
449 * @return An NTSTATUS with NT_STATUS_OK or an appropriate error.
453 _PUBLIC_ NTSTATUS
auth_check_password_recv(struct tevent_req
*req
,
455 struct auth_user_info_dc
**user_info_dc
,
456 uint8_t *pauthoritative
)
458 struct auth_check_password_state
*state
=
459 tevent_req_data(req
, struct auth_check_password_state
);
460 NTSTATUS status
= NT_STATUS_OK
;
462 *pauthoritative
= state
->authoritative
;
464 if (tevent_req_is_nterror(req
, &status
)) {
466 * Please try not to change this string, it is probably in use
467 * in audit logging tools
469 DEBUG(2,("auth_check_password_recv: "
470 "%s authentication for user [%s\\%s] "
471 "FAILED with error %s, authoritative=%u\n",
472 (state
->method
? state
->method
->ops
->name
: "NO_METHOD"),
473 state
->user_info
->mapped
.domain_name
,
474 state
->user_info
->mapped
.account_name
,
475 nt_errstr(status
), state
->authoritative
));
477 log_authentication_event(state
->auth_ctx
->msg_ctx
,
478 state
->auth_ctx
->lp_ctx
,
479 state
->user_info
, status
,
480 NULL
, NULL
, NULL
, NULL
);
481 tevent_req_received(req
);
485 DEBUG(5,("auth_check_password_recv: "
486 "%s authentication for user [%s\\%s] succeeded\n",
487 state
->method
->ops
->name
,
488 state
->user_info_dc
->info
->domain_name
,
489 state
->user_info_dc
->info
->account_name
));
491 log_authentication_event(state
->auth_ctx
->msg_ctx
,
492 state
->auth_ctx
->lp_ctx
,
493 state
->user_info
, status
,
494 state
->user_info_dc
->info
->domain_name
,
495 state
->user_info_dc
->info
->account_name
,
497 &state
->user_info_dc
->sids
[0]);
499 *user_info_dc
= talloc_move(mem_ctx
, &state
->user_info_dc
);
501 tevent_req_received(req
);
505 struct auth_check_password_wrapper_state
{
506 uint8_t authoritative
;
507 struct auth_user_info_dc
*user_info_dc
;
510 static void auth_check_password_wrapper_done(struct tevent_req
*subreq
);
512 static struct tevent_req
*auth_check_password_wrapper_send(TALLOC_CTX
*mem_ctx
,
513 struct tevent_context
*ev
,
514 struct auth4_context
*auth_ctx
,
515 const struct auth_usersupplied_info
*user_info
)
517 struct tevent_req
*req
= NULL
;
518 struct auth_check_password_wrapper
*state
= NULL
;
519 struct tevent_req
*subreq
= NULL
;
521 req
= tevent_req_create(mem_ctx
, &state
,
522 struct auth_check_password_wrapper_state
);
527 subreq
= auth_check_password_send(state
, ev
, auth_ctx
, user_info
);
528 if (tevent_req_nomem(subreq
, req
)) {
529 return tevent_req_post(req
, ev
);
531 tevent_req_set_callback(subreq
,
532 auth_check_password_wrapper_done
,
538 static void auth_check_password_wrapper_done(struct tevent_req
*subreq
)
540 struct tevent_req
*req
=
541 tevent_req_callback_data(subreq
,
543 struct auth_check_password_wrapper_state
*state
=
545 struct auth_check_password_wrapper_state
);
548 status
= auth_check_password_recv(subreq
, state
,
549 &state
->user_info_dc
,
550 &state
->authoritative
);
552 if (tevent_req_nterror(req
, status
)) {
556 tevent_req_done(req
);
559 static NTSTATUS
auth_check_password_wrapper_recv(struct tevent_req
*req
,
561 uint8_t *pauthoritative
,
562 void **server_returned_info
,
563 DATA_BLOB
*user_session_key
,
564 DATA_BLOB
*lm_session_key
)
566 struct auth_check_password_wrapper_state
*state
=
568 struct auth_check_password_wrapper_state
);
569 struct auth_user_info_dc
*user_info_dc
= state
->user_info_dc
;
570 NTSTATUS status
= NT_STATUS_OK
;
572 *pauthoritative
= state
->authoritative
;
574 if (tevent_req_is_nterror(req
, &status
)) {
575 tevent_req_received(req
);
579 talloc_steal(mem_ctx
, user_info_dc
);
580 *server_returned_info
= user_info_dc
;
582 if (user_session_key
) {
583 DEBUG(10, ("Got NT session key of length %u\n",
584 (unsigned)user_info_dc
->user_session_key
.length
));
585 *user_session_key
= user_info_dc
->user_session_key
;
586 talloc_steal(mem_ctx
, user_session_key
->data
);
587 user_info_dc
->user_session_key
= data_blob_null
;
590 if (lm_session_key
) {
591 DEBUG(10, ("Got LM session key of length %u\n",
592 (unsigned)user_info_dc
->lm_session_key
.length
));
593 *lm_session_key
= user_info_dc
->lm_session_key
;
594 talloc_steal(mem_ctx
, lm_session_key
->data
);
595 user_info_dc
->lm_session_key
= data_blob_null
;
598 tevent_req_received(req
);
602 /* Wrapper because we don't want to expose all callers to needing to
603 * know that session_info is generated from the main ldb, and because
604 * we need to break a depenency loop between the DCE/RPC layer and the
605 * generation of unix tokens via IRPC */
606 static NTSTATUS
auth_generate_session_info_wrapper(struct auth4_context
*auth_context
,
608 void *server_returned_info
,
609 const char *original_user_name
,
610 uint32_t session_info_flags
,
611 struct auth_session_info
**session_info
)
614 struct auth_user_info_dc
*user_info_dc
= talloc_get_type_abort(server_returned_info
, struct auth_user_info_dc
);
616 if (user_info_dc
->info
->authenticated
) {
617 session_info_flags
|= AUTH_SESSION_INFO_AUTHENTICATED
;
620 status
= auth_generate_session_info(mem_ctx
, auth_context
->lp_ctx
,
621 auth_context
->sam_ctx
, user_info_dc
,
622 session_info_flags
, session_info
);
623 if (!NT_STATUS_IS_OK(status
)) {
627 if ((session_info_flags
& AUTH_SESSION_INFO_UNIX_TOKEN
)
628 && NT_STATUS_IS_OK(status
)) {
629 status
= auth_session_info_fill_unix(auth_context
->lp_ctx
,
632 if (!NT_STATUS_IS_OK(status
)) {
633 TALLOC_FREE(*session_info
);
639 /* Wrapper because we don't want to expose all callers to needing to
640 * know anything about the PAC or auth subsystem internal structures
641 * before we output a struct auth session_info */
642 static NTSTATUS
auth_generate_session_info_pac(struct auth4_context
*auth_ctx
,
644 struct smb_krb5_context
*smb_krb5_context
,
646 const char *principal_name
,
647 const struct tsocket_address
*remote_address
,
648 uint32_t session_info_flags
,
649 struct auth_session_info
**session_info
)
652 struct auth_user_info_dc
*user_info_dc
;
656 return auth_generate_session_info_principal(auth_ctx
, mem_ctx
, principal_name
,
657 NULL
, session_info_flags
, session_info
);
660 tmp_ctx
= talloc_named(mem_ctx
, 0, "gensec_gssapi_session_info context");
661 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx
);
663 status
= kerberos_pac_blob_to_user_info_dc(tmp_ctx
,
665 smb_krb5_context
->krb5_context
,
666 &user_info_dc
, NULL
, NULL
);
667 if (!NT_STATUS_IS_OK(status
)) {
668 talloc_free(tmp_ctx
);
672 if (user_info_dc
->info
->authenticated
) {
673 session_info_flags
|= AUTH_SESSION_INFO_AUTHENTICATED
;
676 status
= auth_generate_session_info_wrapper(auth_ctx
, mem_ctx
,
678 user_info_dc
->info
->account_name
,
679 session_info_flags
, session_info
);
680 talloc_free(tmp_ctx
);
684 /***************************************************************************
685 Make a auth_info struct for the auth subsystem
686 - Allow the caller to specify the methods to use, including optionally the SAM to use
687 ***************************************************************************/
688 _PUBLIC_ NTSTATUS
auth_context_create_methods(TALLOC_CTX
*mem_ctx
, const char * const *methods
,
689 struct tevent_context
*ev
,
690 struct imessaging_context
*msg
,
691 struct loadparm_context
*lp_ctx
,
692 struct ldb_context
*sam_ctx
,
693 struct auth4_context
**auth_ctx
)
696 struct auth4_context
*ctx
;
701 DEBUG(0,("auth_context_create: called with out event context\n"));
702 return NT_STATUS_INTERNAL_ERROR
;
705 ctx
= talloc_zero(mem_ctx
, struct auth4_context
);
706 NT_STATUS_HAVE_NO_MEMORY(ctx
);
707 ctx
->challenge
.data
= data_blob(NULL
, 0);
711 ctx
->lp_ctx
= lp_ctx
;
714 ctx
->sam_ctx
= sam_ctx
;
716 ctx
->sam_ctx
= samdb_connect(ctx
, ctx
->event_ctx
, ctx
->lp_ctx
, system_session(ctx
->lp_ctx
), 0);
719 for (i
=0; methods
&& methods
[i
] ; i
++) {
720 struct auth_method_context
*method
;
722 method
= talloc(ctx
, struct auth_method_context
);
723 NT_STATUS_HAVE_NO_MEMORY(method
);
725 method
->ops
= auth_backend_byname(methods
[i
]);
727 DEBUG(1,("auth_context_create: failed to find method=%s\n",
729 return NT_STATUS_INTERNAL_ERROR
;
731 method
->auth_ctx
= ctx
;
733 DLIST_ADD_END(ctx
->methods
, method
);
736 ctx
->check_ntlm_password_send
= auth_check_password_wrapper_send
;
737 ctx
->check_ntlm_password_recv
= auth_check_password_wrapper_recv
;
738 ctx
->get_ntlm_challenge
= auth_get_challenge
;
739 ctx
->set_ntlm_challenge
= auth_context_set_challenge
;
740 ctx
->generate_session_info
= auth_generate_session_info_wrapper
;
741 ctx
->generate_session_info_pac
= auth_generate_session_info_pac
;
748 const char **auth_methods_from_lp(TALLOC_CTX
*mem_ctx
, struct loadparm_context
*lp_ctx
)
750 char **auth_methods
= NULL
;
752 switch (lpcfg_server_role(lp_ctx
)) {
753 case ROLE_STANDALONE
:
754 auth_methods
= str_list_make(mem_ctx
, "anonymous sam_ignoredomain", NULL
);
756 case ROLE_DOMAIN_MEMBER
:
757 case ROLE_DOMAIN_BDC
:
758 case ROLE_DOMAIN_PDC
:
759 case ROLE_ACTIVE_DIRECTORY_DC
:
760 auth_methods
= str_list_make(mem_ctx
, "anonymous sam winbind sam_ignoredomain", NULL
);
763 return discard_const_p(const char *, auth_methods
);
766 /***************************************************************************
767 Make a auth_info struct for the auth subsystem
768 - Uses default auth_methods, depending on server role and smb.conf settings
769 ***************************************************************************/
770 _PUBLIC_ NTSTATUS
auth_context_create(TALLOC_CTX
*mem_ctx
,
771 struct tevent_context
*ev
,
772 struct imessaging_context
*msg
,
773 struct loadparm_context
*lp_ctx
,
774 struct auth4_context
**auth_ctx
)
777 const char **auth_methods
;
778 TALLOC_CTX
*tmp_ctx
= talloc_new(mem_ctx
);
780 return NT_STATUS_NO_MEMORY
;
783 auth_methods
= auth_methods_from_lp(tmp_ctx
, lp_ctx
);
785 return NT_STATUS_INVALID_PARAMETER
;
787 status
= auth_context_create_methods(mem_ctx
, auth_methods
, ev
, msg
, lp_ctx
, NULL
, auth_ctx
);
788 talloc_free(tmp_ctx
);
792 _PUBLIC_ NTSTATUS
auth_context_create_for_netlogon(TALLOC_CTX
*mem_ctx
,
793 struct tevent_context
*ev
,
794 struct imessaging_context
*msg
,
795 struct loadparm_context
*lp_ctx
,
796 struct auth4_context
**auth_ctx
)
799 char **_auth_methods
= NULL
;
800 const char **auth_methods
= NULL
;
803 * Here we only allow 'sam winbind' instead of
804 * the 'anonymous sam winbind sam_ignoredomain'
805 * we typically use for authentication from clients.
807 _auth_methods
= str_list_make(mem_ctx
, "sam winbind", NULL
);
808 if (_auth_methods
== NULL
) {
809 return NT_STATUS_NO_MEMORY
;
811 auth_methods
= discard_const_p(const char *, _auth_methods
);
813 status
= auth_context_create_methods(mem_ctx
, auth_methods
, ev
, msg
,
814 lp_ctx
, NULL
, auth_ctx
);
815 talloc_free(_auth_methods
);
819 /* the list of currently registered AUTH backends */
820 static struct auth_backend
{
821 const struct auth_operations
*ops
;
823 static int num_backends
;
826 register a AUTH backend.
828 The 'name' can be later used by other backends to find the operations
829 structure for this backend.
831 _PUBLIC_ NTSTATUS
auth_register(TALLOC_CTX
*mem_ctx
,
832 const struct auth_operations
*ops
)
834 struct auth_operations
*new_ops
;
836 if (auth_backend_byname(ops
->name
) != NULL
) {
837 /* its already registered! */
838 DEBUG(0,("AUTH backend '%s' already registered\n",
840 return NT_STATUS_OBJECT_NAME_COLLISION
;
843 backends
= talloc_realloc(mem_ctx
, backends
,
844 struct auth_backend
, num_backends
+1);
845 NT_STATUS_HAVE_NO_MEMORY(backends
);
847 new_ops
= (struct auth_operations
*)talloc_memdup(backends
, ops
, sizeof(*ops
));
848 NT_STATUS_HAVE_NO_MEMORY(new_ops
);
849 new_ops
->name
= talloc_strdup(new_ops
, ops
->name
);
850 NT_STATUS_HAVE_NO_MEMORY(new_ops
->name
);
852 backends
[num_backends
].ops
= new_ops
;
856 DEBUG(3,("AUTH backend '%s' registered\n",
863 return the operations structure for a named backend of the specified type
865 const struct auth_operations
*auth_backend_byname(const char *name
)
869 for (i
=0;i
<num_backends
;i
++) {
870 if (strcmp(backends
[i
].ops
->name
, name
) == 0) {
871 return backends
[i
].ops
;
879 return the AUTH interface version, and the size of some critical types
880 This can be used by backends to either detect compilation errors, or provide
881 multiple implementations for different smbd compilation options in one module
883 const struct auth_critical_sizes
*auth_interface_version(void)
885 static const struct auth_critical_sizes critical_sizes
= {
886 AUTH4_INTERFACE_VERSION
,
887 sizeof(struct auth_operations
),
888 sizeof(struct auth_method_context
),
889 sizeof(struct auth4_context
),
890 sizeof(struct auth_usersupplied_info
),
891 sizeof(struct auth_user_info_dc
)
894 return &critical_sizes
;
897 _PUBLIC_ NTSTATUS
auth4_init(void)
899 static bool initialized
= false;
900 #define _MODULE_PROTO(init) extern NTSTATUS init(TALLOC_CTX *);
901 STATIC_auth4_MODULES_PROTO
;
902 init_module_fn static_init
[] = { STATIC_auth4_MODULES
};
904 if (initialized
) return NT_STATUS_OK
;
907 run_init_functions(NULL
, static_init
);