s4:lib/socket: simplify iface_list_wildcard() and its callers
[Samba.git] / source3 / auth / auth_util.c
blobfb9e8c8258a44faafb404caddf400989b1dcf6e8
1 /*
2 Unix SMB/CIFS implementation.
3 Authentication utility functions
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001-2011
6 Copyright (C) Jeremy Allison 2000-2001
7 Copyright (C) Rafal Szczesniak 2002
8 Copyright (C) Volker Lendecke 2006-2008
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "includes.h"
25 #include "auth.h"
26 #include "../libcli/auth/libcli_auth.h"
27 #include "../lib/crypto/arcfour.h"
28 #include "rpc_client/init_lsa.h"
29 #include "../libcli/security/security.h"
30 #include "../lib/util/util_pw.h"
31 #include "lib/winbind_util.h"
32 #include "passdb.h"
33 #include "../librpc/gen_ndr/ndr_auth.h"
34 #include "../auth/auth_sam_reply.h"
35 #include "../librpc/gen_ndr/idmap.h"
36 #include "lib/param/loadparm.h"
38 #undef DBGC_CLASS
39 #define DBGC_CLASS DBGC_AUTH
41 /****************************************************************************
42 Create a UNIX user on demand.
43 ****************************************************************************/
45 static int _smb_create_user(const char *domain, const char *unix_username, const char *homedir)
47 TALLOC_CTX *ctx = talloc_tos();
48 char *add_script;
49 int ret;
51 add_script = lp_add_user_script(ctx);
52 if (!add_script || !*add_script) {
53 return -1;
55 add_script = talloc_all_string_sub(ctx,
56 add_script,
57 "%u",
58 unix_username);
59 if (!add_script) {
60 return -1;
62 if (domain) {
63 add_script = talloc_all_string_sub(ctx,
64 add_script,
65 "%D",
66 domain);
67 if (!add_script) {
68 return -1;
71 if (homedir) {
72 add_script = talloc_all_string_sub(ctx,
73 add_script,
74 "%H",
75 homedir);
76 if (!add_script) {
77 return -1;
80 ret = smbrun(add_script,NULL);
81 flush_pwnam_cache();
82 DEBUG(ret ? 0 : 3,
83 ("smb_create_user: Running the command `%s' gave %d\n",
84 add_script,ret));
85 return ret;
88 /****************************************************************************
89 Create an auth_usersupplied_data structure after appropriate mapping.
90 ****************************************************************************/
92 NTSTATUS make_user_info_map(struct auth_usersupplied_info **user_info,
93 const char *smb_name,
94 const char *client_domain,
95 const char *workstation_name,
96 const struct tsocket_address *remote_address,
97 const DATA_BLOB *lm_pwd,
98 const DATA_BLOB *nt_pwd,
99 const struct samr_Password *lm_interactive_pwd,
100 const struct samr_Password *nt_interactive_pwd,
101 const char *plaintext,
102 enum auth_password_state password_state)
104 const char *domain;
105 NTSTATUS result;
106 bool was_mapped;
107 char *internal_username = NULL;
109 was_mapped = map_username(talloc_tos(), smb_name, &internal_username);
110 if (!internal_username) {
111 return NT_STATUS_NO_MEMORY;
114 DEBUG(5, ("Mapping user [%s]\\[%s] from workstation [%s]\n",
115 client_domain, smb_name, workstation_name));
117 domain = client_domain;
119 /* If you connect to a Windows domain member using a bogus domain name,
120 * the Windows box will map the BOGUS\user to SAMNAME\user. Thus, if
121 * the Windows box is a DC the name will become DOMAIN\user and be
122 * authenticated against AD, if the Windows box is a member server but
123 * not a DC the name will become WORKSTATION\user. A standalone
124 * non-domain member box will also map to WORKSTATION\user.
125 * This also deals with the client passing in a "" domain */
127 if (!is_trusted_domain(domain) &&
128 !strequal(domain, my_sam_name()) &&
129 !strequal(domain, get_global_sam_name()))
131 if (lp_map_untrusted_to_domain())
132 domain = my_sam_name();
133 else
134 domain = get_global_sam_name();
135 DEBUG(5, ("Mapped domain from [%s] to [%s] for user [%s] from "
136 "workstation [%s]\n",
137 client_domain, domain, smb_name, workstation_name));
140 /* We know that the given domain is trusted (and we are allowing them),
141 * it is our global SAM name, or for legacy behavior it is our
142 * primary domain name */
144 result = make_user_info(user_info, smb_name, internal_username,
145 client_domain, domain, workstation_name,
146 remote_address, lm_pwd, nt_pwd,
147 lm_interactive_pwd, nt_interactive_pwd,
148 plaintext, password_state);
149 if (NT_STATUS_IS_OK(result)) {
150 /* We have tried mapping */
151 (*user_info)->mapped_state = true;
152 /* did we actually map the user to a different name? */
153 (*user_info)->was_mapped = was_mapped;
155 return result;
158 /****************************************************************************
159 Create an auth_usersupplied_data, making the DATA_BLOBs here.
160 Decrypt and encrypt the passwords.
161 ****************************************************************************/
163 bool make_user_info_netlogon_network(struct auth_usersupplied_info **user_info,
164 const char *smb_name,
165 const char *client_domain,
166 const char *workstation_name,
167 const struct tsocket_address *remote_address,
168 uint32 logon_parameters,
169 const uchar *lm_network_pwd,
170 int lm_pwd_len,
171 const uchar *nt_network_pwd,
172 int nt_pwd_len)
174 bool ret;
175 NTSTATUS status;
176 DATA_BLOB lm_blob = data_blob(lm_network_pwd, lm_pwd_len);
177 DATA_BLOB nt_blob = data_blob(nt_network_pwd, nt_pwd_len);
179 status = make_user_info_map(user_info,
180 smb_name, client_domain,
181 workstation_name,
182 remote_address,
183 lm_pwd_len ? &lm_blob : NULL,
184 nt_pwd_len ? &nt_blob : NULL,
185 NULL, NULL, NULL,
186 AUTH_PASSWORD_RESPONSE);
188 if (NT_STATUS_IS_OK(status)) {
189 (*user_info)->logon_parameters = logon_parameters;
191 ret = NT_STATUS_IS_OK(status) ? true : false;
193 data_blob_free(&lm_blob);
194 data_blob_free(&nt_blob);
195 return ret;
198 /****************************************************************************
199 Create an auth_usersupplied_data, making the DATA_BLOBs here.
200 Decrypt and encrypt the passwords.
201 ****************************************************************************/
203 bool make_user_info_netlogon_interactive(struct auth_usersupplied_info **user_info,
204 const char *smb_name,
205 const char *client_domain,
206 const char *workstation_name,
207 const struct tsocket_address *remote_address,
208 uint32 logon_parameters,
209 const uchar chal[8],
210 const uchar lm_interactive_pwd[16],
211 const uchar nt_interactive_pwd[16])
213 struct samr_Password lm_pwd;
214 struct samr_Password nt_pwd;
215 unsigned char local_lm_response[24];
216 unsigned char local_nt_response[24];
218 if (lm_interactive_pwd)
219 memcpy(lm_pwd.hash, lm_interactive_pwd, sizeof(lm_pwd.hash));
221 if (nt_interactive_pwd)
222 memcpy(nt_pwd.hash, nt_interactive_pwd, sizeof(nt_pwd.hash));
224 if (lm_interactive_pwd)
225 SMBOWFencrypt(lm_pwd.hash, chal,
226 local_lm_response);
228 if (nt_interactive_pwd)
229 SMBOWFencrypt(nt_pwd.hash, chal,
230 local_nt_response);
233 bool ret;
234 NTSTATUS nt_status;
235 DATA_BLOB local_lm_blob = data_blob_null;
236 DATA_BLOB local_nt_blob = data_blob_null;
238 if (lm_interactive_pwd) {
239 local_lm_blob = data_blob(local_lm_response,
240 sizeof(local_lm_response));
243 if (nt_interactive_pwd) {
244 local_nt_blob = data_blob(local_nt_response,
245 sizeof(local_nt_response));
248 nt_status = make_user_info_map(
249 user_info,
250 smb_name, client_domain, workstation_name,
251 remote_address,
252 lm_interactive_pwd ? &local_lm_blob : NULL,
253 nt_interactive_pwd ? &local_nt_blob : NULL,
254 lm_interactive_pwd ? &lm_pwd : NULL,
255 nt_interactive_pwd ? &nt_pwd : NULL,
256 NULL, AUTH_PASSWORD_HASH);
258 if (NT_STATUS_IS_OK(nt_status)) {
259 (*user_info)->logon_parameters = logon_parameters;
262 ret = NT_STATUS_IS_OK(nt_status) ? true : false;
263 data_blob_free(&local_lm_blob);
264 data_blob_free(&local_nt_blob);
265 return ret;
270 /****************************************************************************
271 Create an auth_usersupplied_data structure
272 ****************************************************************************/
274 bool make_user_info_for_reply(struct auth_usersupplied_info **user_info,
275 const char *smb_name,
276 const char *client_domain,
277 const struct tsocket_address *remote_address,
278 const uint8 chal[8],
279 DATA_BLOB plaintext_password)
282 DATA_BLOB local_lm_blob;
283 DATA_BLOB local_nt_blob;
284 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
285 char *plaintext_password_string;
287 * Not encrypted - do so.
290 DEBUG(5,("make_user_info_for_reply: User passwords not in encrypted "
291 "format.\n"));
292 if (plaintext_password.data && plaintext_password.length) {
293 unsigned char local_lm_response[24];
295 #ifdef DEBUG_PASSWORD
296 DEBUG(10,("Unencrypted password (len %d):\n",
297 (int)plaintext_password.length));
298 dump_data(100, plaintext_password.data,
299 plaintext_password.length);
300 #endif
302 SMBencrypt( (const char *)plaintext_password.data,
303 (const uchar*)chal, local_lm_response);
304 local_lm_blob = data_blob(local_lm_response, 24);
306 /* We can't do an NT hash here, as the password needs to be
307 case insensitive */
308 local_nt_blob = data_blob_null;
309 } else {
310 local_lm_blob = data_blob_null;
311 local_nt_blob = data_blob_null;
314 plaintext_password_string = talloc_strndup(talloc_tos(),
315 (const char *)plaintext_password.data,
316 plaintext_password.length);
317 if (!plaintext_password_string) {
318 return false;
321 ret = make_user_info(
322 user_info, smb_name, smb_name, client_domain, client_domain,
323 get_remote_machine_name(),
324 remote_address,
325 local_lm_blob.data ? &local_lm_blob : NULL,
326 local_nt_blob.data ? &local_nt_blob : NULL,
327 NULL, NULL,
328 plaintext_password_string,
329 AUTH_PASSWORD_PLAIN);
331 if (plaintext_password_string) {
332 memset(plaintext_password_string, '\0', strlen(plaintext_password_string));
333 talloc_free(plaintext_password_string);
336 data_blob_free(&local_lm_blob);
337 return NT_STATUS_IS_OK(ret) ? true : false;
340 /****************************************************************************
341 Create an auth_usersupplied_data structure
342 ****************************************************************************/
344 NTSTATUS make_user_info_for_reply_enc(struct auth_usersupplied_info **user_info,
345 const char *smb_name,
346 const char *client_domain,
347 const struct tsocket_address *remote_address,
348 DATA_BLOB lm_resp, DATA_BLOB nt_resp)
350 return make_user_info(user_info, smb_name, smb_name,
351 client_domain, client_domain,
352 get_remote_machine_name(),
353 remote_address,
354 lm_resp.data && (lm_resp.length > 0) ? &lm_resp : NULL,
355 nt_resp.data && (nt_resp.length > 0) ? &nt_resp : NULL,
356 NULL, NULL, NULL,
357 AUTH_PASSWORD_RESPONSE);
360 /****************************************************************************
361 Create a guest user_info blob, for anonymous authentication.
362 ****************************************************************************/
364 bool make_user_info_guest(const struct tsocket_address *remote_address,
365 struct auth_usersupplied_info **user_info)
367 NTSTATUS nt_status;
369 nt_status = make_user_info(user_info,
370 "","",
371 "","",
372 "",
373 remote_address,
374 NULL, NULL,
375 NULL, NULL,
376 NULL,
377 AUTH_PASSWORD_RESPONSE);
379 return NT_STATUS_IS_OK(nt_status) ? true : false;
382 static NTSTATUS log_nt_token(struct security_token *token)
384 TALLOC_CTX *frame = talloc_stackframe();
385 char *command;
386 char *group_sidstr;
387 size_t i;
389 if ((lp_log_nt_token_command(frame) == NULL) ||
390 (strlen(lp_log_nt_token_command(frame)) == 0)) {
391 TALLOC_FREE(frame);
392 return NT_STATUS_OK;
395 group_sidstr = talloc_strdup(frame, "");
396 for (i=1; i<token->num_sids; i++) {
397 group_sidstr = talloc_asprintf(
398 frame, "%s %s", group_sidstr,
399 sid_string_talloc(frame, &token->sids[i]));
402 command = talloc_string_sub(
403 frame, lp_log_nt_token_command(frame),
404 "%s", sid_string_talloc(frame, &token->sids[0]));
405 command = talloc_string_sub(frame, command, "%t", group_sidstr);
407 if (command == NULL) {
408 TALLOC_FREE(frame);
409 return NT_STATUS_NO_MEMORY;
412 DEBUG(8, ("running command: [%s]\n", command));
413 if (smbrun(command, NULL) != 0) {
414 DEBUG(0, ("Could not log NT token\n"));
415 TALLOC_FREE(frame);
416 return NT_STATUS_ACCESS_DENIED;
419 TALLOC_FREE(frame);
420 return NT_STATUS_OK;
424 * Create the token to use from server_info->info3 and
425 * server_info->sids (the info3/sam groups). Find the unix gids.
428 NTSTATUS create_local_token(TALLOC_CTX *mem_ctx,
429 const struct auth_serversupplied_info *server_info,
430 DATA_BLOB *session_key,
431 const char *smb_username, /* for ->sanitized_username, for %U subs */
432 struct auth_session_info **session_info_out)
434 struct security_token *t;
435 NTSTATUS status;
436 size_t i;
437 struct dom_sid tmp_sid;
438 struct auth_session_info *session_info;
439 struct unixid *ids;
440 fstring tmp;
442 /* Ensure we can't possible take a code path leading to a
443 * null defref. */
444 if (!server_info) {
445 return NT_STATUS_LOGON_FAILURE;
448 session_info = talloc_zero(mem_ctx, struct auth_session_info);
449 if (!session_info) {
450 return NT_STATUS_NO_MEMORY;
453 session_info->unix_token = talloc_zero(session_info, struct security_unix_token);
454 if (!session_info->unix_token) {
455 TALLOC_FREE(session_info);
456 return NT_STATUS_NO_MEMORY;
459 session_info->unix_token->uid = server_info->utok.uid;
460 session_info->unix_token->gid = server_info->utok.gid;
462 session_info->unix_info = talloc_zero(session_info, struct auth_user_info_unix);
463 if (!session_info->unix_info) {
464 TALLOC_FREE(session_info);
465 return NT_STATUS_NO_MEMORY;
468 session_info->unix_info->unix_name = talloc_strdup(session_info, server_info->unix_name);
469 if (!session_info->unix_info->unix_name) {
470 TALLOC_FREE(session_info);
471 return NT_STATUS_NO_MEMORY;
474 /* This is a potentially untrusted username for use in %U */
475 alpha_strcpy(tmp, smb_username, ". _-$", sizeof(tmp));
476 session_info->unix_info->sanitized_username =
477 talloc_strdup(session_info->unix_info, tmp);
479 if (session_key) {
480 data_blob_free(&session_info->session_key);
481 session_info->session_key = data_blob_talloc(session_info,
482 session_key->data,
483 session_key->length);
484 if (!session_info->session_key.data && session_key->length) {
485 return NT_STATUS_NO_MEMORY;
487 } else {
488 session_info->session_key = data_blob_talloc( session_info, server_info->session_key.data,
489 server_info->session_key.length);
492 /* We need to populate session_info->info with the information found in server_info->info3 */
493 status = make_user_info_SamBaseInfo(session_info, "", &server_info->info3->base,
494 server_info->guest == false,
495 &session_info->info);
496 if (!NT_STATUS_IS_OK(status)) {
497 DEBUG(0, ("conversion of info3 into auth_user_info failed!\n"));
498 TALLOC_FREE(session_info);
499 return status;
502 if (server_info->security_token) {
503 /* Just copy the token, it has already been finalised
504 * (nasty hack to support a cached guest/system session_info
507 session_info->security_token = dup_nt_token(session_info, server_info->security_token);
508 if (!session_info->security_token) {
509 TALLOC_FREE(session_info);
510 return NT_STATUS_NO_MEMORY;
513 session_info->unix_token->ngroups = server_info->utok.ngroups;
514 if (server_info->utok.ngroups != 0) {
515 session_info->unix_token->groups = (gid_t *)talloc_memdup(
516 session_info->unix_token, server_info->utok.groups,
517 sizeof(gid_t)*session_info->unix_token->ngroups);
518 } else {
519 session_info->unix_token->groups = NULL;
522 *session_info_out = session_info;
523 return NT_STATUS_OK;
527 * If winbind is not around, we can not make much use of the SIDs the
528 * domain controller provided us with. Likewise if the user name was
529 * mapped to some local unix user.
532 if (((lp_server_role() == ROLE_DOMAIN_MEMBER) && !winbind_ping()) ||
533 (server_info->nss_token)) {
534 char *found_username = NULL;
535 status = create_token_from_username(session_info,
536 server_info->unix_name,
537 server_info->guest,
538 &session_info->unix_token->uid,
539 &session_info->unix_token->gid,
540 &found_username,
541 &session_info->security_token);
542 if (NT_STATUS_IS_OK(status)) {
543 session_info->unix_info->unix_name = found_username;
545 } else {
546 status = create_local_nt_token_from_info3(session_info,
547 server_info->guest,
548 server_info->info3,
549 &server_info->extra,
550 &session_info->security_token);
553 if (!NT_STATUS_IS_OK(status)) {
554 return status;
557 /* Convert the SIDs to gids. */
559 session_info->unix_token->ngroups = 0;
560 session_info->unix_token->groups = NULL;
562 t = session_info->security_token;
564 ids = talloc_array(talloc_tos(), struct unixid,
565 t->num_sids);
566 if (ids == NULL) {
567 return NT_STATUS_NO_MEMORY;
570 if (!sids_to_unixids(t->sids, t->num_sids, ids)) {
571 TALLOC_FREE(ids);
572 return NT_STATUS_NO_MEMORY;
575 for (i=0; i<t->num_sids; i++) {
577 if (i == 0 && ids[i].type != ID_TYPE_BOTH) {
578 continue;
581 if (ids[i].type != ID_TYPE_GID &&
582 ids[i].type != ID_TYPE_BOTH) {
583 DEBUG(10, ("Could not convert SID %s to gid, "
584 "ignoring it\n",
585 sid_string_dbg(&t->sids[i])));
586 continue;
588 if (!add_gid_to_array_unique(session_info, ids[i].id,
589 &session_info->unix_token->groups,
590 &session_info->unix_token->ngroups)) {
591 return NT_STATUS_NO_MEMORY;
596 * Add the "Unix Group" SID for each gid to catch mapped groups
597 * and their Unix equivalent. This is to solve the backwards
598 * compatibility problem of 'valid users = +ntadmin' where
599 * ntadmin has been paired with "Domain Admins" in the group
600 * mapping table. Otherwise smb.conf would need to be changed
601 * to 'valid user = "Domain Admins"'. --jerry
603 * For consistency we also add the "Unix User" SID,
604 * so that the complete unix token is represented within
605 * the nt token.
608 uid_to_unix_users_sid(session_info->unix_token->uid, &tmp_sid);
610 add_sid_to_array_unique(session_info->security_token, &tmp_sid,
611 &session_info->security_token->sids,
612 &session_info->security_token->num_sids);
614 for ( i=0; i<session_info->unix_token->ngroups; i++ ) {
615 gid_to_unix_groups_sid(session_info->unix_token->groups[i], &tmp_sid);
616 add_sid_to_array_unique(session_info->security_token, &tmp_sid,
617 &session_info->security_token->sids,
618 &session_info->security_token->num_sids);
621 security_token_debug(DBGC_AUTH, 10, session_info->security_token);
622 debug_unix_user_token(DBGC_AUTH, 10,
623 session_info->unix_token->uid,
624 session_info->unix_token->gid,
625 session_info->unix_token->ngroups,
626 session_info->unix_token->groups);
628 status = log_nt_token(session_info->security_token);
629 if (!NT_STATUS_IS_OK(status)) {
630 return status;
633 *session_info_out = session_info;
634 return NT_STATUS_OK;
637 /***************************************************************************
638 Make (and fill) a server_info struct from a 'struct passwd' by conversion
639 to a struct samu
640 ***************************************************************************/
642 NTSTATUS make_server_info_pw(TALLOC_CTX *mem_ctx,
643 const char *unix_username,
644 const struct passwd *pwd,
645 struct auth_serversupplied_info **server_info)
647 NTSTATUS status;
648 TALLOC_CTX *tmp_ctx = NULL;
649 struct auth_serversupplied_info *result;
651 tmp_ctx = talloc_stackframe();
652 if (tmp_ctx == NULL) {
653 return NT_STATUS_NO_MEMORY;
656 result = make_server_info(tmp_ctx);
657 if (result == NULL) {
658 status = NT_STATUS_NO_MEMORY;
659 goto done;
662 status = passwd_to_SamInfo3(result,
663 unix_username,
664 pwd,
665 &result->info3);
666 if (!NT_STATUS_IS_OK(status)) {
667 goto done;
670 result->unix_name = talloc_strdup(result, unix_username);
671 if (result->unix_name == NULL) {
672 status = NT_STATUS_NO_MEMORY;
673 goto done;
676 result->utok.uid = pwd->pw_uid;
677 result->utok.gid = pwd->pw_gid;
679 *server_info = talloc_steal(mem_ctx, result);
680 status = NT_STATUS_OK;
681 done:
682 talloc_free(tmp_ctx);
684 return status;
687 static NTSTATUS get_system_info3(TALLOC_CTX *mem_ctx,
688 struct netr_SamInfo3 *info3)
690 NTSTATUS status;
691 struct dom_sid *system_sid;
693 /* Set account name */
694 init_lsa_String(&info3->base.account_name, "SYSTEM");
696 /* Set domain name */
697 init_lsa_StringLarge(&info3->base.logon_domain, "NT AUTHORITY");
700 /* The SID set here will be overwirtten anyway, but try and make it SID_NT_SYSTEM anyway */
701 /* Domain sid is NT_AUTHORITY */
703 system_sid = dom_sid_parse_talloc(mem_ctx, SID_NT_SYSTEM);
704 if (system_sid == NULL) {
705 return NT_STATUS_NO_MEMORY;
708 status = dom_sid_split_rid(mem_ctx, system_sid, &info3->base.domain_sid,
709 &info3->base.rid);
710 TALLOC_FREE(system_sid);
711 if (!NT_STATUS_IS_OK(status)) {
712 return status;
715 /* Primary gid is the same */
716 info3->base.primary_gid = info3->base.rid;
718 return NT_STATUS_OK;
721 static NTSTATUS get_guest_info3(TALLOC_CTX *mem_ctx,
722 struct netr_SamInfo3 *info3)
724 const char *guest_account = lp_guest_account();
725 struct dom_sid domain_sid;
726 struct passwd *pwd;
727 const char *tmp;
729 pwd = Get_Pwnam_alloc(mem_ctx, guest_account);
730 if (pwd == NULL) {
731 DEBUG(0,("SamInfo3_for_guest: Unable to locate guest "
732 "account [%s]!\n", guest_account));
733 return NT_STATUS_NO_SUCH_USER;
736 /* Set account name */
737 tmp = talloc_strdup(mem_ctx, pwd->pw_name);
738 if (tmp == NULL) {
739 return NT_STATUS_NO_MEMORY;
741 init_lsa_String(&info3->base.account_name, tmp);
743 /* Set domain name */
744 tmp = talloc_strdup(mem_ctx, get_global_sam_name());
745 if (tmp == NULL) {
746 return NT_STATUS_NO_MEMORY;
748 init_lsa_StringLarge(&info3->base.logon_domain, tmp);
750 /* Domain sid */
751 sid_copy(&domain_sid, get_global_sam_sid());
753 info3->base.domain_sid = dom_sid_dup(mem_ctx, &domain_sid);
754 if (info3->base.domain_sid == NULL) {
755 return NT_STATUS_NO_MEMORY;
758 /* Guest rid */
759 info3->base.rid = DOMAIN_RID_GUEST;
761 /* Primary gid */
762 info3->base.primary_gid = DOMAIN_RID_GUESTS;
764 /* Set as guest */
765 info3->base.user_flags = NETLOGON_GUEST;
767 TALLOC_FREE(pwd);
768 return NT_STATUS_OK;
771 /***************************************************************************
772 Make (and fill) a user_info struct for a guest login.
773 This *must* succeed for smbd to start. If there is no mapping entry for
774 the guest gid, then create one.
776 The resulting structure is a 'session_info' because
777 create_local_token() has already been called on it. This is quite
778 nasty, as the auth subsystem isn't expect this, but the behavior is
779 left as-is for now.
780 ***************************************************************************/
782 static NTSTATUS make_new_session_info_guest(struct auth_session_info **session_info, struct auth_serversupplied_info **server_info)
784 static const char zeros[16] = {0};
785 const char *guest_account = lp_guest_account();
786 const char *domain = lp_netbios_name();
787 struct netr_SamInfo3 info3;
788 TALLOC_CTX *tmp_ctx;
789 NTSTATUS status;
791 tmp_ctx = talloc_stackframe();
792 if (tmp_ctx == NULL) {
793 return NT_STATUS_NO_MEMORY;
796 ZERO_STRUCT(info3);
798 status = get_guest_info3(tmp_ctx, &info3);
799 if (!NT_STATUS_IS_OK(status)) {
800 DEBUG(0, ("get_guest_info3 failed with %s\n",
801 nt_errstr(status)));
802 goto done;
805 status = make_server_info_info3(tmp_ctx,
806 guest_account,
807 domain,
808 server_info,
809 &info3);
810 if (!NT_STATUS_IS_OK(status)) {
811 DEBUG(0, ("make_server_info_info3 failed with %s\n",
812 nt_errstr(status)));
813 goto done;
816 (*server_info)->guest = true;
818 /* This should not be done here (we should produce a server
819 * info, and later construct a session info from it), but for
820 * now this does not change the previous behavior */
821 status = create_local_token(tmp_ctx, *server_info, NULL,
822 (*server_info)->info3->base.account_name.string,
823 session_info);
824 if (!NT_STATUS_IS_OK(status)) {
825 DEBUG(0, ("create_local_token failed: %s\n",
826 nt_errstr(status)));
827 goto done;
829 talloc_steal(NULL, *session_info);
830 talloc_steal(NULL, *server_info);
832 /* annoying, but the Guest really does have a session key, and it is
833 all zeros! */
834 (*session_info)->session_key = data_blob(zeros, sizeof(zeros));
836 status = NT_STATUS_OK;
837 done:
838 TALLOC_FREE(tmp_ctx);
839 return status;
842 /***************************************************************************
843 Make (and fill) a auth_session_info struct for a system user login.
844 This *must* succeed for smbd to start.
845 ***************************************************************************/
847 static NTSTATUS make_new_session_info_system(TALLOC_CTX *mem_ctx,
848 struct auth_session_info **session_info)
850 NTSTATUS status;
851 struct auth_serversupplied_info *server_info;
852 TALLOC_CTX *tmp_ctx;
854 tmp_ctx = talloc_stackframe();
855 if (tmp_ctx == NULL) {
856 return NT_STATUS_NO_MEMORY;
859 server_info = make_server_info(tmp_ctx);
860 if (!server_info) {
861 status = NT_STATUS_NO_MEMORY;
862 DEBUG(0, ("failed making server_info\n"));
863 goto done;
866 server_info->info3 = talloc_zero(server_info, struct netr_SamInfo3);
867 if (!server_info->info3) {
868 status = NT_STATUS_NO_MEMORY;
869 DEBUG(0, ("talloc failed setting info3\n"));
870 goto done;
873 status = get_system_info3(server_info, server_info->info3);
874 if (!NT_STATUS_IS_OK(status)) {
875 DEBUG(0, ("Failed creating system info3 with %s\n",
876 nt_errstr(status)));
877 goto done;
880 server_info->utok.uid = sec_initial_uid();
881 server_info->utok.gid = sec_initial_gid();
882 server_info->unix_name = talloc_asprintf(server_info,
883 "NT AUTHORITY%cSYSTEM",
884 *lp_winbind_separator());
886 if (!server_info->unix_name) {
887 status = NT_STATUS_NO_MEMORY;
888 DEBUG(0, ("talloc_asprintf failed setting unix_name\n"));
889 goto done;
892 server_info->security_token = talloc_zero(server_info, struct security_token);
893 if (!server_info->security_token) {
894 status = NT_STATUS_NO_MEMORY;
895 DEBUG(0, ("talloc failed setting security token\n"));
896 goto done;
899 status = add_sid_to_array_unique(server_info->security_token->sids,
900 &global_sid_System,
901 &server_info->security_token->sids,
902 &server_info->security_token->num_sids);
903 if (!NT_STATUS_IS_OK(status)) {
904 goto done;
907 /* SYSTEM has all privilages */
908 server_info->security_token->privilege_mask = ~0;
910 /* Now turn the server_info into a session_info with the full token etc */
911 status = create_local_token(mem_ctx, server_info, NULL, "SYSTEM", session_info);
912 talloc_free(server_info);
914 if (!NT_STATUS_IS_OK(status)) {
915 DEBUG(0, ("create_local_token failed: %s\n",
916 nt_errstr(status)));
917 goto done;
920 talloc_steal(mem_ctx, *session_info);
922 done:
923 TALLOC_FREE(tmp_ctx);
924 return status;
927 /****************************************************************************
928 Fake a auth_session_info just from a username (as a
929 session_info structure, with create_local_token() already called on
931 ****************************************************************************/
933 NTSTATUS make_session_info_from_username(TALLOC_CTX *mem_ctx,
934 const char *username,
935 bool is_guest,
936 struct auth_session_info **session_info)
938 struct passwd *pwd;
939 NTSTATUS status;
940 struct auth_serversupplied_info *result;
941 TALLOC_CTX *tmp_ctx;
943 tmp_ctx = talloc_stackframe();
944 if (tmp_ctx == NULL) {
945 return NT_STATUS_NO_MEMORY;
948 pwd = Get_Pwnam_alloc(tmp_ctx, username);
949 if (pwd == NULL) {
950 status = NT_STATUS_NO_SUCH_USER;
951 goto done;
954 status = make_server_info_pw(tmp_ctx, pwd->pw_name, pwd, &result);
955 if (!NT_STATUS_IS_OK(status)) {
956 goto done;
959 result->nss_token = true;
960 result->guest = is_guest;
962 /* Now turn the server_info into a session_info with the full token etc */
963 status = create_local_token(mem_ctx,
964 result,
965 NULL,
966 pwd->pw_name,
967 session_info);
969 done:
970 talloc_free(tmp_ctx);
972 return status;
975 /* This function MUST only used to create the cached server_info for
976 * guest.
978 * This is a lossy conversion. Variables known to be lost so far
979 * include:
981 * - nss_token (not needed because the only read doesn't happen
982 * for the GUEST user, as this routine populates ->security_token
984 * - extra (not needed because the guest account must have valid RIDs per the output of get_guest_info3())
986 * - The 'server_info' parameter allows the missing 'info3' to be copied across.
988 static struct auth_serversupplied_info *copy_session_info_serverinfo_guest(TALLOC_CTX *mem_ctx,
989 const struct auth_session_info *src,
990 struct auth_serversupplied_info *server_info)
992 struct auth_serversupplied_info *dst;
994 dst = make_server_info(mem_ctx);
995 if (dst == NULL) {
996 return NULL;
999 /* This element must be provided to convert back to an auth_serversupplied_info */
1000 SMB_ASSERT(src->unix_info);
1002 dst->guest = true;
1003 dst->system = false;
1005 /* This element must be provided to convert back to an
1006 * auth_serversupplied_info. This needs to be from the
1007 * auth_session_info because the group values in particular
1008 * may change during create_local_token() processing */
1009 SMB_ASSERT(src->unix_token);
1010 dst->utok.uid = src->unix_token->uid;
1011 dst->utok.gid = src->unix_token->gid;
1012 dst->utok.ngroups = src->unix_token->ngroups;
1013 if (src->unix_token->ngroups != 0) {
1014 dst->utok.groups = (gid_t *)talloc_memdup(
1015 dst, src->unix_token->groups,
1016 sizeof(gid_t)*dst->utok.ngroups);
1017 } else {
1018 dst->utok.groups = NULL;
1021 /* We must have a security_token as otherwise the lossy
1022 * conversion without nss_token would cause create_local_token
1023 * to take the wrong path */
1024 SMB_ASSERT(src->security_token);
1026 dst->security_token = dup_nt_token(dst, src->security_token);
1027 if (!dst->security_token) {
1028 TALLOC_FREE(dst);
1029 return NULL;
1032 dst->session_key = data_blob_talloc( dst, src->session_key.data,
1033 src->session_key.length);
1035 /* This is OK because this functions is only used for the
1036 * GUEST account, which has all-zero keys for both values */
1037 dst->lm_session_key = data_blob_talloc(dst, src->session_key.data,
1038 src->session_key.length);
1040 dst->info3 = copy_netr_SamInfo3(dst, server_info->info3);
1041 if (!dst->info3) {
1042 TALLOC_FREE(dst);
1043 return NULL;
1046 dst->unix_name = talloc_strdup(dst, src->unix_info->unix_name);
1047 if (!dst->unix_name) {
1048 TALLOC_FREE(dst);
1049 return NULL;
1052 return dst;
1055 struct auth_session_info *copy_session_info(TALLOC_CTX *mem_ctx,
1056 const struct auth_session_info *src)
1058 struct auth_session_info *dst;
1059 DATA_BLOB blob;
1060 enum ndr_err_code ndr_err;
1062 ndr_err = ndr_push_struct_blob(
1063 &blob, talloc_tos(), src,
1064 (ndr_push_flags_fn_t)ndr_push_auth_session_info);
1065 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1066 DEBUG(0, ("copy_session_info(): ndr_push_auth_session_info failed: "
1067 "%s\n", ndr_errstr(ndr_err)));
1068 return NULL;
1071 dst = talloc(mem_ctx, struct auth_session_info);
1072 if (dst == NULL) {
1073 DEBUG(0, ("talloc failed\n"));
1074 TALLOC_FREE(blob.data);
1075 return NULL;
1078 ndr_err = ndr_pull_struct_blob(
1079 &blob, dst, dst,
1080 (ndr_pull_flags_fn_t)ndr_pull_auth_session_info);
1081 TALLOC_FREE(blob.data);
1083 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1084 DEBUG(0, ("copy_session_info(): ndr_pull_auth_session_info failed: "
1085 "%s\n", ndr_errstr(ndr_err)));
1086 TALLOC_FREE(dst);
1087 return NULL;
1090 return dst;
1094 * Set a new session key. Used in the rpc server where we have to override the
1095 * SMB level session key with SystemLibraryDTC
1098 bool session_info_set_session_key(struct auth_session_info *info,
1099 DATA_BLOB session_key)
1101 TALLOC_FREE(info->session_key.data);
1103 info->session_key = data_blob_talloc(
1104 info, session_key.data, session_key.length);
1106 return (info->session_key.data != NULL);
1109 static struct auth_session_info *guest_info = NULL;
1111 static struct auth_serversupplied_info *guest_server_info = NULL;
1113 bool init_guest_info(void)
1115 if (guest_info != NULL)
1116 return true;
1118 return NT_STATUS_IS_OK(make_new_session_info_guest(&guest_info, &guest_server_info));
1121 NTSTATUS make_server_info_guest(TALLOC_CTX *mem_ctx,
1122 struct auth_serversupplied_info **server_info)
1124 /* This is trickier than it would appear to need to be because
1125 * we are trying to avoid certain costly operations when the
1126 * structure is converted to a 'auth_session_info' again in
1127 * create_local_token() */
1128 *server_info = copy_session_info_serverinfo_guest(mem_ctx, guest_info, guest_server_info);
1129 return (*server_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1132 NTSTATUS make_session_info_guest(TALLOC_CTX *mem_ctx,
1133 struct auth_session_info **session_info)
1135 *session_info = copy_session_info(mem_ctx, guest_info);
1136 return (*session_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1139 static struct auth_session_info *system_info = NULL;
1141 NTSTATUS init_system_session_info(void)
1143 if (system_info != NULL)
1144 return NT_STATUS_OK;
1146 return make_new_session_info_system(NULL, &system_info);
1149 NTSTATUS make_session_info_system(TALLOC_CTX *mem_ctx,
1150 struct auth_session_info **session_info)
1152 if (system_info == NULL) return NT_STATUS_UNSUCCESSFUL;
1153 *session_info = copy_session_info(mem_ctx, system_info);
1154 return (*session_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1157 const struct auth_session_info *get_session_info_system(void)
1159 return system_info;
1162 /***************************************************************************
1163 Purely internal function for make_server_info_info3
1164 ***************************************************************************/
1166 static NTSTATUS check_account(TALLOC_CTX *mem_ctx, const char *domain,
1167 const char *username, char **found_username,
1168 struct passwd **pwd,
1169 bool *username_was_mapped)
1171 char *orig_dom_user = NULL;
1172 char *dom_user = NULL;
1173 char *lower_username = NULL;
1174 char *real_username = NULL;
1175 struct passwd *passwd;
1177 lower_username = talloc_strdup(mem_ctx, username);
1178 if (!lower_username) {
1179 return NT_STATUS_NO_MEMORY;
1181 if (!strlower_m( lower_username )) {
1182 return NT_STATUS_INVALID_PARAMETER;
1185 orig_dom_user = talloc_asprintf(mem_ctx,
1186 "%s%c%s",
1187 domain,
1188 *lp_winbind_separator(),
1189 lower_username);
1190 if (!orig_dom_user) {
1191 return NT_STATUS_NO_MEMORY;
1194 /* Get the passwd struct. Try to create the account if necessary. */
1196 *username_was_mapped = map_username(mem_ctx, orig_dom_user, &dom_user);
1197 if (!dom_user) {
1198 return NT_STATUS_NO_MEMORY;
1201 passwd = smb_getpwnam(mem_ctx, dom_user, &real_username, true );
1202 if (!passwd) {
1203 DEBUG(3, ("Failed to find authenticated user %s via "
1204 "getpwnam(), denying access.\n", dom_user));
1205 return NT_STATUS_NO_SUCH_USER;
1208 if (!real_username) {
1209 return NT_STATUS_NO_MEMORY;
1212 *pwd = passwd;
1214 /* This is pointless -- there is no support for differing
1215 unix and windows names. Make sure to always store the
1216 one we actually looked up and succeeded. Have I mentioned
1217 why I hate the 'winbind use default domain' parameter?
1218 --jerry */
1220 *found_username = talloc_strdup( mem_ctx, real_username );
1222 return NT_STATUS_OK;
1225 /****************************************************************************
1226 Wrapper to allow the getpwnam() call to strip the domain name and
1227 try again in case a local UNIX user is already there. Also run through
1228 the username if we fallback to the username only.
1229 ****************************************************************************/
1231 struct passwd *smb_getpwnam( TALLOC_CTX *mem_ctx, const char *domuser,
1232 char **p_save_username, bool create )
1234 struct passwd *pw = NULL;
1235 char *p = NULL;
1236 char *username = NULL;
1238 /* we only save a copy of the username it has been mangled
1239 by winbindd use default domain */
1240 *p_save_username = NULL;
1242 /* don't call map_username() here since it has to be done higher
1243 up the stack so we don't call it multiple times */
1245 username = talloc_strdup(mem_ctx, domuser);
1246 if (!username) {
1247 return NULL;
1250 p = strchr_m( username, *lp_winbind_separator() );
1252 /* code for a DOMAIN\user string */
1254 if ( p ) {
1255 pw = Get_Pwnam_alloc( mem_ctx, domuser );
1256 if ( pw ) {
1257 /* make sure we get the case of the username correct */
1258 /* work around 'winbind use default domain = yes' */
1260 if ( lp_winbind_use_default_domain() &&
1261 !strchr_m( pw->pw_name, *lp_winbind_separator() ) ) {
1262 char *domain;
1264 /* split the domain and username into 2 strings */
1265 *p = '\0';
1266 domain = username;
1268 *p_save_username = talloc_asprintf(mem_ctx,
1269 "%s%c%s",
1270 domain,
1271 *lp_winbind_separator(),
1272 pw->pw_name);
1273 if (!*p_save_username) {
1274 TALLOC_FREE(pw);
1275 return NULL;
1277 } else {
1278 *p_save_username = talloc_strdup(mem_ctx, pw->pw_name);
1281 /* whew -- done! */
1282 return pw;
1285 /* setup for lookup of just the username */
1286 /* remember that p and username are overlapping memory */
1288 p++;
1289 username = talloc_strdup(mem_ctx, p);
1290 if (!username) {
1291 return NULL;
1295 /* just lookup a plain username */
1297 pw = Get_Pwnam_alloc(mem_ctx, username);
1299 /* Create local user if requested but only if winbindd
1300 is not running. We need to protect against cases
1301 where winbindd is failing and then prematurely
1302 creating users in /etc/passwd */
1304 if ( !pw && create && !winbind_ping() ) {
1305 /* Don't add a machine account. */
1306 if (username[strlen(username)-1] == '$')
1307 return NULL;
1309 _smb_create_user(NULL, username, NULL);
1310 pw = Get_Pwnam_alloc(mem_ctx, username);
1313 /* one last check for a valid passwd struct */
1315 if (pw) {
1316 *p_save_username = talloc_strdup(mem_ctx, pw->pw_name);
1318 return pw;
1321 /***************************************************************************
1322 Make a server_info struct from the info3 returned by a domain logon
1323 ***************************************************************************/
1325 NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
1326 const char *sent_nt_username,
1327 const char *domain,
1328 struct auth_serversupplied_info **server_info,
1329 struct netr_SamInfo3 *info3)
1331 static const char zeros[16] = {0, };
1333 NTSTATUS nt_status = NT_STATUS_OK;
1334 char *found_username = NULL;
1335 const char *nt_domain;
1336 const char *nt_username;
1337 struct dom_sid user_sid;
1338 struct dom_sid group_sid;
1339 bool username_was_mapped;
1340 struct passwd *pwd;
1341 struct auth_serversupplied_info *result;
1344 Here is where we should check the list of
1345 trusted domains, and verify that the SID
1346 matches.
1349 if (!sid_compose(&user_sid, info3->base.domain_sid, info3->base.rid)) {
1350 return NT_STATUS_INVALID_PARAMETER;
1353 if (!sid_compose(&group_sid, info3->base.domain_sid,
1354 info3->base.primary_gid)) {
1355 return NT_STATUS_INVALID_PARAMETER;
1358 nt_username = talloc_strdup(mem_ctx, info3->base.account_name.string);
1359 if (!nt_username) {
1360 /* If the server didn't give us one, just use the one we sent
1361 * them */
1362 nt_username = sent_nt_username;
1365 nt_domain = talloc_strdup(mem_ctx, info3->base.logon_domain.string);
1366 if (!nt_domain) {
1367 /* If the server didn't give us one, just use the one we sent
1368 * them */
1369 nt_domain = domain;
1372 /* If getpwnam() fails try the add user script (2.2.x behavior).
1374 We use the _unmapped_ username here in an attempt to provide
1375 consistent username mapping behavior between kerberos and NTLM[SSP]
1376 authentication in domain mode security. I.E. Username mapping
1377 should be applied to the fully qualified username
1378 (e.g. DOMAIN\user) and not just the login name. Yes this means we
1379 called map_username() unnecessarily in make_user_info_map() but
1380 that is how the current code is designed. Making the change here
1381 is the least disruptive place. -- jerry */
1383 /* this call will try to create the user if necessary */
1385 nt_status = check_account(mem_ctx, nt_domain, sent_nt_username,
1386 &found_username, &pwd,
1387 &username_was_mapped);
1389 if (!NT_STATUS_IS_OK(nt_status)) {
1390 return nt_status;
1393 result = make_server_info(NULL);
1394 if (result == NULL) {
1395 DEBUG(4, ("make_server_info failed!\n"));
1396 return NT_STATUS_NO_MEMORY;
1399 result->unix_name = talloc_strdup(result, found_username);
1401 /* copy in the info3 */
1402 result->info3 = copy_netr_SamInfo3(result, info3);
1403 if (result->info3 == NULL) {
1404 TALLOC_FREE(result);
1405 return NT_STATUS_NO_MEMORY;
1408 /* Fill in the unix info we found on the way */
1410 result->utok.uid = pwd->pw_uid;
1411 result->utok.gid = pwd->pw_gid;
1413 /* ensure we are never given NULL session keys */
1415 if (memcmp(info3->base.key.key, zeros, sizeof(zeros)) == 0) {
1416 result->session_key = data_blob_null;
1417 } else {
1418 result->session_key = data_blob_talloc(
1419 result, info3->base.key.key,
1420 sizeof(info3->base.key.key));
1423 if (memcmp(info3->base.LMSessKey.key, zeros, 8) == 0) {
1424 result->lm_session_key = data_blob_null;
1425 } else {
1426 result->lm_session_key = data_blob_talloc(
1427 result, info3->base.LMSessKey.key,
1428 sizeof(info3->base.LMSessKey.key));
1431 result->nss_token |= username_was_mapped;
1433 result->guest = (info3->base.user_flags & NETLOGON_GUEST);
1435 *server_info = result;
1437 return NT_STATUS_OK;
1440 /*****************************************************************************
1441 Make a server_info struct from the wbcAuthUserInfo returned by a domain logon
1442 ******************************************************************************/
1444 NTSTATUS make_server_info_wbcAuthUserInfo(TALLOC_CTX *mem_ctx,
1445 const char *sent_nt_username,
1446 const char *domain,
1447 const struct wbcAuthUserInfo *info,
1448 struct auth_serversupplied_info **server_info)
1450 struct netr_SamInfo3 *info3;
1452 info3 = wbcAuthUserInfo_to_netr_SamInfo3(mem_ctx, info);
1453 if (!info3) {
1454 return NT_STATUS_NO_MEMORY;
1457 return make_server_info_info3(mem_ctx,
1458 sent_nt_username, domain,
1459 server_info, info3);
1463 * Verify whether or not given domain is trusted.
1465 * @param domain_name name of the domain to be verified
1466 * @return true if domain is one of the trusted ones or
1467 * false if otherwise
1470 bool is_trusted_domain(const char* dom_name)
1472 struct dom_sid trustdom_sid;
1473 bool ret;
1475 /* no trusted domains for a standalone server */
1477 if ( lp_server_role() == ROLE_STANDALONE )
1478 return false;
1480 if (dom_name == NULL || dom_name[0] == '\0') {
1481 return false;
1484 if (strequal(dom_name, get_global_sam_name())) {
1485 return false;
1488 /* if we are a DC, then check for a direct trust relationships */
1490 if ( IS_DC ) {
1491 become_root();
1492 DEBUG (5,("is_trusted_domain: Checking for domain trust with "
1493 "[%s]\n", dom_name ));
1494 ret = pdb_get_trusteddom_pw(dom_name, NULL, NULL, NULL);
1495 unbecome_root();
1496 if (ret)
1497 return true;
1499 else {
1500 wbcErr result;
1502 /* If winbind is around, ask it */
1504 result = wb_is_trusted_domain(dom_name);
1506 if (result == WBC_ERR_SUCCESS) {
1507 return true;
1510 if (result == WBC_ERR_DOMAIN_NOT_FOUND) {
1511 /* winbind could not find the domain */
1512 return false;
1515 /* The only other possible result is that winbind is not up
1516 and running. We need to update the trustdom_cache
1517 ourselves */
1519 update_trustdom_cache();
1522 /* now the trustdom cache should be available a DC could still
1523 * have a transitive trust so fall back to the cache of trusted
1524 * domains (like a domain member would use */
1526 if ( trustdom_cache_fetch(dom_name, &trustdom_sid) ) {
1527 return true;
1530 return false;
1536 on a logon error possibly map the error to success if "map to guest"
1537 is set approriately
1539 NTSTATUS do_map_to_guest_server_info(TALLOC_CTX *mem_ctx,
1540 NTSTATUS status,
1541 const char *user,
1542 const char *domain,
1543 struct auth_serversupplied_info **server_info)
1545 user = user ? user : "";
1546 domain = domain ? domain : "";
1548 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
1549 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
1550 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
1551 DEBUG(3,("No such user %s [%s] - using guest account\n",
1552 user, domain));
1553 return make_server_info_guest(mem_ctx, server_info);
1555 } else if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1556 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
1557 DEBUG(3,("Registered username %s for guest access\n",
1558 user));
1559 return make_server_info_guest(mem_ctx, server_info);
1563 return status;
1567 Extract session key from a session info and return it in a blob
1568 if intent is KEY_USE_16BYTES, truncate it to 16 bytes
1570 See sections 3.2.4.15 and 3.3.4.2 of MS-SMB
1571 Also see https://lists.samba.org/archive/cifs-protocol/2012-January/002265.html for details
1573 Note that returned session_key is referencing the original key, it is supposed to be
1574 short-lived. If original session_info->session_key is gone, the reference will be broken.
1576 NTSTATUS session_extract_session_key(const struct auth_session_info *session_info, DATA_BLOB *session_key, enum session_key_use_intent intent)
1579 if (session_key == NULL || session_info == NULL) {
1580 return NT_STATUS_INVALID_PARAMETER;
1583 if (session_info->session_key.length == 0) {
1584 return NT_STATUS_NO_USER_SESSION_KEY;
1587 *session_key = session_info->session_key;
1588 if (intent == KEY_USE_16BYTES) {
1589 session_key->length = MIN(session_info->session_key.length, 16);
1591 return NT_STATUS_OK;