~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source4/auth/ntlm/auth.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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/ntlm/auth_proto.h"
 
25
#include "lib/events/events.h"
 
26
#include "param/param.h"
 
27
 
 
28
/***************************************************************************
 
29
 Set a fixed challenge
 
30
***************************************************************************/
 
31
_PUBLIC_ NTSTATUS auth_context_set_challenge(struct auth_context *auth_ctx, const uint8_t chal[8], const char *set_by) 
 
32
{
 
33
        auth_ctx->challenge.set_by = talloc_strdup(auth_ctx, set_by);
 
34
        NT_STATUS_HAVE_NO_MEMORY(auth_ctx->challenge.set_by);
 
35
 
 
36
        auth_ctx->challenge.data = data_blob_talloc(auth_ctx, chal, 8);
 
37
        NT_STATUS_HAVE_NO_MEMORY(auth_ctx->challenge.data.data);
 
38
 
 
39
        return NT_STATUS_OK;
 
40
}
 
41
 
 
42
/***************************************************************************
 
43
 Set a fixed challenge
 
44
***************************************************************************/
 
45
bool auth_challenge_may_be_modified(struct auth_context *auth_ctx) 
 
46
{
 
47
        return auth_ctx->challenge.may_be_modified;
 
48
}
 
49
 
 
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)
 
55
{
 
56
        NTSTATUS nt_status;
 
57
        struct auth_method_context *method;
 
58
 
 
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;
 
63
                return NT_STATUS_OK;
 
64
        }
 
65
 
 
66
        for (method = auth_ctx->methods; method; method = method->next) {
 
67
                DATA_BLOB challenge = data_blob(NULL,0);
 
68
 
 
69
                nt_status = method->ops->get_challenge(method, auth_ctx, &challenge);
 
70
                if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NOT_IMPLEMENTED)) {
 
71
                        continue;
 
72
                }
 
73
 
 
74
                NT_STATUS_NOT_OK_RETURN(nt_status);
 
75
 
 
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;
 
80
                }
 
81
 
 
82
                auth_ctx->challenge.data        = challenge;
 
83
                auth_ctx->challenge.set_by      = method->ops->name;
 
84
 
 
85
                break;
 
86
        }
 
87
 
 
88
        if (!auth_ctx->challenge.set_by) {
 
89
                uint8_t chal[8];
 
90
                generate_random_buffer(chal, 8);
 
91
 
 
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";
 
95
 
 
96
                auth_ctx->challenge.may_be_modified     = true;
 
97
        }
 
98
 
 
99
        DEBUG(10,("auth_get_challenge: challenge set by %s\n",
 
100
                 auth_ctx->challenge.set_by));
 
101
 
 
102
        *_chal = auth_ctx->challenge.data.data;
 
103
        return NT_STATUS_OK;
 
104
}
 
105
 
 
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)
 
114
{
 
115
        NTSTATUS nt_status;
 
116
        struct auth_method_context *method;
 
117
 
 
118
        for (method = auth_ctx->methods; method; method = method->next) {
 
119
                if (!method->ops->get_server_info_principal) {
 
120
                        continue;
 
121
                }
 
122
 
 
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)) {
 
125
                        continue;
 
126
                }
 
127
 
 
128
                NT_STATUS_NOT_OK_RETURN(nt_status);
 
129
 
 
130
                break;
 
131
        }
 
132
 
 
133
        return NT_STATUS_OK;
 
134
}
 
135
 
 
136
struct auth_check_password_sync_state {
 
137
        bool finished;
 
138
        NTSTATUS status;
 
139
        struct auth_serversupplied_info *server_info;
 
140
};
 
141
 
 
142
static void auth_check_password_sync_callback(struct auth_check_password_request *req,
 
143
                                              void *private_data)
 
144
{
 
145
        struct auth_check_password_sync_state *s = talloc_get_type(private_data,
 
146
                                                   struct auth_check_password_sync_state);
 
147
 
 
148
        s->finished = true;
 
149
        s->status = auth_check_password_recv(req, s, &s->server_info);
 
150
}
 
151
 
 
152
/**
 
153
 * Check a user's Plaintext, LM or NTLM password.
 
154
 * (sync version)
 
155
 *
 
156
 * Check a user's password, as given in the user_info struct and return various
 
157
 * interesting details in the server_info struct.
 
158
 *
 
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.
 
162
 *
 
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().  
 
167
 *
 
168
 * @param user_info Contains the user supplied components, including the passwords.
 
169
 *
 
170
 * @param mem_ctx The parent memory context for the server_info structure
 
171
 *
 
172
 * @param server_info If successful, contains information about the authentication, 
 
173
 *                    including a SAM_ACCOUNT struct describing the user.
 
174
 *
 
175
 * @return An NTSTATUS with NT_STATUS_OK or an appropriate error.
 
176
 *
 
177
 **/
 
178
 
 
179
_PUBLIC_ NTSTATUS auth_check_password(struct auth_context *auth_ctx,
 
180
                             TALLOC_CTX *mem_ctx,
 
181
                             const struct auth_usersupplied_info *user_info, 
 
182
                             struct auth_serversupplied_info **server_info)
 
183
{
 
184
        struct auth_check_password_sync_state *sync_state;
 
185
        NTSTATUS status;
 
186
 
 
187
        sync_state = talloc_zero(auth_ctx, struct auth_check_password_sync_state);
 
188
        NT_STATUS_HAVE_NO_MEMORY(sync_state);
 
189
 
 
190
        auth_check_password_send(auth_ctx, user_info, auth_check_password_sync_callback, sync_state);
 
191
 
 
192
        while (!sync_state->finished) {
 
193
                event_loop_once(auth_ctx->event_ctx);
 
194
        }
 
195
 
 
196
        status = sync_state->status;
 
197
 
 
198
        if (NT_STATUS_IS_OK(status)) {
 
199
                *server_info = talloc_steal(mem_ctx, sync_state->server_info);
 
200
        }
 
201
 
 
202
        talloc_free(sync_state);
 
203
        return status;
 
204
}
 
205
 
 
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;
 
211
        NTSTATUS status;
 
212
        struct {
 
213
                void (*fn)(struct auth_check_password_request *req, void *private_data);
 
214
                void *private_data;
 
215
        } callback;
 
216
};
 
217
 
 
218
static void auth_check_password_async_timed_handler(struct tevent_context *ev, struct tevent_timer *te,
 
219
                                                    struct timeval t, void *ptr)
 
220
{
 
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);
 
224
}
 
225
 
 
226
/**
 
227
 * Check a user's Plaintext, LM or NTLM password.
 
228
 * async send hook
 
229
 *
 
230
 * Check a user's password, as given in the user_info struct and return various
 
231
 * interesting details in the server_info struct.
 
232
 *
 
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.
 
236
 *
 
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().  
 
241
 *
 
242
 * @param user_info Contains the user supplied components, including the passwords.
 
243
 *
 
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
 
246
 *
 
247
 * @param private_data A private pointer which will ba passed to the callback function
 
248
 *
 
249
 **/
 
250
 
 
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),
 
254
                              void *private_data)
 
255
{
 
256
        /* if all the modules say 'not for me' this is reasonable */
 
257
        NTSTATUS nt_status;
 
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;
 
262
 
 
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));
 
265
 
 
266
        req = talloc_zero(auth_ctx, struct auth_check_password_request);
 
267
        if (!req) {
 
268
                callback(NULL, private_data);
 
269
                return;
 
270
        }
 
271
        req->auth_ctx                   = auth_ctx;
 
272
        req->user_info                  = user_info;
 
273
        req->callback.fn                = callback;
 
274
        req->callback.private_data      = private_data;
 
275
 
 
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;
 
281
        }
 
282
 
 
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));
 
285
 
 
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)));
 
290
                goto failed;
 
291
        }
 
292
 
 
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));
 
296
        }
 
297
 
 
298
        DEBUG(10, ("auth_check_password_send: challenge is: \n"));
 
299
        dump_data(5, auth_ctx->challenge.data.data, auth_ctx->challenge.data.length);
 
300
 
 
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) {
 
303
                NTSTATUS result;
 
304
                struct tevent_timer *te = NULL;
 
305
 
 
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));
 
310
                        continue;
 
311
                }
 
312
 
 
313
                nt_status = result;
 
314
                req->method     = method;
 
315
 
 
316
                if (!NT_STATUS_IS_OK(nt_status)) break;
 
317
 
 
318
                te = event_add_timed(auth_ctx->event_ctx, req,
 
319
                                     timeval_zero(),
 
320
                                     auth_check_password_async_timed_handler, req);
 
321
                if (!te) {
 
322
                        nt_status = NT_STATUS_NO_MEMORY;
 
323
                        goto failed;
 
324
                }
 
325
                return;
 
326
        }
 
327
 
 
328
failed:
 
329
        req->status = nt_status;
 
330
        req->callback.fn(req, req->callback.private_data);
 
331
}
 
332
 
 
333
/**
 
334
 * Check a user's Plaintext, LM or NTLM password.
 
335
 * async receive function
 
336
 *
 
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.
 
340
 *
 
341
 *
 
342
 * @param req The async auth_check_password state, passes to the callers callback function
 
343
 *
 
344
 * @param mem_ctx The parent memory context for the server_info structure
 
345
 *
 
346
 * @param server_info If successful, contains information about the authentication, 
 
347
 *                    including a SAM_ACCOUNT struct describing the user.
 
348
 *
 
349
 * @return An NTSTATUS with NT_STATUS_OK or an appropriate error.
 
350
 *
 
351
 **/
 
352
 
 
353
_PUBLIC_ NTSTATUS auth_check_password_recv(struct auth_check_password_request *req,
 
354
                                  TALLOC_CTX *mem_ctx,
 
355
                                  struct auth_serversupplied_info **server_info)
 
356
{
 
357
        NTSTATUS status;
 
358
 
 
359
        NT_STATUS_HAVE_NO_MEMORY(req);
 
360
 
 
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));
 
364
 
 
365
                *server_info = talloc_steal(mem_ctx, req->server_info);
 
366
        } else {
 
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)));
 
372
        }
 
373
 
 
374
        status = req->status;
 
375
        talloc_free(req);
 
376
        return status;
 
377
}
 
378
 
 
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)
 
388
{
 
389
        int i;
 
390
        struct auth_context *ctx;
 
391
 
 
392
        auth_init();
 
393
 
 
394
        if (!methods) {
 
395
                DEBUG(0,("auth_context_create: No auth method list!?\n"));
 
396
                return NT_STATUS_INTERNAL_ERROR;
 
397
        }
 
398
 
 
399
        if (!ev) {
 
400
                DEBUG(0,("auth_context_create: called with out event context\n"));
 
401
                return NT_STATUS_INTERNAL_ERROR;
 
402
        }
 
403
 
 
404
        if (!msg) {
 
405
                DEBUG(0,("auth_context_create: called with out messaging context\n"));
 
406
                return NT_STATUS_INTERNAL_ERROR;
 
407
        }
 
408
 
 
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);
 
414
        ctx->methods                    = NULL;
 
415
        ctx->event_ctx                  = ev;
 
416
        ctx->msg_ctx                    = msg;
 
417
        ctx->lp_ctx                     = lp_ctx;
 
418
 
 
419
        for (i=0; methods[i] ; i++) {
 
420
                struct auth_method_context *method;
 
421
 
 
422
                method = talloc(ctx, struct auth_method_context);
 
423
                NT_STATUS_HAVE_NO_MEMORY(method);
 
424
 
 
425
                method->ops = auth_backend_byname(methods[i]);
 
426
                if (!method->ops) {
 
427
                        DEBUG(1,("auth_context_create: failed to find method=%s\n",
 
428
                                methods[i]));
 
429
                        return NT_STATUS_INTERNAL_ERROR;
 
430
                }
 
431
                method->auth_ctx        = ctx;
 
432
                method->depth           = i;
 
433
                DLIST_ADD_END(ctx->methods, method, struct auth_method_context *);
 
434
        }
 
435
 
 
436
        if (!ctx->methods) {
 
437
                return NT_STATUS_INTERNAL_ERROR;
 
438
        }
 
439
 
 
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;
 
445
 
 
446
        *auth_ctx = ctx;
 
447
 
 
448
        return NT_STATUS_OK;
 
449
}
 
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)
 
459
{
 
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);
 
464
                break;
 
465
        case ROLE_DOMAIN_MEMBER:
 
466
                auth_methods = lp_parm_string_list(mem_ctx, lp_ctx, NULL, "auth methods", "member server", NULL);
 
467
                break;
 
468
        case ROLE_DOMAIN_CONTROLLER:
 
469
                auth_methods = lp_parm_string_list(mem_ctx, lp_ctx, NULL, "auth methods", "domain controller", NULL);
 
470
                break;
 
471
        }
 
472
        return auth_context_create_methods(mem_ctx, auth_methods, ev, msg, lp_ctx, auth_ctx);
 
473
}
 
474
 
 
475
 
 
476
/* the list of currently registered AUTH backends */
 
477
static struct auth_backend {
 
478
        const struct auth_operations *ops;
 
479
} *backends = NULL;
 
480
static int num_backends;
 
481
 
 
482
/*
 
483
  register a AUTH backend. 
 
484
 
 
485
  The 'name' can be later used by other backends to find the operations
 
486
  structure for this backend.
 
487
*/
 
488
_PUBLIC_ NTSTATUS auth_register(const struct auth_operations *ops)
 
489
{
 
490
        struct auth_operations *new_ops;
 
491
        
 
492
        if (auth_backend_byname(ops->name) != NULL) {
 
493
                /* its already registered! */
 
494
                DEBUG(0,("AUTH backend '%s' already registered\n", 
 
495
                         ops->name));
 
496
                return NT_STATUS_OBJECT_NAME_COLLISION;
 
497
        }
 
498
 
 
499
        backends = talloc_realloc(talloc_autofree_context(), backends, 
 
500
                                  struct auth_backend, num_backends+1);
 
501
        NT_STATUS_HAVE_NO_MEMORY(backends);
 
502
 
 
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);
 
507
 
 
508
        backends[num_backends].ops = new_ops;
 
509
 
 
510
        num_backends++;
 
511
 
 
512
        DEBUG(3,("AUTH backend '%s' registered\n", 
 
513
                 ops->name));
 
514
 
 
515
        return NT_STATUS_OK;
 
516
}
 
517
 
 
518
/*
 
519
  return the operations structure for a named backend of the specified type
 
520
*/
 
521
const struct auth_operations *auth_backend_byname(const char *name)
 
522
{
 
523
        int i;
 
524
 
 
525
        for (i=0;i<num_backends;i++) {
 
526
                if (strcmp(backends[i].ops->name, name) == 0) {
 
527
                        return backends[i].ops;
 
528
                }
 
529
        }
 
530
 
 
531
        return NULL;
 
532
}
 
533
 
 
534
/*
 
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
 
538
*/
 
539
const struct auth_critical_sizes *auth_interface_version(void)
 
540
{
 
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)
 
548
        };
 
549
 
 
550
        return &critical_sizes;
 
551
}
 
552
 
 
553
_PUBLIC_ NTSTATUS auth_init(void)
 
554
{
 
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);
 
562
 
 
563
        init_module_fn static_init[] = { STATIC_auth_MODULES };
 
564
        
 
565
        if (initialized) return NT_STATUS_OK;
 
566
        initialized = true;
 
567
        
 
568
        run_init_functions(static_init);
 
569
        
 
570
        return NT_STATUS_OK;    
 
571
}
 
572
 
 
573
NTSTATUS server_service_auth_init(void)
 
574
{
 
575
        return auth_init();
 
576
}