r23792: convert Samba4 to GPLv3
[samba.git] / source4 / auth / 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 "lib/util/dlinklist.h"
23 #include "auth/auth.h"
24 #include "lib/events/events.h"
25 #include "build.h"
26
27 /***************************************************************************
28  Set a fixed challenge
29 ***************************************************************************/
30 NTSTATUS auth_context_set_challenge(struct auth_context *auth_ctx, const uint8_t chal[8], const char *set_by) 
31 {
32         auth_ctx->challenge.set_by = talloc_strdup(auth_ctx, set_by);
33         NT_STATUS_HAVE_NO_MEMORY(auth_ctx->challenge.set_by);
34
35         auth_ctx->challenge.data = data_blob_talloc(auth_ctx, chal, 8);
36         NT_STATUS_HAVE_NO_MEMORY(auth_ctx->challenge.data.data);
37
38         return NT_STATUS_OK;
39 }
40
41 /***************************************************************************
42  Set a fixed challenge
43 ***************************************************************************/
44 BOOL auth_challenge_may_be_modified(struct auth_context *auth_ctx) 
45 {
46         return auth_ctx->challenge.may_be_modified;
47 }
48
49 /****************************************************************************
50  Try to get a challenge out of the various authentication modules.
51  Returns a const char of length 8 bytes.
52 ****************************************************************************/
53 _PUBLIC_ NTSTATUS auth_get_challenge(struct auth_context *auth_ctx, const uint8_t **_chal)
54 {
55         NTSTATUS nt_status;
56         struct auth_method_context *method;
57
58         if (auth_ctx->challenge.data.length) {
59                 DEBUG(5, ("auth_get_challenge: returning previous challenge by module %s (normal)\n", 
60                           auth_ctx->challenge.set_by));
61                 *_chal = auth_ctx->challenge.data.data;
62                 return NT_STATUS_OK;
63         }
64
65         for (method = auth_ctx->methods; method; method = method->next) {
66                 DATA_BLOB challenge = data_blob(NULL,0);
67
68                 nt_status = method->ops->get_challenge(method, auth_ctx, &challenge);
69                 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NOT_IMPLEMENTED)) {
70                         continue;
71                 }
72
73                 NT_STATUS_NOT_OK_RETURN(nt_status);
74
75                 if (challenge.length != 8) {
76                         DEBUG(0, ("auth_get_challenge: invalid challenge (length %u) by mothod [%s]\n",
77                                 (unsigned)challenge.length, method->ops->name));
78                         return NT_STATUS_INTERNAL_ERROR;
79                 }
80
81                 auth_ctx->challenge.data        = challenge;
82                 auth_ctx->challenge.set_by      = method->ops->name;
83
84                 break;
85         }
86
87         if (!auth_ctx->challenge.set_by) {
88                 uint8_t chal[8];
89                 generate_random_buffer(chal, 8);
90
91                 auth_ctx->challenge.data                = data_blob_talloc(auth_ctx, chal, 8);
92                 NT_STATUS_HAVE_NO_MEMORY(auth_ctx->challenge.data.data);
93                 auth_ctx->challenge.set_by              = "random";
94
95                 auth_ctx->challenge.may_be_modified     = True;
96         }
97
98         DEBUG(10,("auth_get_challenge: challenge set by %s\n",
99                  auth_ctx->challenge.set_by));
100
101         *_chal = auth_ctx->challenge.data.data;
102         return NT_STATUS_OK;
103 }
104
105 struct auth_check_password_sync_state {
106         BOOL finished;
107         NTSTATUS status;
108         struct auth_serversupplied_info *server_info;
109 };
110
111 static void auth_check_password_sync_callback(struct auth_check_password_request *req,
112                                               void *private_data)
113 {
114         struct auth_check_password_sync_state *s = talloc_get_type(private_data,
115                                                    struct auth_check_password_sync_state);
116
117         s->finished = True;
118         s->status = auth_check_password_recv(req, s, &s->server_info);
119 }
120
121 /**
122  * Check a user's Plaintext, LM or NTLM password.
123  * (sync version)
124  *
125  * Check a user's password, as given in the user_info struct and return various
126  * interesting details in the server_info struct.
127  *
128  * The return value takes precedence over the contents of the server_info 
129  * struct.  When the return is other than NT_STATUS_OK the contents 
130  * of that structure is undefined.
131  *
132  * @param auth_ctx Supplies the challenges and some other data. 
133  *                  Must be created with auth_context_create(), and the challenges should be 
134  *                  filled in, either at creation or by calling the challenge geneation 
135  *                  function auth_get_challenge().  
136  *
137  * @param user_info Contains the user supplied components, including the passwords.
138  *
139  * @param mem_ctx The parent memory context for the server_info structure
140  *
141  * @param server_info If successful, contains information about the authentication, 
142  *                    including a SAM_ACCOUNT struct describing the user.
143  *
144  * @return An NTSTATUS with NT_STATUS_OK or an appropriate error.
145  *
146  **/
147
148 NTSTATUS auth_check_password(struct auth_context *auth_ctx,
149                              TALLOC_CTX *mem_ctx,
150                              const struct auth_usersupplied_info *user_info, 
151                              struct auth_serversupplied_info **server_info)
152 {
153         struct auth_check_password_sync_state *sync_state;
154         NTSTATUS status;
155
156         sync_state = talloc_zero(auth_ctx, struct auth_check_password_sync_state);
157         NT_STATUS_HAVE_NO_MEMORY(sync_state);
158
159         auth_check_password_send(auth_ctx, user_info, auth_check_password_sync_callback, sync_state);
160
161         while (!sync_state->finished) {
162                 event_loop_once(auth_ctx->event_ctx);
163         }
164
165         status = sync_state->status;
166
167         if (NT_STATUS_IS_OK(status)) {
168                 *server_info = talloc_steal(mem_ctx, sync_state->server_info);
169         }
170
171         talloc_free(sync_state);
172         return status;
173 }
174
175 struct auth_check_password_request {
176         struct auth_context *auth_ctx;
177         const struct auth_usersupplied_info *user_info;
178         struct auth_serversupplied_info *server_info;
179         struct auth_method_context *method;
180         NTSTATUS status;
181         struct {
182                 void (*fn)(struct auth_check_password_request *req, void *private_data);
183                 void *private_data;
184         } callback;
185 };
186
187 static void auth_check_password_async_timed_handler(struct event_context *ev, struct timed_event *te,
188                                                     struct timeval t, void *ptr)
189 {
190         struct auth_check_password_request *req = talloc_get_type(ptr, struct auth_check_password_request);
191         req->status = req->method->ops->check_password(req->method, req, req->user_info, &req->server_info);
192         req->callback.fn(req, req->callback.private_data);
193 }
194
195 /**
196  * Check a user's Plaintext, LM or NTLM password.
197  * async send hook
198  *
199  * Check a user's password, as given in the user_info struct and return various
200  * interesting details in the server_info struct.
201  *
202  * The return value takes precedence over the contents of the server_info 
203  * struct.  When the return is other than NT_STATUS_OK the contents 
204  * of that structure is undefined.
205  *
206  * @param auth_ctx Supplies the challenges and some other data. 
207  *                  Must be created with make_auth_context(), and the challenges should be 
208  *                  filled in, either at creation or by calling the challenge geneation 
209  *                  function auth_get_challenge().  
210  *
211  * @param user_info Contains the user supplied components, including the passwords.
212  *
213  * @param callback A callback function which will be called when the operation is finished.
214  *                 The callback function needs to call auth_check_password_recv() to get the return values
215  *
216  * @param private_data A private pointer which will ba passed to the callback function
217  *
218  **/
219
220 void auth_check_password_send(struct auth_context *auth_ctx,
221                               const struct auth_usersupplied_info *user_info,
222                               void (*callback)(struct auth_check_password_request *req, void *private_data),
223                               void *private_data)
224 {
225         /* if all the modules say 'not for me' this is reasonable */
226         NTSTATUS nt_status;
227         struct auth_method_context *method;
228         const uint8_t *challenge;
229         struct auth_usersupplied_info *user_info_tmp;
230         struct auth_check_password_request *req = NULL;
231
232         DEBUG(3,   ("auth_check_password_send:  Checking password for unmapped user [%s]\\[%s]@[%s]\n", 
233                     user_info->client.domain_name, user_info->client.account_name, user_info->workstation_name));
234
235         req = talloc_zero(auth_ctx, struct auth_check_password_request);
236         if (!req) {
237                 callback(NULL, private_data);
238                 return;
239         }
240         req->auth_ctx                   = auth_ctx;
241         req->user_info                  = user_info;
242         req->callback.fn                = callback;
243         req->callback.private_data      = private_data;
244
245         if (!user_info->mapped_state) {
246                 nt_status = map_user_info(req, user_info, &user_info_tmp);
247                 if (!NT_STATUS_IS_OK(nt_status)) goto failed;
248                 user_info = user_info_tmp;
249                 req->user_info  = user_info_tmp;
250         }
251
252         DEBUGADD(3,("auth_check_password_send:  mapped user is: [%s]\\[%s]@[%s]\n", 
253                     user_info->mapped.domain_name, user_info->mapped.account_name, user_info->workstation_name));
254
255         nt_status = auth_get_challenge(auth_ctx, &challenge);
256         if (!NT_STATUS_IS_OK(nt_status)) {
257                 DEBUG(0, ("auth_check_password_send:  Invalid challenge (length %u) stored for this auth context set_by %s - cannot continue: %s\n",
258                         (unsigned)auth_ctx->challenge.data.length, auth_ctx->challenge.set_by, nt_errstr(nt_status)));
259                 goto failed;
260         }
261
262         if (auth_ctx->challenge.set_by) {
263                 DEBUG(10, ("auth_check_password_send: auth_context challenge created by %s\n",
264                                         auth_ctx->challenge.set_by));
265         }
266
267         DEBUG(10, ("auth_check_password_send: challenge is: \n"));
268         dump_data(5, auth_ctx->challenge.data.data, auth_ctx->challenge.data.length);
269
270         nt_status = NT_STATUS_NO_SUCH_USER; /* If all the modules say 'not for me', then this is reasonable */
271         for (method = auth_ctx->methods; method; method = method->next) {
272                 NTSTATUS result;
273                 struct timed_event *te = NULL;
274
275                 /* check if the module wants to chek the password */
276                 result = method->ops->want_check(method, req, user_info);
277                 if (NT_STATUS_EQUAL(result, NT_STATUS_NOT_IMPLEMENTED)) {
278                         DEBUG(11,("auth_check_password_send: %s had nothing to say\n", method->ops->name));
279                         continue;
280                 }
281
282                 nt_status = result;
283                 req->method     = method;
284
285                 if (!NT_STATUS_IS_OK(nt_status)) break;
286
287                 te = event_add_timed(auth_ctx->event_ctx, req,
288                                      timeval_zero(),
289                                      auth_check_password_async_timed_handler, req);
290                 if (!te) {
291                         nt_status = NT_STATUS_NO_MEMORY;
292                         goto failed;
293                 }
294                 return;
295         }
296
297 failed:
298         req->status = nt_status;
299         req->callback.fn(req, req->callback.private_data);
300 }
301
302 /**
303  * Check a user's Plaintext, LM or NTLM password.
304  * async receive function
305  *
306  * The return value takes precedence over the contents of the server_info 
307  * struct.  When the return is other than NT_STATUS_OK the contents 
308  * of that structure is undefined.
309  *
310  *
311  * @param req The async auth_check_password state, passes to the callers callback function
312  *
313  * @param mem_ctx The parent memory context for the server_info structure
314  *
315  * @param server_info If successful, contains information about the authentication, 
316  *                    including a SAM_ACCOUNT struct describing the user.
317  *
318  * @return An NTSTATUS with NT_STATUS_OK or an appropriate error.
319  *
320  **/
321
322 NTSTATUS auth_check_password_recv(struct auth_check_password_request *req,
323                                   TALLOC_CTX *mem_ctx,
324                                   struct auth_serversupplied_info **server_info)
325 {
326         NTSTATUS status;
327
328         NT_STATUS_HAVE_NO_MEMORY(req);
329
330         if (NT_STATUS_IS_OK(req->status)) {
331                 DEBUG(5,("auth_check_password_recv: %s authentication for user [%s\\%s] succeeded\n",
332                          req->method->ops->name, req->server_info->domain_name, req->server_info->account_name));
333
334                 *server_info = talloc_steal(mem_ctx, req->server_info);
335         } else {
336                 DEBUG(2,("auth_check_password_recv: %s authentication for user [%s\\%s] FAILED with error %s\n", 
337                          (req->method ? req->method->ops->name : "NO_METHOD"),
338                          req->user_info->mapped.domain_name,
339                          req->user_info->mapped.account_name, 
340                          nt_errstr(req->status)));
341         }
342
343         status = req->status;
344         talloc_free(req);
345         return status;
346 }
347
348 /***************************************************************************
349  Make a auth_info struct for the auth subsystem
350  - Allow the caller to specify the methods to use
351 ***************************************************************************/
352 NTSTATUS auth_context_create_methods(TALLOC_CTX *mem_ctx, const char **methods, 
353                                      struct event_context *ev,
354                                      struct messaging_context *msg,
355                                      struct auth_context **auth_ctx)
356 {
357         int i;
358         struct auth_context *ctx;
359
360         if (!methods) {
361                 DEBUG(0,("auth_context_create: No auth method list!?\n"));
362                 return NT_STATUS_INTERNAL_ERROR;
363         }
364
365         if (!ev) {
366                 DEBUG(0,("auth_context_create: called with out event context\n"));
367                 return NT_STATUS_INTERNAL_ERROR;
368         }
369
370         if (!msg) {
371                 DEBUG(0,("auth_context_create: called with out messaging context\n"));
372                 return NT_STATUS_INTERNAL_ERROR;
373         }
374
375         ctx = talloc(mem_ctx, struct auth_context);
376         NT_STATUS_HAVE_NO_MEMORY(ctx);
377         ctx->challenge.set_by           = NULL;
378         ctx->challenge.may_be_modified  = False;
379         ctx->challenge.data             = data_blob(NULL, 0);
380         ctx->methods                    = NULL;
381         ctx->event_ctx                  = ev;
382         ctx->msg_ctx                    = msg;
383
384         for (i=0; methods[i] ; i++) {
385                 struct auth_method_context *method;
386
387                 method = talloc(ctx, struct auth_method_context);
388                 NT_STATUS_HAVE_NO_MEMORY(method);
389
390                 method->ops = auth_backend_byname(methods[i]);
391                 if (!method->ops) {
392                         DEBUG(1,("auth_context_create: failed to find method=%s\n",
393                                 methods[i]));
394                         return NT_STATUS_INTERNAL_ERROR;
395                 }
396                 method->auth_ctx        = ctx;
397                 method->depth           = i;
398                 DLIST_ADD_END(ctx->methods, method, struct auth_method_context *);
399         }
400
401         if (!ctx->methods) {
402                 return NT_STATUS_INTERNAL_ERROR;
403         }
404
405         *auth_ctx = ctx;
406
407         return NT_STATUS_OK;
408 }
409 /***************************************************************************
410  Make a auth_info struct for the auth subsystem
411  - Uses default auth_methods, depending on server role and smb.conf settings
412 ***************************************************************************/
413 NTSTATUS auth_context_create(TALLOC_CTX *mem_ctx, 
414                              struct event_context *ev,
415                              struct messaging_context *msg,
416                              struct auth_context **auth_ctx)
417 {
418         const char **auth_methods = NULL;
419         switch (lp_server_role()) {
420         case ROLE_STANDALONE:
421                 auth_methods = lp_parm_string_list(-1, "auth methods", "standalone", NULL);
422                 break;
423         case ROLE_DOMAIN_MEMBER:
424                 auth_methods = lp_parm_string_list(-1, "auth methods", "member server", NULL);
425                 break;
426         case ROLE_DOMAIN_CONTROLLER:
427                 auth_methods = lp_parm_string_list(-1, "auth methods", "domain controller", NULL);
428                 break;
429         }
430         return auth_context_create_methods(mem_ctx, auth_methods, ev, msg, auth_ctx);
431 }
432
433
434 /* the list of currently registered AUTH backends */
435 static struct auth_backend {
436         const struct auth_operations *ops;
437 } *backends = NULL;
438 static int num_backends;
439
440 /*
441   register a AUTH backend. 
442
443   The 'name' can be later used by other backends to find the operations
444   structure for this backend.
445 */
446 NTSTATUS auth_register(const void *_ops)
447 {
448         const struct auth_operations *ops = _ops;
449         struct auth_operations *new_ops;
450         
451         if (auth_backend_byname(ops->name) != NULL) {
452                 /* its already registered! */
453                 DEBUG(0,("AUTH backend '%s' already registered\n", 
454                          ops->name));
455                 return NT_STATUS_OBJECT_NAME_COLLISION;
456         }
457
458         backends = realloc_p(backends, struct auth_backend, num_backends+1);
459         if (!backends) {
460                 return NT_STATUS_NO_MEMORY;
461         }
462
463         new_ops = smb_xmemdup(ops, sizeof(*ops));
464         new_ops->name = smb_xstrdup(ops->name);
465
466         backends[num_backends].ops = new_ops;
467
468         num_backends++;
469
470         DEBUG(3,("AUTH backend '%s' registered\n", 
471                  ops->name));
472
473         return NT_STATUS_OK;
474 }
475
476 /*
477   return the operations structure for a named backend of the specified type
478 */
479 const struct auth_operations *auth_backend_byname(const char *name)
480 {
481         int i;
482
483         for (i=0;i<num_backends;i++) {
484                 if (strcmp(backends[i].ops->name, name) == 0) {
485                         return backends[i].ops;
486                 }
487         }
488
489         return NULL;
490 }
491
492 /*
493   return the AUTH interface version, and the size of some critical types
494   This can be used by backends to either detect compilation errors, or provide
495   multiple implementations for different smbd compilation options in one module
496 */
497 const struct auth_critical_sizes *auth_interface_version(void)
498 {
499         static const struct auth_critical_sizes critical_sizes = {
500                 AUTH_INTERFACE_VERSION,
501                 sizeof(struct auth_operations),
502                 sizeof(struct auth_method_context),
503                 sizeof(struct auth_context),
504                 sizeof(struct auth_usersupplied_info),
505                 sizeof(struct auth_serversupplied_info)
506         };
507
508         return &critical_sizes;
509 }
510
511 NTSTATUS auth_init(void)
512 {
513         static BOOL initialized = False;
514
515         init_module_fn static_init[] = STATIC_auth_MODULES;
516         init_module_fn *shared_init;
517         
518         if (initialized) return NT_STATUS_OK;
519         initialized = True;
520         
521         shared_init = load_samba_modules(NULL, "auth");
522
523         run_init_functions(static_init);
524         run_init_functions(shared_init);
525
526         talloc_free(shared_init);
527         
528         return NT_STATUS_OK;    
529 }
530
531 NTSTATUS server_service_auth_init(void)
532 {
533         return auth_init();
534 }