Add a test to show that zero-length EA's are never returned over SMB2.
[Samba/vl.git] / source3 / auth / auth_util.c
blobceaa7064d5908d19347f696ee013c0b9a34a5d77
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_adduser_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(struct auth_serversupplied_info **server_info,
643 char *unix_username,
644 struct passwd *pwd)
646 NTSTATUS status;
647 struct samu *sampass = NULL;
648 char *qualified_name = NULL;
649 TALLOC_CTX *mem_ctx = NULL;
650 struct dom_sid u_sid;
651 enum lsa_SidType type;
652 struct auth_serversupplied_info *result;
655 * The SID returned in server_info->sam_account is based
656 * on our SAM sid even though for a pure UNIX account this should
657 * not be the case as it doesn't really exist in the SAM db.
658 * This causes lookups on "[in]valid users" to fail as they
659 * will lookup this name as a "Unix User" SID to check against
660 * the user token. Fix this by adding the "Unix User"\unix_username
661 * SID to the sid array. The correct fix should probably be
662 * changing the server_info->sam_account user SID to be a
663 * S-1-22 Unix SID, but this might break old configs where
664 * plaintext passwords were used with no SAM backend.
667 mem_ctx = talloc_init("make_server_info_pw_tmp");
668 if (!mem_ctx) {
669 return NT_STATUS_NO_MEMORY;
672 qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
673 unix_users_domain_name(),
674 unix_username );
675 if (!qualified_name) {
676 TALLOC_FREE(mem_ctx);
677 return NT_STATUS_NO_MEMORY;
680 if (!lookup_name(mem_ctx, qualified_name, LOOKUP_NAME_ALL,
681 NULL, NULL,
682 &u_sid, &type)) {
683 TALLOC_FREE(mem_ctx);
684 return NT_STATUS_NO_SUCH_USER;
687 TALLOC_FREE(mem_ctx);
689 if (type != SID_NAME_USER) {
690 return NT_STATUS_NO_SUCH_USER;
693 if ( !(sampass = samu_new( NULL )) ) {
694 return NT_STATUS_NO_MEMORY;
697 status = samu_set_unix( sampass, pwd );
698 if (!NT_STATUS_IS_OK(status)) {
699 return status;
702 /* In pathological cases the above call can set the account
703 * name to the DOMAIN\username form. Reset the account name
704 * using unix_username */
705 pdb_set_username(sampass, unix_username, PDB_SET);
707 /* set the user sid to be the calculated u_sid */
708 pdb_set_user_sid(sampass, &u_sid, PDB_SET);
710 result = make_server_info(NULL);
711 if (result == NULL) {
712 TALLOC_FREE(sampass);
713 return NT_STATUS_NO_MEMORY;
716 status = samu_to_SamInfo3(result, sampass, lp_netbios_name(),
717 &result->info3, &result->extra);
718 TALLOC_FREE(sampass);
719 if (!NT_STATUS_IS_OK(status)) {
720 DEBUG(10, ("Failed to convert samu to info3: %s\n",
721 nt_errstr(status)));
722 TALLOC_FREE(result);
723 return status;
726 result->unix_name = talloc_strdup(result, unix_username);
728 if (result->unix_name == NULL) {
729 TALLOC_FREE(result);
730 return NT_STATUS_NO_MEMORY;
733 result->utok.uid = pwd->pw_uid;
734 result->utok.gid = pwd->pw_gid;
736 *server_info = result;
738 return NT_STATUS_OK;
741 static NTSTATUS get_system_info3(TALLOC_CTX *mem_ctx,
742 struct netr_SamInfo3 *info3)
744 NTSTATUS status;
745 struct dom_sid *system_sid;
747 /* Set account name */
748 init_lsa_String(&info3->base.account_name, "SYSTEM");
750 /* Set domain name */
751 init_lsa_StringLarge(&info3->base.logon_domain, "NT AUTHORITY");
754 /* The SID set here will be overwirtten anyway, but try and make it SID_NT_SYSTEM anyway */
755 /* Domain sid is NT_AUTHORITY */
757 system_sid = dom_sid_parse_talloc(mem_ctx, SID_NT_SYSTEM);
758 if (system_sid == NULL) {
759 return NT_STATUS_NO_MEMORY;
762 status = dom_sid_split_rid(mem_ctx, system_sid, &info3->base.domain_sid,
763 &info3->base.rid);
764 TALLOC_FREE(system_sid);
765 if (!NT_STATUS_IS_OK(status)) {
766 return status;
769 /* Primary gid is the same */
770 info3->base.primary_gid = info3->base.rid;
772 return NT_STATUS_OK;
775 static NTSTATUS get_guest_info3(TALLOC_CTX *mem_ctx,
776 struct netr_SamInfo3 *info3)
778 const char *guest_account = lp_guestaccount();
779 struct dom_sid domain_sid;
780 struct passwd *pwd;
781 const char *tmp;
783 pwd = Get_Pwnam_alloc(mem_ctx, guest_account);
784 if (pwd == NULL) {
785 DEBUG(0,("SamInfo3_for_guest: Unable to locate guest "
786 "account [%s]!\n", guest_account));
787 return NT_STATUS_NO_SUCH_USER;
790 /* Set account name */
791 tmp = talloc_strdup(mem_ctx, pwd->pw_name);
792 if (tmp == NULL) {
793 return NT_STATUS_NO_MEMORY;
795 init_lsa_String(&info3->base.account_name, tmp);
797 /* Set domain name */
798 tmp = talloc_strdup(mem_ctx, get_global_sam_name());
799 if (tmp == NULL) {
800 return NT_STATUS_NO_MEMORY;
802 init_lsa_StringLarge(&info3->base.logon_domain, tmp);
804 /* Domain sid */
805 sid_copy(&domain_sid, get_global_sam_sid());
807 info3->base.domain_sid = dom_sid_dup(mem_ctx, &domain_sid);
808 if (info3->base.domain_sid == NULL) {
809 return NT_STATUS_NO_MEMORY;
812 /* Guest rid */
813 info3->base.rid = DOMAIN_RID_GUEST;
815 /* Primary gid */
816 info3->base.primary_gid = DOMAIN_RID_GUESTS;
818 /* Set as guest */
819 info3->base.user_flags = NETLOGON_GUEST;
821 TALLOC_FREE(pwd);
822 return NT_STATUS_OK;
825 /***************************************************************************
826 Make (and fill) a user_info struct for a guest login.
827 This *must* succeed for smbd to start. If there is no mapping entry for
828 the guest gid, then create one.
830 The resulting structure is a 'session_info' because
831 create_local_token() has already been called on it. This is quite
832 nasty, as the auth subsystem isn't expect this, but the behavior is
833 left as-is for now.
834 ***************************************************************************/
836 static NTSTATUS make_new_session_info_guest(struct auth_session_info **session_info, struct auth_serversupplied_info **server_info)
838 static const char zeros[16] = {0};
839 const char *guest_account = lp_guestaccount();
840 const char *domain = lp_netbios_name();
841 struct netr_SamInfo3 info3;
842 TALLOC_CTX *tmp_ctx;
843 NTSTATUS status;
845 tmp_ctx = talloc_stackframe();
846 if (tmp_ctx == NULL) {
847 return NT_STATUS_NO_MEMORY;
850 ZERO_STRUCT(info3);
852 status = get_guest_info3(tmp_ctx, &info3);
853 if (!NT_STATUS_IS_OK(status)) {
854 DEBUG(0, ("get_guest_info3 failed with %s\n",
855 nt_errstr(status)));
856 goto done;
859 status = make_server_info_info3(tmp_ctx,
860 guest_account,
861 domain,
862 server_info,
863 &info3);
864 if (!NT_STATUS_IS_OK(status)) {
865 DEBUG(0, ("make_server_info_info3 failed with %s\n",
866 nt_errstr(status)));
867 goto done;
870 (*server_info)->guest = true;
872 /* This should not be done here (we should produce a server
873 * info, and later construct a session info from it), but for
874 * now this does not change the previous behavior */
875 status = create_local_token(tmp_ctx, *server_info, NULL,
876 (*server_info)->info3->base.account_name.string,
877 session_info);
878 if (!NT_STATUS_IS_OK(status)) {
879 DEBUG(0, ("create_local_token failed: %s\n",
880 nt_errstr(status)));
881 goto done;
883 talloc_steal(NULL, *session_info);
884 talloc_steal(NULL, *server_info);
886 /* annoying, but the Guest really does have a session key, and it is
887 all zeros! */
888 (*session_info)->session_key = data_blob(zeros, sizeof(zeros));
890 status = NT_STATUS_OK;
891 done:
892 TALLOC_FREE(tmp_ctx);
893 return status;
896 /***************************************************************************
897 Make (and fill) a auth_session_info struct for a system user login.
898 This *must* succeed for smbd to start.
899 ***************************************************************************/
901 static NTSTATUS make_new_session_info_system(TALLOC_CTX *mem_ctx,
902 struct auth_session_info **session_info)
904 NTSTATUS status;
905 struct auth_serversupplied_info *server_info;
906 TALLOC_CTX *tmp_ctx;
908 tmp_ctx = talloc_stackframe();
909 if (tmp_ctx == NULL) {
910 return NT_STATUS_NO_MEMORY;
913 server_info = make_server_info(tmp_ctx);
914 if (!server_info) {
915 status = NT_STATUS_NO_MEMORY;
916 DEBUG(0, ("failed making server_info\n"));
917 goto done;
920 server_info->info3 = talloc_zero(server_info, struct netr_SamInfo3);
921 if (!server_info->info3) {
922 status = NT_STATUS_NO_MEMORY;
923 DEBUG(0, ("talloc failed setting info3\n"));
924 goto done;
927 status = get_system_info3(server_info, server_info->info3);
928 if (!NT_STATUS_IS_OK(status)) {
929 DEBUG(0, ("Failed creating system info3 with %s\n",
930 nt_errstr(status)));
931 goto done;
934 server_info->utok.uid = sec_initial_uid();
935 server_info->utok.gid = sec_initial_gid();
936 server_info->unix_name = talloc_asprintf(server_info,
937 "NT AUTHORITY%cSYSTEM",
938 *lp_winbind_separator());
940 if (!server_info->unix_name) {
941 status = NT_STATUS_NO_MEMORY;
942 DEBUG(0, ("talloc_asprintf failed setting unix_name\n"));
943 goto done;
946 server_info->security_token = talloc_zero(server_info, struct security_token);
947 if (!server_info->security_token) {
948 status = NT_STATUS_NO_MEMORY;
949 DEBUG(0, ("talloc failed setting security token\n"));
950 goto done;
953 status = add_sid_to_array_unique(server_info->security_token->sids,
954 &global_sid_System,
955 &server_info->security_token->sids,
956 &server_info->security_token->num_sids);
957 if (!NT_STATUS_IS_OK(status)) {
958 goto done;
961 /* SYSTEM has all privilages */
962 server_info->security_token->privilege_mask = ~0;
964 /* Now turn the server_info into a session_info with the full token etc */
965 status = create_local_token(mem_ctx, server_info, NULL, "SYSTEM", session_info);
966 talloc_free(server_info);
968 if (!NT_STATUS_IS_OK(status)) {
969 DEBUG(0, ("create_local_token failed: %s\n",
970 nt_errstr(status)));
971 goto done;
974 talloc_steal(mem_ctx, *session_info);
976 done:
977 TALLOC_FREE(tmp_ctx);
978 return status;
981 /****************************************************************************
982 Fake a auth_session_info just from a username (as a
983 session_info structure, with create_local_token() already called on
985 ****************************************************************************/
987 NTSTATUS make_session_info_from_username(TALLOC_CTX *mem_ctx,
988 const char *username,
989 bool is_guest,
990 struct auth_session_info **session_info)
992 struct passwd *pwd;
993 NTSTATUS status;
994 struct auth_serversupplied_info *result;
996 pwd = Get_Pwnam_alloc(talloc_tos(), username);
997 if (pwd == NULL) {
998 return NT_STATUS_NO_SUCH_USER;
1001 status = make_server_info_pw(&result, pwd->pw_name, pwd);
1003 if (!NT_STATUS_IS_OK(status)) {
1004 return status;
1007 result->nss_token = true;
1008 result->guest = is_guest;
1010 /* Now turn the server_info into a session_info with the full token etc */
1011 status = create_local_token(mem_ctx, result, NULL, pwd->pw_name, session_info);
1012 TALLOC_FREE(result);
1013 TALLOC_FREE(pwd);
1015 return status;
1018 /* This function MUST only used to create the cached server_info for
1019 * guest.
1021 * This is a lossy conversion. Variables known to be lost so far
1022 * include:
1024 * - nss_token (not needed because the only read doesn't happen
1025 * for the GUEST user, as this routine populates ->security_token
1027 * - extra (not needed because the guest account must have valid RIDs per the output of get_guest_info3())
1029 * - The 'server_info' parameter allows the missing 'info3' to be copied across.
1031 static struct auth_serversupplied_info *copy_session_info_serverinfo_guest(TALLOC_CTX *mem_ctx,
1032 const struct auth_session_info *src,
1033 struct auth_serversupplied_info *server_info)
1035 struct auth_serversupplied_info *dst;
1037 dst = make_server_info(mem_ctx);
1038 if (dst == NULL) {
1039 return NULL;
1042 /* This element must be provided to convert back to an auth_serversupplied_info */
1043 SMB_ASSERT(src->unix_info);
1045 dst->guest = true;
1046 dst->system = false;
1048 /* This element must be provided to convert back to an
1049 * auth_serversupplied_info. This needs to be from the
1050 * auth_session_info because the group values in particular
1051 * may change during create_local_token() processing */
1052 SMB_ASSERT(src->unix_token);
1053 dst->utok.uid = src->unix_token->uid;
1054 dst->utok.gid = src->unix_token->gid;
1055 dst->utok.ngroups = src->unix_token->ngroups;
1056 if (src->unix_token->ngroups != 0) {
1057 dst->utok.groups = (gid_t *)talloc_memdup(
1058 dst, src->unix_token->groups,
1059 sizeof(gid_t)*dst->utok.ngroups);
1060 } else {
1061 dst->utok.groups = NULL;
1064 /* We must have a security_token as otherwise the lossy
1065 * conversion without nss_token would cause create_local_token
1066 * to take the wrong path */
1067 SMB_ASSERT(src->security_token);
1069 dst->security_token = dup_nt_token(dst, src->security_token);
1070 if (!dst->security_token) {
1071 TALLOC_FREE(dst);
1072 return NULL;
1075 dst->session_key = data_blob_talloc( dst, src->session_key.data,
1076 src->session_key.length);
1078 /* This is OK because this functions is only used for the
1079 * GUEST account, which has all-zero keys for both values */
1080 dst->lm_session_key = data_blob_talloc(dst, src->session_key.data,
1081 src->session_key.length);
1083 dst->info3 = copy_netr_SamInfo3(dst, server_info->info3);
1084 if (!dst->info3) {
1085 TALLOC_FREE(dst);
1086 return NULL;
1089 dst->unix_name = talloc_strdup(dst, src->unix_info->unix_name);
1090 if (!dst->unix_name) {
1091 TALLOC_FREE(dst);
1092 return NULL;
1095 return dst;
1098 struct auth_session_info *copy_session_info(TALLOC_CTX *mem_ctx,
1099 const struct auth_session_info *src)
1101 struct auth_session_info *dst;
1102 DATA_BLOB blob;
1103 enum ndr_err_code ndr_err;
1105 ndr_err = ndr_push_struct_blob(
1106 &blob, talloc_tos(), src,
1107 (ndr_push_flags_fn_t)ndr_push_auth_session_info);
1108 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1109 DEBUG(0, ("copy_session_info(): ndr_push_auth_session_info failed: "
1110 "%s\n", ndr_errstr(ndr_err)));
1111 return NULL;
1114 dst = talloc(mem_ctx, struct auth_session_info);
1115 if (dst == NULL) {
1116 DEBUG(0, ("talloc failed\n"));
1117 TALLOC_FREE(blob.data);
1118 return NULL;
1121 ndr_err = ndr_pull_struct_blob(
1122 &blob, dst, dst,
1123 (ndr_pull_flags_fn_t)ndr_pull_auth_session_info);
1124 TALLOC_FREE(blob.data);
1126 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1127 DEBUG(0, ("copy_session_info(): ndr_pull_auth_session_info failed: "
1128 "%s\n", ndr_errstr(ndr_err)));
1129 TALLOC_FREE(dst);
1130 return NULL;
1133 return dst;
1137 * Set a new session key. Used in the rpc server where we have to override the
1138 * SMB level session key with SystemLibraryDTC
1141 bool session_info_set_session_key(struct auth_session_info *info,
1142 DATA_BLOB session_key)
1144 TALLOC_FREE(info->session_key.data);
1146 info->session_key = data_blob_talloc(
1147 info, session_key.data, session_key.length);
1149 return (info->session_key.data != NULL);
1152 static struct auth_session_info *guest_info = NULL;
1154 static struct auth_serversupplied_info *guest_server_info = NULL;
1156 bool init_guest_info(void)
1158 if (guest_info != NULL)
1159 return true;
1161 return NT_STATUS_IS_OK(make_new_session_info_guest(&guest_info, &guest_server_info));
1164 NTSTATUS make_server_info_guest(TALLOC_CTX *mem_ctx,
1165 struct auth_serversupplied_info **server_info)
1167 /* This is trickier than it would appear to need to be because
1168 * we are trying to avoid certain costly operations when the
1169 * structure is converted to a 'auth_session_info' again in
1170 * create_local_token() */
1171 *server_info = copy_session_info_serverinfo_guest(mem_ctx, guest_info, guest_server_info);
1172 return (*server_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1175 NTSTATUS make_session_info_guest(TALLOC_CTX *mem_ctx,
1176 struct auth_session_info **session_info)
1178 *session_info = copy_session_info(mem_ctx, guest_info);
1179 return (*session_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1182 static struct auth_session_info *system_info = NULL;
1184 NTSTATUS init_system_session_info(void)
1186 if (system_info != NULL)
1187 return NT_STATUS_OK;
1189 return make_new_session_info_system(NULL, &system_info);
1192 NTSTATUS make_session_info_system(TALLOC_CTX *mem_ctx,
1193 struct auth_session_info **session_info)
1195 if (system_info == NULL) return NT_STATUS_UNSUCCESSFUL;
1196 *session_info = copy_session_info(mem_ctx, system_info);
1197 return (*session_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1200 const struct auth_session_info *get_session_info_system(void)
1202 return system_info;
1205 /***************************************************************************
1206 Purely internal function for make_server_info_info3
1207 ***************************************************************************/
1209 static NTSTATUS check_account(TALLOC_CTX *mem_ctx, const char *domain,
1210 const char *username, char **found_username,
1211 struct passwd **pwd,
1212 bool *username_was_mapped)
1214 char *orig_dom_user = NULL;
1215 char *dom_user = NULL;
1216 char *lower_username = NULL;
1217 char *real_username = NULL;
1218 struct passwd *passwd;
1220 lower_username = talloc_strdup(mem_ctx, username);
1221 if (!lower_username) {
1222 return NT_STATUS_NO_MEMORY;
1224 if (!strlower_m( lower_username )) {
1225 return NT_STATUS_INVALID_PARAMETER;
1228 orig_dom_user = talloc_asprintf(mem_ctx,
1229 "%s%c%s",
1230 domain,
1231 *lp_winbind_separator(),
1232 lower_username);
1233 if (!orig_dom_user) {
1234 return NT_STATUS_NO_MEMORY;
1237 /* Get the passwd struct. Try to create the account if necessary. */
1239 *username_was_mapped = map_username(mem_ctx, orig_dom_user, &dom_user);
1240 if (!dom_user) {
1241 return NT_STATUS_NO_MEMORY;
1244 passwd = smb_getpwnam(mem_ctx, dom_user, &real_username, true );
1245 if (!passwd) {
1246 DEBUG(3, ("Failed to find authenticated user %s via "
1247 "getpwnam(), denying access.\n", dom_user));
1248 return NT_STATUS_NO_SUCH_USER;
1251 if (!real_username) {
1252 return NT_STATUS_NO_MEMORY;
1255 *pwd = passwd;
1257 /* This is pointless -- there is no support for differing
1258 unix and windows names. Make sure to always store the
1259 one we actually looked up and succeeded. Have I mentioned
1260 why I hate the 'winbind use default domain' parameter?
1261 --jerry */
1263 *found_username = talloc_strdup( mem_ctx, real_username );
1265 return NT_STATUS_OK;
1268 /****************************************************************************
1269 Wrapper to allow the getpwnam() call to strip the domain name and
1270 try again in case a local UNIX user is already there. Also run through
1271 the username if we fallback to the username only.
1272 ****************************************************************************/
1274 struct passwd *smb_getpwnam( TALLOC_CTX *mem_ctx, const char *domuser,
1275 char **p_save_username, bool create )
1277 struct passwd *pw = NULL;
1278 char *p = NULL;
1279 char *username = NULL;
1281 /* we only save a copy of the username it has been mangled
1282 by winbindd use default domain */
1283 *p_save_username = NULL;
1285 /* don't call map_username() here since it has to be done higher
1286 up the stack so we don't call it multiple times */
1288 username = talloc_strdup(mem_ctx, domuser);
1289 if (!username) {
1290 return NULL;
1293 p = strchr_m( username, *lp_winbind_separator() );
1295 /* code for a DOMAIN\user string */
1297 if ( p ) {
1298 pw = Get_Pwnam_alloc( mem_ctx, domuser );
1299 if ( pw ) {
1300 /* make sure we get the case of the username correct */
1301 /* work around 'winbind use default domain = yes' */
1303 if ( lp_winbind_use_default_domain() &&
1304 !strchr_m( pw->pw_name, *lp_winbind_separator() ) ) {
1305 char *domain;
1307 /* split the domain and username into 2 strings */
1308 *p = '\0';
1309 domain = username;
1311 *p_save_username = talloc_asprintf(mem_ctx,
1312 "%s%c%s",
1313 domain,
1314 *lp_winbind_separator(),
1315 pw->pw_name);
1316 if (!*p_save_username) {
1317 TALLOC_FREE(pw);
1318 return NULL;
1320 } else {
1321 *p_save_username = talloc_strdup(mem_ctx, pw->pw_name);
1324 /* whew -- done! */
1325 return pw;
1328 /* setup for lookup of just the username */
1329 /* remember that p and username are overlapping memory */
1331 p++;
1332 username = talloc_strdup(mem_ctx, p);
1333 if (!username) {
1334 return NULL;
1338 /* just lookup a plain username */
1340 pw = Get_Pwnam_alloc(mem_ctx, username);
1342 /* Create local user if requested but only if winbindd
1343 is not running. We need to protect against cases
1344 where winbindd is failing and then prematurely
1345 creating users in /etc/passwd */
1347 if ( !pw && create && !winbind_ping() ) {
1348 /* Don't add a machine account. */
1349 if (username[strlen(username)-1] == '$')
1350 return NULL;
1352 _smb_create_user(NULL, username, NULL);
1353 pw = Get_Pwnam_alloc(mem_ctx, username);
1356 /* one last check for a valid passwd struct */
1358 if (pw) {
1359 *p_save_username = talloc_strdup(mem_ctx, pw->pw_name);
1361 return pw;
1364 /***************************************************************************
1365 Make a server_info struct from the info3 returned by a domain logon
1366 ***************************************************************************/
1368 NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
1369 const char *sent_nt_username,
1370 const char *domain,
1371 struct auth_serversupplied_info **server_info,
1372 struct netr_SamInfo3 *info3)
1374 static const char zeros[16] = {0, };
1376 NTSTATUS nt_status = NT_STATUS_OK;
1377 char *found_username = NULL;
1378 const char *nt_domain;
1379 const char *nt_username;
1380 struct dom_sid user_sid;
1381 struct dom_sid group_sid;
1382 bool username_was_mapped;
1383 struct passwd *pwd;
1384 struct auth_serversupplied_info *result;
1387 Here is where we should check the list of
1388 trusted domains, and verify that the SID
1389 matches.
1392 if (!sid_compose(&user_sid, info3->base.domain_sid, info3->base.rid)) {
1393 return NT_STATUS_INVALID_PARAMETER;
1396 if (!sid_compose(&group_sid, info3->base.domain_sid,
1397 info3->base.primary_gid)) {
1398 return NT_STATUS_INVALID_PARAMETER;
1401 nt_username = talloc_strdup(mem_ctx, info3->base.account_name.string);
1402 if (!nt_username) {
1403 /* If the server didn't give us one, just use the one we sent
1404 * them */
1405 nt_username = sent_nt_username;
1408 nt_domain = talloc_strdup(mem_ctx, info3->base.logon_domain.string);
1409 if (!nt_domain) {
1410 /* If the server didn't give us one, just use the one we sent
1411 * them */
1412 nt_domain = domain;
1415 /* If getpwnam() fails try the add user script (2.2.x behavior).
1417 We use the _unmapped_ username here in an attempt to provide
1418 consistent username mapping behavior between kerberos and NTLM[SSP]
1419 authentication in domain mode security. I.E. Username mapping
1420 should be applied to the fully qualified username
1421 (e.g. DOMAIN\user) and not just the login name. Yes this means we
1422 called map_username() unnecessarily in make_user_info_map() but
1423 that is how the current code is designed. Making the change here
1424 is the least disruptive place. -- jerry */
1426 /* this call will try to create the user if necessary */
1428 nt_status = check_account(mem_ctx, nt_domain, sent_nt_username,
1429 &found_username, &pwd,
1430 &username_was_mapped);
1432 if (!NT_STATUS_IS_OK(nt_status)) {
1433 return nt_status;
1436 result = make_server_info(NULL);
1437 if (result == NULL) {
1438 DEBUG(4, ("make_server_info failed!\n"));
1439 return NT_STATUS_NO_MEMORY;
1442 result->unix_name = talloc_strdup(result, found_username);
1444 /* copy in the info3 */
1445 result->info3 = copy_netr_SamInfo3(result, info3);
1446 if (result->info3 == NULL) {
1447 TALLOC_FREE(result);
1448 return NT_STATUS_NO_MEMORY;
1451 /* Fill in the unix info we found on the way */
1453 result->utok.uid = pwd->pw_uid;
1454 result->utok.gid = pwd->pw_gid;
1456 /* ensure we are never given NULL session keys */
1458 if (memcmp(info3->base.key.key, zeros, sizeof(zeros)) == 0) {
1459 result->session_key = data_blob_null;
1460 } else {
1461 result->session_key = data_blob_talloc(
1462 result, info3->base.key.key,
1463 sizeof(info3->base.key.key));
1466 if (memcmp(info3->base.LMSessKey.key, zeros, 8) == 0) {
1467 result->lm_session_key = data_blob_null;
1468 } else {
1469 result->lm_session_key = data_blob_talloc(
1470 result, info3->base.LMSessKey.key,
1471 sizeof(info3->base.LMSessKey.key));
1474 result->nss_token |= username_was_mapped;
1476 result->guest = (info3->base.user_flags & NETLOGON_GUEST);
1478 *server_info = result;
1480 return NT_STATUS_OK;
1483 /*****************************************************************************
1484 Make a server_info struct from the wbcAuthUserInfo returned by a domain logon
1485 ******************************************************************************/
1487 NTSTATUS make_server_info_wbcAuthUserInfo(TALLOC_CTX *mem_ctx,
1488 const char *sent_nt_username,
1489 const char *domain,
1490 const struct wbcAuthUserInfo *info,
1491 struct auth_serversupplied_info **server_info)
1493 struct netr_SamInfo3 *info3;
1495 info3 = wbcAuthUserInfo_to_netr_SamInfo3(mem_ctx, info);
1496 if (!info3) {
1497 return NT_STATUS_NO_MEMORY;
1500 return make_server_info_info3(mem_ctx,
1501 sent_nt_username, domain,
1502 server_info, info3);
1506 * Verify whether or not given domain is trusted.
1508 * @param domain_name name of the domain to be verified
1509 * @return true if domain is one of the trusted ones or
1510 * false if otherwise
1513 bool is_trusted_domain(const char* dom_name)
1515 struct dom_sid trustdom_sid;
1516 bool ret;
1518 /* no trusted domains for a standalone server */
1520 if ( lp_server_role() == ROLE_STANDALONE )
1521 return false;
1523 if (dom_name == NULL || dom_name[0] == '\0') {
1524 return false;
1527 if (strequal(dom_name, get_global_sam_name())) {
1528 return false;
1531 /* if we are a DC, then check for a direct trust relationships */
1533 if ( IS_DC ) {
1534 become_root();
1535 DEBUG (5,("is_trusted_domain: Checking for domain trust with "
1536 "[%s]\n", dom_name ));
1537 ret = pdb_get_trusteddom_pw(dom_name, NULL, NULL, NULL);
1538 unbecome_root();
1539 if (ret)
1540 return true;
1542 else {
1543 wbcErr result;
1545 /* If winbind is around, ask it */
1547 result = wb_is_trusted_domain(dom_name);
1549 if (result == WBC_ERR_SUCCESS) {
1550 return true;
1553 if (result == WBC_ERR_DOMAIN_NOT_FOUND) {
1554 /* winbind could not find the domain */
1555 return false;
1558 /* The only other possible result is that winbind is not up
1559 and running. We need to update the trustdom_cache
1560 ourselves */
1562 update_trustdom_cache();
1565 /* now the trustdom cache should be available a DC could still
1566 * have a transitive trust so fall back to the cache of trusted
1567 * domains (like a domain member would use */
1569 if ( trustdom_cache_fetch(dom_name, &trustdom_sid) ) {
1570 return true;
1573 return false;
1579 on a logon error possibly map the error to success if "map to guest"
1580 is set approriately
1582 NTSTATUS do_map_to_guest_server_info(NTSTATUS status,
1583 struct auth_serversupplied_info **server_info,
1584 const char *user, const char *domain)
1586 user = user ? user : "";
1587 domain = domain ? domain : "";
1589 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
1590 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
1591 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
1592 DEBUG(3,("No such user %s [%s] - using guest account\n",
1593 user, domain));
1594 return make_server_info_guest(NULL, server_info);
1596 } else if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1597 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
1598 DEBUG(3,("Registered username %s for guest access\n",
1599 user));
1600 return make_server_info_guest(NULL, server_info);
1604 return status;
1608 Extract session key from a session info and return it in a blob
1609 if intent is KEY_USE_16BYTES, truncate it to 16 bytes
1611 See sections 3.2.4.15 and 3.3.4.2 of MS-SMB
1612 Also see https://lists.samba.org/archive/cifs-protocol/2012-January/002265.html for details
1614 Note that returned session_key is referencing the original key, it is supposed to be
1615 short-lived. If original session_info->session_key is gone, the reference will be broken.
1617 NTSTATUS session_extract_session_key(const struct auth_session_info *session_info, DATA_BLOB *session_key, enum session_key_use_intent intent)
1620 if (session_key == NULL || session_info == NULL) {
1621 return NT_STATUS_INVALID_PARAMETER;
1624 if (session_info->session_key.length == 0) {
1625 return NT_STATUS_NO_USER_SESSION_KEY;
1628 *session_key = session_info->session_key;
1629 if (intent == KEY_USE_16BYTES) {
1630 session_key->length = MIN(session_info->session_key.length, 16);
1632 return NT_STATUS_OK;