Fix valgrind "uninitialized read" error on "info" when returning !NT_STATUS_OK.
[Samba.git] / source3 / auth / auth_util.c
blob16fa421f8b00cd662cbb844237ad1480f0f5331b
1 /*
2 Unix SMB/CIFS implementation.
3 Authentication utility functions
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 2000-2001
7 Copyright (C) Rafal Szczesniak 2002
8 Copyright (C) Volker Lendecke 2006
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 "smbd/globals.h"
26 #include "../libcli/auth/libcli_auth.h"
27 #include "../lib/crypto/arcfour.h"
29 #undef DBGC_CLASS
30 #define DBGC_CLASS DBGC_AUTH
32 /****************************************************************************
33 Create a UNIX user on demand.
34 ****************************************************************************/
36 static int _smb_create_user(const char *domain, const char *unix_username, const char *homedir)
38 TALLOC_CTX *ctx = talloc_tos();
39 char *add_script;
40 int ret;
42 add_script = talloc_strdup(ctx, lp_adduser_script());
43 if (!add_script || !*add_script) {
44 return -1;
46 add_script = talloc_all_string_sub(ctx,
47 add_script,
48 "%u",
49 unix_username);
50 if (!add_script) {
51 return -1;
53 if (domain) {
54 add_script = talloc_all_string_sub(ctx,
55 add_script,
56 "%D",
57 domain);
58 if (!add_script) {
59 return -1;
62 if (homedir) {
63 add_script = talloc_all_string_sub(ctx,
64 add_script,
65 "%H",
66 homedir);
67 if (!add_script) {
68 return -1;
71 ret = smbrun(add_script,NULL);
72 flush_pwnam_cache();
73 DEBUG(ret ? 0 : 3,
74 ("smb_create_user: Running the command `%s' gave %d\n",
75 add_script,ret));
76 return ret;
79 /****************************************************************************
80 Create an auth_usersupplied_data structure after appropriate mapping.
81 ****************************************************************************/
83 NTSTATUS make_user_info_map(struct auth_usersupplied_info **user_info,
84 const char *smb_name,
85 const char *client_domain,
86 const char *workstation_name,
87 DATA_BLOB *lm_pwd,
88 DATA_BLOB *nt_pwd,
89 DATA_BLOB *lm_interactive_pwd,
90 DATA_BLOB *nt_interactive_pwd,
91 DATA_BLOB *plaintext,
92 bool encrypted)
94 const char *domain;
95 NTSTATUS result;
96 bool was_mapped;
97 fstring internal_username;
98 fstrcpy(internal_username, smb_name);
99 was_mapped = map_username(internal_username);
101 DEBUG(5, ("Mapping user [%s]\\[%s] from workstation [%s]\n",
102 client_domain, smb_name, workstation_name));
104 domain = client_domain;
106 /* If you connect to a Windows domain member using a bogus domain name,
107 * the Windows box will map the BOGUS\user to SAMNAME\user. Thus, if
108 * the Windows box is a DC the name will become DOMAIN\user and be
109 * authenticated against AD, if the Windows box is a member server but
110 * not a DC the name will become WORKSTATION\user. A standalone
111 * non-domain member box will also map to WORKSTATION\user.
112 * This also deals with the client passing in a "" domain */
114 if (!is_trusted_domain(domain) &&
115 !strequal(domain, my_sam_name()))
117 if (lp_map_untrusted_to_domain())
118 domain = my_sam_name();
119 else
120 domain = get_global_sam_name();
121 DEBUG(5, ("Mapped domain from [%s] to [%s] for user [%s] from "
122 "workstation [%s]\n",
123 client_domain, domain, smb_name, workstation_name));
126 /* We know that the given domain is trusted (and we are allowing them),
127 * it is our global SAM name, or for legacy behavior it is our
128 * primary domain name */
130 result = make_user_info(user_info, smb_name, internal_username,
131 client_domain, domain, workstation_name,
132 lm_pwd, nt_pwd,
133 lm_interactive_pwd, nt_interactive_pwd,
134 plaintext, encrypted);
135 if (NT_STATUS_IS_OK(result)) {
136 (*user_info)->was_mapped = was_mapped;
138 return result;
141 /****************************************************************************
142 Create an auth_usersupplied_data, making the DATA_BLOBs here.
143 Decrypt and encrypt the passwords.
144 ****************************************************************************/
146 bool make_user_info_netlogon_network(struct auth_usersupplied_info **user_info,
147 const char *smb_name,
148 const char *client_domain,
149 const char *workstation_name,
150 uint32 logon_parameters,
151 const uchar *lm_network_pwd,
152 int lm_pwd_len,
153 const uchar *nt_network_pwd,
154 int nt_pwd_len)
156 bool ret;
157 NTSTATUS status;
158 DATA_BLOB lm_blob = data_blob(lm_network_pwd, lm_pwd_len);
159 DATA_BLOB nt_blob = data_blob(nt_network_pwd, nt_pwd_len);
161 status = make_user_info_map(user_info,
162 smb_name, client_domain,
163 workstation_name,
164 lm_pwd_len ? &lm_blob : NULL,
165 nt_pwd_len ? &nt_blob : NULL,
166 NULL, NULL, NULL,
167 True);
169 if (NT_STATUS_IS_OK(status)) {
170 (*user_info)->logon_parameters = logon_parameters;
172 ret = NT_STATUS_IS_OK(status) ? True : False;
174 data_blob_free(&lm_blob);
175 data_blob_free(&nt_blob);
176 return ret;
179 /****************************************************************************
180 Create an auth_usersupplied_data, making the DATA_BLOBs here.
181 Decrypt and encrypt the passwords.
182 ****************************************************************************/
184 bool make_user_info_netlogon_interactive(struct auth_usersupplied_info **user_info,
185 const char *smb_name,
186 const char *client_domain,
187 const char *workstation_name,
188 uint32 logon_parameters,
189 const uchar chal[8],
190 const uchar lm_interactive_pwd[16],
191 const uchar nt_interactive_pwd[16],
192 const uchar *dc_sess_key)
194 unsigned char lm_pwd[16];
195 unsigned char nt_pwd[16];
196 unsigned char local_lm_response[24];
197 unsigned char local_nt_response[24];
198 unsigned char key[16];
200 memcpy(key, dc_sess_key, 16);
202 if (lm_interactive_pwd)
203 memcpy(lm_pwd, lm_interactive_pwd, sizeof(lm_pwd));
205 if (nt_interactive_pwd)
206 memcpy(nt_pwd, nt_interactive_pwd, sizeof(nt_pwd));
208 #ifdef DEBUG_PASSWORD
209 DEBUG(100,("key:"));
210 dump_data(100, key, sizeof(key));
212 DEBUG(100,("lm owf password:"));
213 dump_data(100, lm_pwd, sizeof(lm_pwd));
215 DEBUG(100,("nt owf password:"));
216 dump_data(100, nt_pwd, sizeof(nt_pwd));
217 #endif
219 if (lm_interactive_pwd)
220 arcfour_crypt(lm_pwd, key, sizeof(lm_pwd));
222 if (nt_interactive_pwd)
223 arcfour_crypt(nt_pwd, key, sizeof(nt_pwd));
225 #ifdef DEBUG_PASSWORD
226 DEBUG(100,("decrypt of lm owf password:"));
227 dump_data(100, lm_pwd, sizeof(lm_pwd));
229 DEBUG(100,("decrypt of nt owf password:"));
230 dump_data(100, nt_pwd, sizeof(nt_pwd));
231 #endif
233 if (lm_interactive_pwd)
234 SMBOWFencrypt(lm_pwd, chal,
235 local_lm_response);
237 if (nt_interactive_pwd)
238 SMBOWFencrypt(nt_pwd, chal,
239 local_nt_response);
241 /* Password info paranoia */
242 ZERO_STRUCT(key);
245 bool ret;
246 NTSTATUS nt_status;
247 DATA_BLOB local_lm_blob;
248 DATA_BLOB local_nt_blob;
250 DATA_BLOB lm_interactive_blob;
251 DATA_BLOB nt_interactive_blob;
253 if (lm_interactive_pwd) {
254 local_lm_blob = data_blob(local_lm_response,
255 sizeof(local_lm_response));
256 lm_interactive_blob = data_blob(lm_pwd,
257 sizeof(lm_pwd));
258 ZERO_STRUCT(lm_pwd);
261 if (nt_interactive_pwd) {
262 local_nt_blob = data_blob(local_nt_response,
263 sizeof(local_nt_response));
264 nt_interactive_blob = data_blob(nt_pwd,
265 sizeof(nt_pwd));
266 ZERO_STRUCT(nt_pwd);
269 nt_status = make_user_info_map(
270 user_info,
271 smb_name, client_domain, workstation_name,
272 lm_interactive_pwd ? &local_lm_blob : NULL,
273 nt_interactive_pwd ? &local_nt_blob : NULL,
274 lm_interactive_pwd ? &lm_interactive_blob : NULL,
275 nt_interactive_pwd ? &nt_interactive_blob : NULL,
276 NULL, True);
278 if (NT_STATUS_IS_OK(nt_status)) {
279 (*user_info)->logon_parameters = logon_parameters;
282 ret = NT_STATUS_IS_OK(nt_status) ? True : False;
283 data_blob_free(&local_lm_blob);
284 data_blob_free(&local_nt_blob);
285 data_blob_free(&lm_interactive_blob);
286 data_blob_free(&nt_interactive_blob);
287 return ret;
292 /****************************************************************************
293 Create an auth_usersupplied_data structure
294 ****************************************************************************/
296 bool make_user_info_for_reply(struct auth_usersupplied_info **user_info,
297 const char *smb_name,
298 const char *client_domain,
299 const uint8 chal[8],
300 DATA_BLOB plaintext_password)
303 DATA_BLOB local_lm_blob;
304 DATA_BLOB local_nt_blob;
305 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
308 * Not encrypted - do so.
311 DEBUG(5,("make_user_info_for_reply: User passwords not in encrypted "
312 "format.\n"));
314 if (plaintext_password.data && plaintext_password.length) {
315 unsigned char local_lm_response[24];
317 #ifdef DEBUG_PASSWORD
318 DEBUG(10,("Unencrypted password (len %d):\n",
319 (int)plaintext_password.length));
320 dump_data(100, plaintext_password.data,
321 plaintext_password.length);
322 #endif
324 SMBencrypt( (const char *)plaintext_password.data,
325 (const uchar*)chal, local_lm_response);
326 local_lm_blob = data_blob(local_lm_response, 24);
328 /* We can't do an NT hash here, as the password needs to be
329 case insensitive */
330 local_nt_blob = data_blob_null;
331 } else {
332 local_lm_blob = data_blob_null;
333 local_nt_blob = data_blob_null;
336 ret = make_user_info_map(
337 user_info, smb_name, client_domain,
338 get_remote_machine_name(),
339 local_lm_blob.data ? &local_lm_blob : NULL,
340 local_nt_blob.data ? &local_nt_blob : NULL,
341 NULL, NULL,
342 plaintext_password.data && plaintext_password.length ? &plaintext_password : NULL,
343 False);
345 data_blob_free(&local_lm_blob);
346 return NT_STATUS_IS_OK(ret) ? True : False;
349 /****************************************************************************
350 Create an auth_usersupplied_data structure
351 ****************************************************************************/
353 NTSTATUS make_user_info_for_reply_enc(struct auth_usersupplied_info **user_info,
354 const char *smb_name,
355 const char *client_domain,
356 DATA_BLOB lm_resp, DATA_BLOB nt_resp)
358 return make_user_info_map(user_info, smb_name,
359 client_domain,
360 get_remote_machine_name(),
361 lm_resp.data && (lm_resp.length > 0) ? &lm_resp : NULL,
362 nt_resp.data && (nt_resp.length > 0) ? &nt_resp : NULL,
363 NULL, NULL, NULL,
364 True);
367 /****************************************************************************
368 Create a guest user_info blob, for anonymous authenticaion.
369 ****************************************************************************/
371 bool make_user_info_guest(struct auth_usersupplied_info **user_info)
373 NTSTATUS nt_status;
375 nt_status = make_user_info(user_info,
376 "","",
377 "","",
378 "",
379 NULL, NULL,
380 NULL, NULL,
381 NULL,
382 True);
384 return NT_STATUS_IS_OK(nt_status) ? True : False;
387 static NTSTATUS log_nt_token(NT_USER_TOKEN *token)
389 TALLOC_CTX *frame = talloc_stackframe();
390 char *command;
391 char *group_sidstr;
392 size_t i;
394 if ((lp_log_nt_token_command() == NULL) ||
395 (strlen(lp_log_nt_token_command()) == 0)) {
396 TALLOC_FREE(frame);
397 return NT_STATUS_OK;
400 group_sidstr = talloc_strdup(frame, "");
401 for (i=1; i<token->num_sids; i++) {
402 group_sidstr = talloc_asprintf(
403 frame, "%s %s", group_sidstr,
404 sid_string_talloc(frame, &token->user_sids[i]));
407 command = talloc_string_sub(
408 frame, lp_log_nt_token_command(),
409 "%s", sid_string_talloc(frame, &token->user_sids[0]));
410 command = talloc_string_sub(frame, command, "%t", group_sidstr);
412 if (command == NULL) {
413 TALLOC_FREE(frame);
414 return NT_STATUS_NO_MEMORY;
417 DEBUG(8, ("running command: [%s]\n", command));
418 if (smbrun(command, NULL) != 0) {
419 DEBUG(0, ("Could not log NT token\n"));
420 TALLOC_FREE(frame);
421 return NT_STATUS_ACCESS_DENIED;
424 TALLOC_FREE(frame);
425 return NT_STATUS_OK;
429 * Create the token to use from server_info->info3 and
430 * server_info->sids (the info3/sam groups). Find the unix gids.
433 NTSTATUS create_local_token(struct auth_serversupplied_info *server_info)
435 NTSTATUS status;
436 size_t i;
437 struct dom_sid tmp_sid;
440 * If winbind is not around, we can not make much use of the SIDs the
441 * domain controller provided us with. Likewise if the user name was
442 * mapped to some local unix user.
445 if (((lp_server_role() == ROLE_DOMAIN_MEMBER) && !winbind_ping()) ||
446 (server_info->nss_token)) {
447 status = create_token_from_username(server_info,
448 server_info->unix_name,
449 server_info->guest,
450 &server_info->utok.uid,
451 &server_info->utok.gid,
452 &server_info->unix_name,
453 &server_info->ptok);
455 } else {
456 status = create_local_nt_token_from_info3(server_info,
457 server_info->guest,
458 server_info->info3,
459 &server_info->extra,
460 &server_info->ptok);
463 if (!NT_STATUS_IS_OK(status)) {
464 return status;
467 /* Convert the SIDs to gids. */
469 server_info->utok.ngroups = 0;
470 server_info->utok.groups = NULL;
472 /* Start at index 1, where the groups start. */
474 for (i=1; i<server_info->ptok->num_sids; i++) {
475 gid_t gid;
476 struct dom_sid *sid = &server_info->ptok->user_sids[i];
478 if (!sid_to_gid(sid, &gid)) {
479 DEBUG(10, ("Could not convert SID %s to gid, "
480 "ignoring it\n", sid_string_dbg(sid)));
481 continue;
483 add_gid_to_array_unique(server_info, gid,
484 &server_info->utok.groups,
485 &server_info->utok.ngroups);
489 * Add the "Unix Group" SID for each gid to catch mapped groups
490 * and their Unix equivalent. This is to solve the backwards
491 * compatibility problem of 'valid users = +ntadmin' where
492 * ntadmin has been paired with "Domain Admins" in the group
493 * mapping table. Otherwise smb.conf would need to be changed
494 * to 'valid user = "Domain Admins"'. --jerry
496 * For consistency we also add the "Unix User" SID,
497 * so that the complete unix token is represented within
498 * the nt token.
501 uid_to_unix_users_sid(server_info->utok.uid, &tmp_sid);
503 add_sid_to_array_unique(server_info->ptok, &tmp_sid,
504 &server_info->ptok->user_sids,
505 &server_info->ptok->num_sids);
507 for ( i=0; i<server_info->utok.ngroups; i++ ) {
508 gid_to_unix_groups_sid(server_info->utok.groups[i], &tmp_sid);
509 add_sid_to_array_unique(server_info->ptok, &tmp_sid,
510 &server_info->ptok->user_sids,
511 &server_info->ptok->num_sids);
514 debug_nt_user_token(DBGC_AUTH, 10, server_info->ptok);
515 debug_unix_user_token(DBGC_AUTH, 10,
516 server_info->utok.uid,
517 server_info->utok.gid,
518 server_info->utok.ngroups,
519 server_info->utok.groups);
521 status = log_nt_token(server_info->ptok);
522 return status;
525 /***************************************************************************
526 Make (and fill) a server_info struct from a 'struct passwd' by conversion
527 to a struct samu
528 ***************************************************************************/
530 NTSTATUS make_server_info_pw(struct auth_serversupplied_info **server_info,
531 char *unix_username,
532 struct passwd *pwd)
534 NTSTATUS status;
535 struct samu *sampass = NULL;
536 char *qualified_name = NULL;
537 TALLOC_CTX *mem_ctx = NULL;
538 struct dom_sid u_sid;
539 enum lsa_SidType type;
540 struct auth_serversupplied_info *result;
543 * The SID returned in server_info->sam_account is based
544 * on our SAM sid even though for a pure UNIX account this should
545 * not be the case as it doesn't really exist in the SAM db.
546 * This causes lookups on "[in]valid users" to fail as they
547 * will lookup this name as a "Unix User" SID to check against
548 * the user token. Fix this by adding the "Unix User"\unix_username
549 * SID to the sid array. The correct fix should probably be
550 * changing the server_info->sam_account user SID to be a
551 * S-1-22 Unix SID, but this might break old configs where
552 * plaintext passwords were used with no SAM backend.
555 mem_ctx = talloc_init("make_server_info_pw_tmp");
556 if (!mem_ctx) {
557 return NT_STATUS_NO_MEMORY;
560 qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
561 unix_users_domain_name(),
562 unix_username );
563 if (!qualified_name) {
564 TALLOC_FREE(mem_ctx);
565 return NT_STATUS_NO_MEMORY;
568 if (!lookup_name(mem_ctx, qualified_name, LOOKUP_NAME_ALL,
569 NULL, NULL,
570 &u_sid, &type)) {
571 TALLOC_FREE(mem_ctx);
572 return NT_STATUS_NO_SUCH_USER;
575 TALLOC_FREE(mem_ctx);
577 if (type != SID_NAME_USER) {
578 return NT_STATUS_NO_SUCH_USER;
581 if ( !(sampass = samu_new( NULL )) ) {
582 return NT_STATUS_NO_MEMORY;
585 status = samu_set_unix( sampass, pwd );
586 if (!NT_STATUS_IS_OK(status)) {
587 return status;
590 /* In pathological cases the above call can set the account
591 * name to the DOMAIN\username form. Reset the account name
592 * using unix_username */
593 pdb_set_username(sampass, unix_username, PDB_SET);
595 /* set the user sid to be the calculated u_sid */
596 pdb_set_user_sid(sampass, &u_sid, PDB_SET);
598 result = make_server_info(NULL);
599 if (result == NULL) {
600 TALLOC_FREE(sampass);
601 return NT_STATUS_NO_MEMORY;
604 status = samu_to_SamInfo3(result, sampass, global_myname(),
605 &result->info3, &result->extra);
606 TALLOC_FREE(sampass);
607 if (!NT_STATUS_IS_OK(status)) {
608 DEBUG(10, ("Failed to convert samu to info3: %s\n",
609 nt_errstr(status)));
610 TALLOC_FREE(result);
611 return status;
614 result->unix_name = talloc_strdup(result, unix_username);
615 result->sanitized_username = sanitize_username(result, unix_username);
617 if ((result->unix_name == NULL)
618 || (result->sanitized_username == NULL)) {
619 TALLOC_FREE(result);
620 return NT_STATUS_NO_MEMORY;
623 result->utok.uid = pwd->pw_uid;
624 result->utok.gid = pwd->pw_gid;
626 *server_info = result;
628 return NT_STATUS_OK;
631 /***************************************************************************
632 Make (and fill) a user_info struct for a guest login.
633 This *must* succeed for smbd to start. If there is no mapping entry for
634 the guest gid, then create one.
635 ***************************************************************************/
637 static NTSTATUS make_new_server_info_guest(struct auth_serversupplied_info **server_info)
639 NTSTATUS status;
640 struct samu *sampass = NULL;
641 struct dom_sid guest_sid;
642 bool ret;
643 static const char zeros[16] = {0, };
644 fstring tmp;
646 if ( !(sampass = samu_new( NULL )) ) {
647 return NT_STATUS_NO_MEMORY;
650 sid_compose(&guest_sid, get_global_sam_sid(), DOMAIN_RID_GUEST);
652 become_root();
653 ret = pdb_getsampwsid(sampass, &guest_sid);
654 unbecome_root();
656 if (!ret) {
657 TALLOC_FREE(sampass);
658 return NT_STATUS_NO_SUCH_USER;
661 status = make_server_info_sam(server_info, sampass);
662 if (!NT_STATUS_IS_OK(status)) {
663 TALLOC_FREE(sampass);
664 return status;
667 TALLOC_FREE(sampass);
669 (*server_info)->guest = True;
671 status = create_local_token(*server_info);
672 if (!NT_STATUS_IS_OK(status)) {
673 DEBUG(10, ("create_local_token failed: %s\n",
674 nt_errstr(status)));
675 return status;
678 /* annoying, but the Guest really does have a session key, and it is
679 all zeros! */
680 (*server_info)->user_session_key = data_blob(zeros, sizeof(zeros));
681 (*server_info)->lm_session_key = data_blob(zeros, sizeof(zeros));
683 alpha_strcpy(tmp, (*server_info)->info3->base.account_name.string,
684 ". _-$", sizeof(tmp));
685 (*server_info)->sanitized_username = talloc_strdup(*server_info, tmp);
687 return NT_STATUS_OK;
690 /***************************************************************************
691 Make (and fill) a user_info struct for a system user login.
692 This *must* succeed for smbd to start.
693 ***************************************************************************/
695 static NTSTATUS make_new_server_info_system(TALLOC_CTX *mem_ctx,
696 struct auth_serversupplied_info **server_info)
698 struct passwd *pwd;
699 NTSTATUS status;
701 pwd = getpwuid_alloc(mem_ctx, sec_initial_uid());
702 if (pwd == NULL) {
703 return NT_STATUS_NO_MEMORY;
706 status = make_serverinfo_from_username(mem_ctx,
707 pwd->pw_name,
708 false,
709 server_info);
710 if (!NT_STATUS_IS_OK(status)) {
711 return status;
714 (*server_info)->system = true;
716 return NT_STATUS_OK;
719 /****************************************************************************
720 Fake a auth_serversupplied_info just from a username
721 ****************************************************************************/
723 NTSTATUS make_serverinfo_from_username(TALLOC_CTX *mem_ctx,
724 const char *username,
725 bool is_guest,
726 struct auth_serversupplied_info **presult)
728 struct auth_serversupplied_info *result;
729 struct passwd *pwd;
730 NTSTATUS status;
732 pwd = getpwnam_alloc(talloc_tos(), username);
733 if (pwd == NULL) {
734 return NT_STATUS_NO_SUCH_USER;
737 status = make_server_info_pw(&result, pwd->pw_name, pwd);
739 TALLOC_FREE(pwd);
741 if (!NT_STATUS_IS_OK(status)) {
742 return status;
745 result->nss_token = true;
746 result->guest = is_guest;
748 status = create_local_token(result);
750 if (!NT_STATUS_IS_OK(status)) {
751 TALLOC_FREE(result);
752 return status;
755 *presult = result;
756 return NT_STATUS_OK;
760 struct auth_serversupplied_info *copy_serverinfo(TALLOC_CTX *mem_ctx,
761 const struct auth_serversupplied_info *src)
763 struct auth_serversupplied_info *dst;
765 dst = make_server_info(mem_ctx);
766 if (dst == NULL) {
767 return NULL;
770 dst->guest = src->guest;
771 dst->system = src->system;
772 dst->utok.uid = src->utok.uid;
773 dst->utok.gid = src->utok.gid;
774 dst->utok.ngroups = src->utok.ngroups;
775 if (src->utok.ngroups != 0) {
776 dst->utok.groups = (gid_t *)TALLOC_MEMDUP(
777 dst, src->utok.groups,
778 sizeof(gid_t)*dst->utok.ngroups);
779 } else {
780 dst->utok.groups = NULL;
783 if (src->ptok) {
784 dst->ptok = dup_nt_token(dst, src->ptok);
785 if (!dst->ptok) {
786 TALLOC_FREE(dst);
787 return NULL;
791 dst->user_session_key = data_blob_talloc( dst, src->user_session_key.data,
792 src->user_session_key.length);
794 dst->lm_session_key = data_blob_talloc(dst, src->lm_session_key.data,
795 src->lm_session_key.length);
797 dst->info3 = copy_netr_SamInfo3(dst, src->info3);
798 if (!dst->info3) {
799 TALLOC_FREE(dst);
800 return NULL;
802 dst->extra = src->extra;
804 dst->pam_handle = NULL;
805 dst->unix_name = talloc_strdup(dst, src->unix_name);
806 if (!dst->unix_name) {
807 TALLOC_FREE(dst);
808 return NULL;
811 dst->sanitized_username = talloc_strdup(dst, src->sanitized_username);
812 if (!dst->sanitized_username) {
813 TALLOC_FREE(dst);
814 return NULL;
817 return dst;
821 * Set a new session key. Used in the rpc server where we have to override the
822 * SMB level session key with SystemLibraryDTC
825 bool server_info_set_session_key(struct auth_serversupplied_info *info,
826 DATA_BLOB session_key)
828 TALLOC_FREE(info->user_session_key.data);
830 info->user_session_key = data_blob_talloc(
831 info, session_key.data, session_key.length);
833 return (info->user_session_key.data != NULL);
836 static struct auth_serversupplied_info *guest_info = NULL;
838 bool init_guest_info(void)
840 if (guest_info != NULL)
841 return True;
843 return NT_STATUS_IS_OK(make_new_server_info_guest(&guest_info));
846 NTSTATUS make_server_info_guest(TALLOC_CTX *mem_ctx,
847 struct auth_serversupplied_info **server_info)
849 *server_info = copy_serverinfo(mem_ctx, guest_info);
850 return (*server_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
853 static struct auth_serversupplied_info *system_info = NULL;
855 bool init_system_info(void)
857 if (system_info != NULL)
858 return True;
860 return NT_STATUS_IS_OK(make_new_server_info_system(talloc_autofree_context(), &system_info));
863 NTSTATUS make_server_info_system(TALLOC_CTX *mem_ctx,
864 struct auth_serversupplied_info **server_info)
866 if (system_info == NULL) return NT_STATUS_UNSUCCESSFUL;
867 *server_info = copy_serverinfo(mem_ctx, system_info);
868 return (*server_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
871 bool copy_current_user(struct current_user *dst, struct current_user *src)
873 gid_t *groups;
874 NT_USER_TOKEN *nt_token;
876 groups = (gid_t *)memdup(src->ut.groups,
877 sizeof(gid_t) * src->ut.ngroups);
878 if ((src->ut.ngroups != 0) && (groups == NULL)) {
879 return False;
882 nt_token = dup_nt_token(NULL, src->nt_user_token);
883 if (nt_token == NULL) {
884 SAFE_FREE(groups);
885 return False;
888 dst->conn = src->conn;
889 dst->vuid = src->vuid;
890 dst->ut.uid = src->ut.uid;
891 dst->ut.gid = src->ut.gid;
892 dst->ut.ngroups = src->ut.ngroups;
893 dst->ut.groups = groups;
894 dst->nt_user_token = nt_token;
895 return True;
898 /***************************************************************************
899 Purely internal function for make_server_info_info3
900 ***************************************************************************/
902 static NTSTATUS check_account(TALLOC_CTX *mem_ctx, const char *domain,
903 const char *username, char **found_username,
904 struct passwd **pwd,
905 bool *username_was_mapped)
907 fstring dom_user, lower_username;
908 fstring real_username;
909 struct passwd *passwd;
911 fstrcpy( lower_username, username );
912 strlower_m( lower_username );
914 fstr_sprintf(dom_user, "%s%c%s", domain, *lp_winbind_separator(),
915 lower_username);
917 /* Get the passwd struct. Try to create the account if necessary. */
919 *username_was_mapped = map_username(dom_user);
921 passwd = smb_getpwnam( NULL, dom_user, real_username, True );
922 if (!passwd) {
923 DEBUG(3, ("Failed to find authenticated user %s via "
924 "getpwnam(), denying access.\n", dom_user));
925 return NT_STATUS_NO_SUCH_USER;
928 *pwd = passwd;
930 /* This is pointless -- there is no suport for differing
931 unix and windows names. Make sure to always store the
932 one we actually looked up and succeeded. Have I mentioned
933 why I hate the 'winbind use default domain' parameter?
934 --jerry */
936 *found_username = talloc_strdup( mem_ctx, real_username );
938 return NT_STATUS_OK;
941 /****************************************************************************
942 Wrapper to allow the getpwnam() call to strip the domain name and
943 try again in case a local UNIX user is already there. Also run through
944 the username if we fallback to the username only.
945 ****************************************************************************/
947 struct passwd *smb_getpwnam( TALLOC_CTX *mem_ctx, char *domuser,
948 fstring save_username, bool create )
950 struct passwd *pw = NULL;
951 char *p;
952 fstring username;
954 /* we only save a copy of the username it has been mangled
955 by winbindd use default domain */
957 save_username[0] = '\0';
959 /* don't call map_username() here since it has to be done higher
960 up the stack so we don't call it multiple times */
962 fstrcpy( username, domuser );
964 p = strchr_m( username, *lp_winbind_separator() );
966 /* code for a DOMAIN\user string */
968 if ( p ) {
969 fstring strip_username;
971 pw = Get_Pwnam_alloc( mem_ctx, domuser );
972 if ( pw ) {
973 /* make sure we get the case of the username correct */
974 /* work around 'winbind use default domain = yes' */
976 if ( !strchr_m( pw->pw_name, *lp_winbind_separator() ) ) {
977 char *domain;
979 /* split the domain and username into 2 strings */
980 *p = '\0';
981 domain = username;
983 fstr_sprintf(save_username, "%s%c%s", domain, *lp_winbind_separator(), pw->pw_name);
985 else
986 fstrcpy( save_username, pw->pw_name );
988 /* whew -- done! */
989 return pw;
992 /* setup for lookup of just the username */
993 /* remember that p and username are overlapping memory */
995 p++;
996 fstrcpy( strip_username, p );
997 fstrcpy( username, strip_username );
1000 /* just lookup a plain username */
1002 pw = Get_Pwnam_alloc(mem_ctx, username);
1004 /* Create local user if requested but only if winbindd
1005 is not running. We need to protect against cases
1006 where winbindd is failing and then prematurely
1007 creating users in /etc/passwd */
1009 if ( !pw && create && !winbind_ping() ) {
1010 /* Don't add a machine account. */
1011 if (username[strlen(username)-1] == '$')
1012 return NULL;
1014 _smb_create_user(NULL, username, NULL);
1015 pw = Get_Pwnam_alloc(mem_ctx, username);
1018 /* one last check for a valid passwd struct */
1020 if ( pw )
1021 fstrcpy( save_username, pw->pw_name );
1023 return pw;
1026 /***************************************************************************
1027 Make a server_info struct from the info3 returned by a domain logon
1028 ***************************************************************************/
1030 NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
1031 const char *sent_nt_username,
1032 const char *domain,
1033 struct auth_serversupplied_info **server_info,
1034 struct netr_SamInfo3 *info3)
1036 static const char zeros[16] = {0, };
1038 NTSTATUS nt_status = NT_STATUS_OK;
1039 char *found_username = NULL;
1040 const char *nt_domain;
1041 const char *nt_username;
1042 bool username_was_mapped;
1043 struct passwd *pwd;
1044 struct auth_serversupplied_info *result;
1045 struct dom_sid *group_sid;
1046 struct netr_SamInfo3 *i3;
1049 Here is where we should check the list of
1050 trusted domains, and verify that the SID
1051 matches.
1054 nt_username = talloc_strdup(mem_ctx, info3->base.account_name.string);
1055 if (!nt_username) {
1056 /* If the server didn't give us one, just use the one we sent
1057 * them */
1058 nt_username = sent_nt_username;
1061 nt_domain = talloc_strdup(mem_ctx, info3->base.domain.string);
1062 if (!nt_domain) {
1063 /* If the server didn't give us one, just use the one we sent
1064 * them */
1065 nt_domain = domain;
1068 /* If getpwnam() fails try the add user script (2.2.x behavior).
1070 We use the _unmapped_ username here in an attempt to provide
1071 consistent username mapping behavior between kerberos and NTLM[SSP]
1072 authentication in domain mode security. I.E. Username mapping
1073 should be applied to the fully qualified username
1074 (e.g. DOMAIN\user) and not just the login name. Yes this means we
1075 called map_username() unnecessarily in make_user_info_map() but
1076 that is how the current code is designed. Making the change here
1077 is the least disruptive place. -- jerry */
1079 /* this call will try to create the user if necessary */
1081 nt_status = check_account(mem_ctx, nt_domain, sent_nt_username,
1082 &found_username, &pwd,
1083 &username_was_mapped);
1085 if (!NT_STATUS_IS_OK(nt_status)) {
1086 return nt_status;
1089 result = make_server_info(NULL);
1090 if (result == NULL) {
1091 DEBUG(4, ("make_server_info failed!\n"));
1092 return NT_STATUS_NO_MEMORY;
1095 result->unix_name = talloc_strdup(result, found_username);
1097 result->sanitized_username = sanitize_username(result,
1098 result->unix_name);
1099 if (result->sanitized_username == NULL) {
1100 TALLOC_FREE(result);
1101 return NT_STATUS_NO_MEMORY;
1104 /* copy in the info3 */
1105 result->info3 = i3 = copy_netr_SamInfo3(result, info3);
1106 if (result->info3 == NULL) {
1107 TALLOC_FREE(result);
1108 return NT_STATUS_NO_MEMORY;
1111 /* Fill in the unix info we found on the way */
1112 result->utok.uid = pwd->pw_uid;
1113 result->utok.gid = pwd->pw_gid;
1115 /* We can't just trust that the primary group sid sent us is something
1116 * we can really use. Obtain the useable sid, and store the original
1117 * one as an additional group if it had to be replaced */
1118 nt_status = get_primary_group_sid(mem_ctx, found_username,
1119 &pwd, &group_sid);
1120 if (!NT_STATUS_IS_OK(nt_status)) {
1121 TALLOC_FREE(result);
1122 return nt_status;
1125 /* store and check if it is the same we got originally */
1126 sid_peek_rid(group_sid, &i3->base.primary_gid);
1127 if (i3->base.primary_gid != info3->base.primary_gid) {
1128 uint32_t n = i3->base.groups.count;
1129 /* not the same, store the original as an additional group */
1130 i3->base.groups.rids =
1131 talloc_realloc(i3, i3->base.groups.rids,
1132 struct samr_RidWithAttribute, n + 1);
1133 if (i3->base.groups.rids == NULL) {
1134 TALLOC_FREE(result);
1135 return NT_STATUS_NO_MEMORY;
1137 i3->base.groups.rids[n].rid = info3->base.primary_gid;
1138 i3->base.groups.rids[n].attributes = SE_GROUP_ENABLED;
1139 i3->base.groups.count = n + 1;
1142 /* ensure we are never given NULL session keys */
1144 if (memcmp(info3->base.key.key, zeros, sizeof(zeros)) == 0) {
1145 result->user_session_key = data_blob_null;
1146 } else {
1147 result->user_session_key = data_blob_talloc(
1148 result, info3->base.key.key,
1149 sizeof(info3->base.key.key));
1152 if (memcmp(info3->base.LMSessKey.key, zeros, 8) == 0) {
1153 result->lm_session_key = data_blob_null;
1154 } else {
1155 result->lm_session_key = data_blob_talloc(
1156 result, info3->base.LMSessKey.key,
1157 sizeof(info3->base.LMSessKey.key));
1160 result->nss_token |= username_was_mapped;
1162 *server_info = result;
1164 return NT_STATUS_OK;
1167 /*****************************************************************************
1168 Make a server_info struct from the wbcAuthUserInfo returned by a domain logon
1169 ******************************************************************************/
1171 NTSTATUS make_server_info_wbcAuthUserInfo(TALLOC_CTX *mem_ctx,
1172 const char *sent_nt_username,
1173 const char *domain,
1174 const struct wbcAuthUserInfo *info,
1175 struct auth_serversupplied_info **server_info)
1177 struct netr_SamInfo3 *info3;
1179 info3 = wbcAuthUserInfo_to_netr_SamInfo3(mem_ctx, info);
1180 if (!info3) {
1181 return NT_STATUS_NO_MEMORY;
1184 return make_server_info_info3(mem_ctx,
1185 sent_nt_username, domain,
1186 server_info, info3);
1190 * Verify whether or not given domain is trusted.
1192 * @param domain_name name of the domain to be verified
1193 * @return true if domain is one of the trusted ones or
1194 * false if otherwise
1197 bool is_trusted_domain(const char* dom_name)
1199 struct dom_sid trustdom_sid;
1200 bool ret;
1202 /* no trusted domains for a standalone server */
1204 if ( lp_server_role() == ROLE_STANDALONE )
1205 return False;
1207 if (dom_name == NULL || dom_name[0] == '\0') {
1208 return false;
1211 if (strequal(dom_name, get_global_sam_name())) {
1212 return false;
1215 /* if we are a DC, then check for a direct trust relationships */
1217 if ( IS_DC ) {
1218 become_root();
1219 DEBUG (5,("is_trusted_domain: Checking for domain trust with "
1220 "[%s]\n", dom_name ));
1221 ret = pdb_get_trusteddom_pw(dom_name, NULL, NULL, NULL);
1222 unbecome_root();
1223 if (ret)
1224 return True;
1226 else {
1227 wbcErr result;
1229 /* If winbind is around, ask it */
1231 result = wb_is_trusted_domain(dom_name);
1233 if (result == WBC_ERR_SUCCESS) {
1234 return True;
1237 if (result == WBC_ERR_DOMAIN_NOT_FOUND) {
1238 /* winbind could not find the domain */
1239 return False;
1242 /* The only other possible result is that winbind is not up
1243 and running. We need to update the trustdom_cache
1244 ourselves */
1246 update_trustdom_cache();
1249 /* now the trustdom cache should be available a DC could still
1250 * have a transitive trust so fall back to the cache of trusted
1251 * domains (like a domain member would use */
1253 if ( trustdom_cache_fetch(dom_name, &trustdom_sid) ) {
1254 return True;
1257 return False;