Move NTLM authentication details into auth/ntlm
[Samba.git] / source / auth / ntlm / auth.c
blobb74a4389625376716ee580150275493e4412c4f0
1 /*
2 Unix SMB/CIFS implementation.
3 Password and authentication handling
4 Copyright (C) Andrew Bartlett 2001-2002
5 Copyright (C) Stefan Metzmacher 2005
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.
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.
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/>.
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"
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)
34 auth_ctx->challenge.set_by = talloc_strdup(auth_ctx, set_by);
35 NT_STATUS_HAVE_NO_MEMORY(auth_ctx->challenge.set_by);
37 auth_ctx->challenge.data = data_blob_talloc(auth_ctx, chal, 8);
38 NT_STATUS_HAVE_NO_MEMORY(auth_ctx->challenge.data.data);
40 return NT_STATUS_OK;
43 /***************************************************************************
44 Set a fixed challenge
45 ***************************************************************************/
46 bool auth_challenge_may_be_modified(struct auth_context *auth_ctx)
48 return auth_ctx->challenge.may_be_modified;
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)
57 NTSTATUS nt_status;
58 struct auth_method_context *method;
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;
67 for (method = auth_ctx->methods; method; method = method->next) {
68 DATA_BLOB challenge = data_blob(NULL,0);
70 nt_status = method->ops->get_challenge(method, auth_ctx, &challenge);
71 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NOT_IMPLEMENTED)) {
72 continue;
75 NT_STATUS_NOT_OK_RETURN(nt_status);
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;
83 auth_ctx->challenge.data = challenge;
84 auth_ctx->challenge.set_by = method->ops->name;
86 break;
89 if (!auth_ctx->challenge.set_by) {
90 uint8_t chal[8];
91 generate_random_buffer(chal, 8);
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";
97 auth_ctx->challenge.may_be_modified = true;
100 DEBUG(10,("auth_get_challenge: challenge set by %s\n",
101 auth_ctx->challenge.set_by));
103 *_chal = auth_ctx->challenge.data.data;
104 return NT_STATUS_OK;
107 struct auth_check_password_sync_state {
108 bool finished;
109 NTSTATUS status;
110 struct auth_serversupplied_info *server_info;
113 static void auth_check_password_sync_callback(struct auth_check_password_request *req,
114 void *private_data)
116 struct auth_check_password_sync_state *s = talloc_get_type(private_data,
117 struct auth_check_password_sync_state);
119 s->finished = true;
120 s->status = auth_check_password_recv(req, s, &s->server_info);
124 * Check a user's Plaintext, LM or NTLM password.
125 * (sync version)
127 * Check a user's password, as given in the user_info struct and return various
128 * interesting details in the server_info struct.
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.
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().
139 * @param user_info Contains the user supplied components, including the passwords.
141 * @param mem_ctx The parent memory context for the server_info structure
143 * @param server_info If successful, contains information about the authentication,
144 * including a SAM_ACCOUNT struct describing the user.
146 * @return An NTSTATUS with NT_STATUS_OK or an appropriate error.
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)
155 struct auth_check_password_sync_state *sync_state;
156 NTSTATUS status;
158 sync_state = talloc_zero(auth_ctx, struct auth_check_password_sync_state);
159 NT_STATUS_HAVE_NO_MEMORY(sync_state);
161 auth_check_password_send(auth_ctx, user_info, auth_check_password_sync_callback, sync_state);
163 while (!sync_state->finished) {
164 event_loop_once(auth_ctx->event_ctx);
167 status = sync_state->status;
169 if (NT_STATUS_IS_OK(status)) {
170 *server_info = talloc_steal(mem_ctx, sync_state->server_info);
173 talloc_free(sync_state);
174 return status;
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;
189 static void auth_check_password_async_timed_handler(struct event_context *ev, struct timed_event *te,
190 struct timeval t, void *ptr)
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);
198 * Check a user's Plaintext, LM or NTLM password.
199 * async send hook
201 * Check a user's password, as given in the user_info struct and return various
202 * interesting details in the server_info struct.
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.
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().
213 * @param user_info Contains the user supplied components, including the passwords.
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
218 * @param private_data A private pointer which will ba passed to the callback function
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)
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;
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));
237 req = talloc_zero(auth_ctx, struct auth_check_password_request);
238 if (!req) {
239 callback(NULL, private_data);
240 return;
242 req->auth_ctx = auth_ctx;
243 req->user_info = user_info;
244 req->callback.fn = callback;
245 req->callback.private_data = private_data;
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;
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));
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;
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));
269 DEBUG(10, ("auth_check_password_send: challenge is: \n"));
270 dump_data(5, auth_ctx->challenge.data.data, auth_ctx->challenge.data.length);
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;
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;
284 nt_status = result;
285 req->method = method;
287 if (!NT_STATUS_IS_OK(nt_status)) break;
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;
296 return;
299 failed:
300 req->status = nt_status;
301 req->callback.fn(req, req->callback.private_data);
305 * Check a user's Plaintext, LM or NTLM password.
306 * async receive function
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.
313 * @param req The async auth_check_password state, passes to the callers callback function
315 * @param mem_ctx The parent memory context for the server_info structure
317 * @param server_info If successful, contains information about the authentication,
318 * including a SAM_ACCOUNT struct describing the user.
320 * @return An NTSTATUS with NT_STATUS_OK or an appropriate error.
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)
328 NTSTATUS status;
330 NT_STATUS_HAVE_NO_MEMORY(req);
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));
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)));
345 status = req->status;
346 talloc_free(req);
347 return status;
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)
360 int i;
361 struct auth_context *ctx;
363 if (!methods) {
364 DEBUG(0,("auth_context_create: No auth method list!?\n"));
365 return NT_STATUS_INTERNAL_ERROR;
368 if (!ev) {
369 DEBUG(0,("auth_context_create: called with out event context\n"));
370 return NT_STATUS_INTERNAL_ERROR;
373 if (!msg) {
374 DEBUG(0,("auth_context_create: called with out messaging context\n"));
375 return NT_STATUS_INTERNAL_ERROR;
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;
388 for (i=0; methods[i] ; i++) {
389 struct auth_method_context *method;
391 method = talloc(ctx, struct auth_method_context);
392 NT_STATUS_HAVE_NO_MEMORY(method);
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;
400 method->auth_ctx = ctx;
401 method->depth = i;
402 DLIST_ADD_END(ctx->methods, method, struct auth_method_context *);
405 if (!ctx->methods) {
406 return NT_STATUS_INTERNAL_ERROR;
409 *auth_ctx = ctx;
411 return NT_STATUS_OK;
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)
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;
435 return auth_context_create_methods(mem_ctx, auth_methods, ev, msg, lp_ctx, auth_ctx);
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;
446 register a AUTH backend.
448 The 'name' can be later used by other backends to find the operations
449 structure for this backend.
451 _PUBLIC_ NTSTATUS auth_register(const struct auth_operations *ops)
453 struct auth_operations *new_ops;
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;
462 backends = talloc_realloc(talloc_autofree_context(), backends,
463 struct auth_backend, num_backends+1);
464 NT_STATUS_HAVE_NO_MEMORY(backends);
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);
471 backends[num_backends].ops = new_ops;
473 num_backends++;
475 DEBUG(3,("AUTH backend '%s' registered\n",
476 ops->name));
478 return NT_STATUS_OK;
482 return the operations structure for a named backend of the specified type
484 const struct auth_operations *auth_backend_byname(const char *name)
486 int i;
488 for (i=0;i<num_backends;i++) {
489 if (strcmp(backends[i].ops->name, name) == 0) {
490 return backends[i].ops;
494 return NULL;
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
502 const struct auth_critical_sizes *auth_interface_version(void)
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)
513 return &critical_sizes;
516 _PUBLIC_ NTSTATUS auth_init(void)
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);
526 init_module_fn static_init[] = { STATIC_auth_MODULES };
528 if (initialized) return NT_STATUS_OK;
529 initialized = true;
531 run_init_functions(static_init);
533 return NT_STATUS_OK;
536 NTSTATUS server_service_auth_init(void)
538 return auth_init();