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