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/>.
22
#include "../lib/util/dlinklist.h"
23
#include "auth/auth.h"
24
#include "auth/ntlm/auth_proto.h"
25
#include "lib/events/events.h"
26
#include "param/param.h"
28
/***************************************************************************
30
***************************************************************************/
31
_PUBLIC_ NTSTATUS auth_context_set_challenge(struct auth_context *auth_ctx, const uint8_t chal[8], const char *set_by)
33
auth_ctx->challenge.set_by = talloc_strdup(auth_ctx, set_by);
34
NT_STATUS_HAVE_NO_MEMORY(auth_ctx->challenge.set_by);
36
auth_ctx->challenge.data = data_blob_talloc(auth_ctx, chal, 8);
37
NT_STATUS_HAVE_NO_MEMORY(auth_ctx->challenge.data.data);
42
/***************************************************************************
44
***************************************************************************/
45
bool auth_challenge_may_be_modified(struct auth_context *auth_ctx)
47
return auth_ctx->challenge.may_be_modified;
50
/****************************************************************************
51
Try to get a challenge out of the various authentication modules.
52
Returns a const char of length 8 bytes.
53
****************************************************************************/
54
_PUBLIC_ NTSTATUS auth_get_challenge(struct auth_context *auth_ctx, const uint8_t **_chal)
57
struct auth_method_context *method;
59
if (auth_ctx->challenge.data.length) {
60
DEBUG(5, ("auth_get_challenge: returning previous challenge by module %s (normal)\n",
61
auth_ctx->challenge.set_by));
62
*_chal = auth_ctx->challenge.data.data;
66
for (method = auth_ctx->methods; method; method = method->next) {
67
DATA_BLOB challenge = data_blob(NULL,0);
69
nt_status = method->ops->get_challenge(method, auth_ctx, &challenge);
70
if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NOT_IMPLEMENTED)) {
74
NT_STATUS_NOT_OK_RETURN(nt_status);
76
if (challenge.length != 8) {
77
DEBUG(0, ("auth_get_challenge: invalid challenge (length %u) by mothod [%s]\n",
78
(unsigned)challenge.length, method->ops->name));
79
return NT_STATUS_INTERNAL_ERROR;
82
auth_ctx->challenge.data = challenge;
83
auth_ctx->challenge.set_by = method->ops->name;
88
if (!auth_ctx->challenge.set_by) {
90
generate_random_buffer(chal, 8);
92
auth_ctx->challenge.data = data_blob_talloc(auth_ctx, chal, 8);
93
NT_STATUS_HAVE_NO_MEMORY(auth_ctx->challenge.data.data);
94
auth_ctx->challenge.set_by = "random";
96
auth_ctx->challenge.may_be_modified = true;
99
DEBUG(10,("auth_get_challenge: challenge set by %s\n",
100
auth_ctx->challenge.set_by));
102
*_chal = auth_ctx->challenge.data.data;
106
/****************************************************************************
107
Try to get a challenge out of the various authentication modules.
108
Returns a const char of length 8 bytes.
109
****************************************************************************/
110
_PUBLIC_ NTSTATUS auth_get_server_info_principal(TALLOC_CTX *mem_ctx,
111
struct auth_context *auth_ctx,
112
const char *principal,
113
struct auth_serversupplied_info **server_info)
116
struct auth_method_context *method;
118
for (method = auth_ctx->methods; method; method = method->next) {
119
if (!method->ops->get_server_info_principal) {
123
nt_status = method->ops->get_server_info_principal(mem_ctx, auth_ctx, principal, server_info);
124
if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NOT_IMPLEMENTED)) {
128
NT_STATUS_NOT_OK_RETURN(nt_status);
136
struct auth_check_password_sync_state {
139
struct auth_serversupplied_info *server_info;
142
static void auth_check_password_sync_callback(struct auth_check_password_request *req,
145
struct auth_check_password_sync_state *s = talloc_get_type(private_data,
146
struct auth_check_password_sync_state);
149
s->status = auth_check_password_recv(req, s, &s->server_info);
153
* Check a user's Plaintext, LM or NTLM password.
156
* Check a user's password, as given in the user_info struct and return various
157
* interesting details in the server_info struct.
159
* The return value takes precedence over the contents of the server_info
160
* struct. When the return is other than NT_STATUS_OK the contents
161
* of that structure is undefined.
163
* @param auth_ctx Supplies the challenges and some other data.
164
* Must be created with auth_context_create(), and the challenges should be
165
* filled in, either at creation or by calling the challenge geneation
166
* function auth_get_challenge().
168
* @param user_info Contains the user supplied components, including the passwords.
170
* @param mem_ctx The parent memory context for the server_info structure
172
* @param server_info If successful, contains information about the authentication,
173
* including a SAM_ACCOUNT struct describing the user.
175
* @return An NTSTATUS with NT_STATUS_OK or an appropriate error.
179
_PUBLIC_ NTSTATUS auth_check_password(struct auth_context *auth_ctx,
181
const struct auth_usersupplied_info *user_info,
182
struct auth_serversupplied_info **server_info)
184
struct auth_check_password_sync_state *sync_state;
187
sync_state = talloc_zero(auth_ctx, struct auth_check_password_sync_state);
188
NT_STATUS_HAVE_NO_MEMORY(sync_state);
190
auth_check_password_send(auth_ctx, user_info, auth_check_password_sync_callback, sync_state);
192
while (!sync_state->finished) {
193
event_loop_once(auth_ctx->event_ctx);
196
status = sync_state->status;
198
if (NT_STATUS_IS_OK(status)) {
199
*server_info = talloc_steal(mem_ctx, sync_state->server_info);
202
talloc_free(sync_state);
206
struct auth_check_password_request {
207
struct auth_context *auth_ctx;
208
const struct auth_usersupplied_info *user_info;
209
struct auth_serversupplied_info *server_info;
210
struct auth_method_context *method;
213
void (*fn)(struct auth_check_password_request *req, void *private_data);
218
static void auth_check_password_async_timed_handler(struct tevent_context *ev, struct tevent_timer *te,
219
struct timeval t, void *ptr)
221
struct auth_check_password_request *req = talloc_get_type(ptr, struct auth_check_password_request);
222
req->status = req->method->ops->check_password(req->method, req, req->user_info, &req->server_info);
223
req->callback.fn(req, req->callback.private_data);
227
* Check a user's Plaintext, LM or NTLM password.
230
* Check a user's password, as given in the user_info struct and return various
231
* interesting details in the server_info struct.
233
* The return value takes precedence over the contents of the server_info
234
* struct. When the return is other than NT_STATUS_OK the contents
235
* of that structure is undefined.
237
* @param auth_ctx Supplies the challenges and some other data.
238
* Must be created with make_auth_context(), and the challenges should be
239
* filled in, either at creation or by calling the challenge geneation
240
* function auth_get_challenge().
242
* @param user_info Contains the user supplied components, including the passwords.
244
* @param callback A callback function which will be called when the operation is finished.
245
* The callback function needs to call auth_check_password_recv() to get the return values
247
* @param private_data A private pointer which will ba passed to the callback function
251
_PUBLIC_ void auth_check_password_send(struct auth_context *auth_ctx,
252
const struct auth_usersupplied_info *user_info,
253
void (*callback)(struct auth_check_password_request *req, void *private_data),
256
/* if all the modules say 'not for me' this is reasonable */
258
struct auth_method_context *method;
259
const uint8_t *challenge;
260
struct auth_usersupplied_info *user_info_tmp;
261
struct auth_check_password_request *req = NULL;
263
DEBUG(3, ("auth_check_password_send: Checking password for unmapped user [%s]\\[%s]@[%s]\n",
264
user_info->client.domain_name, user_info->client.account_name, user_info->workstation_name));
266
req = talloc_zero(auth_ctx, struct auth_check_password_request);
268
callback(NULL, private_data);
271
req->auth_ctx = auth_ctx;
272
req->user_info = user_info;
273
req->callback.fn = callback;
274
req->callback.private_data = private_data;
276
if (!user_info->mapped_state) {
277
nt_status = map_user_info(req, lp_workgroup(auth_ctx->lp_ctx), user_info, &user_info_tmp);
278
if (!NT_STATUS_IS_OK(nt_status)) goto failed;
279
user_info = user_info_tmp;
280
req->user_info = user_info_tmp;
283
DEBUGADD(3,("auth_check_password_send: mapped user is: [%s]\\[%s]@[%s]\n",
284
user_info->mapped.domain_name, user_info->mapped.account_name, user_info->workstation_name));
286
nt_status = auth_get_challenge(auth_ctx, &challenge);
287
if (!NT_STATUS_IS_OK(nt_status)) {
288
DEBUG(0, ("auth_check_password_send: Invalid challenge (length %u) stored for this auth context set_by %s - cannot continue: %s\n",
289
(unsigned)auth_ctx->challenge.data.length, auth_ctx->challenge.set_by, nt_errstr(nt_status)));
293
if (auth_ctx->challenge.set_by) {
294
DEBUG(10, ("auth_check_password_send: auth_context challenge created by %s\n",
295
auth_ctx->challenge.set_by));
298
DEBUG(10, ("auth_check_password_send: challenge is: \n"));
299
dump_data(5, auth_ctx->challenge.data.data, auth_ctx->challenge.data.length);
301
nt_status = NT_STATUS_NO_SUCH_USER; /* If all the modules say 'not for me', then this is reasonable */
302
for (method = auth_ctx->methods; method; method = method->next) {
304
struct tevent_timer *te = NULL;
306
/* check if the module wants to chek the password */
307
result = method->ops->want_check(method, req, user_info);
308
if (NT_STATUS_EQUAL(result, NT_STATUS_NOT_IMPLEMENTED)) {
309
DEBUG(11,("auth_check_password_send: %s had nothing to say\n", method->ops->name));
314
req->method = method;
316
if (!NT_STATUS_IS_OK(nt_status)) break;
318
te = event_add_timed(auth_ctx->event_ctx, req,
320
auth_check_password_async_timed_handler, req);
322
nt_status = NT_STATUS_NO_MEMORY;
329
req->status = nt_status;
330
req->callback.fn(req, req->callback.private_data);
334
* Check a user's Plaintext, LM or NTLM password.
335
* async receive function
337
* The return value takes precedence over the contents of the server_info
338
* struct. When the return is other than NT_STATUS_OK the contents
339
* of that structure is undefined.
342
* @param req The async auth_check_password state, passes to the callers callback function
344
* @param mem_ctx The parent memory context for the server_info structure
346
* @param server_info If successful, contains information about the authentication,
347
* including a SAM_ACCOUNT struct describing the user.
349
* @return An NTSTATUS with NT_STATUS_OK or an appropriate error.
353
_PUBLIC_ NTSTATUS auth_check_password_recv(struct auth_check_password_request *req,
355
struct auth_serversupplied_info **server_info)
359
NT_STATUS_HAVE_NO_MEMORY(req);
361
if (NT_STATUS_IS_OK(req->status)) {
362
DEBUG(5,("auth_check_password_recv: %s authentication for user [%s\\%s] succeeded\n",
363
req->method->ops->name, req->server_info->domain_name, req->server_info->account_name));
365
*server_info = talloc_steal(mem_ctx, req->server_info);
367
DEBUG(2,("auth_check_password_recv: %s authentication for user [%s\\%s] FAILED with error %s\n",
368
(req->method ? req->method->ops->name : "NO_METHOD"),
369
req->user_info->mapped.domain_name,
370
req->user_info->mapped.account_name,
371
nt_errstr(req->status)));
374
status = req->status;
379
/***************************************************************************
380
Make a auth_info struct for the auth subsystem
381
- Allow the caller to specify the methods to use
382
***************************************************************************/
383
_PUBLIC_ NTSTATUS auth_context_create_methods(TALLOC_CTX *mem_ctx, const char **methods,
384
struct tevent_context *ev,
385
struct messaging_context *msg,
386
struct loadparm_context *lp_ctx,
387
struct auth_context **auth_ctx)
390
struct auth_context *ctx;
395
DEBUG(0,("auth_context_create: No auth method list!?\n"));
396
return NT_STATUS_INTERNAL_ERROR;
400
DEBUG(0,("auth_context_create: called with out event context\n"));
401
return NT_STATUS_INTERNAL_ERROR;
405
DEBUG(0,("auth_context_create: called with out messaging context\n"));
406
return NT_STATUS_INTERNAL_ERROR;
409
ctx = talloc(mem_ctx, struct auth_context);
410
NT_STATUS_HAVE_NO_MEMORY(ctx);
411
ctx->challenge.set_by = NULL;
412
ctx->challenge.may_be_modified = false;
413
ctx->challenge.data = data_blob(NULL, 0);
417
ctx->lp_ctx = lp_ctx;
419
for (i=0; methods[i] ; i++) {
420
struct auth_method_context *method;
422
method = talloc(ctx, struct auth_method_context);
423
NT_STATUS_HAVE_NO_MEMORY(method);
425
method->ops = auth_backend_byname(methods[i]);
427
DEBUG(1,("auth_context_create: failed to find method=%s\n",
429
return NT_STATUS_INTERNAL_ERROR;
431
method->auth_ctx = ctx;
433
DLIST_ADD_END(ctx->methods, method, struct auth_method_context *);
437
return NT_STATUS_INTERNAL_ERROR;
440
ctx->check_password = auth_check_password;
441
ctx->get_challenge = auth_get_challenge;
442
ctx->set_challenge = auth_context_set_challenge;
443
ctx->challenge_may_be_modified = auth_challenge_may_be_modified;
444
ctx->get_server_info_principal = auth_get_server_info_principal;
450
/***************************************************************************
451
Make a auth_info struct for the auth subsystem
452
- Uses default auth_methods, depending on server role and smb.conf settings
453
***************************************************************************/
454
_PUBLIC_ NTSTATUS auth_context_create(TALLOC_CTX *mem_ctx,
455
struct tevent_context *ev,
456
struct messaging_context *msg,
457
struct loadparm_context *lp_ctx,
458
struct auth_context **auth_ctx)
460
const char **auth_methods = NULL;
461
switch (lp_server_role(lp_ctx)) {
462
case ROLE_STANDALONE:
463
auth_methods = lp_parm_string_list(mem_ctx, lp_ctx, NULL, "auth methods", "standalone", NULL);
465
case ROLE_DOMAIN_MEMBER:
466
auth_methods = lp_parm_string_list(mem_ctx, lp_ctx, NULL, "auth methods", "member server", NULL);
468
case ROLE_DOMAIN_CONTROLLER:
469
auth_methods = lp_parm_string_list(mem_ctx, lp_ctx, NULL, "auth methods", "domain controller", NULL);
472
return auth_context_create_methods(mem_ctx, auth_methods, ev, msg, lp_ctx, auth_ctx);
476
/* the list of currently registered AUTH backends */
477
static struct auth_backend {
478
const struct auth_operations *ops;
480
static int num_backends;
483
register a AUTH backend.
485
The 'name' can be later used by other backends to find the operations
486
structure for this backend.
488
_PUBLIC_ NTSTATUS auth_register(const struct auth_operations *ops)
490
struct auth_operations *new_ops;
492
if (auth_backend_byname(ops->name) != NULL) {
493
/* its already registered! */
494
DEBUG(0,("AUTH backend '%s' already registered\n",
496
return NT_STATUS_OBJECT_NAME_COLLISION;
499
backends = talloc_realloc(talloc_autofree_context(), backends,
500
struct auth_backend, num_backends+1);
501
NT_STATUS_HAVE_NO_MEMORY(backends);
503
new_ops = (struct auth_operations *)talloc_memdup(backends, ops, sizeof(*ops));
504
NT_STATUS_HAVE_NO_MEMORY(new_ops);
505
new_ops->name = talloc_strdup(new_ops, ops->name);
506
NT_STATUS_HAVE_NO_MEMORY(new_ops->name);
508
backends[num_backends].ops = new_ops;
512
DEBUG(3,("AUTH backend '%s' registered\n",
519
return the operations structure for a named backend of the specified type
521
const struct auth_operations *auth_backend_byname(const char *name)
525
for (i=0;i<num_backends;i++) {
526
if (strcmp(backends[i].ops->name, name) == 0) {
527
return backends[i].ops;
535
return the AUTH interface version, and the size of some critical types
536
This can be used by backends to either detect compilation errors, or provide
537
multiple implementations for different smbd compilation options in one module
539
const struct auth_critical_sizes *auth_interface_version(void)
541
static const struct auth_critical_sizes critical_sizes = {
542
AUTH_INTERFACE_VERSION,
543
sizeof(struct auth_operations),
544
sizeof(struct auth_method_context),
545
sizeof(struct auth_context),
546
sizeof(struct auth_usersupplied_info),
547
sizeof(struct auth_serversupplied_info)
550
return &critical_sizes;
553
_PUBLIC_ NTSTATUS auth_init(void)
555
static bool initialized = false;
556
extern NTSTATUS auth_developer_init(void);
557
extern NTSTATUS auth_winbind_init(void);
558
extern NTSTATUS auth_anonymous_init(void);
559
extern NTSTATUS auth_unix_init(void);
560
extern NTSTATUS auth_sam_init(void);
561
extern NTSTATUS auth_server_init(void);
563
init_module_fn static_init[] = { STATIC_auth_MODULES };
565
if (initialized) return NT_STATUS_OK;
568
run_init_functions(static_init);
573
NTSTATUS server_service_auth_init(void)