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