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