Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : Password and authentication handling
4 : Copyright (C) Andrew Bartlett 2001-2002
5 : Copyright (C) Stefan Metzmacher 2005
6 :
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.
11 :
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.
16 :
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/>.
19 : */
20 :
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"
36 :
37 : #undef DBGC_CLASS
38 : #define DBGC_CLASS DBGC_AUTH
39 :
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);
46 :
47 : /***************************************************************************
48 : Set a fixed challenge
49 : ***************************************************************************/
50 10163 : _PUBLIC_ NTSTATUS auth_context_set_challenge(struct auth4_context *auth_ctx, const uint8_t chal[8], const char *set_by)
51 : {
52 10163 : auth_ctx->challenge.set_by = talloc_strdup(auth_ctx, set_by);
53 10163 : NT_STATUS_HAVE_NO_MEMORY(auth_ctx->challenge.set_by);
54 :
55 10163 : auth_ctx->challenge.data = data_blob_talloc(auth_ctx, chal, 8);
56 10163 : NT_STATUS_HAVE_NO_MEMORY(auth_ctx->challenge.data.data);
57 :
58 10163 : return NT_STATUS_OK;
59 : }
60 :
61 : /****************************************************************************
62 : Try to get a challenge out of the various authentication modules.
63 : Returns a const char of length 8 bytes.
64 : ****************************************************************************/
65 35128 : _PUBLIC_ NTSTATUS auth_get_challenge(struct auth4_context *auth_ctx, uint8_t chal[8])
66 : {
67 :
68 35128 : if (auth_ctx->challenge.data.length == 8) {
69 22578 : DEBUG(5, ("auth_get_challenge: returning previous challenge by module %s (normal)\n",
70 : auth_ctx->challenge.set_by));
71 22578 : memcpy(chal, auth_ctx->challenge.data.data, 8);
72 22578 : return NT_STATUS_OK;
73 : }
74 :
75 12550 : if (!auth_ctx->challenge.set_by) {
76 12550 : generate_random_buffer(chal, 8);
77 :
78 12550 : auth_ctx->challenge.data = data_blob_talloc(auth_ctx, chal, 8);
79 12550 : NT_STATUS_HAVE_NO_MEMORY(auth_ctx->challenge.data.data);
80 12550 : auth_ctx->challenge.set_by = "random";
81 : }
82 :
83 12550 : DEBUG(10,("auth_get_challenge: challenge set by %s\n",
84 : auth_ctx->challenge.set_by));
85 :
86 12550 : return NT_STATUS_OK;
87 : }
88 :
89 : /**
90 : * Check a user's Plaintext, LM or NTLM password.
91 : * (sync version)
92 : *
93 : * Check a user's password, as given in the user_info struct and return various
94 : * interesting details in the user_info_dc struct.
95 : *
96 : * The return value takes precedence over the contents of the user_info_dc
97 : * struct. When the return is other than NT_STATUS_OK the contents
98 : * of that structure is undefined.
99 : *
100 : * @param auth_ctx Supplies the challenges and some other data.
101 : * Must be created with auth_context_create(), and the challenges should be
102 : * filled in, either at creation or by calling the challenge geneation
103 : * function auth_get_challenge().
104 : *
105 : * @param user_info Contains the user supplied components, including the passwords.
106 : *
107 : * @param mem_ctx The parent memory context for the user_info_dc structure
108 : *
109 : * @param user_info_dc If successful, contains information about the authentication,
110 : * including a SAM_ACCOUNT struct describing the user.
111 : *
112 : * @return An NTSTATUS with NT_STATUS_OK or an appropriate error.
113 : *
114 : **/
115 :
116 1 : _PUBLIC_ NTSTATUS auth_check_password(struct auth4_context *auth_ctx,
117 : TALLOC_CTX *mem_ctx,
118 : const struct auth_usersupplied_info *user_info,
119 : struct auth_user_info_dc **user_info_dc,
120 : uint8_t *pauthoritative)
121 : {
122 : struct tevent_req *subreq;
123 : struct tevent_context *ev;
124 : bool ok;
125 : NTSTATUS status;
126 :
127 : /*TODO: create a new event context here! */
128 1 : ev = auth_ctx->event_ctx;
129 :
130 : /*
131 : * We are authoritative by default
132 : */
133 1 : *pauthoritative = 1;
134 :
135 1 : subreq = auth_check_password_send(mem_ctx,
136 : ev,
137 : auth_ctx,
138 : user_info);
139 1 : if (subreq == NULL) {
140 0 : return NT_STATUS_NO_MEMORY;
141 : }
142 :
143 1 : ok = tevent_req_poll(subreq, ev);
144 1 : if (!ok) {
145 0 : return NT_STATUS_INTERNAL_ERROR;
146 : }
147 :
148 1 : status = auth_check_password_recv(subreq, mem_ctx,
149 : user_info_dc, pauthoritative);
150 1 : TALLOC_FREE(subreq);
151 :
152 1 : return status;
153 : }
154 :
155 : struct auth_check_password_state {
156 : struct tevent_context *ev;
157 : struct auth4_context *auth_ctx;
158 : const struct auth_usersupplied_info *user_info;
159 : struct auth_user_info_dc *user_info_dc;
160 : struct auth_method_context *method;
161 : uint8_t authoritative;
162 : };
163 :
164 : static void auth_check_password_next(struct tevent_req *req);
165 :
166 : /**
167 : * Check a user's Plaintext, LM or NTLM password.
168 : * async send hook
169 : *
170 : * Check a user's password, as given in the user_info struct and return various
171 : * interesting details in the user_info_dc struct.
172 : *
173 : * The return value takes precedence over the contents of the user_info_dc
174 : * struct. When the return is other than NT_STATUS_OK the contents
175 : * of that structure is undefined.
176 : *
177 : * @param mem_ctx The memory context the request should operate on
178 : *
179 : * @param ev The tevent context the request should operate on
180 : *
181 : * @param auth_ctx Supplies the challenges and some other data. Must
182 : * be created with make_auth_context(), and the
183 : * challenges should be filled in, either at creation
184 : * or by calling the challenge generation function
185 : * auth_get_challenge().
186 : *
187 : * @param user_info Contains the user supplied components, including the passwords.
188 : *
189 : * @return The request handle or NULL on no memory error.
190 : *
191 : **/
192 :
193 22704 : _PUBLIC_ struct tevent_req *auth_check_password_send(TALLOC_CTX *mem_ctx,
194 : struct tevent_context *ev,
195 : struct auth4_context *auth_ctx,
196 : const struct auth_usersupplied_info *user_info)
197 : {
198 : struct tevent_req *req;
199 : struct auth_check_password_state *state;
200 : /* if all the modules say 'not for me' this is reasonable */
201 : NTSTATUS nt_status;
202 : uint8_t chal[8];
203 :
204 22704 : DEBUG(3,("auth_check_password_send: "
205 : "Checking password for unmapped user [%s]\\[%s]@[%s]\n",
206 : user_info->client.domain_name, user_info->client.account_name,
207 : user_info->workstation_name));
208 :
209 22704 : req = tevent_req_create(mem_ctx, &state,
210 : struct auth_check_password_state);
211 22704 : if (req == NULL) {
212 0 : return NULL;
213 : }
214 :
215 : /*
216 : * We are authoritative by default.
217 : */
218 22704 : state->ev = ev;
219 22704 : state->auth_ctx = auth_ctx;
220 22704 : state->user_info = user_info;
221 22704 : state->authoritative = 1;
222 :
223 22704 : if (user_info->mapped.account_name == NULL) {
224 : struct auth_usersupplied_info *user_info_tmp;
225 :
226 : /*
227 : * We don't really do any mapping here.
228 : *
229 : * It's up to the backends to do mappings
230 : * for their authentication.
231 : */
232 22703 : user_info_tmp = talloc_zero(state, struct auth_usersupplied_info);
233 22703 : if (tevent_req_nomem(user_info_tmp, req)) {
234 0 : return tevent_req_post(req, ev);;
235 : }
236 :
237 : /*
238 : * The lifetime of user_info is longer than
239 : * user_info_tmp, so we don't need to copy the
240 : * strings.
241 : */
242 22703 : *user_info_tmp = *user_info;
243 22703 : user_info_tmp->mapped.domain_name = user_info->client.domain_name;
244 22703 : user_info_tmp->mapped.account_name = user_info->client.account_name;
245 :
246 22703 : user_info = user_info_tmp;
247 22703 : state->user_info = user_info_tmp;
248 : }
249 :
250 22704 : DEBUGADD(3,("auth_check_password_send: "
251 : "user is: [%s]\\[%s]@[%s]\n",
252 : user_info->mapped.domain_name,
253 : user_info->mapped.account_name,
254 : user_info->workstation_name));
255 :
256 22704 : nt_status = auth_get_challenge(auth_ctx, chal);
257 22704 : if (tevent_req_nterror(req, nt_status)) {
258 0 : DEBUG(0,("auth_check_password_send: "
259 : "Invalid challenge (length %u) stored for "
260 : "this auth context set_by %s - cannot continue: %s\n",
261 : (unsigned)auth_ctx->challenge.data.length,
262 : auth_ctx->challenge.set_by,
263 : nt_errstr(nt_status)));
264 0 : return tevent_req_post(req, ev);
265 : }
266 :
267 22704 : if (auth_ctx->challenge.set_by) {
268 22704 : DEBUG(10,("auth_check_password_send: "
269 : "auth_context challenge created by %s\n",
270 : auth_ctx->challenge.set_by));
271 : }
272 :
273 22704 : DEBUG(10, ("auth_check_password_send: challenge is: \n"));
274 22704 : dump_data(5, auth_ctx->challenge.data.data,
275 22704 : auth_ctx->challenge.data.length);
276 :
277 22704 : state->method = state->auth_ctx->methods;
278 22704 : auth_check_password_next(req);
279 22704 : if (!tevent_req_is_in_progress(req)) {
280 10 : return tevent_req_post(req, ev);
281 : }
282 :
283 22694 : return req;
284 : }
285 :
286 : static void auth_check_password_done(struct tevent_req *subreq);
287 :
288 35861 : static void auth_check_password_next(struct tevent_req *req)
289 : {
290 : struct auth_check_password_state *state =
291 35861 : tevent_req_data(req, struct auth_check_password_state);
292 35861 : struct tevent_req *subreq = NULL;
293 : NTSTATUS status;
294 :
295 35861 : if (state->method == NULL) {
296 48 : state->authoritative = 0;
297 48 : tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER);
298 48 : return;
299 : }
300 :
301 : /* check if the module wants to check the password */
302 35813 : status = state->method->ops->want_check(state->method, state,
303 : state->user_info);
304 35813 : if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
305 12467 : DEBUG(11,("auth_check_password_send: "
306 : "%s doesn't want to check\n",
307 : state->method->ops->name));
308 12467 : state->method = state->method->next;
309 12467 : auth_check_password_next(req);
310 12467 : return;
311 : }
312 :
313 23346 : if (tevent_req_nterror(req, status)) {
314 0 : return;
315 : }
316 :
317 23346 : subreq = state->method->ops->check_password_send(
318 : state, state->ev, state->method, state->user_info);
319 23346 : if (tevent_req_nomem(subreq, req)) {
320 0 : return;
321 : }
322 23346 : tevent_req_set_callback(subreq, auth_check_password_done, req);
323 : }
324 :
325 23346 : static void auth_check_password_done(struct tevent_req *subreq)
326 : {
327 : struct tevent_req *req =
328 23346 : tevent_req_callback_data(subreq,
329 : struct tevent_req);
330 : struct auth_check_password_state *state =
331 23346 : tevent_req_data(req,
332 : struct auth_check_password_state);
333 23346 : bool authoritative = true;
334 : NTSTATUS status;
335 :
336 23346 : status = state->method->ops->check_password_recv(subreq, state,
337 : &state->user_info_dc,
338 : &authoritative);
339 23346 : TALLOC_FREE(subreq);
340 23346 : if (!authoritative ||
341 22781 : NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
342 690 : DEBUG(11,("auth_check_password_send: "
343 : "%s passes to the next method\n",
344 : state->method->ops->name));
345 690 : state->method = state->method->next;
346 690 : auth_check_password_next(req);
347 690 : return;
348 : }
349 :
350 : /* the backend has handled the request */
351 :
352 22656 : if (tevent_req_nterror(req, status)) {
353 4380 : return;
354 : }
355 :
356 18276 : tevent_req_done(req);
357 : }
358 :
359 : /**
360 : * Check a user's Plaintext, LM or NTLM password.
361 : * async receive function
362 : *
363 : * The return value takes precedence over the contents of the user_info_dc
364 : * struct. When the return is other than NT_STATUS_OK the contents
365 : * of that structure is undefined.
366 : *
367 : *
368 : * @param req The async request state
369 : *
370 : * @param mem_ctx The parent memory context for the user_info_dc structure
371 : *
372 : * @param user_info_dc If successful, contains information about the authentication,
373 : * including a SAM_ACCOUNT struct describing the user.
374 : *
375 : * @return An NTSTATUS with NT_STATUS_OK or an appropriate error.
376 : *
377 : **/
378 :
379 22704 : _PUBLIC_ NTSTATUS auth_check_password_recv(struct tevent_req *req,
380 : TALLOC_CTX *mem_ctx,
381 : struct auth_user_info_dc **user_info_dc,
382 : uint8_t *pauthoritative)
383 : {
384 : struct auth_check_password_state *state =
385 22704 : tevent_req_data(req, struct auth_check_password_state);
386 22704 : NTSTATUS status = NT_STATUS_OK;
387 :
388 22704 : *pauthoritative = state->authoritative;
389 :
390 22704 : if (tevent_req_is_nterror(req, &status)) {
391 : /*
392 : * Please try not to change this string, it is probably in use
393 : * in audit logging tools
394 : */
395 4428 : DEBUG(2,("auth_check_password_recv: "
396 : "%s authentication for user [%s\\%s] "
397 : "FAILED with error %s, authoritative=%u\n",
398 : (state->method ? state->method->ops->name : "NO_METHOD"),
399 : state->user_info->mapped.domain_name,
400 : state->user_info->mapped.account_name,
401 : nt_errstr(status), state->authoritative));
402 :
403 4428 : log_authentication_event(state->auth_ctx->msg_ctx,
404 4428 : state->auth_ctx->lp_ctx,
405 4428 : &state->auth_ctx->start_time,
406 : state->user_info, status,
407 : NULL, NULL, NULL);
408 4428 : tevent_req_received(req);
409 4428 : return status;
410 : }
411 :
412 18276 : DEBUG(5,("auth_check_password_recv: "
413 : "%s authentication for user [%s\\%s] succeeded\n",
414 : state->method->ops->name,
415 : state->user_info_dc->info->domain_name,
416 : state->user_info_dc->info->account_name));
417 :
418 18276 : log_authentication_event(state->auth_ctx->msg_ctx,
419 18276 : state->auth_ctx->lp_ctx,
420 18276 : &state->auth_ctx->start_time,
421 : state->user_info, status,
422 18276 : state->user_info_dc->info->domain_name,
423 18276 : state->user_info_dc->info->account_name,
424 18276 : &state->user_info_dc->sids[0]);
425 :
426 18276 : *user_info_dc = talloc_move(mem_ctx, &state->user_info_dc);
427 :
428 18276 : tevent_req_received(req);
429 18276 : return NT_STATUS_OK;
430 : }
431 :
432 : struct auth_check_password_wrapper_state {
433 : uint8_t authoritative;
434 : struct auth_user_info_dc *user_info_dc;
435 : };
436 :
437 : static void auth_check_password_wrapper_done(struct tevent_req *subreq);
438 :
439 11603 : static struct tevent_req *auth_check_password_wrapper_send(TALLOC_CTX *mem_ctx,
440 : struct tevent_context *ev,
441 : struct auth4_context *auth_ctx,
442 : const struct auth_usersupplied_info *user_info)
443 : {
444 11603 : struct tevent_req *req = NULL;
445 11603 : struct auth_check_password_wrapper *state = NULL;
446 11603 : struct tevent_req *subreq = NULL;
447 :
448 11603 : req = tevent_req_create(mem_ctx, &state,
449 : struct auth_check_password_wrapper_state);
450 11603 : if (req == NULL) {
451 0 : return NULL;
452 : }
453 :
454 11603 : subreq = auth_check_password_send(state, ev, auth_ctx, user_info);
455 11603 : if (tevent_req_nomem(subreq, req)) {
456 0 : return tevent_req_post(req, ev);
457 : }
458 11603 : tevent_req_set_callback(subreq,
459 : auth_check_password_wrapper_done,
460 : req);
461 :
462 11603 : return req;
463 : }
464 :
465 11603 : static void auth_check_password_wrapper_done(struct tevent_req *subreq)
466 : {
467 : struct tevent_req *req =
468 11603 : tevent_req_callback_data(subreq,
469 : struct tevent_req);
470 : struct auth_check_password_wrapper_state *state =
471 11603 : tevent_req_data(req,
472 : struct auth_check_password_wrapper_state);
473 : NTSTATUS status;
474 :
475 11603 : status = auth_check_password_recv(subreq, state,
476 : &state->user_info_dc,
477 : &state->authoritative);
478 11603 : TALLOC_FREE(subreq);
479 11603 : if (tevent_req_nterror(req, status)) {
480 680 : return;
481 : }
482 :
483 10923 : tevent_req_done(req);
484 : }
485 :
486 11603 : static NTSTATUS auth_check_password_wrapper_recv(struct tevent_req *req,
487 : TALLOC_CTX *mem_ctx,
488 : uint8_t *pauthoritative,
489 : void **server_returned_info,
490 : DATA_BLOB *user_session_key,
491 : DATA_BLOB *lm_session_key)
492 : {
493 : struct auth_check_password_wrapper_state *state =
494 11603 : tevent_req_data(req,
495 : struct auth_check_password_wrapper_state);
496 11603 : struct auth_user_info_dc *user_info_dc = state->user_info_dc;
497 11603 : NTSTATUS status = NT_STATUS_OK;
498 :
499 11603 : *pauthoritative = state->authoritative;
500 :
501 11603 : if (tevent_req_is_nterror(req, &status)) {
502 680 : tevent_req_received(req);
503 680 : return status;
504 : }
505 :
506 10923 : talloc_steal(mem_ctx, user_info_dc);
507 10923 : *server_returned_info = user_info_dc;
508 :
509 10923 : if (user_session_key) {
510 10923 : DEBUG(10, ("Got NT session key of length %u\n",
511 : (unsigned)user_info_dc->user_session_key.length));
512 10923 : *user_session_key = user_info_dc->user_session_key;
513 10923 : talloc_steal(mem_ctx, user_session_key->data);
514 10923 : user_info_dc->user_session_key = data_blob_null;
515 : }
516 :
517 10923 : if (lm_session_key) {
518 10923 : DEBUG(10, ("Got LM session key of length %u\n",
519 : (unsigned)user_info_dc->lm_session_key.length));
520 10923 : *lm_session_key = user_info_dc->lm_session_key;
521 10923 : talloc_steal(mem_ctx, lm_session_key->data);
522 10923 : user_info_dc->lm_session_key = data_blob_null;
523 : }
524 :
525 10923 : tevent_req_received(req);
526 10923 : return NT_STATUS_OK;
527 : }
528 :
529 : /* Wrapper because we don't want to expose all callers to needing to
530 : * know that session_info is generated from the main ldb, and because
531 : * we need to break a depenency loop between the DCE/RPC layer and the
532 : * generation of unix tokens via IRPC */
533 34968 : static NTSTATUS auth_generate_session_info_wrapper(struct auth4_context *auth_context,
534 : TALLOC_CTX *mem_ctx,
535 : void *server_returned_info,
536 : const char *original_user_name,
537 : uint32_t session_info_flags,
538 : struct auth_session_info **session_info)
539 : {
540 : NTSTATUS status;
541 34968 : struct auth_user_info_dc *user_info_dc = talloc_get_type_abort(server_returned_info, struct auth_user_info_dc);
542 :
543 34968 : if (user_info_dc->info->authenticated) {
544 33519 : session_info_flags |= AUTH_SESSION_INFO_AUTHENTICATED;
545 : }
546 :
547 34968 : status = auth_generate_session_info(mem_ctx, auth_context->lp_ctx,
548 : auth_context->sam_ctx, user_info_dc,
549 : session_info_flags, session_info);
550 34968 : if (!NT_STATUS_IS_OK(status)) {
551 0 : return status;
552 : }
553 :
554 34968 : if ((session_info_flags & AUTH_SESSION_INFO_UNIX_TOKEN)
555 3670 : && NT_STATUS_IS_OK(status)) {
556 3670 : status = auth_session_info_fill_unix(auth_context->lp_ctx,
557 : original_user_name,
558 : *session_info);
559 3670 : if (!NT_STATUS_IS_OK(status)) {
560 0 : TALLOC_FREE(*session_info);
561 : }
562 : }
563 34968 : return status;
564 : }
565 :
566 : /* Wrapper because we don't want to expose all callers to needing to
567 : * know anything about the PAC or auth subsystem internal structures
568 : * before we output a struct auth session_info */
569 22258 : static NTSTATUS auth_generate_session_info_pac(struct auth4_context *auth_ctx,
570 : TALLOC_CTX *mem_ctx,
571 : struct smb_krb5_context *smb_krb5_context,
572 : DATA_BLOB *pac_blob,
573 : const char *principal_name,
574 : const struct tsocket_address *remote_address,
575 : uint32_t session_info_flags,
576 : struct auth_session_info **session_info)
577 : {
578 : NTSTATUS status;
579 : struct auth_user_info_dc *user_info_dc;
580 : TALLOC_CTX *tmp_ctx;
581 :
582 22258 : if (!pac_blob) {
583 : /*
584 : * This should already be catched at the main
585 : * gensec layer, but better check twice
586 : */
587 0 : return NT_STATUS_INTERNAL_ERROR;
588 : }
589 :
590 22258 : tmp_ctx = talloc_named(mem_ctx, 0, "gensec_gssapi_session_info context");
591 22258 : NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
592 :
593 22258 : status = kerberos_pac_blob_to_user_info_dc(tmp_ctx,
594 : *pac_blob,
595 : smb_krb5_context->krb5_context,
596 : &user_info_dc, NULL, NULL);
597 22258 : if (!NT_STATUS_IS_OK(status)) {
598 0 : talloc_free(tmp_ctx);
599 0 : return status;
600 : }
601 :
602 22258 : if (user_info_dc->info->authenticated) {
603 22258 : session_info_flags |= AUTH_SESSION_INFO_AUTHENTICATED;
604 : }
605 :
606 22258 : status = auth_generate_session_info_wrapper(auth_ctx, mem_ctx,
607 : user_info_dc,
608 22258 : user_info_dc->info->account_name,
609 : session_info_flags, session_info);
610 22258 : talloc_free(tmp_ctx);
611 22258 : return status;
612 : }
613 :
614 : /***************************************************************************
615 : Make a auth_info struct for the auth subsystem
616 : - Allow the caller to specify the methods to use, including optionally the SAM to use
617 : ***************************************************************************/
618 99429 : _PUBLIC_ NTSTATUS auth_context_create_methods(TALLOC_CTX *mem_ctx, const char * const *methods,
619 : struct tevent_context *ev,
620 : struct imessaging_context *msg,
621 : struct loadparm_context *lp_ctx,
622 : struct ldb_context *sam_ctx,
623 : struct auth4_context **auth_ctx)
624 : {
625 : int i;
626 : struct auth4_context *ctx;
627 :
628 99429 : auth4_init();
629 :
630 99429 : if (!ev) {
631 0 : DEBUG(0,("auth_context_create: called with out event context\n"));
632 0 : return NT_STATUS_INTERNAL_ERROR;
633 : }
634 :
635 99429 : ctx = talloc_zero(mem_ctx, struct auth4_context);
636 99429 : NT_STATUS_HAVE_NO_MEMORY(ctx);
637 99429 : ctx->challenge.data = data_blob(NULL, 0);
638 99429 : ctx->methods = NULL;
639 99429 : ctx->event_ctx = ev;
640 99429 : ctx->msg_ctx = msg;
641 99429 : ctx->lp_ctx = lp_ctx;
642 99429 : ctx->start_time = timeval_current();
643 :
644 99429 : if (sam_ctx) {
645 5 : ctx->sam_ctx = sam_ctx;
646 : } else {
647 99424 : ctx->sam_ctx = samdb_connect(ctx,
648 : ctx->event_ctx,
649 : ctx->lp_ctx,
650 : system_session(ctx->lp_ctx),
651 : NULL,
652 : 0);
653 : }
654 :
655 475697 : for (i=0; methods && methods[i] ; i++) {
656 : struct auth_method_context *method;
657 :
658 376268 : method = talloc(ctx, struct auth_method_context);
659 376268 : NT_STATUS_HAVE_NO_MEMORY(method);
660 :
661 376268 : method->ops = auth_backend_byname(methods[i]);
662 376268 : if (!method->ops) {
663 0 : DEBUG(1,("auth_context_create: failed to find method=%s\n",
664 : methods[i]));
665 0 : return NT_STATUS_INTERNAL_ERROR;
666 : }
667 376268 : method->auth_ctx = ctx;
668 376268 : method->depth = i;
669 376268 : DLIST_ADD_END(ctx->methods, method);
670 : }
671 :
672 99429 : ctx->check_ntlm_password_send = auth_check_password_wrapper_send;
673 99429 : ctx->check_ntlm_password_recv = auth_check_password_wrapper_recv;
674 99429 : ctx->get_ntlm_challenge = auth_get_challenge;
675 99429 : ctx->set_ntlm_challenge = auth_context_set_challenge;
676 99429 : ctx->generate_session_info = auth_generate_session_info_wrapper;
677 99429 : ctx->generate_session_info_pac = auth_generate_session_info_pac;
678 :
679 99429 : *auth_ctx = ctx;
680 :
681 99429 : return NT_STATUS_OK;
682 : }
683 :
684 88714 : const char **auth_methods_from_lp(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx)
685 : {
686 88714 : char **auth_methods = NULL;
687 :
688 88714 : switch (lpcfg_server_role(lp_ctx)) {
689 4 : case ROLE_STANDALONE:
690 4 : auth_methods = str_list_make(mem_ctx, "anonymous sam_ignoredomain", NULL);
691 4 : break;
692 88710 : case ROLE_DOMAIN_MEMBER:
693 : case ROLE_DOMAIN_BDC:
694 : case ROLE_DOMAIN_PDC:
695 : case ROLE_ACTIVE_DIRECTORY_DC:
696 : case ROLE_IPA_DC:
697 88710 : auth_methods = str_list_make(mem_ctx, "anonymous sam winbind sam_ignoredomain", NULL);
698 88710 : break;
699 : }
700 88714 : return discard_const_p(const char *, auth_methods);
701 : }
702 :
703 : /***************************************************************************
704 : Make a auth_info struct for the auth subsystem
705 : - Uses default auth_methods, depending on server role and smb.conf settings
706 : ***************************************************************************/
707 88714 : _PUBLIC_ NTSTATUS auth_context_create(TALLOC_CTX *mem_ctx,
708 : struct tevent_context *ev,
709 : struct imessaging_context *msg,
710 : struct loadparm_context *lp_ctx,
711 : struct auth4_context **auth_ctx)
712 : {
713 : NTSTATUS status;
714 : const char **auth_methods;
715 88714 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
716 88714 : if (!tmp_ctx) {
717 0 : return NT_STATUS_NO_MEMORY;
718 : }
719 :
720 88714 : auth_methods = auth_methods_from_lp(tmp_ctx, lp_ctx);
721 88714 : if (!auth_methods) {
722 0 : return NT_STATUS_INVALID_PARAMETER;
723 : }
724 88714 : status = auth_context_create_methods(mem_ctx, auth_methods, ev, msg, lp_ctx, NULL, auth_ctx);
725 88714 : talloc_free(tmp_ctx);
726 88714 : return status;
727 : }
728 :
729 10710 : _PUBLIC_ NTSTATUS auth_context_create_for_netlogon(TALLOC_CTX *mem_ctx,
730 : struct tevent_context *ev,
731 : struct imessaging_context *msg,
732 : struct loadparm_context *lp_ctx,
733 : struct auth4_context **auth_ctx)
734 : {
735 : NTSTATUS status;
736 10710 : char **_auth_methods = NULL;
737 10710 : const char **auth_methods = NULL;
738 :
739 : /*
740 : * Here we only allow 'sam winbind' instead of
741 : * the 'anonymous sam winbind sam_ignoredomain'
742 : * we typically use for authentication from clients.
743 : */
744 10710 : _auth_methods = str_list_make(mem_ctx, "sam winbind", NULL);
745 10710 : if (_auth_methods == NULL) {
746 0 : return NT_STATUS_NO_MEMORY;
747 : }
748 10710 : auth_methods = discard_const_p(const char *, _auth_methods);
749 :
750 10710 : status = auth_context_create_methods(mem_ctx, auth_methods, ev, msg,
751 : lp_ctx, NULL, auth_ctx);
752 10710 : talloc_free(_auth_methods);
753 10710 : return status;
754 : }
755 :
756 : /* the list of currently registered AUTH backends */
757 : static struct auth_backend {
758 : const struct auth_operations *ops;
759 : } *backends = NULL;
760 : static int num_backends;
761 :
762 : /*
763 : register a AUTH backend.
764 :
765 : The 'name' can be later used by other backends to find the operations
766 : structure for this backend.
767 : */
768 18865 : _PUBLIC_ NTSTATUS auth_register(TALLOC_CTX *mem_ctx,
769 : const struct auth_operations *ops)
770 : {
771 : struct auth_operations *new_ops;
772 :
773 18865 : if (auth_backend_byname(ops->name) != NULL) {
774 : /* its already registered! */
775 0 : DEBUG(0,("AUTH backend '%s' already registered\n",
776 : ops->name));
777 0 : return NT_STATUS_OBJECT_NAME_COLLISION;
778 : }
779 :
780 18865 : backends = talloc_realloc(mem_ctx, backends,
781 : struct auth_backend, num_backends+1);
782 18865 : NT_STATUS_HAVE_NO_MEMORY(backends);
783 :
784 18865 : new_ops = (struct auth_operations *)talloc_memdup(backends, ops, sizeof(*ops));
785 18865 : NT_STATUS_HAVE_NO_MEMORY(new_ops);
786 18865 : new_ops->name = talloc_strdup(new_ops, ops->name);
787 18865 : NT_STATUS_HAVE_NO_MEMORY(new_ops->name);
788 :
789 18865 : backends[num_backends].ops = new_ops;
790 :
791 18865 : num_backends++;
792 :
793 18865 : DEBUG(3,("AUTH backend '%s' registered\n",
794 : ops->name));
795 :
796 18865 : return NT_STATUS_OK;
797 : }
798 :
799 : /*
800 : return the operations structure for a named backend of the specified type
801 : */
802 395133 : const struct auth_operations *auth_backend_byname(const char *name)
803 : {
804 : int i;
805 :
806 997265 : for (i=0;i<num_backends;i++) {
807 978400 : if (strcmp(backends[i].ops->name, name) == 0) {
808 376268 : return backends[i].ops;
809 : }
810 : }
811 :
812 18865 : return NULL;
813 : }
814 :
815 : /*
816 : return the AUTH interface version, and the size of some critical types
817 : This can be used by backends to either detect compilation errors, or provide
818 : multiple implementations for different smbd compilation options in one module
819 : */
820 0 : const struct auth_critical_sizes *auth_interface_version(void)
821 : {
822 : static const struct auth_critical_sizes critical_sizes = {
823 : AUTH4_INTERFACE_VERSION,
824 : sizeof(struct auth_operations),
825 : sizeof(struct auth_method_context),
826 : sizeof(struct auth4_context),
827 : sizeof(struct auth_usersupplied_info),
828 : sizeof(struct auth_user_info_dc)
829 : };
830 :
831 0 : return &critical_sizes;
832 : }
833 :
834 99484 : _PUBLIC_ NTSTATUS auth4_init(void)
835 : {
836 : static bool initialized = false;
837 : #define _MODULE_PROTO(init) extern NTSTATUS init(TALLOC_CTX *);
838 : STATIC_auth4_MODULES_PROTO;
839 99484 : init_module_fn static_init[] = { STATIC_auth4_MODULES };
840 :
841 99484 : if (initialized) return NT_STATUS_OK;
842 3773 : initialized = true;
843 :
844 3773 : run_init_functions(NULL, static_init);
845 :
846 3773 : return NT_STATUS_OK;
847 : }
|