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 static NTSTATUS auth_check_password_wrapper(struct auth4_context *auth_ctx,
191 const struct auth_usersupplied_info *user_info,
192 uint8_t *pauthoritative,
193 void **server_returned_info,
194 DATA_BLOB *user_session_key, DATA_BLOB *lm_session_key)
196 struct auth_user_info_dc *user_info_dc;
199 status = auth_check_password(auth_ctx, mem_ctx, user_info,
200 &user_info_dc, pauthoritative);
201 if (!NT_STATUS_IS_OK(status)) {
205 *server_returned_info = user_info_dc;
207 if (user_session_key) {
208 DEBUG(10, ("Got NT session key of length %u\n",
209 (unsigned)user_info_dc->user_session_key.length));
210 *user_session_key = user_info_dc->user_session_key;
211 talloc_steal(mem_ctx, user_session_key->data);
212 user_info_dc->user_session_key = data_blob_null;
215 if (lm_session_key) {
216 DEBUG(10, ("Got LM session key of length %u\n",
217 (unsigned)user_info_dc->lm_session_key.length));
218 *lm_session_key = user_info_dc->lm_session_key;
219 talloc_steal(mem_ctx, lm_session_key->data);
220 user_info_dc->lm_session_key = data_blob_null;
226 struct auth_check_password_state {
227 struct auth4_context *auth_ctx;
228 const struct auth_usersupplied_info *user_info;
229 struct auth_user_info_dc *user_info_dc;
230 struct auth_method_context *method;
231 uint8_t authoritative;
234 static void auth_check_password_async_trigger(struct tevent_context *ev,
235 struct tevent_immediate *im,
238 * Check a user's Plaintext, LM or NTLM password.
241 * Check a user's password, as given in the user_info struct and return various
242 * interesting details in the user_info_dc struct.
244 * The return value takes precedence over the contents of the user_info_dc
245 * struct. When the return is other than NT_STATUS_OK the contents
246 * of that structure is undefined.
248 * @param mem_ctx The memory context the request should operate on
250 * @param ev The tevent context the request should operate on
252 * @param auth_ctx Supplies the challenges and some other data.
253 * Must be created with make_auth_context(), and the challenges should be
254 * filled in, either at creation or by calling the challenge geneation
255 * function auth_get_challenge().
257 * @param user_info Contains the user supplied components, including the passwords.
259 * @return The request handle or NULL on no memory error.
263 _PUBLIC_ struct tevent_req *auth_check_password_send(TALLOC_CTX *mem_ctx,
264 struct tevent_context *ev,
265 struct auth4_context *auth_ctx,
266 const struct auth_usersupplied_info *user_info)
268 struct tevent_req *req;
269 struct auth_check_password_state *state;
270 /* if all the modules say 'not for me' this is reasonable */
273 struct tevent_immediate *im;
275 DEBUG(3,("auth_check_password_send: "
276 "Checking password for unmapped user [%s]\\[%s]@[%s]\n",
277 user_info->client.domain_name, user_info->client.account_name,
278 user_info->workstation_name));
280 req = tevent_req_create(mem_ctx, &state,
281 struct auth_check_password_state);
287 * We are authoritative by default.
289 state->authoritative = 1;
290 state->auth_ctx = auth_ctx;
291 state->user_info = user_info;
293 if (!user_info->mapped_state) {
294 int server_role = lpcfg_server_role(auth_ctx->lp_ctx);
295 struct auth_usersupplied_info *user_info_tmp;
297 nt_status = map_user_info(
298 auth_ctx->sam_ctx, req,
299 server_role == ROLE_ACTIVE_DIRECTORY_DC,
300 lpcfg_workgroup(auth_ctx->lp_ctx),
301 user_info, &user_info_tmp);
303 if (tevent_req_nterror(req, nt_status)) {
304 return tevent_req_post(req, ev);
306 user_info = user_info_tmp;
307 state->user_info = user_info_tmp;
310 DEBUGADD(3,("auth_check_password_send: "
311 "mapped user is: [%s]\\[%s]@[%s]\n",
312 user_info->mapped.domain_name,
313 user_info->mapped.account_name,
314 user_info->workstation_name));
316 nt_status = auth_get_challenge(auth_ctx, chal);
317 if (tevent_req_nterror(req, nt_status)) {
318 DEBUG(0,("auth_check_password_send: "
319 "Invalid challenge (length %u) stored for "
320 "this auth context set_by %s - cannot continue: %s\n",
321 (unsigned)auth_ctx->challenge.data.length,
322 auth_ctx->challenge.set_by,
323 nt_errstr(nt_status)));
324 return tevent_req_post(req, ev);
327 if (auth_ctx->challenge.set_by) {
328 DEBUG(10,("auth_check_password_send: "
329 "auth_context challenge created by %s\n",
330 auth_ctx->challenge.set_by));
333 DEBUG(10, ("auth_check_password_send: challenge is: \n"));
334 dump_data(5, auth_ctx->challenge.data.data,
335 auth_ctx->challenge.data.length);
337 im = tevent_create_immediate(state);
338 if (tevent_req_nomem(im, req)) {
339 return tevent_req_post(req, ev);
342 tevent_schedule_immediate(im,
344 auth_check_password_async_trigger,
349 static void auth_check_password_async_trigger(struct tevent_context *ev,
350 struct tevent_immediate *im,
353 struct tevent_req *req =
354 talloc_get_type_abort(private_data, struct tevent_req);
355 struct auth_check_password_state *state =
356 tevent_req_data(req, struct auth_check_password_state);
358 struct auth_method_context *method;
360 status = NT_STATUS_OK;
362 for (method=state->auth_ctx->methods; method; method = method->next) {
364 /* we fill in state->method here so debug messages in
365 the callers know which method failed */
366 state->method = method;
368 /* check if the module wants to check the password */
369 status = method->ops->want_check(method, req, state->user_info);
370 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
371 DEBUG(11,("auth_check_password_send: "
372 "%s doesn't want to check\n",
377 if (tevent_req_nterror(req, status)) {
381 status = method->ops->check_password(method,
384 &state->user_info_dc);
385 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
386 DEBUG(11,("auth_check_password_send: "
387 "%s passes to the next method\n",
392 /* the backend has handled the request */
396 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
397 state->authoritative = 0;
398 status = NT_STATUS_NO_SUCH_USER;
401 if (tevent_req_nterror(req, status)) {
405 tevent_req_done(req);
409 * Check a user's Plaintext, LM or NTLM password.
410 * async receive function
412 * The return value takes precedence over the contents of the user_info_dc
413 * struct. When the return is other than NT_STATUS_OK the contents
414 * of that structure is undefined.
417 * @param req The async request state
419 * @param mem_ctx The parent memory context for the user_info_dc structure
421 * @param user_info_dc If successful, contains information about the authentication,
422 * including a SAM_ACCOUNT struct describing the user.
424 * @return An NTSTATUS with NT_STATUS_OK or an appropriate error.
428 _PUBLIC_ NTSTATUS auth_check_password_recv(struct tevent_req *req,
430 struct auth_user_info_dc **user_info_dc,
431 uint8_t *pauthoritative)
433 struct auth_check_password_state *state =
434 tevent_req_data(req, struct auth_check_password_state);
435 NTSTATUS status = NT_STATUS_OK;
437 *pauthoritative = state->authoritative;
439 if (tevent_req_is_nterror(req, &status)) {
441 * Please try not to change this string, it is probably in use
442 * in audit logging tools
444 DEBUG(2,("auth_check_password_recv: "
445 "%s authentication for user [%s\\%s] "
446 "FAILED with error %s, authoritative=%u\n",
447 (state->method ? state->method->ops->name : "NO_METHOD"),
448 state->user_info->mapped.domain_name,
449 state->user_info->mapped.account_name,
450 nt_errstr(status), state->authoritative));
452 log_authentication_event(state->auth_ctx->msg_ctx,
453 state->auth_ctx->lp_ctx,
454 state->user_info, status,
455 NULL, NULL, NULL, NULL);
456 tevent_req_received(req);
460 DEBUG(5,("auth_check_password_recv: "
461 "%s authentication for user [%s\\%s] succeeded\n",
462 state->method->ops->name,
463 state->user_info_dc->info->domain_name,
464 state->user_info_dc->info->account_name));
466 log_authentication_event(state->auth_ctx->msg_ctx,
467 state->auth_ctx->lp_ctx,
468 state->user_info, status,
469 state->user_info_dc->info->domain_name,
470 state->user_info_dc->info->account_name,
472 &state->user_info_dc->sids[0]);
474 *user_info_dc = talloc_move(mem_ctx, &state->user_info_dc);
476 tevent_req_received(req);
480 /* Wrapper because we don't want to expose all callers to needing to
481 * know that session_info is generated from the main ldb, and because
482 * we need to break a depenency loop between the DCE/RPC layer and the
483 * generation of unix tokens via IRPC */
484 static NTSTATUS auth_generate_session_info_wrapper(struct auth4_context *auth_context,
486 void *server_returned_info,
487 const char *original_user_name,
488 uint32_t session_info_flags,
489 struct auth_session_info **session_info)
492 struct auth_user_info_dc *user_info_dc = talloc_get_type_abort(server_returned_info, struct auth_user_info_dc);
494 if (user_info_dc->info->authenticated) {
495 session_info_flags |= AUTH_SESSION_INFO_AUTHENTICATED;
498 status = auth_generate_session_info(mem_ctx, auth_context->lp_ctx,
499 auth_context->sam_ctx, user_info_dc,
500 session_info_flags, session_info);
501 if (!NT_STATUS_IS_OK(status)) {
505 if ((session_info_flags & AUTH_SESSION_INFO_UNIX_TOKEN)
506 && NT_STATUS_IS_OK(status)) {
507 status = auth_session_info_fill_unix(auth_context->event_ctx,
508 auth_context->lp_ctx,
509 original_user_name, *session_info);
510 if (!NT_STATUS_IS_OK(status)) {
511 TALLOC_FREE(*session_info);
517 /* Wrapper because we don't want to expose all callers to needing to
518 * know anything about the PAC or auth subsystem internal structures
519 * before we output a struct auth session_info */
520 static NTSTATUS auth_generate_session_info_pac(struct auth4_context *auth_ctx,
522 struct smb_krb5_context *smb_krb5_context,
524 const char *principal_name,
525 const struct tsocket_address *remote_address,
526 uint32_t session_info_flags,
527 struct auth_session_info **session_info)
530 struct auth_user_info_dc *user_info_dc;
534 return auth_generate_session_info_principal(auth_ctx, mem_ctx, principal_name,
535 NULL, session_info_flags, session_info);
538 tmp_ctx = talloc_named(mem_ctx, 0, "gensec_gssapi_session_info context");
539 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
541 status = kerberos_pac_blob_to_user_info_dc(tmp_ctx,
543 smb_krb5_context->krb5_context,
544 &user_info_dc, NULL, NULL);
545 if (!NT_STATUS_IS_OK(status)) {
546 talloc_free(tmp_ctx);
550 if (user_info_dc->info->authenticated) {
551 session_info_flags |= AUTH_SESSION_INFO_AUTHENTICATED;
554 status = auth_generate_session_info_wrapper(auth_ctx, mem_ctx,
556 user_info_dc->info->account_name,
557 session_info_flags, session_info);
558 talloc_free(tmp_ctx);
562 /***************************************************************************
563 Make a auth_info struct for the auth subsystem
564 - Allow the caller to specify the methods to use, including optionally the SAM to use
565 ***************************************************************************/
566 _PUBLIC_ NTSTATUS auth_context_create_methods(TALLOC_CTX *mem_ctx, const char * const *methods,
567 struct tevent_context *ev,
568 struct imessaging_context *msg,
569 struct loadparm_context *lp_ctx,
570 struct ldb_context *sam_ctx,
571 struct auth4_context **auth_ctx)
574 struct auth4_context *ctx;
579 DEBUG(0,("auth_context_create: called with out event context\n"));
580 return NT_STATUS_INTERNAL_ERROR;
583 ctx = talloc_zero(mem_ctx, struct auth4_context);
584 NT_STATUS_HAVE_NO_MEMORY(ctx);
585 ctx->challenge.data = data_blob(NULL, 0);
589 ctx->lp_ctx = lp_ctx;
592 ctx->sam_ctx = sam_ctx;
594 ctx->sam_ctx = samdb_connect(ctx, ctx->event_ctx, ctx->lp_ctx, system_session(ctx->lp_ctx), 0);
597 for (i=0; methods && methods[i] ; i++) {
598 struct auth_method_context *method;
600 method = talloc(ctx, struct auth_method_context);
601 NT_STATUS_HAVE_NO_MEMORY(method);
603 method->ops = auth_backend_byname(methods[i]);
605 DEBUG(1,("auth_context_create: failed to find method=%s\n",
607 return NT_STATUS_INTERNAL_ERROR;
609 method->auth_ctx = ctx;
611 DLIST_ADD_END(ctx->methods, method);
614 ctx->check_ntlm_password = auth_check_password_wrapper;
615 ctx->get_ntlm_challenge = auth_get_challenge;
616 ctx->set_ntlm_challenge = auth_context_set_challenge;
617 ctx->generate_session_info = auth_generate_session_info_wrapper;
618 ctx->generate_session_info_pac = auth_generate_session_info_pac;
625 const char **auth_methods_from_lp(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx)
627 char **auth_methods = NULL;
628 const char **const_auth_methods = NULL;
631 * As 'auth methods' is deprecated it will be removed
632 * in future releases again, but for now give
633 * admins the flexibility to configure, the behavior
634 * from Samba 4.6: "auth methods = anonymous sam_ignoredomain",
637 const_auth_methods = lpcfg_auth_methods(lp_ctx);
638 if (const_auth_methods != NULL) {
639 DBG_NOTICE("using deprecated 'auth methods' values.\n");
640 return const_auth_methods;
643 switch (lpcfg_server_role(lp_ctx)) {
644 case ROLE_STANDALONE:
645 auth_methods = str_list_make(mem_ctx, "anonymous sam_ignoredomain", NULL);
647 case ROLE_DOMAIN_MEMBER:
648 auth_methods = str_list_make(mem_ctx, "anonymous sam winbind sam_ignoredomain", NULL);
650 case ROLE_DOMAIN_BDC:
651 case ROLE_DOMAIN_PDC:
652 case ROLE_ACTIVE_DIRECTORY_DC:
654 * TODO: we should replace "winbind_rodc sam_failtrusts" with "winbind"
655 * if everything (gensec/auth4) is fully async without nested
658 * But for now we'll fail authentications for trusted
659 * domain consistently with NT_STATUS_NO_TRUST_LSA_SECRET,
660 * instead of silently mapping to local users.
662 auth_methods = str_list_make(mem_ctx,
664 "winbind_rodc sam_failtrusts "
669 return discard_const_p(const char *, auth_methods);
672 /***************************************************************************
673 Make a auth_info struct for the auth subsystem
674 - Uses default auth_methods, depending on server role and smb.conf settings
675 ***************************************************************************/
676 _PUBLIC_ NTSTATUS auth_context_create(TALLOC_CTX *mem_ctx,
677 struct tevent_context *ev,
678 struct imessaging_context *msg,
679 struct loadparm_context *lp_ctx,
680 struct auth4_context **auth_ctx)
683 const char **auth_methods;
684 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
686 return NT_STATUS_NO_MEMORY;
689 auth_methods = auth_methods_from_lp(tmp_ctx, lp_ctx);
691 return NT_STATUS_INVALID_PARAMETER;
693 status = auth_context_create_methods(mem_ctx, auth_methods, ev, msg, lp_ctx, NULL, auth_ctx);
694 talloc_free(tmp_ctx);
698 _PUBLIC_ NTSTATUS auth_context_create_for_netlogon(TALLOC_CTX *mem_ctx,
699 struct tevent_context *ev,
700 struct imessaging_context *msg,
701 struct loadparm_context *lp_ctx,
702 struct auth4_context **auth_ctx)
704 return auth_context_create(mem_ctx, ev, msg, lp_ctx, auth_ctx);
707 /* the list of currently registered AUTH backends */
708 static struct auth_backend {
709 const struct auth_operations *ops;
711 static int num_backends;
714 register a AUTH backend.
716 The 'name' can be later used by other backends to find the operations
717 structure for this backend.
719 _PUBLIC_ NTSTATUS auth_register(const struct auth_operations *ops)
721 struct auth_operations *new_ops;
723 if (auth_backend_byname(ops->name) != NULL) {
724 /* its already registered! */
725 DEBUG(0,("AUTH backend '%s' already registered\n",
727 return NT_STATUS_OBJECT_NAME_COLLISION;
730 backends = talloc_realloc(talloc_autofree_context(), backends,
731 struct auth_backend, num_backends+1);
732 NT_STATUS_HAVE_NO_MEMORY(backends);
734 new_ops = (struct auth_operations *)talloc_memdup(backends, ops, sizeof(*ops));
735 NT_STATUS_HAVE_NO_MEMORY(new_ops);
736 new_ops->name = talloc_strdup(new_ops, ops->name);
737 NT_STATUS_HAVE_NO_MEMORY(new_ops->name);
739 backends[num_backends].ops = new_ops;
743 DEBUG(3,("AUTH backend '%s' registered\n",
750 return the operations structure for a named backend of the specified type
752 const struct auth_operations *auth_backend_byname(const char *name)
756 for (i=0;i<num_backends;i++) {
757 if (strcmp(backends[i].ops->name, name) == 0) {
758 return backends[i].ops;
766 return the AUTH interface version, and the size of some critical types
767 This can be used by backends to either detect compilation errors, or provide
768 multiple implementations for different smbd compilation options in one module
770 const struct auth_critical_sizes *auth_interface_version(void)
772 static const struct auth_critical_sizes critical_sizes = {
773 AUTH4_INTERFACE_VERSION,
774 sizeof(struct auth_operations),
775 sizeof(struct auth_method_context),
776 sizeof(struct auth4_context),
777 sizeof(struct auth_usersupplied_info),
778 sizeof(struct auth_user_info_dc)
781 return &critical_sizes;
784 _PUBLIC_ NTSTATUS auth4_init(void)
786 static bool initialized = false;
787 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
788 STATIC_auth4_MODULES_PROTO;
789 init_module_fn static_init[] = { STATIC_auth4_MODULES };
791 if (initialized) return NT_STATUS_OK;
794 run_init_functions(static_init);