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)
160 struct tevent_req *subreq;
161 struct tevent_context *ev;
165 /*TODO: create a new event context here! */
166 ev = auth_ctx->event_ctx;
168 subreq = auth_check_password_send(mem_ctx,
172 if (subreq == NULL) {
173 return NT_STATUS_NO_MEMORY;
176 ok = tevent_req_poll(subreq, ev);
178 return NT_STATUS_INTERNAL_ERROR;
181 status = auth_check_password_recv(subreq, mem_ctx, user_info_dc);
187 _PUBLIC_ NTSTATUS auth_check_password_wrapper(struct auth4_context *auth_ctx,
189 const struct auth_usersupplied_info *user_info,
190 void **server_returned_info,
191 DATA_BLOB *user_session_key, DATA_BLOB *lm_session_key)
193 struct auth_user_info_dc *user_info_dc;
194 NTSTATUS status = auth_check_password(auth_ctx, mem_ctx, user_info, &user_info_dc);
196 if (NT_STATUS_IS_OK(status)) {
197 *server_returned_info = user_info_dc;
199 if (user_session_key) {
200 DEBUG(10, ("Got NT session key of length %u\n",
201 (unsigned)user_info_dc->user_session_key.length));
202 *user_session_key = user_info_dc->user_session_key;
203 talloc_steal(mem_ctx, user_session_key->data);
204 user_info_dc->user_session_key = data_blob_null;
207 if (lm_session_key) {
208 DEBUG(10, ("Got LM session key of length %u\n",
209 (unsigned)user_info_dc->lm_session_key.length));
210 *lm_session_key = user_info_dc->lm_session_key;
211 talloc_steal(mem_ctx, lm_session_key->data);
212 user_info_dc->lm_session_key = data_blob_null;
219 struct auth_check_password_state {
220 struct auth4_context *auth_ctx;
221 const struct auth_usersupplied_info *user_info;
222 struct auth_user_info_dc *user_info_dc;
223 struct auth_method_context *method;
226 static void auth_check_password_async_trigger(struct tevent_context *ev,
227 struct tevent_immediate *im,
230 * Check a user's Plaintext, LM or NTLM password.
233 * Check a user's password, as given in the user_info struct and return various
234 * interesting details in the user_info_dc struct.
236 * The return value takes precedence over the contents of the user_info_dc
237 * struct. When the return is other than NT_STATUS_OK the contents
238 * of that structure is undefined.
240 * @param mem_ctx The memory context the request should operate on
242 * @param ev The tevent context the request should operate on
244 * @param auth_ctx Supplies the challenges and some other data.
245 * Must be created with make_auth_context(), and the challenges should be
246 * filled in, either at creation or by calling the challenge geneation
247 * function auth_get_challenge().
249 * @param user_info Contains the user supplied components, including the passwords.
251 * @return The request handle or NULL on no memory error.
255 _PUBLIC_ struct tevent_req *auth_check_password_send(TALLOC_CTX *mem_ctx,
256 struct tevent_context *ev,
257 struct auth4_context *auth_ctx,
258 const struct auth_usersupplied_info *user_info)
260 struct tevent_req *req;
261 struct auth_check_password_state *state;
262 /* if all the modules say 'not for me' this is reasonable */
265 struct auth_usersupplied_info *user_info_tmp;
266 struct tevent_immediate *im;
268 DEBUG(3,("auth_check_password_send: "
269 "Checking password for unmapped user [%s]\\[%s]@[%s]\n",
270 user_info->client.domain_name, user_info->client.account_name,
271 user_info->workstation_name));
273 req = tevent_req_create(mem_ctx, &state,
274 struct auth_check_password_state);
279 state->auth_ctx = auth_ctx;
280 state->user_info = user_info;
282 if (!user_info->mapped_state) {
283 nt_status = map_user_info(auth_ctx->sam_ctx, req, lpcfg_workgroup(auth_ctx->lp_ctx),
284 user_info, &user_info_tmp);
285 if (tevent_req_nterror(req, nt_status)) {
286 return tevent_req_post(req, ev);
288 user_info = user_info_tmp;
289 state->user_info = user_info_tmp;
292 DEBUGADD(3,("auth_check_password_send: "
293 "mapped user is: [%s]\\[%s]@[%s]\n",
294 user_info->mapped.domain_name,
295 user_info->mapped.account_name,
296 user_info->workstation_name));
298 nt_status = auth_get_challenge(auth_ctx, chal);
299 if (tevent_req_nterror(req, nt_status)) {
300 DEBUG(0,("auth_check_password_send: "
301 "Invalid challenge (length %u) stored for "
302 "this auth context set_by %s - cannot continue: %s\n",
303 (unsigned)auth_ctx->challenge.data.length,
304 auth_ctx->challenge.set_by,
305 nt_errstr(nt_status)));
306 return tevent_req_post(req, ev);
309 if (auth_ctx->challenge.set_by) {
310 DEBUG(10,("auth_check_password_send: "
311 "auth_context challenge created by %s\n",
312 auth_ctx->challenge.set_by));
315 DEBUG(10, ("auth_check_password_send: challenge is: \n"));
316 dump_data(5, auth_ctx->challenge.data.data,
317 auth_ctx->challenge.data.length);
319 im = tevent_create_immediate(state);
320 if (tevent_req_nomem(im, req)) {
321 return tevent_req_post(req, ev);
324 tevent_schedule_immediate(im,
326 auth_check_password_async_trigger,
331 static void auth_check_password_async_trigger(struct tevent_context *ev,
332 struct tevent_immediate *im,
335 struct tevent_req *req =
336 talloc_get_type_abort(private_data, struct tevent_req);
337 struct auth_check_password_state *state =
338 tevent_req_data(req, struct auth_check_password_state);
340 struct auth_method_context *method;
342 status = NT_STATUS_OK;
344 for (method=state->auth_ctx->methods; method; method = method->next) {
346 if (state->user_info->flags & USER_INFO_LOCAL_SAM_ONLY
347 && !(method->ops->flags & AUTH_METHOD_LOCAL_SAM)) {
351 /* we fill in state->method here so debug messages in
352 the callers know which method failed */
353 state->method = method;
355 /* check if the module wants to check the password */
356 status = method->ops->want_check(method, req, state->user_info);
357 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
358 DEBUG(11,("auth_check_password_send: "
359 "%s had nothing to say\n",
364 if (tevent_req_nterror(req, status)) {
368 status = method->ops->check_password(method,
371 &state->user_info_dc);
372 if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
373 /* the backend has handled the request */
378 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
379 if (!(state->user_info->flags & USER_INFO_LOCAL_SAM_ONLY)) {
380 /* don't expose the NT_STATUS_NOT_IMPLEMENTED
381 * internals, except when the caller is only probing
382 * one method, as they may do the fallback
384 status = NT_STATUS_NO_SUCH_USER;
388 if (tevent_req_nterror(req, status)) {
392 tevent_req_done(req);
396 * Check a user's Plaintext, LM or NTLM password.
397 * async receive function
399 * The return value takes precedence over the contents of the user_info_dc
400 * struct. When the return is other than NT_STATUS_OK the contents
401 * of that structure is undefined.
404 * @param req The async request state
406 * @param mem_ctx The parent memory context for the user_info_dc structure
408 * @param user_info_dc If successful, contains information about the authentication,
409 * including a SAM_ACCOUNT struct describing the user.
411 * @return An NTSTATUS with NT_STATUS_OK or an appropriate error.
415 _PUBLIC_ NTSTATUS auth_check_password_recv(struct tevent_req *req,
417 struct auth_user_info_dc **user_info_dc)
419 struct auth_check_password_state *state =
420 tevent_req_data(req, struct auth_check_password_state);
423 if (tevent_req_is_nterror(req, &status)) {
424 DEBUG(2,("auth_check_password_recv: "
425 "%s authentication for user [%s\\%s] "
426 "FAILED with error %s\n",
427 (state->method ? state->method->ops->name : "NO_METHOD"),
428 state->user_info->mapped.domain_name,
429 state->user_info->mapped.account_name,
431 tevent_req_received(req);
435 DEBUG(5,("auth_check_password_recv: "
436 "%s authentication for user [%s\\%s] succeeded\n",
437 state->method->ops->name,
438 state->user_info_dc->info->domain_name,
439 state->user_info_dc->info->account_name));
441 *user_info_dc = talloc_move(mem_ctx, &state->user_info_dc);
443 tevent_req_received(req);
447 /* Wrapper because we don't want to expose all callers to needing to
448 * know that session_info is generated from the main ldb, and because
449 * we need to break a depenency loop between the DCE/RPC layer and the
450 * generation of unix tokens via IRPC */
451 static NTSTATUS auth_generate_session_info_wrapper(struct auth4_context *auth_context,
453 void *server_returned_info,
454 const char *original_user_name,
455 uint32_t session_info_flags,
456 struct auth_session_info **session_info)
459 struct auth_user_info_dc *user_info_dc = talloc_get_type_abort(server_returned_info, struct auth_user_info_dc);
461 if (user_info_dc->info->authenticated) {
462 session_info_flags |= AUTH_SESSION_INFO_AUTHENTICATED;
465 status = auth_generate_session_info(mem_ctx, auth_context->lp_ctx,
466 auth_context->sam_ctx, user_info_dc,
467 session_info_flags, session_info);
468 if (!NT_STATUS_IS_OK(status)) {
472 if ((session_info_flags & AUTH_SESSION_INFO_UNIX_TOKEN)
473 && NT_STATUS_IS_OK(status)) {
474 status = auth_session_info_fill_unix(auth_context->event_ctx,
475 auth_context->lp_ctx,
476 original_user_name, *session_info);
477 if (!NT_STATUS_IS_OK(status)) {
478 TALLOC_FREE(*session_info);
484 /* Wrapper because we don't want to expose all callers to needing to
485 * know anything about the PAC or auth subsystem internal structures
486 * before we output a struct auth session_info */
487 static NTSTATUS auth_generate_session_info_pac(struct auth4_context *auth_ctx,
489 struct smb_krb5_context *smb_krb5_context,
491 const char *principal_name,
492 const struct tsocket_address *remote_address,
493 uint32_t session_info_flags,
494 struct auth_session_info **session_info)
497 struct auth_user_info_dc *user_info_dc;
501 return auth_generate_session_info_principal(auth_ctx, mem_ctx, principal_name,
502 NULL, session_info_flags, session_info);
505 tmp_ctx = talloc_named(mem_ctx, 0, "gensec_gssapi_session_info context");
506 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
508 status = kerberos_pac_blob_to_user_info_dc(tmp_ctx,
510 smb_krb5_context->krb5_context,
511 &user_info_dc, NULL, NULL);
512 if (!NT_STATUS_IS_OK(status)) {
513 talloc_free(tmp_ctx);
517 if (user_info_dc->info->authenticated) {
518 session_info_flags |= AUTH_SESSION_INFO_AUTHENTICATED;
521 status = auth_generate_session_info_wrapper(auth_ctx, mem_ctx,
523 user_info_dc->info->account_name,
524 session_info_flags, session_info);
525 talloc_free(tmp_ctx);
529 /***************************************************************************
530 Make a auth_info struct for the auth subsystem
531 - Allow the caller to specify the methods to use, including optionally the SAM to use
532 ***************************************************************************/
533 _PUBLIC_ NTSTATUS auth_context_create_methods(TALLOC_CTX *mem_ctx, const char * const *methods,
534 struct tevent_context *ev,
535 struct imessaging_context *msg,
536 struct loadparm_context *lp_ctx,
537 struct ldb_context *sam_ctx,
538 struct auth4_context **auth_ctx)
541 struct auth4_context *ctx;
546 DEBUG(0,("auth_context_create: called with out event context\n"));
547 return NT_STATUS_INTERNAL_ERROR;
550 ctx = talloc_zero(mem_ctx, struct auth4_context);
551 NT_STATUS_HAVE_NO_MEMORY(ctx);
552 ctx->challenge.data = data_blob(NULL, 0);
556 ctx->lp_ctx = lp_ctx;
559 ctx->sam_ctx = sam_ctx;
561 ctx->sam_ctx = samdb_connect(ctx, ctx->event_ctx, ctx->lp_ctx, system_session(ctx->lp_ctx), 0);
564 for (i=0; methods && methods[i] ; i++) {
565 struct auth_method_context *method;
567 method = talloc(ctx, struct auth_method_context);
568 NT_STATUS_HAVE_NO_MEMORY(method);
570 method->ops = auth_backend_byname(methods[i]);
572 DEBUG(1,("auth_context_create: failed to find method=%s\n",
574 return NT_STATUS_INTERNAL_ERROR;
576 method->auth_ctx = ctx;
578 DLIST_ADD_END(ctx->methods, method, struct auth_method_context *);
581 ctx->check_ntlm_password = auth_check_password_wrapper;
582 ctx->get_ntlm_challenge = auth_get_challenge;
583 ctx->set_ntlm_challenge = auth_context_set_challenge;
584 ctx->generate_session_info = auth_generate_session_info_wrapper;
585 ctx->generate_session_info_pac = auth_generate_session_info_pac;
592 const char **auth_methods_from_lp(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx)
594 char **auth_methods = NULL;
596 switch (lpcfg_server_role(lp_ctx)) {
597 case ROLE_STANDALONE:
598 auth_methods = str_list_make(mem_ctx, "anonymous sam_ignoredomain", NULL);
600 case ROLE_DOMAIN_MEMBER:
601 auth_methods = str_list_make(mem_ctx, "anonymous sam winbind", NULL);
603 case ROLE_DOMAIN_BDC:
604 case ROLE_DOMAIN_PDC:
605 case ROLE_ACTIVE_DIRECTORY_DC:
606 auth_methods = str_list_make(mem_ctx, "anonymous sam_ignoredomain winbind", NULL);
609 return discard_const_p(const char *, auth_methods);
612 /***************************************************************************
613 Make a auth_info struct for the auth subsystem
614 - Uses default auth_methods, depending on server role and smb.conf settings
615 ***************************************************************************/
616 _PUBLIC_ NTSTATUS auth_context_create(TALLOC_CTX *mem_ctx,
617 struct tevent_context *ev,
618 struct imessaging_context *msg,
619 struct loadparm_context *lp_ctx,
620 struct auth4_context **auth_ctx)
623 const char **auth_methods;
624 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
626 return NT_STATUS_NO_MEMORY;
629 auth_methods = auth_methods_from_lp(tmp_ctx, lp_ctx);
631 return NT_STATUS_INVALID_PARAMETER;
633 status = auth_context_create_methods(mem_ctx, auth_methods, ev, msg, lp_ctx, NULL, auth_ctx);
634 talloc_free(tmp_ctx);
638 /* the list of currently registered AUTH backends */
639 static struct auth_backend {
640 const struct auth_operations *ops;
642 static int num_backends;
645 register a AUTH backend.
647 The 'name' can be later used by other backends to find the operations
648 structure for this backend.
650 _PUBLIC_ NTSTATUS auth_register(const struct auth_operations *ops)
652 struct auth_operations *new_ops;
654 if (auth_backend_byname(ops->name) != NULL) {
655 /* its already registered! */
656 DEBUG(0,("AUTH backend '%s' already registered\n",
658 return NT_STATUS_OBJECT_NAME_COLLISION;
661 backends = talloc_realloc(talloc_autofree_context(), backends,
662 struct auth_backend, num_backends+1);
663 NT_STATUS_HAVE_NO_MEMORY(backends);
665 new_ops = (struct auth_operations *)talloc_memdup(backends, ops, sizeof(*ops));
666 NT_STATUS_HAVE_NO_MEMORY(new_ops);
667 new_ops->name = talloc_strdup(new_ops, ops->name);
668 NT_STATUS_HAVE_NO_MEMORY(new_ops->name);
670 backends[num_backends].ops = new_ops;
674 DEBUG(3,("AUTH backend '%s' registered\n",
681 return the operations structure for a named backend of the specified type
683 const struct auth_operations *auth_backend_byname(const char *name)
687 for (i=0;i<num_backends;i++) {
688 if (strcmp(backends[i].ops->name, name) == 0) {
689 return backends[i].ops;
697 return the AUTH interface version, and the size of some critical types
698 This can be used by backends to either detect compilation errors, or provide
699 multiple implementations for different smbd compilation options in one module
701 const struct auth_critical_sizes *auth_interface_version(void)
703 static const struct auth_critical_sizes critical_sizes = {
704 AUTH4_INTERFACE_VERSION,
705 sizeof(struct auth_operations),
706 sizeof(struct auth_method_context),
707 sizeof(struct auth4_context),
708 sizeof(struct auth_usersupplied_info),
709 sizeof(struct auth_user_info_dc)
712 return &critical_sizes;
715 _PUBLIC_ NTSTATUS auth4_init(void)
717 static bool initialized = false;
718 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
719 STATIC_auth4_MODULES_PROTO;
720 init_module_fn static_init[] = { STATIC_auth4_MODULES };
722 if (initialized) return NT_STATUS_OK;
725 run_init_functions(static_init);