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