s3:lib: make use of SMB_SIGNING_* constants
[Samba/gebeck_regimport.git] / source4 / auth / ntlm / auth.c
blob65abeae50b89e41f0e8c3b15539701f27e125783
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_module.h"
32 /***************************************************************************
33 Set a fixed challenge
34 ***************************************************************************/
35 _PUBLIC_ NTSTATUS auth_context_set_challenge(struct auth4_context *auth_ctx, const uint8_t chal[8], const char *set_by)
37 auth_ctx->challenge.set_by = talloc_strdup(auth_ctx, set_by);
38 NT_STATUS_HAVE_NO_MEMORY(auth_ctx->challenge.set_by);
40 auth_ctx->challenge.data = data_blob_talloc(auth_ctx, chal, 8);
41 NT_STATUS_HAVE_NO_MEMORY(auth_ctx->challenge.data.data);
43 return NT_STATUS_OK;
46 /***************************************************************************
47 Set a fixed challenge
48 ***************************************************************************/
49 _PUBLIC_ bool auth_challenge_may_be_modified(struct auth4_context *auth_ctx)
51 return auth_ctx->challenge.may_be_modified;
54 /****************************************************************************
55 Try to get a challenge out of the various authentication modules.
56 Returns a const char of length 8 bytes.
57 ****************************************************************************/
58 _PUBLIC_ NTSTATUS auth_get_challenge(struct auth4_context *auth_ctx, uint8_t chal[8])
60 NTSTATUS nt_status;
61 struct auth_method_context *method;
63 if (auth_ctx->challenge.data.length == 8) {
64 DEBUG(5, ("auth_get_challenge: returning previous challenge by module %s (normal)\n",
65 auth_ctx->challenge.set_by));
66 memcpy(chal, auth_ctx->challenge.data.data, 8);
67 return NT_STATUS_OK;
70 for (method = auth_ctx->methods; method; method = method->next) {
71 nt_status = method->ops->get_challenge(method, auth_ctx, chal);
72 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NOT_IMPLEMENTED)) {
73 continue;
76 NT_STATUS_NOT_OK_RETURN(nt_status);
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 = method->ops->name;
82 break;
85 if (!auth_ctx->challenge.set_by) {
86 generate_random_buffer(chal, 8);
88 auth_ctx->challenge.data = data_blob_talloc(auth_ctx, chal, 8);
89 NT_STATUS_HAVE_NO_MEMORY(auth_ctx->challenge.data.data);
90 auth_ctx->challenge.set_by = "random";
92 auth_ctx->challenge.may_be_modified = true;
95 DEBUG(10,("auth_get_challenge: challenge set by %s\n",
96 auth_ctx->challenge.set_by));
98 return NT_STATUS_OK;
101 /****************************************************************************
102 Used in the gensec_gssapi and gensec_krb5 server-side code, where the
103 PAC isn't available, and for tokenGroups in the DSDB stack.
105 Supply either a principal or a DN
106 ****************************************************************************/
107 _PUBLIC_ NTSTATUS auth_get_user_info_dc_principal(TALLOC_CTX *mem_ctx,
108 struct auth4_context *auth_ctx,
109 const char *principal,
110 struct ldb_dn *user_dn,
111 struct auth_user_info_dc **user_info_dc)
113 NTSTATUS nt_status;
114 struct auth_method_context *method;
116 for (method = auth_ctx->methods; method; method = method->next) {
117 if (!method->ops->get_user_info_dc_principal) {
118 continue;
121 nt_status = method->ops->get_user_info_dc_principal(mem_ctx, auth_ctx, principal, user_dn, user_info_dc);
122 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NOT_IMPLEMENTED)) {
123 continue;
126 return nt_status;
129 return NT_STATUS_NOT_IMPLEMENTED;
133 * Check a user's Plaintext, LM or NTLM password.
134 * (sync version)
136 * Check a user's password, as given in the user_info struct and return various
137 * interesting details in the user_info_dc struct.
139 * The return value takes precedence over the contents of the user_info_dc
140 * struct. When the return is other than NT_STATUS_OK the contents
141 * of that structure is undefined.
143 * @param auth_ctx Supplies the challenges and some other data.
144 * Must be created with auth_context_create(), and the challenges should be
145 * filled in, either at creation or by calling the challenge geneation
146 * function auth_get_challenge().
148 * @param user_info Contains the user supplied components, including the passwords.
150 * @param mem_ctx The parent memory context for the user_info_dc structure
152 * @param user_info_dc If successful, contains information about the authentication,
153 * including a SAM_ACCOUNT struct describing the user.
155 * @return An NTSTATUS with NT_STATUS_OK or an appropriate error.
159 _PUBLIC_ NTSTATUS auth_check_password(struct auth4_context *auth_ctx,
160 TALLOC_CTX *mem_ctx,
161 const struct auth_usersupplied_info *user_info,
162 struct auth_user_info_dc **user_info_dc)
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, user_info_dc);
186 TALLOC_FREE(subreq);
188 return status;
191 struct auth_check_password_state {
192 struct auth4_context *auth_ctx;
193 const struct auth_usersupplied_info *user_info;
194 struct auth_user_info_dc *user_info_dc;
195 struct auth_method_context *method;
198 static void auth_check_password_async_trigger(struct tevent_context *ev,
199 struct tevent_immediate *im,
200 void *private_data);
202 * Check a user's Plaintext, LM or NTLM password.
203 * async send hook
205 * Check a user's password, as given in the user_info struct and return various
206 * interesting details in the user_info_dc struct.
208 * The return value takes precedence over the contents of the user_info_dc
209 * struct. When the return is other than NT_STATUS_OK the contents
210 * of that structure is undefined.
212 * @param mem_ctx The memory context the request should operate on
214 * @param ev The tevent context the request should operate on
216 * @param auth_ctx Supplies the challenges and some other data.
217 * Must be created with make_auth_context(), and the challenges should be
218 * filled in, either at creation or by calling the challenge geneation
219 * function auth_get_challenge().
221 * @param user_info Contains the user supplied components, including the passwords.
223 * @return The request handle or NULL on no memory error.
227 _PUBLIC_ struct tevent_req *auth_check_password_send(TALLOC_CTX *mem_ctx,
228 struct tevent_context *ev,
229 struct auth4_context *auth_ctx,
230 const struct auth_usersupplied_info *user_info)
232 struct tevent_req *req;
233 struct auth_check_password_state *state;
234 /* if all the modules say 'not for me' this is reasonable */
235 NTSTATUS nt_status;
236 uint8_t chal[8];
237 struct auth_usersupplied_info *user_info_tmp;
238 struct tevent_immediate *im;
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;
251 state->auth_ctx = auth_ctx;
252 state->user_info = user_info;
254 if (!user_info->mapped_state) {
255 nt_status = map_user_info(auth_ctx->sam_ctx, req, lpcfg_workgroup(auth_ctx->lp_ctx),
256 user_info, &user_info_tmp);
257 if (tevent_req_nterror(req, nt_status)) {
258 return tevent_req_post(req, ev);
260 user_info = user_info_tmp;
261 state->user_info = user_info_tmp;
264 DEBUGADD(3,("auth_check_password_send: "
265 "mapped user is: [%s]\\[%s]@[%s]\n",
266 user_info->mapped.domain_name,
267 user_info->mapped.account_name,
268 user_info->workstation_name));
270 nt_status = auth_get_challenge(auth_ctx, chal);
271 if (tevent_req_nterror(req, nt_status)) {
272 DEBUG(0,("auth_check_password_send: "
273 "Invalid challenge (length %u) stored for "
274 "this auth context set_by %s - cannot continue: %s\n",
275 (unsigned)auth_ctx->challenge.data.length,
276 auth_ctx->challenge.set_by,
277 nt_errstr(nt_status)));
278 return tevent_req_post(req, ev);
281 if (auth_ctx->challenge.set_by) {
282 DEBUG(10,("auth_check_password_send: "
283 "auth_context challenge created by %s\n",
284 auth_ctx->challenge.set_by));
287 DEBUG(10, ("auth_check_password_send: challenge is: \n"));
288 dump_data(5, auth_ctx->challenge.data.data,
289 auth_ctx->challenge.data.length);
291 im = tevent_create_immediate(state);
292 if (tevent_req_nomem(im, req)) {
293 return tevent_req_post(req, ev);
296 tevent_schedule_immediate(im,
297 auth_ctx->event_ctx,
298 auth_check_password_async_trigger,
299 req);
300 return req;
303 static void auth_check_password_async_trigger(struct tevent_context *ev,
304 struct tevent_immediate *im,
305 void *private_data)
307 struct tevent_req *req =
308 talloc_get_type_abort(private_data, struct tevent_req);
309 struct auth_check_password_state *state =
310 tevent_req_data(req, struct auth_check_password_state);
311 NTSTATUS status;
312 struct auth_method_context *method;
314 status = NT_STATUS_OK;
316 for (method=state->auth_ctx->methods; method; method = method->next) {
318 /* we fill in state->method here so debug messages in
319 the callers know which method failed */
320 state->method = method;
322 /* check if the module wants to check the password */
323 status = method->ops->want_check(method, req, state->user_info);
324 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
325 DEBUG(11,("auth_check_password_send: "
326 "%s had nothing to say\n",
327 method->ops->name));
328 continue;
331 if (tevent_req_nterror(req, status)) {
332 return;
335 status = method->ops->check_password(method,
336 state,
337 state->user_info,
338 &state->user_info_dc);
339 if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
340 /* the backend has handled the request */
341 break;
345 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
346 /* don't expose the NT_STATUS_NOT_IMPLEMENTED
347 internals */
348 status = NT_STATUS_NO_SUCH_USER;
351 if (tevent_req_nterror(req, status)) {
352 return;
355 tevent_req_done(req);
359 * Check a user's Plaintext, LM or NTLM password.
360 * async receive function
362 * The return value takes precedence over the contents of the user_info_dc
363 * struct. When the return is other than NT_STATUS_OK the contents
364 * of that structure is undefined.
367 * @param req The async request state
369 * @param mem_ctx The parent memory context for the user_info_dc structure
371 * @param user_info_dc If successful, contains information about the authentication,
372 * including a SAM_ACCOUNT struct describing the user.
374 * @return An NTSTATUS with NT_STATUS_OK or an appropriate error.
378 _PUBLIC_ NTSTATUS auth_check_password_recv(struct tevent_req *req,
379 TALLOC_CTX *mem_ctx,
380 struct auth_user_info_dc **user_info_dc)
382 struct auth_check_password_state *state =
383 tevent_req_data(req, struct auth_check_password_state);
384 NTSTATUS status;
386 if (tevent_req_is_nterror(req, &status)) {
387 DEBUG(2,("auth_check_password_recv: "
388 "%s authentication for user [%s\\%s] "
389 "FAILED with error %s\n",
390 (state->method ? state->method->ops->name : "NO_METHOD"),
391 state->user_info->mapped.domain_name,
392 state->user_info->mapped.account_name,
393 nt_errstr(status)));
394 tevent_req_received(req);
395 return status;
398 DEBUG(5,("auth_check_password_recv: "
399 "%s authentication for user [%s\\%s] succeeded\n",
400 state->method->ops->name,
401 state->user_info_dc->info->domain_name,
402 state->user_info_dc->info->account_name));
404 *user_info_dc = talloc_move(mem_ctx, &state->user_info_dc);
406 tevent_req_received(req);
407 return NT_STATUS_OK;
410 /* Wrapper because we don't want to expose all callers to needing to
411 * know that session_info is generated from the main ldb, and because
412 * we need to break a depenency loop between the DCE/RPC layer and the
413 * generation of unix tokens via IRPC */
414 static NTSTATUS auth_generate_session_info_wrapper(TALLOC_CTX *mem_ctx,
415 struct auth4_context *auth_context,
416 struct auth_user_info_dc *user_info_dc,
417 uint32_t session_info_flags,
418 struct auth_session_info **session_info)
420 NTSTATUS status = auth_generate_session_info(mem_ctx, auth_context->lp_ctx,
421 auth_context->sam_ctx, user_info_dc,
422 session_info_flags, session_info);
424 if ((session_info_flags & AUTH_SESSION_INFO_UNIX_TOKEN)
425 && NT_STATUS_IS_OK(status)) {
426 struct wbc_context *wbc_ctx = wbc_init(auth_context,
427 auth_context->msg_ctx,
428 auth_context->event_ctx);
429 if (!wbc_ctx) {
430 TALLOC_FREE(*session_info);
431 DEBUG(1, ("Cannot contact winbind to provide unix token\n"));
432 return NT_STATUS_INVALID_SERVER_STATE;
434 status = auth_session_info_fill_unix(wbc_ctx, auth_context->lp_ctx,
435 *session_info);
436 if (!NT_STATUS_IS_OK(status)) {
437 TALLOC_FREE(*session_info);
439 TALLOC_FREE(wbc_ctx);
441 return status;
444 /***************************************************************************
445 Make a auth_info struct for the auth subsystem
446 - Allow the caller to specify the methods to use, including optionally the SAM to use
447 ***************************************************************************/
448 _PUBLIC_ NTSTATUS auth_context_create_methods(TALLOC_CTX *mem_ctx, const char **methods,
449 struct tevent_context *ev,
450 struct imessaging_context *msg,
451 struct loadparm_context *lp_ctx,
452 struct ldb_context *sam_ctx,
453 struct auth4_context **auth_ctx)
455 int i;
456 struct auth4_context *ctx;
458 auth4_init();
460 if (!ev) {
461 DEBUG(0,("auth_context_create: called with out event context\n"));
462 return NT_STATUS_INTERNAL_ERROR;
465 ctx = talloc(mem_ctx, struct auth4_context);
466 NT_STATUS_HAVE_NO_MEMORY(ctx);
467 ctx->challenge.set_by = NULL;
468 ctx->challenge.may_be_modified = false;
469 ctx->challenge.data = data_blob(NULL, 0);
470 ctx->methods = NULL;
471 ctx->event_ctx = ev;
472 ctx->msg_ctx = msg;
473 ctx->lp_ctx = lp_ctx;
475 if (sam_ctx) {
476 ctx->sam_ctx = sam_ctx;
477 } else {
478 ctx->sam_ctx = samdb_connect(ctx, ctx->event_ctx, ctx->lp_ctx, system_session(ctx->lp_ctx), 0);
481 for (i=0; methods && methods[i] ; i++) {
482 struct auth_method_context *method;
484 method = talloc(ctx, struct auth_method_context);
485 NT_STATUS_HAVE_NO_MEMORY(method);
487 method->ops = auth_backend_byname(methods[i]);
488 if (!method->ops) {
489 DEBUG(1,("auth_context_create: failed to find method=%s\n",
490 methods[i]));
491 return NT_STATUS_INTERNAL_ERROR;
493 method->auth_ctx = ctx;
494 method->depth = i;
495 DLIST_ADD_END(ctx->methods, method, struct auth_method_context *);
498 ctx->check_password = auth_check_password;
499 ctx->get_challenge = auth_get_challenge;
500 ctx->set_challenge = auth_context_set_challenge;
501 ctx->challenge_may_be_modified = auth_challenge_may_be_modified;
502 ctx->get_user_info_dc_principal = auth_get_user_info_dc_principal;
503 ctx->generate_session_info = auth_generate_session_info_wrapper;
505 *auth_ctx = ctx;
507 return NT_STATUS_OK;
510 const char **auth_methods_from_lp(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx)
512 char **auth_methods = NULL;
514 switch (lpcfg_server_role(lp_ctx)) {
515 case ROLE_STANDALONE:
516 auth_methods = str_list_make(mem_ctx, "anonymous sam_ignoredomain", NULL);
517 break;
518 case ROLE_DOMAIN_MEMBER:
519 auth_methods = str_list_make(mem_ctx, "anonymous sam winbind", NULL);
520 break;
521 case ROLE_DOMAIN_BDC:
522 case ROLE_DOMAIN_PDC:
523 auth_methods = str_list_make(mem_ctx, "anonymous sam_ignoredomain winbind", NULL);
524 break;
526 return (const char **) auth_methods;
529 /***************************************************************************
530 Make a auth_info struct for the auth subsystem
531 - Uses default auth_methods, depending on server role and smb.conf settings
532 ***************************************************************************/
533 _PUBLIC_ NTSTATUS auth_context_create(TALLOC_CTX *mem_ctx,
534 struct tevent_context *ev,
535 struct imessaging_context *msg,
536 struct loadparm_context *lp_ctx,
537 struct auth4_context **auth_ctx)
539 NTSTATUS status;
540 const char **auth_methods;
541 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
542 if (!tmp_ctx) {
543 return NT_STATUS_NO_MEMORY;
546 auth_methods = auth_methods_from_lp(tmp_ctx, lp_ctx);
547 if (!auth_methods) {
548 return NT_STATUS_INVALID_PARAMETER;
550 status = auth_context_create_methods(mem_ctx, auth_methods, ev, msg, lp_ctx, NULL, auth_ctx);
551 talloc_free(tmp_ctx);
552 return status;
555 /* Create an auth context from an open LDB.
557 This allows us not to re-open the LDB when we need to do a some authentication logic (such as tokenGroups)
560 NTSTATUS auth_context_create_from_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, struct auth4_context **auth_ctx)
562 NTSTATUS status;
563 const char **auth_methods;
564 struct loadparm_context *lp_ctx = talloc_get_type_abort(ldb_get_opaque(ldb, "loadparm"), struct loadparm_context);
565 struct tevent_context *ev = ldb_get_event_context(ldb);
567 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
568 if (!tmp_ctx) {
569 return NT_STATUS_NO_MEMORY;
572 auth_methods = auth_methods_from_lp(tmp_ctx, lp_ctx);
573 if (!auth_methods) {
574 return NT_STATUS_INVALID_PARAMETER;
576 status = auth_context_create_methods(mem_ctx, auth_methods, ev, NULL, lp_ctx, ldb, auth_ctx);
577 talloc_free(tmp_ctx);
578 return status;
581 /* the list of currently registered AUTH backends */
582 static struct auth_backend {
583 const struct auth_operations *ops;
584 } *backends = NULL;
585 static int num_backends;
588 register a AUTH backend.
590 The 'name' can be later used by other backends to find the operations
591 structure for this backend.
593 _PUBLIC_ NTSTATUS auth_register(const struct auth_operations *ops)
595 struct auth_operations *new_ops;
597 if (auth_backend_byname(ops->name) != NULL) {
598 /* its already registered! */
599 DEBUG(0,("AUTH backend '%s' already registered\n",
600 ops->name));
601 return NT_STATUS_OBJECT_NAME_COLLISION;
604 backends = talloc_realloc(talloc_autofree_context(), backends,
605 struct auth_backend, num_backends+1);
606 NT_STATUS_HAVE_NO_MEMORY(backends);
608 new_ops = (struct auth_operations *)talloc_memdup(backends, ops, sizeof(*ops));
609 NT_STATUS_HAVE_NO_MEMORY(new_ops);
610 new_ops->name = talloc_strdup(new_ops, ops->name);
611 NT_STATUS_HAVE_NO_MEMORY(new_ops->name);
613 backends[num_backends].ops = new_ops;
615 num_backends++;
617 DEBUG(3,("AUTH backend '%s' registered\n",
618 ops->name));
620 return NT_STATUS_OK;
624 return the operations structure for a named backend of the specified type
626 const struct auth_operations *auth_backend_byname(const char *name)
628 int i;
630 for (i=0;i<num_backends;i++) {
631 if (strcmp(backends[i].ops->name, name) == 0) {
632 return backends[i].ops;
636 return NULL;
640 return the AUTH interface version, and the size of some critical types
641 This can be used by backends to either detect compilation errors, or provide
642 multiple implementations for different smbd compilation options in one module
644 const struct auth_critical_sizes *auth_interface_version(void)
646 static const struct auth_critical_sizes critical_sizes = {
647 AUTH4_INTERFACE_VERSION,
648 sizeof(struct auth_operations),
649 sizeof(struct auth_method_context),
650 sizeof(struct auth4_context),
651 sizeof(struct auth_usersupplied_info),
652 sizeof(struct auth_user_info_dc)
655 return &critical_sizes;
658 _PUBLIC_ NTSTATUS auth4_init(void)
660 static bool initialized = false;
661 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
662 STATIC_auth4_MODULES_PROTO;
663 samba_module_init_fn static_init[] = { STATIC_auth4_MODULES };
665 if (initialized) return NT_STATUS_OK;
666 initialized = true;
668 samba_module_init_fns_run(static_init);
670 return NT_STATUS_OK;