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