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