auth: Generate a human readable Authentication log message.
[nivanova/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 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->user_info, status,
453                                          NULL, NULL, NULL, NULL);
454                 tevent_req_received(req);
455                 return status;
456         }
457
458         DEBUG(5,("auth_check_password_recv: "
459                  "%s authentication for user [%s\\%s] succeeded\n",
460                  state->method->ops->name,
461                  state->user_info_dc->info->domain_name,
462                  state->user_info_dc->info->account_name));
463
464         log_authentication_event(state->user_info, status,
465                                  state->user_info_dc->info->domain_name,
466                                  state->user_info_dc->info->account_name,
467                                  NULL,
468                                  &state->user_info_dc->sids[0]);
469
470         *user_info_dc = talloc_move(mem_ctx, &state->user_info_dc);
471
472         tevent_req_received(req);
473         return NT_STATUS_OK;
474 }
475
476  /* Wrapper because we don't want to expose all callers to needing to
477   * know that session_info is generated from the main ldb, and because
478   * we need to break a depenency loop between the DCE/RPC layer and the
479   * generation of unix tokens via IRPC */
480 static NTSTATUS auth_generate_session_info_wrapper(struct auth4_context *auth_context,
481                                                    TALLOC_CTX *mem_ctx,
482                                                    void *server_returned_info,
483                                                    const char *original_user_name,
484                                                   uint32_t session_info_flags,
485                                                   struct auth_session_info **session_info)
486 {
487         NTSTATUS status;
488         struct auth_user_info_dc *user_info_dc = talloc_get_type_abort(server_returned_info, struct auth_user_info_dc);
489
490         if (user_info_dc->info->authenticated) {
491                 session_info_flags |= AUTH_SESSION_INFO_AUTHENTICATED;
492         }
493
494         status = auth_generate_session_info(mem_ctx, auth_context->lp_ctx,
495                                             auth_context->sam_ctx, user_info_dc,
496                                             session_info_flags, session_info);
497         if (!NT_STATUS_IS_OK(status)) {
498                 return status;
499         }
500
501         if ((session_info_flags & AUTH_SESSION_INFO_UNIX_TOKEN)
502             && NT_STATUS_IS_OK(status)) {
503                 status = auth_session_info_fill_unix(auth_context->event_ctx,
504                                                      auth_context->lp_ctx,
505                                                      original_user_name, *session_info);
506                 if (!NT_STATUS_IS_OK(status)) {
507                         TALLOC_FREE(*session_info);
508                 }
509         }
510         return status;
511 }
512
513 /* Wrapper because we don't want to expose all callers to needing to
514  * know anything about the PAC or auth subsystem internal structures
515  * before we output a struct auth session_info */
516 static NTSTATUS auth_generate_session_info_pac(struct auth4_context *auth_ctx,
517                                                TALLOC_CTX *mem_ctx,
518                                                struct smb_krb5_context *smb_krb5_context,
519                                                DATA_BLOB *pac_blob,
520                                                const char *principal_name,
521                                                const struct tsocket_address *remote_address,
522                                                uint32_t session_info_flags,
523                                                struct auth_session_info **session_info)
524 {
525         NTSTATUS status;
526         struct auth_user_info_dc *user_info_dc;
527         TALLOC_CTX *tmp_ctx;
528
529         if (!pac_blob) {
530                 return auth_generate_session_info_principal(auth_ctx, mem_ctx, principal_name,
531                                                        NULL, session_info_flags, session_info);
532         }
533
534         tmp_ctx = talloc_named(mem_ctx, 0, "gensec_gssapi_session_info context");
535         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
536
537         status = kerberos_pac_blob_to_user_info_dc(tmp_ctx,
538                                                    *pac_blob,
539                                                    smb_krb5_context->krb5_context,
540                                                    &user_info_dc, NULL, NULL);
541         if (!NT_STATUS_IS_OK(status)) {
542                 talloc_free(tmp_ctx);
543                 return status;
544         }
545
546         if (user_info_dc->info->authenticated) {
547                 session_info_flags |= AUTH_SESSION_INFO_AUTHENTICATED;
548         }
549
550         status = auth_generate_session_info_wrapper(auth_ctx, mem_ctx, 
551                                                     user_info_dc,
552                                                     user_info_dc->info->account_name,
553                                                     session_info_flags, session_info);
554         talloc_free(tmp_ctx);
555         return status;
556 }
557
558 /***************************************************************************
559  Make a auth_info struct for the auth subsystem
560  - Allow the caller to specify the methods to use, including optionally the SAM to use
561 ***************************************************************************/
562 _PUBLIC_ NTSTATUS auth_context_create_methods(TALLOC_CTX *mem_ctx, const char * const *methods, 
563                                               struct tevent_context *ev,
564                                               struct imessaging_context *msg,
565                                               struct loadparm_context *lp_ctx,
566                                               struct ldb_context *sam_ctx,
567                                               struct auth4_context **auth_ctx)
568 {
569         int i;
570         struct auth4_context *ctx;
571
572         auth4_init();
573
574         if (!ev) {
575                 DEBUG(0,("auth_context_create: called with out event context\n"));
576                 return NT_STATUS_INTERNAL_ERROR;
577         }
578
579         ctx = talloc_zero(mem_ctx, struct auth4_context);
580         NT_STATUS_HAVE_NO_MEMORY(ctx);
581         ctx->challenge.data             = data_blob(NULL, 0);
582         ctx->methods                    = NULL;
583         ctx->event_ctx                  = ev;
584         ctx->msg_ctx                    = msg;
585         ctx->lp_ctx                     = lp_ctx;
586
587         if (sam_ctx) {
588                 ctx->sam_ctx = sam_ctx;
589         } else {
590                 ctx->sam_ctx = samdb_connect(ctx, ctx->event_ctx, ctx->lp_ctx, system_session(ctx->lp_ctx), 0);
591         }
592
593         for (i=0; methods && methods[i] ; i++) {
594                 struct auth_method_context *method;
595
596                 method = talloc(ctx, struct auth_method_context);
597                 NT_STATUS_HAVE_NO_MEMORY(method);
598
599                 method->ops = auth_backend_byname(methods[i]);
600                 if (!method->ops) {
601                         DEBUG(1,("auth_context_create: failed to find method=%s\n",
602                                 methods[i]));
603                         return NT_STATUS_INTERNAL_ERROR;
604                 }
605                 method->auth_ctx        = ctx;
606                 method->depth           = i;
607                 DLIST_ADD_END(ctx->methods, method);
608         }
609
610         ctx->check_ntlm_password = auth_check_password_wrapper;
611         ctx->get_ntlm_challenge = auth_get_challenge;
612         ctx->set_ntlm_challenge = auth_context_set_challenge;
613         ctx->generate_session_info = auth_generate_session_info_wrapper;
614         ctx->generate_session_info_pac = auth_generate_session_info_pac;
615
616         *auth_ctx = ctx;
617
618         return NT_STATUS_OK;
619 }
620
621 const char **auth_methods_from_lp(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx)
622 {
623         char **auth_methods = NULL;
624         const char **const_auth_methods = NULL;
625
626         /*
627          * As 'auth methods' is deprecated it will be removed
628          * in future releases again, but for now give
629          * admins the flexibility to configure, the behavior
630          * from Samba 4.6: "auth methods = anonymous sam_ignoredomain",
631          * for a while.
632          */
633         const_auth_methods = lpcfg_auth_methods(lp_ctx);
634         if (const_auth_methods != NULL) {
635                 DBG_NOTICE("using deprecated 'auth methods' values.\n");
636                 return const_auth_methods;
637         }
638
639         switch (lpcfg_server_role(lp_ctx)) {
640         case ROLE_STANDALONE:
641                 auth_methods = str_list_make(mem_ctx, "anonymous sam_ignoredomain", NULL);
642                 break;
643         case ROLE_DOMAIN_MEMBER:
644                 auth_methods = str_list_make(mem_ctx, "anonymous sam winbind", NULL);
645                 break;
646         case ROLE_DOMAIN_BDC:
647         case ROLE_DOMAIN_PDC:
648         case ROLE_ACTIVE_DIRECTORY_DC:
649                 auth_methods = str_list_make(mem_ctx, "anonymous sam_ignoredomain winbind_rodc", NULL);
650                 break;
651         }
652         return discard_const_p(const char *, auth_methods);
653 }
654
655 /***************************************************************************
656  Make a auth_info struct for the auth subsystem
657  - Uses default auth_methods, depending on server role and smb.conf settings
658 ***************************************************************************/
659 _PUBLIC_ NTSTATUS auth_context_create(TALLOC_CTX *mem_ctx,
660                              struct tevent_context *ev,
661                              struct imessaging_context *msg,
662                              struct loadparm_context *lp_ctx,
663                              struct auth4_context **auth_ctx)
664 {
665         NTSTATUS status;
666         const char **auth_methods;
667         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
668         if (!tmp_ctx) {
669                 return NT_STATUS_NO_MEMORY;
670         }
671
672         auth_methods = auth_methods_from_lp(tmp_ctx, lp_ctx);
673         if (!auth_methods) {
674                 return NT_STATUS_INVALID_PARAMETER;
675         }
676         status = auth_context_create_methods(mem_ctx, auth_methods, ev, msg, lp_ctx, NULL, auth_ctx);
677         talloc_free(tmp_ctx);
678         return status;
679 }
680
681 _PUBLIC_ NTSTATUS auth_context_create_for_netlogon(TALLOC_CTX *mem_ctx,
682                                                    struct tevent_context *ev,
683                                                    struct imessaging_context *msg,
684                                                    struct loadparm_context *lp_ctx,
685                                                    struct auth4_context **auth_ctx)
686 {
687         return auth_context_create(mem_ctx, ev, msg, lp_ctx, auth_ctx);
688 }
689
690 /* the list of currently registered AUTH backends */
691 static struct auth_backend {
692         const struct auth_operations *ops;
693 } *backends = NULL;
694 static int num_backends;
695
696 /*
697   register a AUTH backend. 
698
699   The 'name' can be later used by other backends to find the operations
700   structure for this backend.
701 */
702 _PUBLIC_ NTSTATUS auth_register(const struct auth_operations *ops)
703 {
704         struct auth_operations *new_ops;
705         
706         if (auth_backend_byname(ops->name) != NULL) {
707                 /* its already registered! */
708                 DEBUG(0,("AUTH backend '%s' already registered\n", 
709                          ops->name));
710                 return NT_STATUS_OBJECT_NAME_COLLISION;
711         }
712
713         backends = talloc_realloc(talloc_autofree_context(), backends, 
714                                   struct auth_backend, num_backends+1);
715         NT_STATUS_HAVE_NO_MEMORY(backends);
716
717         new_ops = (struct auth_operations *)talloc_memdup(backends, ops, sizeof(*ops));
718         NT_STATUS_HAVE_NO_MEMORY(new_ops);
719         new_ops->name = talloc_strdup(new_ops, ops->name);
720         NT_STATUS_HAVE_NO_MEMORY(new_ops->name);
721
722         backends[num_backends].ops = new_ops;
723
724         num_backends++;
725
726         DEBUG(3,("AUTH backend '%s' registered\n", 
727                  ops->name));
728
729         return NT_STATUS_OK;
730 }
731
732 /*
733   return the operations structure for a named backend of the specified type
734 */
735 const struct auth_operations *auth_backend_byname(const char *name)
736 {
737         int i;
738
739         for (i=0;i<num_backends;i++) {
740                 if (strcmp(backends[i].ops->name, name) == 0) {
741                         return backends[i].ops;
742                 }
743         }
744
745         return NULL;
746 }
747
748 /*
749   return the AUTH interface version, and the size of some critical types
750   This can be used by backends to either detect compilation errors, or provide
751   multiple implementations for different smbd compilation options in one module
752 */
753 const struct auth_critical_sizes *auth_interface_version(void)
754 {
755         static const struct auth_critical_sizes critical_sizes = {
756                 AUTH4_INTERFACE_VERSION,
757                 sizeof(struct auth_operations),
758                 sizeof(struct auth_method_context),
759                 sizeof(struct auth4_context),
760                 sizeof(struct auth_usersupplied_info),
761                 sizeof(struct auth_user_info_dc)
762         };
763
764         return &critical_sizes;
765 }
766
767 _PUBLIC_ NTSTATUS auth4_init(void)
768 {
769         static bool initialized = false;
770 #define _MODULE_PROTO(init) extern NTSTATUS init(void);
771         STATIC_auth4_MODULES_PROTO;
772         init_module_fn static_init[] = { STATIC_auth4_MODULES };
773         
774         if (initialized) return NT_STATUS_OK;
775         initialized = true;
776         
777         run_init_functions(static_init);
778         
779         return NT_STATUS_OK;    
780 }