docs: Remove duplicate synonym min protocol.
[Samba.git] / source3 / auth / auth_util.c
bloba08d0945a59a4b113e5d95b4d5f6ad379a45945b
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()))
130 if (lp_map_untrusted_to_domain())
131 domain = my_sam_name();
132 else
133 domain = get_global_sam_name();
134 DEBUG(5, ("Mapped domain from [%s] to [%s] for user [%s] from "
135 "workstation [%s]\n",
136 client_domain, domain, smb_name, workstation_name));
139 /* We know that the given domain is trusted (and we are allowing them),
140 * it is our global SAM name, or for legacy behavior it is our
141 * primary domain name */
143 result = make_user_info(user_info, smb_name, internal_username,
144 client_domain, domain, workstation_name,
145 remote_address, lm_pwd, nt_pwd,
146 lm_interactive_pwd, nt_interactive_pwd,
147 plaintext, password_state);
148 if (NT_STATUS_IS_OK(result)) {
149 /* We have tried mapping */
150 (*user_info)->mapped_state = true;
151 /* did we actually map the user to a different name? */
152 (*user_info)->was_mapped = was_mapped;
154 return result;
157 /****************************************************************************
158 Create an auth_usersupplied_data, making the DATA_BLOBs here.
159 Decrypt and encrypt the passwords.
160 ****************************************************************************/
162 bool make_user_info_netlogon_network(struct auth_usersupplied_info **user_info,
163 const char *smb_name,
164 const char *client_domain,
165 const char *workstation_name,
166 const struct tsocket_address *remote_address,
167 uint32 logon_parameters,
168 const uchar *lm_network_pwd,
169 int lm_pwd_len,
170 const uchar *nt_network_pwd,
171 int nt_pwd_len)
173 bool ret;
174 NTSTATUS status;
175 DATA_BLOB lm_blob = data_blob(lm_network_pwd, lm_pwd_len);
176 DATA_BLOB nt_blob = data_blob(nt_network_pwd, nt_pwd_len);
178 status = make_user_info_map(user_info,
179 smb_name, client_domain,
180 workstation_name,
181 remote_address,
182 lm_pwd_len ? &lm_blob : NULL,
183 nt_pwd_len ? &nt_blob : NULL,
184 NULL, NULL, NULL,
185 AUTH_PASSWORD_RESPONSE);
187 if (NT_STATUS_IS_OK(status)) {
188 (*user_info)->logon_parameters = logon_parameters;
190 ret = NT_STATUS_IS_OK(status) ? true : false;
192 data_blob_free(&lm_blob);
193 data_blob_free(&nt_blob);
194 return ret;
197 /****************************************************************************
198 Create an auth_usersupplied_data, making the DATA_BLOBs here.
199 Decrypt and encrypt the passwords.
200 ****************************************************************************/
202 bool make_user_info_netlogon_interactive(struct auth_usersupplied_info **user_info,
203 const char *smb_name,
204 const char *client_domain,
205 const char *workstation_name,
206 const struct tsocket_address *remote_address,
207 uint32 logon_parameters,
208 const uchar chal[8],
209 const uchar lm_interactive_pwd[16],
210 const uchar nt_interactive_pwd[16],
211 const uchar *dc_sess_key)
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];
217 unsigned char key[16];
219 memcpy(key, dc_sess_key, 16);
221 if (lm_interactive_pwd)
222 memcpy(lm_pwd.hash, lm_interactive_pwd, sizeof(lm_pwd.hash));
224 if (nt_interactive_pwd)
225 memcpy(nt_pwd.hash, nt_interactive_pwd, sizeof(nt_pwd.hash));
227 #ifdef DEBUG_PASSWORD
228 DEBUG(100,("key:"));
229 dump_data(100, key, sizeof(key));
231 DEBUG(100,("lm owf password:"));
232 dump_data(100, lm_pwd.hash, sizeof(lm_pwd.hash));
234 DEBUG(100,("nt owf password:"));
235 dump_data(100, nt_pwd.hash, sizeof(nt_pwd.hash));
236 #endif
238 if (lm_interactive_pwd)
239 arcfour_crypt(lm_pwd.hash, key, sizeof(lm_pwd.hash));
241 if (nt_interactive_pwd)
242 arcfour_crypt(nt_pwd.hash, key, sizeof(nt_pwd.hash));
244 #ifdef DEBUG_PASSWORD
245 DEBUG(100,("decrypt of lm owf password:"));
246 dump_data(100, lm_pwd.hash, sizeof(lm_pwd));
248 DEBUG(100,("decrypt of nt owf password:"));
249 dump_data(100, nt_pwd.hash, sizeof(nt_pwd));
250 #endif
252 if (lm_interactive_pwd)
253 SMBOWFencrypt(lm_pwd.hash, chal,
254 local_lm_response);
256 if (nt_interactive_pwd)
257 SMBOWFencrypt(nt_pwd.hash, chal,
258 local_nt_response);
260 /* Password info paranoia */
261 ZERO_STRUCT(key);
264 bool ret;
265 NTSTATUS nt_status;
266 DATA_BLOB local_lm_blob;
267 DATA_BLOB local_nt_blob;
269 if (lm_interactive_pwd) {
270 local_lm_blob = data_blob(local_lm_response,
271 sizeof(local_lm_response));
274 if (nt_interactive_pwd) {
275 local_nt_blob = data_blob(local_nt_response,
276 sizeof(local_nt_response));
279 nt_status = make_user_info_map(
280 user_info,
281 smb_name, client_domain, workstation_name,
282 remote_address,
283 lm_interactive_pwd ? &local_lm_blob : NULL,
284 nt_interactive_pwd ? &local_nt_blob : NULL,
285 lm_interactive_pwd ? &lm_pwd : NULL,
286 nt_interactive_pwd ? &nt_pwd : NULL,
287 NULL, AUTH_PASSWORD_HASH);
289 if (NT_STATUS_IS_OK(nt_status)) {
290 (*user_info)->logon_parameters = logon_parameters;
293 ret = NT_STATUS_IS_OK(nt_status) ? true : false;
294 data_blob_free(&local_lm_blob);
295 data_blob_free(&local_nt_blob);
296 return ret;
301 /****************************************************************************
302 Create an auth_usersupplied_data structure
303 ****************************************************************************/
305 bool make_user_info_for_reply(struct auth_usersupplied_info **user_info,
306 const char *smb_name,
307 const char *client_domain,
308 const struct tsocket_address *remote_address,
309 const uint8 chal[8],
310 DATA_BLOB plaintext_password)
313 DATA_BLOB local_lm_blob;
314 DATA_BLOB local_nt_blob;
315 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
316 char *plaintext_password_string;
318 * Not encrypted - do so.
321 DEBUG(5,("make_user_info_for_reply: User passwords not in encrypted "
322 "format.\n"));
323 if (plaintext_password.data && plaintext_password.length) {
324 unsigned char local_lm_response[24];
326 #ifdef DEBUG_PASSWORD
327 DEBUG(10,("Unencrypted password (len %d):\n",
328 (int)plaintext_password.length));
329 dump_data(100, plaintext_password.data,
330 plaintext_password.length);
331 #endif
333 SMBencrypt( (const char *)plaintext_password.data,
334 (const uchar*)chal, local_lm_response);
335 local_lm_blob = data_blob(local_lm_response, 24);
337 /* We can't do an NT hash here, as the password needs to be
338 case insensitive */
339 local_nt_blob = data_blob_null;
340 } else {
341 local_lm_blob = data_blob_null;
342 local_nt_blob = data_blob_null;
345 plaintext_password_string = talloc_strndup(talloc_tos(),
346 (const char *)plaintext_password.data,
347 plaintext_password.length);
348 if (!plaintext_password_string) {
349 return false;
352 ret = make_user_info(
353 user_info, smb_name, smb_name, client_domain, client_domain,
354 get_remote_machine_name(),
355 remote_address,
356 local_lm_blob.data ? &local_lm_blob : NULL,
357 local_nt_blob.data ? &local_nt_blob : NULL,
358 NULL, NULL,
359 plaintext_password_string,
360 AUTH_PASSWORD_PLAIN);
362 if (plaintext_password_string) {
363 memset(plaintext_password_string, '\0', strlen(plaintext_password_string));
364 talloc_free(plaintext_password_string);
367 data_blob_free(&local_lm_blob);
368 return NT_STATUS_IS_OK(ret) ? true : false;
371 /****************************************************************************
372 Create an auth_usersupplied_data structure
373 ****************************************************************************/
375 NTSTATUS make_user_info_for_reply_enc(struct auth_usersupplied_info **user_info,
376 const char *smb_name,
377 const char *client_domain,
378 const struct tsocket_address *remote_address,
379 DATA_BLOB lm_resp, DATA_BLOB nt_resp)
381 return make_user_info(user_info, smb_name, smb_name,
382 client_domain, client_domain,
383 get_remote_machine_name(),
384 remote_address,
385 lm_resp.data && (lm_resp.length > 0) ? &lm_resp : NULL,
386 nt_resp.data && (nt_resp.length > 0) ? &nt_resp : NULL,
387 NULL, NULL, NULL,
388 AUTH_PASSWORD_RESPONSE);
391 /****************************************************************************
392 Create a guest user_info blob, for anonymous authentication.
393 ****************************************************************************/
395 bool make_user_info_guest(const struct tsocket_address *remote_address,
396 struct auth_usersupplied_info **user_info)
398 NTSTATUS nt_status;
400 nt_status = make_user_info(user_info,
401 "","",
402 "","",
403 "",
404 remote_address,
405 NULL, NULL,
406 NULL, NULL,
407 NULL,
408 AUTH_PASSWORD_RESPONSE);
410 return NT_STATUS_IS_OK(nt_status) ? true : false;
413 static NTSTATUS log_nt_token(struct security_token *token)
415 TALLOC_CTX *frame = talloc_stackframe();
416 char *command;
417 char *group_sidstr;
418 size_t i;
420 if ((lp_log_nt_token_command(frame) == NULL) ||
421 (strlen(lp_log_nt_token_command(frame)) == 0)) {
422 TALLOC_FREE(frame);
423 return NT_STATUS_OK;
426 group_sidstr = talloc_strdup(frame, "");
427 for (i=1; i<token->num_sids; i++) {
428 group_sidstr = talloc_asprintf(
429 frame, "%s %s", group_sidstr,
430 sid_string_talloc(frame, &token->sids[i]));
433 command = talloc_string_sub(
434 frame, lp_log_nt_token_command(frame),
435 "%s", sid_string_talloc(frame, &token->sids[0]));
436 command = talloc_string_sub(frame, command, "%t", group_sidstr);
438 if (command == NULL) {
439 TALLOC_FREE(frame);
440 return NT_STATUS_NO_MEMORY;
443 DEBUG(8, ("running command: [%s]\n", command));
444 if (smbrun(command, NULL) != 0) {
445 DEBUG(0, ("Could not log NT token\n"));
446 TALLOC_FREE(frame);
447 return NT_STATUS_ACCESS_DENIED;
450 TALLOC_FREE(frame);
451 return NT_STATUS_OK;
455 * Create the token to use from server_info->info3 and
456 * server_info->sids (the info3/sam groups). Find the unix gids.
459 NTSTATUS create_local_token(TALLOC_CTX *mem_ctx,
460 const struct auth_serversupplied_info *server_info,
461 DATA_BLOB *session_key,
462 const char *smb_username, /* for ->sanitized_username, for %U subs */
463 struct auth_session_info **session_info_out)
465 struct security_token *t;
466 NTSTATUS status;
467 size_t i;
468 struct dom_sid tmp_sid;
469 struct auth_session_info *session_info;
470 struct unixid *ids;
471 fstring tmp;
473 /* Ensure we can't possible take a code path leading to a
474 * null defref. */
475 if (!server_info) {
476 return NT_STATUS_LOGON_FAILURE;
479 session_info = talloc_zero(mem_ctx, struct auth_session_info);
480 if (!session_info) {
481 return NT_STATUS_NO_MEMORY;
484 session_info->unix_token = talloc_zero(session_info, struct security_unix_token);
485 if (!session_info->unix_token) {
486 TALLOC_FREE(session_info);
487 return NT_STATUS_NO_MEMORY;
490 session_info->unix_token->uid = server_info->utok.uid;
491 session_info->unix_token->gid = server_info->utok.gid;
493 session_info->unix_info = talloc_zero(session_info, struct auth_user_info_unix);
494 if (!session_info->unix_info) {
495 TALLOC_FREE(session_info);
496 return NT_STATUS_NO_MEMORY;
499 session_info->unix_info->unix_name = talloc_strdup(session_info, server_info->unix_name);
500 if (!session_info->unix_info->unix_name) {
501 TALLOC_FREE(session_info);
502 return NT_STATUS_NO_MEMORY;
505 /* This is a potentially untrusted username for use in %U */
506 alpha_strcpy(tmp, smb_username, ". _-$", sizeof(tmp));
507 session_info->unix_info->sanitized_username =
508 talloc_strdup(session_info->unix_info, tmp);
510 if (session_key) {
511 data_blob_free(&session_info->session_key);
512 session_info->session_key = data_blob_talloc(session_info,
513 session_key->data,
514 session_key->length);
515 if (!session_info->session_key.data && session_key->length) {
516 return NT_STATUS_NO_MEMORY;
518 } else {
519 session_info->session_key = data_blob_talloc( session_info, server_info->session_key.data,
520 server_info->session_key.length);
523 /* We need to populate session_info->info with the information found in server_info->info3 */
524 status = make_user_info_SamBaseInfo(session_info, "", &server_info->info3->base,
525 server_info->guest == false,
526 &session_info->info);
527 if (!NT_STATUS_IS_OK(status)) {
528 DEBUG(0, ("conversion of info3 into auth_user_info failed!\n"));
529 TALLOC_FREE(session_info);
530 return status;
533 if (server_info->security_token) {
534 /* Just copy the token, it has already been finalised
535 * (nasty hack to support a cached guest/system session_info
538 session_info->security_token = dup_nt_token(session_info, server_info->security_token);
539 if (!session_info->security_token) {
540 TALLOC_FREE(session_info);
541 return NT_STATUS_NO_MEMORY;
544 session_info->unix_token->ngroups = server_info->utok.ngroups;
545 if (server_info->utok.ngroups != 0) {
546 session_info->unix_token->groups = (gid_t *)talloc_memdup(
547 session_info->unix_token, server_info->utok.groups,
548 sizeof(gid_t)*session_info->unix_token->ngroups);
549 } else {
550 session_info->unix_token->groups = NULL;
553 *session_info_out = session_info;
554 return NT_STATUS_OK;
558 * If winbind is not around, we can not make much use of the SIDs the
559 * domain controller provided us with. Likewise if the user name was
560 * mapped to some local unix user.
563 if (((lp_server_role() == ROLE_DOMAIN_MEMBER) && !winbind_ping()) ||
564 (server_info->nss_token)) {
565 char *found_username = NULL;
566 status = create_token_from_username(session_info,
567 server_info->unix_name,
568 server_info->guest,
569 &session_info->unix_token->uid,
570 &session_info->unix_token->gid,
571 &found_username,
572 &session_info->security_token);
573 if (NT_STATUS_IS_OK(status)) {
574 session_info->unix_info->unix_name = found_username;
576 } else {
577 status = create_local_nt_token_from_info3(session_info,
578 server_info->guest,
579 server_info->info3,
580 &server_info->extra,
581 &session_info->security_token);
584 if (!NT_STATUS_IS_OK(status)) {
585 return status;
588 /* Convert the SIDs to gids. */
590 session_info->unix_token->ngroups = 0;
591 session_info->unix_token->groups = NULL;
593 t = session_info->security_token;
595 ids = talloc_array(talloc_tos(), struct unixid,
596 t->num_sids);
597 if (ids == NULL) {
598 return NT_STATUS_NO_MEMORY;
601 if (!sids_to_unixids(t->sids, t->num_sids, ids)) {
602 TALLOC_FREE(ids);
603 return NT_STATUS_NO_MEMORY;
606 for (i=0; i<t->num_sids; i++) {
608 if (i == 0 && ids[i].type != ID_TYPE_BOTH) {
609 continue;
612 if (ids[i].type != ID_TYPE_GID &&
613 ids[i].type != ID_TYPE_BOTH) {
614 DEBUG(10, ("Could not convert SID %s to gid, "
615 "ignoring it\n",
616 sid_string_dbg(&t->sids[i])));
617 continue;
619 if (!add_gid_to_array_unique(session_info, ids[i].id,
620 &session_info->unix_token->groups,
621 &session_info->unix_token->ngroups)) {
622 return NT_STATUS_NO_MEMORY;
627 * Add the "Unix Group" SID for each gid to catch mapped groups
628 * and their Unix equivalent. This is to solve the backwards
629 * compatibility problem of 'valid users = +ntadmin' where
630 * ntadmin has been paired with "Domain Admins" in the group
631 * mapping table. Otherwise smb.conf would need to be changed
632 * to 'valid user = "Domain Admins"'. --jerry
634 * For consistency we also add the "Unix User" SID,
635 * so that the complete unix token is represented within
636 * the nt token.
639 uid_to_unix_users_sid(session_info->unix_token->uid, &tmp_sid);
641 add_sid_to_array_unique(session_info->security_token, &tmp_sid,
642 &session_info->security_token->sids,
643 &session_info->security_token->num_sids);
645 for ( i=0; i<session_info->unix_token->ngroups; i++ ) {
646 gid_to_unix_groups_sid(session_info->unix_token->groups[i], &tmp_sid);
647 add_sid_to_array_unique(session_info->security_token, &tmp_sid,
648 &session_info->security_token->sids,
649 &session_info->security_token->num_sids);
652 security_token_debug(DBGC_AUTH, 10, session_info->security_token);
653 debug_unix_user_token(DBGC_AUTH, 10,
654 session_info->unix_token->uid,
655 session_info->unix_token->gid,
656 session_info->unix_token->ngroups,
657 session_info->unix_token->groups);
659 status = log_nt_token(session_info->security_token);
660 if (!NT_STATUS_IS_OK(status)) {
661 return status;
664 *session_info_out = session_info;
665 return NT_STATUS_OK;
668 /***************************************************************************
669 Make (and fill) a server_info struct from a 'struct passwd' by conversion
670 to a struct samu
671 ***************************************************************************/
673 NTSTATUS make_server_info_pw(struct auth_serversupplied_info **server_info,
674 char *unix_username,
675 struct passwd *pwd)
677 NTSTATUS status;
678 struct samu *sampass = NULL;
679 char *qualified_name = NULL;
680 TALLOC_CTX *mem_ctx = NULL;
681 struct dom_sid u_sid;
682 enum lsa_SidType type;
683 struct auth_serversupplied_info *result;
686 * The SID returned in server_info->sam_account is based
687 * on our SAM sid even though for a pure UNIX account this should
688 * not be the case as it doesn't really exist in the SAM db.
689 * This causes lookups on "[in]valid users" to fail as they
690 * will lookup this name as a "Unix User" SID to check against
691 * the user token. Fix this by adding the "Unix User"\unix_username
692 * SID to the sid array. The correct fix should probably be
693 * changing the server_info->sam_account user SID to be a
694 * S-1-22 Unix SID, but this might break old configs where
695 * plaintext passwords were used with no SAM backend.
698 mem_ctx = talloc_init("make_server_info_pw_tmp");
699 if (!mem_ctx) {
700 return NT_STATUS_NO_MEMORY;
703 qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
704 unix_users_domain_name(),
705 unix_username );
706 if (!qualified_name) {
707 TALLOC_FREE(mem_ctx);
708 return NT_STATUS_NO_MEMORY;
711 if (!lookup_name(mem_ctx, qualified_name, LOOKUP_NAME_ALL,
712 NULL, NULL,
713 &u_sid, &type)) {
714 TALLOC_FREE(mem_ctx);
715 return NT_STATUS_NO_SUCH_USER;
718 TALLOC_FREE(mem_ctx);
720 if (type != SID_NAME_USER) {
721 return NT_STATUS_NO_SUCH_USER;
724 if ( !(sampass = samu_new( NULL )) ) {
725 return NT_STATUS_NO_MEMORY;
728 status = samu_set_unix( sampass, pwd );
729 if (!NT_STATUS_IS_OK(status)) {
730 return status;
733 /* In pathological cases the above call can set the account
734 * name to the DOMAIN\username form. Reset the account name
735 * using unix_username */
736 pdb_set_username(sampass, unix_username, PDB_SET);
738 /* set the user sid to be the calculated u_sid */
739 pdb_set_user_sid(sampass, &u_sid, PDB_SET);
741 result = make_server_info(NULL);
742 if (result == NULL) {
743 TALLOC_FREE(sampass);
744 return NT_STATUS_NO_MEMORY;
747 status = samu_to_SamInfo3(result, sampass, lp_netbios_name(),
748 &result->info3, &result->extra);
749 TALLOC_FREE(sampass);
750 if (!NT_STATUS_IS_OK(status)) {
751 DEBUG(10, ("Failed to convert samu to info3: %s\n",
752 nt_errstr(status)));
753 TALLOC_FREE(result);
754 return status;
757 result->unix_name = talloc_strdup(result, unix_username);
759 if (result->unix_name == NULL) {
760 TALLOC_FREE(result);
761 return NT_STATUS_NO_MEMORY;
764 result->utok.uid = pwd->pw_uid;
765 result->utok.gid = pwd->pw_gid;
767 *server_info = result;
769 return NT_STATUS_OK;
772 static NTSTATUS get_system_info3(TALLOC_CTX *mem_ctx,
773 struct netr_SamInfo3 *info3)
775 NTSTATUS status;
776 struct dom_sid *system_sid;
778 /* Set account name */
779 init_lsa_String(&info3->base.account_name, "SYSTEM");
781 /* Set domain name */
782 init_lsa_StringLarge(&info3->base.logon_domain, "NT AUTHORITY");
785 /* The SID set here will be overwirtten anyway, but try and make it SID_NT_SYSTEM anyway */
786 /* Domain sid is NT_AUTHORITY */
788 system_sid = dom_sid_parse_talloc(mem_ctx, SID_NT_SYSTEM);
789 if (system_sid == NULL) {
790 return NT_STATUS_NO_MEMORY;
793 status = dom_sid_split_rid(mem_ctx, system_sid, &info3->base.domain_sid,
794 &info3->base.rid);
795 TALLOC_FREE(system_sid);
796 if (!NT_STATUS_IS_OK(status)) {
797 return status;
800 /* Primary gid is the same */
801 info3->base.primary_gid = info3->base.rid;
803 return NT_STATUS_OK;
806 static NTSTATUS get_guest_info3(TALLOC_CTX *mem_ctx,
807 struct netr_SamInfo3 *info3)
809 const char *guest_account = lp_guestaccount();
810 struct dom_sid domain_sid;
811 struct passwd *pwd;
812 const char *tmp;
814 pwd = Get_Pwnam_alloc(mem_ctx, guest_account);
815 if (pwd == NULL) {
816 DEBUG(0,("SamInfo3_for_guest: Unable to locate guest "
817 "account [%s]!\n", guest_account));
818 return NT_STATUS_NO_SUCH_USER;
821 /* Set account name */
822 tmp = talloc_strdup(mem_ctx, pwd->pw_name);
823 if (tmp == NULL) {
824 return NT_STATUS_NO_MEMORY;
826 init_lsa_String(&info3->base.account_name, tmp);
828 /* Set domain name */
829 tmp = talloc_strdup(mem_ctx, get_global_sam_name());
830 if (tmp == NULL) {
831 return NT_STATUS_NO_MEMORY;
833 init_lsa_StringLarge(&info3->base.logon_domain, tmp);
835 /* Domain sid */
836 sid_copy(&domain_sid, get_global_sam_sid());
838 info3->base.domain_sid = dom_sid_dup(mem_ctx, &domain_sid);
839 if (info3->base.domain_sid == NULL) {
840 return NT_STATUS_NO_MEMORY;
843 /* Guest rid */
844 info3->base.rid = DOMAIN_RID_GUEST;
846 /* Primary gid */
847 info3->base.primary_gid = DOMAIN_RID_GUESTS;
849 /* Set as guest */
850 info3->base.user_flags = NETLOGON_GUEST;
852 TALLOC_FREE(pwd);
853 return NT_STATUS_OK;
856 /***************************************************************************
857 Make (and fill) a user_info struct for a guest login.
858 This *must* succeed for smbd to start. If there is no mapping entry for
859 the guest gid, then create one.
861 The resulting structure is a 'session_info' because
862 create_local_token() has already been called on it. This is quite
863 nasty, as the auth subsystem isn't expect this, but the behavior is
864 left as-is for now.
865 ***************************************************************************/
867 static NTSTATUS make_new_session_info_guest(struct auth_session_info **session_info, struct auth_serversupplied_info **server_info)
869 static const char zeros[16] = {0};
870 const char *guest_account = lp_guestaccount();
871 const char *domain = lp_netbios_name();
872 struct netr_SamInfo3 info3;
873 TALLOC_CTX *tmp_ctx;
874 NTSTATUS status;
876 tmp_ctx = talloc_stackframe();
877 if (tmp_ctx == NULL) {
878 return NT_STATUS_NO_MEMORY;
881 ZERO_STRUCT(info3);
883 status = get_guest_info3(tmp_ctx, &info3);
884 if (!NT_STATUS_IS_OK(status)) {
885 DEBUG(0, ("get_guest_info3 failed with %s\n",
886 nt_errstr(status)));
887 goto done;
890 status = make_server_info_info3(tmp_ctx,
891 guest_account,
892 domain,
893 server_info,
894 &info3);
895 if (!NT_STATUS_IS_OK(status)) {
896 DEBUG(0, ("make_server_info_info3 failed with %s\n",
897 nt_errstr(status)));
898 goto done;
901 (*server_info)->guest = true;
903 /* This should not be done here (we should produce a server
904 * info, and later construct a session info from it), but for
905 * now this does not change the previous behavior */
906 status = create_local_token(tmp_ctx, *server_info, NULL,
907 (*server_info)->info3->base.account_name.string,
908 session_info);
909 if (!NT_STATUS_IS_OK(status)) {
910 DEBUG(0, ("create_local_token failed: %s\n",
911 nt_errstr(status)));
912 goto done;
914 talloc_steal(NULL, *session_info);
915 talloc_steal(NULL, *server_info);
917 /* annoying, but the Guest really does have a session key, and it is
918 all zeros! */
919 (*session_info)->session_key = data_blob(zeros, sizeof(zeros));
921 status = NT_STATUS_OK;
922 done:
923 TALLOC_FREE(tmp_ctx);
924 return status;
927 /***************************************************************************
928 Make (and fill) a auth_session_info struct for a system user login.
929 This *must* succeed for smbd to start.
930 ***************************************************************************/
932 static NTSTATUS make_new_session_info_system(TALLOC_CTX *mem_ctx,
933 struct auth_session_info **session_info)
935 NTSTATUS status;
936 struct auth_serversupplied_info *server_info;
937 TALLOC_CTX *tmp_ctx;
939 tmp_ctx = talloc_stackframe();
940 if (tmp_ctx == NULL) {
941 return NT_STATUS_NO_MEMORY;
944 server_info = make_server_info(tmp_ctx);
945 if (!server_info) {
946 status = NT_STATUS_NO_MEMORY;
947 DEBUG(0, ("failed making server_info\n"));
948 goto done;
951 server_info->info3 = talloc_zero(server_info, struct netr_SamInfo3);
952 if (!server_info->info3) {
953 status = NT_STATUS_NO_MEMORY;
954 DEBUG(0, ("talloc failed setting info3\n"));
955 goto done;
958 status = get_system_info3(server_info, server_info->info3);
959 if (!NT_STATUS_IS_OK(status)) {
960 DEBUG(0, ("Failed creating system info3 with %s\n",
961 nt_errstr(status)));
962 goto done;
965 server_info->utok.uid = sec_initial_uid();
966 server_info->utok.gid = sec_initial_gid();
967 server_info->unix_name = talloc_asprintf(server_info,
968 "NT AUTHORITY%cSYSTEM",
969 *lp_winbind_separator());
971 if (!server_info->unix_name) {
972 status = NT_STATUS_NO_MEMORY;
973 DEBUG(0, ("talloc_asprintf failed setting unix_name\n"));
974 goto done;
977 server_info->security_token = talloc_zero(server_info, struct security_token);
978 if (!server_info->security_token) {
979 status = NT_STATUS_NO_MEMORY;
980 DEBUG(0, ("talloc failed setting security token\n"));
981 goto done;
984 status = add_sid_to_array_unique(server_info->security_token->sids,
985 &global_sid_System,
986 &server_info->security_token->sids,
987 &server_info->security_token->num_sids);
988 if (!NT_STATUS_IS_OK(status)) {
989 goto done;
992 /* SYSTEM has all privilages */
993 server_info->security_token->privilege_mask = ~0;
995 /* Now turn the server_info into a session_info with the full token etc */
996 status = create_local_token(mem_ctx, server_info, NULL, "SYSTEM", session_info);
997 talloc_free(server_info);
999 if (!NT_STATUS_IS_OK(status)) {
1000 DEBUG(0, ("create_local_token failed: %s\n",
1001 nt_errstr(status)));
1002 goto done;
1005 talloc_steal(mem_ctx, *session_info);
1007 done:
1008 TALLOC_FREE(tmp_ctx);
1009 return status;
1012 /****************************************************************************
1013 Fake a auth_session_info just from a username (as a
1014 session_info structure, with create_local_token() already called on
1016 ****************************************************************************/
1018 NTSTATUS make_session_info_from_username(TALLOC_CTX *mem_ctx,
1019 const char *username,
1020 bool is_guest,
1021 struct auth_session_info **session_info)
1023 struct passwd *pwd;
1024 NTSTATUS status;
1025 struct auth_serversupplied_info *result;
1027 pwd = Get_Pwnam_alloc(talloc_tos(), username);
1028 if (pwd == NULL) {
1029 return NT_STATUS_NO_SUCH_USER;
1032 status = make_server_info_pw(&result, pwd->pw_name, pwd);
1034 if (!NT_STATUS_IS_OK(status)) {
1035 return status;
1038 result->nss_token = true;
1039 result->guest = is_guest;
1041 /* Now turn the server_info into a session_info with the full token etc */
1042 status = create_local_token(mem_ctx, result, NULL, pwd->pw_name, session_info);
1043 TALLOC_FREE(result);
1044 TALLOC_FREE(pwd);
1046 return status;
1049 /* This function MUST only used to create the cached server_info for
1050 * guest.
1052 * This is a lossy conversion. Variables known to be lost so far
1053 * include:
1055 * - nss_token (not needed because the only read doesn't happen
1056 * for the GUEST user, as this routine populates ->security_token
1058 * - extra (not needed because the guest account must have valid RIDs per the output of get_guest_info3())
1060 * - The 'server_info' parameter allows the missing 'info3' to be copied across.
1062 static struct auth_serversupplied_info *copy_session_info_serverinfo_guest(TALLOC_CTX *mem_ctx,
1063 const struct auth_session_info *src,
1064 struct auth_serversupplied_info *server_info)
1066 struct auth_serversupplied_info *dst;
1068 dst = make_server_info(mem_ctx);
1069 if (dst == NULL) {
1070 return NULL;
1073 /* This element must be provided to convert back to an auth_serversupplied_info */
1074 SMB_ASSERT(src->unix_info);
1076 dst->guest = true;
1077 dst->system = false;
1079 /* This element must be provided to convert back to an
1080 * auth_serversupplied_info. This needs to be from the
1081 * auth_session_info because the group values in particular
1082 * may change during create_local_token() processing */
1083 SMB_ASSERT(src->unix_token);
1084 dst->utok.uid = src->unix_token->uid;
1085 dst->utok.gid = src->unix_token->gid;
1086 dst->utok.ngroups = src->unix_token->ngroups;
1087 if (src->unix_token->ngroups != 0) {
1088 dst->utok.groups = (gid_t *)talloc_memdup(
1089 dst, src->unix_token->groups,
1090 sizeof(gid_t)*dst->utok.ngroups);
1091 } else {
1092 dst->utok.groups = NULL;
1095 /* We must have a security_token as otherwise the lossy
1096 * conversion without nss_token would cause create_local_token
1097 * to take the wrong path */
1098 SMB_ASSERT(src->security_token);
1100 dst->security_token = dup_nt_token(dst, src->security_token);
1101 if (!dst->security_token) {
1102 TALLOC_FREE(dst);
1103 return NULL;
1106 dst->session_key = data_blob_talloc( dst, src->session_key.data,
1107 src->session_key.length);
1109 /* This is OK because this functions is only used for the
1110 * GUEST account, which has all-zero keys for both values */
1111 dst->lm_session_key = data_blob_talloc(dst, src->session_key.data,
1112 src->session_key.length);
1114 dst->info3 = copy_netr_SamInfo3(dst, server_info->info3);
1115 if (!dst->info3) {
1116 TALLOC_FREE(dst);
1117 return NULL;
1120 dst->unix_name = talloc_strdup(dst, src->unix_info->unix_name);
1121 if (!dst->unix_name) {
1122 TALLOC_FREE(dst);
1123 return NULL;
1126 return dst;
1129 struct auth_session_info *copy_session_info(TALLOC_CTX *mem_ctx,
1130 const struct auth_session_info *src)
1132 struct auth_session_info *dst;
1133 DATA_BLOB blob;
1134 enum ndr_err_code ndr_err;
1136 ndr_err = ndr_push_struct_blob(
1137 &blob, talloc_tos(), src,
1138 (ndr_push_flags_fn_t)ndr_push_auth_session_info);
1139 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1140 DEBUG(0, ("copy_session_info(): ndr_push_auth_session_info failed: "
1141 "%s\n", ndr_errstr(ndr_err)));
1142 return NULL;
1145 dst = talloc(mem_ctx, struct auth_session_info);
1146 if (dst == NULL) {
1147 DEBUG(0, ("talloc failed\n"));
1148 TALLOC_FREE(blob.data);
1149 return NULL;
1152 ndr_err = ndr_pull_struct_blob(
1153 &blob, dst, dst,
1154 (ndr_pull_flags_fn_t)ndr_pull_auth_session_info);
1155 TALLOC_FREE(blob.data);
1157 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1158 DEBUG(0, ("copy_session_info(): ndr_pull_auth_session_info failed: "
1159 "%s\n", ndr_errstr(ndr_err)));
1160 TALLOC_FREE(dst);
1161 return NULL;
1164 return dst;
1168 * Set a new session key. Used in the rpc server where we have to override the
1169 * SMB level session key with SystemLibraryDTC
1172 bool session_info_set_session_key(struct auth_session_info *info,
1173 DATA_BLOB session_key)
1175 TALLOC_FREE(info->session_key.data);
1177 info->session_key = data_blob_talloc(
1178 info, session_key.data, session_key.length);
1180 return (info->session_key.data != NULL);
1183 static struct auth_session_info *guest_info = NULL;
1185 static struct auth_serversupplied_info *guest_server_info = NULL;
1187 bool init_guest_info(void)
1189 if (guest_info != NULL)
1190 return true;
1192 return NT_STATUS_IS_OK(make_new_session_info_guest(&guest_info, &guest_server_info));
1195 NTSTATUS make_server_info_guest(TALLOC_CTX *mem_ctx,
1196 struct auth_serversupplied_info **server_info)
1198 /* This is trickier than it would appear to need to be because
1199 * we are trying to avoid certain costly operations when the
1200 * structure is converted to a 'auth_session_info' again in
1201 * create_local_token() */
1202 *server_info = copy_session_info_serverinfo_guest(mem_ctx, guest_info, guest_server_info);
1203 return (*server_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1206 NTSTATUS make_session_info_guest(TALLOC_CTX *mem_ctx,
1207 struct auth_session_info **session_info)
1209 *session_info = copy_session_info(mem_ctx, guest_info);
1210 return (*session_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1213 static struct auth_session_info *system_info = NULL;
1215 NTSTATUS init_system_session_info(void)
1217 if (system_info != NULL)
1218 return NT_STATUS_OK;
1220 return make_new_session_info_system(NULL, &system_info);
1223 NTSTATUS make_session_info_system(TALLOC_CTX *mem_ctx,
1224 struct auth_session_info **session_info)
1226 if (system_info == NULL) return NT_STATUS_UNSUCCESSFUL;
1227 *session_info = copy_session_info(mem_ctx, system_info);
1228 return (*session_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1231 const struct auth_session_info *get_session_info_system(void)
1233 return system_info;
1236 /***************************************************************************
1237 Purely internal function for make_server_info_info3
1238 ***************************************************************************/
1240 static NTSTATUS check_account(TALLOC_CTX *mem_ctx, const char *domain,
1241 const char *username, char **found_username,
1242 struct passwd **pwd,
1243 bool *username_was_mapped)
1245 char *orig_dom_user = NULL;
1246 char *dom_user = NULL;
1247 char *lower_username = NULL;
1248 char *real_username = NULL;
1249 struct passwd *passwd;
1251 lower_username = talloc_strdup(mem_ctx, username);
1252 if (!lower_username) {
1253 return NT_STATUS_NO_MEMORY;
1255 if (!strlower_m( lower_username )) {
1256 return NT_STATUS_INVALID_PARAMETER;
1259 orig_dom_user = talloc_asprintf(mem_ctx,
1260 "%s%c%s",
1261 domain,
1262 *lp_winbind_separator(),
1263 lower_username);
1264 if (!orig_dom_user) {
1265 return NT_STATUS_NO_MEMORY;
1268 /* Get the passwd struct. Try to create the account if necessary. */
1270 *username_was_mapped = map_username(mem_ctx, orig_dom_user, &dom_user);
1271 if (!dom_user) {
1272 return NT_STATUS_NO_MEMORY;
1275 passwd = smb_getpwnam(mem_ctx, dom_user, &real_username, true );
1276 if (!passwd) {
1277 DEBUG(3, ("Failed to find authenticated user %s via "
1278 "getpwnam(), denying access.\n", dom_user));
1279 return NT_STATUS_NO_SUCH_USER;
1282 if (!real_username) {
1283 return NT_STATUS_NO_MEMORY;
1286 *pwd = passwd;
1288 /* This is pointless -- there is no support for differing
1289 unix and windows names. Make sure to always store the
1290 one we actually looked up and succeeded. Have I mentioned
1291 why I hate the 'winbind use default domain' parameter?
1292 --jerry */
1294 *found_username = talloc_strdup( mem_ctx, real_username );
1296 return NT_STATUS_OK;
1299 /****************************************************************************
1300 Wrapper to allow the getpwnam() call to strip the domain name and
1301 try again in case a local UNIX user is already there. Also run through
1302 the username if we fallback to the username only.
1303 ****************************************************************************/
1305 struct passwd *smb_getpwnam( TALLOC_CTX *mem_ctx, const char *domuser,
1306 char **p_save_username, bool create )
1308 struct passwd *pw = NULL;
1309 char *p = NULL;
1310 char *username = NULL;
1312 /* we only save a copy of the username it has been mangled
1313 by winbindd use default domain */
1314 *p_save_username = NULL;
1316 /* don't call map_username() here since it has to be done higher
1317 up the stack so we don't call it multiple times */
1319 username = talloc_strdup(mem_ctx, domuser);
1320 if (!username) {
1321 return NULL;
1324 p = strchr_m( username, *lp_winbind_separator() );
1326 /* code for a DOMAIN\user string */
1328 if ( p ) {
1329 pw = Get_Pwnam_alloc( mem_ctx, domuser );
1330 if ( pw ) {
1331 /* make sure we get the case of the username correct */
1332 /* work around 'winbind use default domain = yes' */
1334 if ( !strchr_m( pw->pw_name, *lp_winbind_separator() ) ) {
1335 char *domain;
1337 /* split the domain and username into 2 strings */
1338 *p = '\0';
1339 domain = username;
1341 *p_save_username = talloc_asprintf(mem_ctx,
1342 "%s%c%s",
1343 domain,
1344 *lp_winbind_separator(),
1345 pw->pw_name);
1346 if (!*p_save_username) {
1347 TALLOC_FREE(pw);
1348 return NULL;
1350 } else {
1351 *p_save_username = talloc_strdup(mem_ctx, pw->pw_name);
1354 /* whew -- done! */
1355 return pw;
1358 /* setup for lookup of just the username */
1359 /* remember that p and username are overlapping memory */
1361 p++;
1362 username = talloc_strdup(mem_ctx, p);
1363 if (!username) {
1364 return NULL;
1368 /* just lookup a plain username */
1370 pw = Get_Pwnam_alloc(mem_ctx, username);
1372 /* Create local user if requested but only if winbindd
1373 is not running. We need to protect against cases
1374 where winbindd is failing and then prematurely
1375 creating users in /etc/passwd */
1377 if ( !pw && create && !winbind_ping() ) {
1378 /* Don't add a machine account. */
1379 if (username[strlen(username)-1] == '$')
1380 return NULL;
1382 _smb_create_user(NULL, username, NULL);
1383 pw = Get_Pwnam_alloc(mem_ctx, username);
1386 /* one last check for a valid passwd struct */
1388 if (pw) {
1389 *p_save_username = talloc_strdup(mem_ctx, pw->pw_name);
1391 return pw;
1394 /***************************************************************************
1395 Make a server_info struct from the info3 returned by a domain logon
1396 ***************************************************************************/
1398 NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
1399 const char *sent_nt_username,
1400 const char *domain,
1401 struct auth_serversupplied_info **server_info,
1402 struct netr_SamInfo3 *info3)
1404 static const char zeros[16] = {0, };
1406 NTSTATUS nt_status = NT_STATUS_OK;
1407 char *found_username = NULL;
1408 const char *nt_domain;
1409 const char *nt_username;
1410 struct dom_sid user_sid;
1411 struct dom_sid group_sid;
1412 bool username_was_mapped;
1413 struct passwd *pwd;
1414 struct auth_serversupplied_info *result;
1417 Here is where we should check the list of
1418 trusted domains, and verify that the SID
1419 matches.
1422 if (!sid_compose(&user_sid, info3->base.domain_sid, info3->base.rid)) {
1423 return NT_STATUS_INVALID_PARAMETER;
1426 if (!sid_compose(&group_sid, info3->base.domain_sid,
1427 info3->base.primary_gid)) {
1428 return NT_STATUS_INVALID_PARAMETER;
1431 nt_username = talloc_strdup(mem_ctx, info3->base.account_name.string);
1432 if (!nt_username) {
1433 /* If the server didn't give us one, just use the one we sent
1434 * them */
1435 nt_username = sent_nt_username;
1438 nt_domain = talloc_strdup(mem_ctx, info3->base.logon_domain.string);
1439 if (!nt_domain) {
1440 /* If the server didn't give us one, just use the one we sent
1441 * them */
1442 nt_domain = domain;
1445 /* If getpwnam() fails try the add user script (2.2.x behavior).
1447 We use the _unmapped_ username here in an attempt to provide
1448 consistent username mapping behavior between kerberos and NTLM[SSP]
1449 authentication in domain mode security. I.E. Username mapping
1450 should be applied to the fully qualified username
1451 (e.g. DOMAIN\user) and not just the login name. Yes this means we
1452 called map_username() unnecessarily in make_user_info_map() but
1453 that is how the current code is designed. Making the change here
1454 is the least disruptive place. -- jerry */
1456 /* this call will try to create the user if necessary */
1458 nt_status = check_account(mem_ctx, nt_domain, sent_nt_username,
1459 &found_username, &pwd,
1460 &username_was_mapped);
1462 if (!NT_STATUS_IS_OK(nt_status)) {
1463 return nt_status;
1466 result = make_server_info(NULL);
1467 if (result == NULL) {
1468 DEBUG(4, ("make_server_info failed!\n"));
1469 return NT_STATUS_NO_MEMORY;
1472 result->unix_name = talloc_strdup(result, found_username);
1474 /* copy in the info3 */
1475 result->info3 = copy_netr_SamInfo3(result, info3);
1476 if (result->info3 == NULL) {
1477 TALLOC_FREE(result);
1478 return NT_STATUS_NO_MEMORY;
1481 /* Fill in the unix info we found on the way */
1483 result->utok.uid = pwd->pw_uid;
1484 result->utok.gid = pwd->pw_gid;
1486 /* ensure we are never given NULL session keys */
1488 if (memcmp(info3->base.key.key, zeros, sizeof(zeros)) == 0) {
1489 result->session_key = data_blob_null;
1490 } else {
1491 result->session_key = data_blob_talloc(
1492 result, info3->base.key.key,
1493 sizeof(info3->base.key.key));
1496 if (memcmp(info3->base.LMSessKey.key, zeros, 8) == 0) {
1497 result->lm_session_key = data_blob_null;
1498 } else {
1499 result->lm_session_key = data_blob_talloc(
1500 result, info3->base.LMSessKey.key,
1501 sizeof(info3->base.LMSessKey.key));
1504 result->nss_token |= username_was_mapped;
1506 result->guest = (info3->base.user_flags & NETLOGON_GUEST);
1508 *server_info = result;
1510 return NT_STATUS_OK;
1513 /*****************************************************************************
1514 Make a server_info struct from the wbcAuthUserInfo returned by a domain logon
1515 ******************************************************************************/
1517 NTSTATUS make_server_info_wbcAuthUserInfo(TALLOC_CTX *mem_ctx,
1518 const char *sent_nt_username,
1519 const char *domain,
1520 const struct wbcAuthUserInfo *info,
1521 struct auth_serversupplied_info **server_info)
1523 struct netr_SamInfo3 *info3;
1525 info3 = wbcAuthUserInfo_to_netr_SamInfo3(mem_ctx, info);
1526 if (!info3) {
1527 return NT_STATUS_NO_MEMORY;
1530 return make_server_info_info3(mem_ctx,
1531 sent_nt_username, domain,
1532 server_info, info3);
1536 * Verify whether or not given domain is trusted.
1538 * @param domain_name name of the domain to be verified
1539 * @return true if domain is one of the trusted ones or
1540 * false if otherwise
1543 bool is_trusted_domain(const char* dom_name)
1545 struct dom_sid trustdom_sid;
1546 bool ret;
1548 /* no trusted domains for a standalone server */
1550 if ( lp_server_role() == ROLE_STANDALONE )
1551 return false;
1553 if (dom_name == NULL || dom_name[0] == '\0') {
1554 return false;
1557 if (strequal(dom_name, get_global_sam_name())) {
1558 return false;
1561 /* if we are a DC, then check for a direct trust relationships */
1563 if ( IS_DC ) {
1564 become_root();
1565 DEBUG (5,("is_trusted_domain: Checking for domain trust with "
1566 "[%s]\n", dom_name ));
1567 ret = pdb_get_trusteddom_pw(dom_name, NULL, NULL, NULL);
1568 unbecome_root();
1569 if (ret)
1570 return true;
1572 else {
1573 wbcErr result;
1575 /* If winbind is around, ask it */
1577 result = wb_is_trusted_domain(dom_name);
1579 if (result == WBC_ERR_SUCCESS) {
1580 return true;
1583 if (result == WBC_ERR_DOMAIN_NOT_FOUND) {
1584 /* winbind could not find the domain */
1585 return false;
1588 /* The only other possible result is that winbind is not up
1589 and running. We need to update the trustdom_cache
1590 ourselves */
1592 update_trustdom_cache();
1595 /* now the trustdom cache should be available a DC could still
1596 * have a transitive trust so fall back to the cache of trusted
1597 * domains (like a domain member would use */
1599 if ( trustdom_cache_fetch(dom_name, &trustdom_sid) ) {
1600 return true;
1603 return false;
1609 on a logon error possibly map the error to success if "map to guest"
1610 is set approriately
1612 NTSTATUS do_map_to_guest_server_info(NTSTATUS status,
1613 struct auth_serversupplied_info **server_info,
1614 const char *user, const char *domain)
1616 user = user ? user : "";
1617 domain = domain ? domain : "";
1619 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
1620 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
1621 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
1622 DEBUG(3,("No such user %s [%s] - using guest account\n",
1623 user, domain));
1624 return make_server_info_guest(NULL, server_info);
1626 } else if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1627 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
1628 DEBUG(3,("Registered username %s for guest access\n",
1629 user));
1630 return make_server_info_guest(NULL, server_info);
1634 return status;
1638 Extract session key from a session info and return it in a blob
1639 if intent is KEY_USE_16BYTES, truncate it to 16 bytes
1641 See sections 3.2.4.15 and 3.3.4.2 of MS-SMB
1642 Also see https://lists.samba.org/archive/cifs-protocol/2012-January/002265.html for details
1644 Note that returned session_key is referencing the original key, it is supposed to be
1645 short-lived. If original session_info->session_key is gone, the reference will be broken.
1647 NTSTATUS session_extract_session_key(const struct auth_session_info *session_info, DATA_BLOB *session_key, enum session_key_use_intent intent)
1650 if (session_key == NULL || session_info == NULL) {
1651 return NT_STATUS_INVALID_PARAMETER;
1654 if (session_info->session_key.length == 0) {
1655 return NT_STATUS_NO_USER_SESSION_KEY;
1658 *session_key = session_info->session_key;
1659 if (intent == KEY_USE_16BYTES) {
1660 session_key->length = MIN(session_info->session_key.length, 16);
1662 return NT_STATUS_OK;