/src/samba/source3/auth/auth.c
Line | Count | Source |
1 | | /* |
2 | | Unix SMB/CIFS implementation. |
3 | | Password and authentication handling |
4 | | Copyright (C) Andrew Bartlett 2001-2002 |
5 | | |
6 | | This program is free software; you can redistribute it and/or modify |
7 | | it under the terms of the GNU General Public License as published by |
8 | | the Free Software Foundation; either version 3 of the License, or |
9 | | (at your option) any later version. |
10 | | |
11 | | This program is distributed in the hope that it will be useful, |
12 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | | GNU General Public License for more details. |
15 | | |
16 | | You should have received a copy of the GNU General Public License |
17 | | along with this program. If not, see <http://www.gnu.org/licenses/>. |
18 | | */ |
19 | | |
20 | | #include "includes.h" |
21 | | #include "auth.h" |
22 | | #include "../lib/tsocket/tsocket.h" |
23 | | |
24 | | #include "param/param.h" |
25 | | #include "../lib/messaging/messaging.h" |
26 | | #include "lib/global_contexts.h" |
27 | | |
28 | | #undef DBGC_CLASS |
29 | 0 | #define DBGC_CLASS DBGC_AUTH |
30 | | |
31 | | static_decl_auth; |
32 | | |
33 | | static struct auth_init_function_entry *auth_backends = NULL; |
34 | | |
35 | | static struct auth_init_function_entry *auth_find_backend_entry(const char *name); |
36 | | |
37 | | NTSTATUS smb_register_auth(int version, const char *name, auth_init_function init) |
38 | 0 | { |
39 | 0 | struct auth_init_function_entry *entry = NULL; |
40 | |
|
41 | 0 | if (version != AUTH_INTERFACE_VERSION) { |
42 | 0 | DEBUG(0,("Can't register auth_method!\n" |
43 | 0 | "You tried to register an auth module with AUTH_INTERFACE_VERSION %d, while this version of samba uses %d\n", |
44 | 0 | version,AUTH_INTERFACE_VERSION)); |
45 | 0 | return NT_STATUS_OBJECT_TYPE_MISMATCH; |
46 | 0 | } |
47 | | |
48 | 0 | if (!name || !init) { |
49 | 0 | return NT_STATUS_INVALID_PARAMETER; |
50 | 0 | } |
51 | | |
52 | 0 | DEBUG(5,("Attempting to register auth backend %s\n", name)); |
53 | |
|
54 | 0 | if (auth_find_backend_entry(name)) { |
55 | 0 | DEBUG(0,("There already is an auth method registered with the name %s!\n", name)); |
56 | 0 | return NT_STATUS_OBJECT_NAME_COLLISION; |
57 | 0 | } |
58 | | |
59 | 0 | entry = SMB_XMALLOC_P(struct auth_init_function_entry); |
60 | 0 | entry->name = smb_xstrdup(name); |
61 | 0 | entry->init = init; |
62 | |
|
63 | 0 | DLIST_ADD(auth_backends, entry); |
64 | 0 | DEBUG(5,("Successfully added auth method '%s'\n", name)); |
65 | 0 | return NT_STATUS_OK; |
66 | 0 | } |
67 | | |
68 | | static struct auth_init_function_entry *auth_find_backend_entry(const char *name) |
69 | 0 | { |
70 | 0 | struct auth_init_function_entry *entry = auth_backends; |
71 | |
|
72 | 0 | while(entry) { |
73 | 0 | if (strcmp(entry->name, name)==0) return entry; |
74 | 0 | entry = entry->next; |
75 | 0 | } |
76 | | |
77 | 0 | return NULL; |
78 | 0 | } |
79 | | |
80 | | /**************************************************************************** |
81 | | Try to get a challenge out of the various authentication modules. |
82 | | Returns a const char of length 8 bytes. |
83 | | ****************************************************************************/ |
84 | | |
85 | | NTSTATUS auth_get_ntlm_challenge(struct auth_context *auth_context, |
86 | | uint8_t chal[8]) |
87 | 0 | { |
88 | 0 | if (auth_context->challenge.length) { |
89 | 0 | DBG_INFO("get_ntlm_challenge (auth subsystem): returning " |
90 | 0 | "previous challenge by module %s (normal)\n", |
91 | 0 | auth_context->challenge_set_by); |
92 | 0 | memcpy(chal, auth_context->challenge.data, 8); |
93 | 0 | return NT_STATUS_OK; |
94 | 0 | } |
95 | | |
96 | 0 | auth_context->challenge = data_blob_talloc(auth_context, NULL, 8); |
97 | 0 | if (auth_context->challenge.data == NULL) { |
98 | 0 | DBG_WARNING("data_blob_talloc failed\n"); |
99 | 0 | return NT_STATUS_NO_MEMORY; |
100 | 0 | } |
101 | 0 | generate_random_buffer( |
102 | 0 | auth_context->challenge.data, auth_context->challenge.length); |
103 | |
|
104 | 0 | auth_context->challenge_set_by = "random"; |
105 | |
|
106 | 0 | memcpy(chal, auth_context->challenge.data, 8); |
107 | 0 | return NT_STATUS_OK; |
108 | 0 | } |
109 | | |
110 | | |
111 | | /** |
112 | | * Check user is in correct domain (if required) |
113 | | * |
114 | | * @param user Only used to fill in the debug message |
115 | | * |
116 | | * @param domain The domain to be verified |
117 | | * |
118 | | * @return True if the user can connect with that domain, |
119 | | * False otherwise. |
120 | | **/ |
121 | | |
122 | | static bool check_domain_match(const char *user, const char *domain) |
123 | 0 | { |
124 | | /* |
125 | | * If we aren't serving to trusted domains, we must make sure that |
126 | | * the validation request comes from an account in the same domain |
127 | | * as the Samba server |
128 | | */ |
129 | |
|
130 | 0 | if (!lp_allow_trusted_domains() && |
131 | 0 | !(strequal("", domain) || |
132 | 0 | strequal(lp_workgroup(), domain) || |
133 | 0 | is_myname(domain))) { |
134 | 0 | DEBUG(1, ("check_domain_match: Attempt to connect as user %s from domain %s denied.\n", user, domain)); |
135 | 0 | return False; |
136 | 0 | } else { |
137 | 0 | return True; |
138 | 0 | } |
139 | 0 | } |
140 | | |
141 | | /** |
142 | | * Check a user's Plaintext, LM or NTLM password. |
143 | | * |
144 | | * Check a user's password, as given in the user_info struct and return various |
145 | | * interesting details in the server_info struct. |
146 | | * |
147 | | * This function does NOT need to be in a become_root()/unbecome_root() pair |
148 | | * as it makes the calls itself when needed. |
149 | | * |
150 | | * The return value takes precedence over the contents of the server_info |
151 | | * struct. When the return is other than NT_STATUS_OK the contents |
152 | | * of that structure is undefined. |
153 | | * |
154 | | * @param user_info Contains the user supplied components, including the passwords. |
155 | | * Must be created with make_user_info() or one of its wrappers. |
156 | | * |
157 | | * @param auth_context Supplies the challenges and some other data. |
158 | | * Must be created with make_auth_context(), and the challenges should be |
159 | | * filled in, either at creation or by calling the challenge generation |
160 | | * function auth_get_challenge(). |
161 | | * |
162 | | * @param pserver_info If successful, contains information about the authentication, |
163 | | * including a struct samu struct describing the user. |
164 | | * |
165 | | * @param pauthoritative Indicates if the result should be treated as final |
166 | | * result. |
167 | | * |
168 | | * @return An NTSTATUS with NT_STATUS_OK or an appropriate error. |
169 | | * |
170 | | **/ |
171 | | NTSTATUS auth_check_ntlm_password(TALLOC_CTX *mem_ctx, |
172 | | const struct auth_context *auth_context, |
173 | | const struct auth_usersupplied_info *user_info, |
174 | | struct auth_serversupplied_info **pserver_info, |
175 | | uint8_t *pauthoritative) |
176 | 0 | { |
177 | 0 | TALLOC_CTX *frame; |
178 | 0 | const char *auth_method_name = ""; |
179 | | /* if all the modules say 'not for me' this is reasonable */ |
180 | 0 | NTSTATUS nt_status = NT_STATUS_NOT_IMPLEMENTED; |
181 | 0 | const char *unix_username; |
182 | 0 | struct auth_methods *auth_method; |
183 | 0 | struct auth_serversupplied_info *server_info = NULL; |
184 | 0 | struct dom_sid sid = {0}; |
185 | 0 | struct imessaging_context *msg_ctx = NULL; |
186 | 0 | struct loadparm_context *lp_ctx = NULL; |
187 | |
|
188 | 0 | if (user_info == NULL || auth_context == NULL || pserver_info == NULL) { |
189 | 0 | return NT_STATUS_LOGON_FAILURE; |
190 | 0 | } |
191 | | |
192 | 0 | frame = talloc_stackframe(); |
193 | |
|
194 | 0 | if (lp_auth_event_notification()) { |
195 | 0 | lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers()); |
196 | 0 | msg_ctx = imessaging_client_init( |
197 | 0 | frame, lp_ctx, global_event_context()); |
198 | 0 | } |
199 | |
|
200 | 0 | *pauthoritative = 1; |
201 | |
|
202 | 0 | DBG_NOTICE("check_ntlm_password: Checking password for unmapped user " |
203 | 0 | "[%s]\\[%s]@[%s] with the new password interface\n", |
204 | 0 | user_info->client.domain_name, |
205 | 0 | user_info->client.account_name, |
206 | 0 | user_info->workstation_name); |
207 | |
|
208 | 0 | DBG_NOTICE("check_ntlm_password: mapped user is: [%s]\\[%s]@[%s]\n", |
209 | 0 | user_info->mapped.domain_name, |
210 | 0 | user_info->mapped.account_name, |
211 | 0 | user_info->workstation_name); |
212 | |
|
213 | 0 | if (auth_context->challenge.length != 8) { |
214 | 0 | DEBUG(0, ("check_ntlm_password: Invalid challenge stored for this auth context - cannot continue\n")); |
215 | 0 | nt_status = NT_STATUS_LOGON_FAILURE; |
216 | 0 | goto fail; |
217 | 0 | } |
218 | | |
219 | 0 | if (auth_context->challenge_set_by) |
220 | 0 | DEBUG(10, ("check_ntlm_password: auth_context challenge created by %s\n", |
221 | 0 | auth_context->challenge_set_by)); |
222 | |
|
223 | 0 | DEBUG(10, ("challenge is: \n")); |
224 | 0 | dump_data(5, auth_context->challenge.data, auth_context->challenge.length); |
225 | |
|
226 | 0 | #ifdef DEBUG_PASSWORD |
227 | 0 | DEBUG(100, ("user_info has passwords of length %d and %d\n", |
228 | 0 | (int)user_info->password.response.lanman.length, (int)user_info->password.response.nt.length)); |
229 | 0 | DEBUG(100, ("lm:\n")); |
230 | 0 | dump_data(100, user_info->password.response.lanman.data, user_info->password.response.lanman.length); |
231 | 0 | DEBUG(100, ("nt:\n")); |
232 | 0 | dump_data(100, user_info->password.response.nt.data, user_info->password.response.nt.length); |
233 | 0 | #endif |
234 | | |
235 | | /* This needs to be sorted: If it doesn't match, what should we do? */ |
236 | 0 | if (!check_domain_match(user_info->client.account_name, |
237 | 0 | user_info->mapped.domain_name)) { |
238 | 0 | nt_status = NT_STATUS_LOGON_FAILURE; |
239 | 0 | goto fail; |
240 | 0 | } |
241 | | |
242 | 0 | for (auth_method = auth_context->auth_method_list;auth_method; auth_method = auth_method->next) { |
243 | |
|
244 | 0 | auth_method_name = auth_method->name; |
245 | |
|
246 | 0 | nt_status = auth_method->auth(auth_context, |
247 | 0 | auth_method->private_data, |
248 | 0 | talloc_tos(), |
249 | 0 | user_info, |
250 | 0 | &server_info); |
251 | |
|
252 | 0 | if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_NOT_IMPLEMENTED)) { |
253 | 0 | break; |
254 | 0 | } |
255 | | |
256 | 0 | DBG_DEBUG("%s had nothing to say\n", auth_method->name); |
257 | 0 | } |
258 | |
|
259 | 0 | if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NOT_IMPLEMENTED)) { |
260 | 0 | *pauthoritative = 0; |
261 | 0 | nt_status = NT_STATUS_NO_SUCH_USER; |
262 | 0 | } |
263 | |
|
264 | 0 | if (!NT_STATUS_IS_OK(nt_status)) { |
265 | 0 | DBG_INFO("%s authentication for user [%s] FAILED with " |
266 | 0 | "error %s, authoritative=%u\n", |
267 | 0 | auth_method_name, |
268 | 0 | user_info->client.account_name, |
269 | 0 | nt_errstr(nt_status), |
270 | 0 | *pauthoritative); |
271 | 0 | goto fail; |
272 | 0 | } |
273 | | |
274 | 0 | DBG_NOTICE("%s authentication for user [%s] succeeded\n", |
275 | 0 | auth_method_name, user_info->client.account_name); |
276 | |
|
277 | 0 | unix_username = server_info->unix_name; |
278 | | |
279 | | /* We skip doing this step if the caller asked us not to */ |
280 | 0 | if (!(user_info->flags & USER_INFO_INFO3_AND_NO_AUTHZ) |
281 | 0 | && !(server_info->guest)) { |
282 | 0 | const char *rhost; |
283 | |
|
284 | 0 | if (tsocket_address_is_inet(user_info->remote_host, "ip")) { |
285 | 0 | rhost = tsocket_address_inet_addr_string( |
286 | 0 | user_info->remote_host, talloc_tos()); |
287 | 0 | if (rhost == NULL) { |
288 | 0 | nt_status = NT_STATUS_NO_MEMORY; |
289 | 0 | goto fail; |
290 | 0 | } |
291 | 0 | } else { |
292 | 0 | rhost = "127.0.0.1"; |
293 | 0 | } |
294 | | |
295 | | /* We might not be root if we are an RPC call */ |
296 | 0 | become_root(); |
297 | 0 | nt_status = smb_pam_accountcheck(unix_username, rhost); |
298 | 0 | unbecome_root(); |
299 | |
|
300 | 0 | if (NT_STATUS_IS_OK(nt_status)) { |
301 | 0 | DEBUG(5, ("check_ntlm_password: PAM Account for user [%s] " |
302 | 0 | "succeeded\n", unix_username)); |
303 | 0 | } else { |
304 | 0 | DEBUG(3, ("check_ntlm_password: PAM Account for user [%s] " |
305 | 0 | "FAILED with error %s\n", |
306 | 0 | unix_username, nt_errstr(nt_status))); |
307 | 0 | } |
308 | 0 | } |
309 | | |
310 | 0 | if (!NT_STATUS_IS_OK(nt_status)) { |
311 | 0 | goto fail; |
312 | 0 | } |
313 | | |
314 | 0 | nt_status = get_user_sid_info3_and_extra(server_info->info3, |
315 | 0 | &server_info->extra, |
316 | 0 | &sid); |
317 | 0 | if (!NT_STATUS_IS_OK(nt_status)) { |
318 | 0 | sid = (struct dom_sid) {0}; |
319 | 0 | } |
320 | |
|
321 | 0 | log_authentication_event(msg_ctx, |
322 | 0 | lp_ctx, |
323 | 0 | &auth_context->start_time, |
324 | 0 | user_info, |
325 | 0 | nt_status, |
326 | 0 | server_info->info3->base.logon_domain.string, |
327 | 0 | server_info->info3->base.account_name.string, |
328 | 0 | &sid, |
329 | 0 | NULL /* client_audit_info */, |
330 | 0 | NULL /* server_audit_info */); |
331 | |
|
332 | 0 | DEBUG(server_info->guest ? 5 : 2, |
333 | 0 | ("check_ntlm_password: %sauthentication for user " |
334 | 0 | "[%s] -> [%s] -> [%s] succeeded\n", |
335 | 0 | server_info->guest ? "guest " : "", |
336 | 0 | user_info->client.account_name, |
337 | 0 | user_info->mapped.account_name, |
338 | 0 | unix_username)); |
339 | |
|
340 | 0 | *pserver_info = talloc_move(mem_ctx, &server_info); |
341 | |
|
342 | 0 | TALLOC_FREE(frame); |
343 | 0 | return NT_STATUS_OK; |
344 | | |
345 | 0 | fail: |
346 | | |
347 | | /* failed authentication; check for guest lapping */ |
348 | | |
349 | | /* |
350 | | * Please try not to change this string, it is probably in use |
351 | | * in audit logging tools |
352 | | */ |
353 | 0 | DEBUG(2, ("check_ntlm_password: Authentication for user " |
354 | 0 | "[%s] -> [%s] FAILED with error %s, authoritative=%u\n", |
355 | 0 | user_info->client.account_name, user_info->mapped.account_name, |
356 | 0 | nt_errstr(nt_status), *pauthoritative)); |
357 | |
|
358 | 0 | log_authentication_event(msg_ctx, |
359 | 0 | lp_ctx, |
360 | 0 | &auth_context->start_time, |
361 | 0 | user_info, |
362 | 0 | nt_status, |
363 | 0 | NULL, |
364 | 0 | NULL, |
365 | 0 | NULL, |
366 | 0 | NULL /* client_audit_info */, |
367 | 0 | NULL /* server_audit_info */); |
368 | |
|
369 | 0 | ZERO_STRUCTP(pserver_info); |
370 | |
|
371 | 0 | TALLOC_FREE(frame); |
372 | |
|
373 | 0 | return nt_status; |
374 | 0 | } |
375 | | |
376 | | /*************************************************************************** |
377 | | Clear out a auth_context, and destroy the attached TALLOC_CTX |
378 | | ***************************************************************************/ |
379 | | |
380 | | static int auth_context_destructor(void *ptr) |
381 | 0 | { |
382 | 0 | struct auth_context *ctx = talloc_get_type(ptr, struct auth_context); |
383 | 0 | struct auth_methods *am; |
384 | | |
385 | | |
386 | | /* Free private data of context's authentication methods */ |
387 | 0 | for (am = ctx->auth_method_list; am; am = am->next) { |
388 | 0 | TALLOC_FREE(am->private_data); |
389 | 0 | } |
390 | |
|
391 | 0 | return 0; |
392 | 0 | } |
393 | | |
394 | | /*************************************************************************** |
395 | | Make a auth_info struct |
396 | | ***************************************************************************/ |
397 | | |
398 | | static NTSTATUS make_auth_context(TALLOC_CTX *mem_ctx, |
399 | | struct auth_context **auth_context) |
400 | 0 | { |
401 | 0 | struct auth_context *ctx; |
402 | |
|
403 | 0 | ctx = talloc_zero(mem_ctx, struct auth_context); |
404 | 0 | if (!ctx) { |
405 | 0 | DEBUG(0,("make_auth_context: talloc failed!\n")); |
406 | 0 | return NT_STATUS_NO_MEMORY; |
407 | 0 | } |
408 | | |
409 | 0 | ctx->start_time = timeval_current(); |
410 | |
|
411 | 0 | talloc_set_destructor((TALLOC_CTX *)ctx, auth_context_destructor); |
412 | |
|
413 | 0 | *auth_context = ctx; |
414 | 0 | return NT_STATUS_OK; |
415 | 0 | } |
416 | | |
417 | | static bool load_auth_module( |
418 | | struct auth_context *auth_context, |
419 | | const char *module, |
420 | | struct auth_methods **ret) |
421 | 0 | { |
422 | 0 | static bool initialised_static_modules = False; |
423 | |
|
424 | 0 | struct auth_init_function_entry *entry; |
425 | 0 | char *module_name = smb_xstrdup(module); |
426 | 0 | char *module_params = NULL; |
427 | 0 | char *p; |
428 | 0 | bool good = False; |
429 | | |
430 | | /* Initialise static modules if not done so yet */ |
431 | 0 | if(!initialised_static_modules) { |
432 | 0 | static_init_auth(NULL); |
433 | 0 | initialised_static_modules = True; |
434 | 0 | } |
435 | |
|
436 | 0 | DEBUG(5,("load_auth_module: Attempting to find an auth method to match %s\n", |
437 | 0 | module)); |
438 | |
|
439 | 0 | p = strchr(module_name, ':'); |
440 | 0 | if (p) { |
441 | 0 | *p = 0; |
442 | 0 | module_params = p+1; |
443 | 0 | trim_char(module_params, ' ', ' '); |
444 | 0 | } |
445 | |
|
446 | 0 | trim_char(module_name, ' ', ' '); |
447 | |
|
448 | 0 | entry = auth_find_backend_entry(module_name); |
449 | |
|
450 | 0 | if (entry == NULL) { |
451 | 0 | if (NT_STATUS_IS_OK(smb_probe_module("auth", module_name))) { |
452 | 0 | entry = auth_find_backend_entry(module_name); |
453 | 0 | } |
454 | 0 | } |
455 | |
|
456 | 0 | if (entry != NULL) { |
457 | 0 | if (!NT_STATUS_IS_OK(entry->init(auth_context, module_params, ret))) { |
458 | 0 | DEBUG(0,("load_auth_module: auth method %s did not correctly init\n", |
459 | 0 | module_name)); |
460 | 0 | } else { |
461 | 0 | DEBUG(5,("load_auth_module: auth method %s has a valid init\n", |
462 | 0 | module_name)); |
463 | 0 | good = True; |
464 | 0 | } |
465 | 0 | } else { |
466 | 0 | DEBUG(0,("load_auth_module: can't find auth method %s!\n", module_name)); |
467 | 0 | } |
468 | |
|
469 | 0 | SAFE_FREE(module_name); |
470 | 0 | return good; |
471 | 0 | } |
472 | | |
473 | | /*************************************************************************** |
474 | | Make a auth_info struct for the auth subsystem |
475 | | ***************************************************************************/ |
476 | | |
477 | | static NTSTATUS make_auth_context_text_list(TALLOC_CTX *mem_ctx, |
478 | | struct auth_context **auth_context, |
479 | | char **text_list) |
480 | 0 | { |
481 | 0 | struct auth_methods *list = NULL; |
482 | 0 | struct auth_methods *t, *method = NULL; |
483 | 0 | NTSTATUS nt_status; |
484 | |
|
485 | 0 | if (!text_list) { |
486 | 0 | DEBUG(2,("make_auth_context_text_list: No auth method list!?\n")); |
487 | 0 | return NT_STATUS_UNSUCCESSFUL; |
488 | 0 | } |
489 | | |
490 | 0 | nt_status = make_auth_context(mem_ctx, auth_context); |
491 | |
|
492 | 0 | if (!NT_STATUS_IS_OK(nt_status)) { |
493 | 0 | return nt_status; |
494 | 0 | } |
495 | | |
496 | 0 | for (;*text_list; text_list++) { |
497 | 0 | if (load_auth_module(*auth_context, *text_list, &t)) { |
498 | 0 | DLIST_ADD_END(list, t); |
499 | 0 | } |
500 | 0 | } |
501 | |
|
502 | 0 | (*auth_context)->auth_method_list = list; |
503 | | |
504 | | /* Look for the first module to provide a prepare_gensec and |
505 | | * make_auth4_context hook, and set that if provided */ |
506 | 0 | for (method = (*auth_context)->auth_method_list; method; method = method->next) { |
507 | 0 | if (method->prepare_gensec && method->make_auth4_context) { |
508 | 0 | (*auth_context)->prepare_gensec = method->prepare_gensec; |
509 | 0 | (*auth_context)->make_auth4_context = method->make_auth4_context; |
510 | 0 | break; |
511 | 0 | } |
512 | 0 | } |
513 | 0 | return NT_STATUS_OK; |
514 | 0 | } |
515 | | |
516 | | static NTSTATUS make_auth_context_specific(TALLOC_CTX *mem_ctx, |
517 | | struct auth_context **auth_context, |
518 | | const char *methods) |
519 | 0 | { |
520 | 0 | char **method_list; |
521 | 0 | NTSTATUS status; |
522 | |
|
523 | 0 | method_list = str_list_make_v3(talloc_tos(), methods, NULL); |
524 | 0 | if (method_list == NULL) { |
525 | 0 | return NT_STATUS_NO_MEMORY; |
526 | 0 | } |
527 | | |
528 | 0 | status = make_auth_context_text_list( |
529 | 0 | mem_ctx, auth_context, method_list); |
530 | |
|
531 | 0 | TALLOC_FREE(method_list); |
532 | |
|
533 | 0 | return status; |
534 | 0 | } |
535 | | |
536 | | /*************************************************************************** |
537 | | Make a auth_context struct for the auth subsystem |
538 | | ***************************************************************************/ |
539 | | |
540 | | NTSTATUS make_auth3_context_for_ntlm(TALLOC_CTX *mem_ctx, |
541 | | struct auth_context **auth_context) |
542 | 0 | { |
543 | 0 | const char *methods = NULL; |
544 | 0 | const char *role = NULL; |
545 | |
|
546 | 0 | switch (lp_server_role()) { |
547 | 0 | case ROLE_ACTIVE_DIRECTORY_DC: |
548 | 0 | role = "'active directory domain controller'"; |
549 | 0 | methods = "samba4"; |
550 | 0 | break; |
551 | 0 | case ROLE_DOMAIN_MEMBER: |
552 | 0 | role = "'domain member'"; |
553 | 0 | methods = "anonymous sam winbind sam_ignoredomain"; |
554 | 0 | break; |
555 | 0 | case ROLE_DOMAIN_BDC: |
556 | 0 | case ROLE_DOMAIN_PDC: |
557 | 0 | case ROLE_IPA_DC: |
558 | 0 | role = "'DC'"; |
559 | 0 | methods = "anonymous sam winbind sam_ignoredomain"; |
560 | 0 | break; |
561 | 0 | case ROLE_STANDALONE: |
562 | 0 | if (lp_encrypt_passwords()) { |
563 | 0 | role = "'standalone server', encrypt passwords = yes"; |
564 | 0 | methods = "anonymous sam_ignoredomain"; |
565 | 0 | } else { |
566 | 0 | role = "'standalone server', encrypt passwords = no"; |
567 | 0 | methods = "anonymous unix"; |
568 | 0 | } |
569 | 0 | break; |
570 | 0 | default: |
571 | 0 | DEBUG(5,("Unknown auth method!\n")); |
572 | 0 | return NT_STATUS_UNSUCCESSFUL; |
573 | 0 | } |
574 | | |
575 | 0 | DBG_INFO("Making default auth method list for server role = %s\n", |
576 | 0 | role); |
577 | |
|
578 | 0 | return make_auth_context_specific(mem_ctx, auth_context, methods); |
579 | 0 | } |
580 | | |
581 | | NTSTATUS make_auth3_context_for_netlogon(TALLOC_CTX *mem_ctx, |
582 | | struct auth_context **auth_context) |
583 | 0 | { |
584 | 0 | const char *methods = NULL; |
585 | 0 | NTSTATUS status; |
586 | |
|
587 | 0 | switch (lp_server_role()) { |
588 | 0 | case ROLE_DOMAIN_BDC: |
589 | 0 | case ROLE_DOMAIN_PDC: |
590 | 0 | case ROLE_IPA_DC: |
591 | 0 | methods = "sam_netlogon3 winbind"; |
592 | 0 | break; |
593 | | |
594 | 0 | default: |
595 | 0 | DBG_ERR("Invalid server role!\n"); |
596 | 0 | return NT_STATUS_INVALID_SERVER_STATE; |
597 | 0 | } |
598 | | |
599 | 0 | status = make_auth_context_specific(mem_ctx, auth_context, methods); |
600 | 0 | if (!NT_STATUS_IS_OK(status)) { |
601 | 0 | return status; |
602 | 0 | } |
603 | | |
604 | 0 | (*auth_context)->for_netlogon = true; |
605 | 0 | return NT_STATUS_OK; |
606 | 0 | } |
607 | | |
608 | | NTSTATUS make_auth3_context_for_winbind(TALLOC_CTX *mem_ctx, |
609 | | struct auth_context **auth_context) |
610 | 0 | { |
611 | 0 | const char *methods = NULL; |
612 | |
|
613 | 0 | switch (lp_server_role()) { |
614 | 0 | case ROLE_STANDALONE: |
615 | 0 | case ROLE_DOMAIN_MEMBER: |
616 | 0 | case ROLE_DOMAIN_BDC: |
617 | 0 | case ROLE_DOMAIN_PDC: |
618 | 0 | case ROLE_IPA_DC: |
619 | 0 | methods = "sam"; |
620 | 0 | break; |
621 | 0 | case ROLE_ACTIVE_DIRECTORY_DC: |
622 | 0 | methods = "samba4:sam"; |
623 | 0 | break; |
624 | 0 | default: |
625 | 0 | DEBUG(5,("Unknown auth method!\n")); |
626 | 0 | return NT_STATUS_UNSUCCESSFUL; |
627 | 0 | } |
628 | | |
629 | 0 | return make_auth_context_specific(mem_ctx, auth_context, methods); |
630 | 0 | } |
631 | | |
632 | | bool auth3_context_set_challenge( |
633 | | struct auth_context *ctx, |
634 | | const uint8_t chal[8], |
635 | | const char *challenge_set_by) |
636 | 0 | { |
637 | 0 | ctx->challenge = data_blob_talloc(ctx, chal, 8); |
638 | 0 | if (ctx->challenge.data == NULL) { |
639 | 0 | return false; |
640 | 0 | } |
641 | 0 | ctx->challenge_set_by = talloc_strdup(ctx, challenge_set_by); |
642 | 0 | if (ctx->challenge_set_by == NULL) { |
643 | 0 | return false; |
644 | 0 | } |
645 | 0 | return true; |
646 | 0 | } |