s3: Use wbcSidsToUnixIds in create_local_token
[Samba.git] / source3 / auth / auth_util.c
blobcba7156026f386294c544016641d8bcbeff08e1b
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 "auth.h"
26 #include "smbd/globals.h"
27 #include "../libcli/auth/libcli_auth.h"
28 #include "../lib/crypto/arcfour.h"
29 #include "rpc_client/init_lsa.h"
30 #include "../libcli/security/security.h"
31 #include "../lib/util/util_pw.h"
32 #include "lib/winbind_util.h"
33 #include "passdb.h"
35 #undef DBGC_CLASS
36 #define DBGC_CLASS DBGC_AUTH
38 /****************************************************************************
39 Create a UNIX user on demand.
40 ****************************************************************************/
42 static int _smb_create_user(const char *domain, const char *unix_username, const char *homedir)
44 TALLOC_CTX *ctx = talloc_tos();
45 char *add_script;
46 int ret;
48 add_script = talloc_strdup(ctx, lp_adduser_script());
49 if (!add_script || !*add_script) {
50 return -1;
52 add_script = talloc_all_string_sub(ctx,
53 add_script,
54 "%u",
55 unix_username);
56 if (!add_script) {
57 return -1;
59 if (domain) {
60 add_script = talloc_all_string_sub(ctx,
61 add_script,
62 "%D",
63 domain);
64 if (!add_script) {
65 return -1;
68 if (homedir) {
69 add_script = talloc_all_string_sub(ctx,
70 add_script,
71 "%H",
72 homedir);
73 if (!add_script) {
74 return -1;
77 ret = smbrun(add_script,NULL);
78 flush_pwnam_cache();
79 DEBUG(ret ? 0 : 3,
80 ("smb_create_user: Running the command `%s' gave %d\n",
81 add_script,ret));
82 return ret;
85 /****************************************************************************
86 Create an auth_usersupplied_data structure after appropriate mapping.
87 ****************************************************************************/
89 NTSTATUS make_user_info_map(struct auth_usersupplied_info **user_info,
90 const char *smb_name,
91 const char *client_domain,
92 const char *workstation_name,
93 DATA_BLOB *lm_pwd,
94 DATA_BLOB *nt_pwd,
95 const struct samr_Password *lm_interactive_pwd,
96 const struct samr_Password *nt_interactive_pwd,
97 const char *plaintext,
98 enum auth_password_state password_state)
100 const char *domain;
101 NTSTATUS result;
102 bool was_mapped;
103 char *internal_username = NULL;
105 was_mapped = map_username(talloc_tos(), smb_name, &internal_username);
106 if (!internal_username) {
107 return NT_STATUS_NO_MEMORY;
110 DEBUG(5, ("Mapping user [%s]\\[%s] from workstation [%s]\n",
111 client_domain, smb_name, workstation_name));
113 domain = client_domain;
115 /* If you connect to a Windows domain member using a bogus domain name,
116 * the Windows box will map the BOGUS\user to SAMNAME\user. Thus, if
117 * the Windows box is a DC the name will become DOMAIN\user and be
118 * authenticated against AD, if the Windows box is a member server but
119 * not a DC the name will become WORKSTATION\user. A standalone
120 * non-domain member box will also map to WORKSTATION\user.
121 * This also deals with the client passing in a "" domain */
123 if (!is_trusted_domain(domain) &&
124 !strequal(domain, my_sam_name()))
126 if (lp_map_untrusted_to_domain())
127 domain = my_sam_name();
128 else
129 domain = get_global_sam_name();
130 DEBUG(5, ("Mapped domain from [%s] to [%s] for user [%s] from "
131 "workstation [%s]\n",
132 client_domain, domain, smb_name, workstation_name));
135 /* We know that the given domain is trusted (and we are allowing them),
136 * it is our global SAM name, or for legacy behavior it is our
137 * primary domain name */
139 result = make_user_info(user_info, smb_name, internal_username,
140 client_domain, domain, workstation_name,
141 lm_pwd, nt_pwd,
142 lm_interactive_pwd, nt_interactive_pwd,
143 plaintext, password_state);
144 if (NT_STATUS_IS_OK(result)) {
145 /* We have tried mapping */
146 (*user_info)->mapped_state = True;
147 /* did we actually map the user to a different name? */
148 (*user_info)->was_mapped = was_mapped;
150 return result;
153 /****************************************************************************
154 Create an auth_usersupplied_data, making the DATA_BLOBs here.
155 Decrypt and encrypt the passwords.
156 ****************************************************************************/
158 bool make_user_info_netlogon_network(struct auth_usersupplied_info **user_info,
159 const char *smb_name,
160 const char *client_domain,
161 const char *workstation_name,
162 uint32 logon_parameters,
163 const uchar *lm_network_pwd,
164 int lm_pwd_len,
165 const uchar *nt_network_pwd,
166 int nt_pwd_len)
168 bool ret;
169 NTSTATUS status;
170 DATA_BLOB lm_blob = data_blob(lm_network_pwd, lm_pwd_len);
171 DATA_BLOB nt_blob = data_blob(nt_network_pwd, nt_pwd_len);
173 status = make_user_info_map(user_info,
174 smb_name, client_domain,
175 workstation_name,
176 lm_pwd_len ? &lm_blob : NULL,
177 nt_pwd_len ? &nt_blob : NULL,
178 NULL, NULL, NULL,
179 AUTH_PASSWORD_RESPONSE);
181 if (NT_STATUS_IS_OK(status)) {
182 (*user_info)->logon_parameters = logon_parameters;
184 ret = NT_STATUS_IS_OK(status) ? True : False;
186 data_blob_free(&lm_blob);
187 data_blob_free(&nt_blob);
188 return ret;
191 /****************************************************************************
192 Create an auth_usersupplied_data, making the DATA_BLOBs here.
193 Decrypt and encrypt the passwords.
194 ****************************************************************************/
196 bool make_user_info_netlogon_interactive(struct auth_usersupplied_info **user_info,
197 const char *smb_name,
198 const char *client_domain,
199 const char *workstation_name,
200 uint32 logon_parameters,
201 const uchar chal[8],
202 const uchar lm_interactive_pwd[16],
203 const uchar nt_interactive_pwd[16],
204 const uchar *dc_sess_key)
206 struct samr_Password lm_pwd;
207 struct samr_Password nt_pwd;
208 unsigned char local_lm_response[24];
209 unsigned char local_nt_response[24];
210 unsigned char key[16];
212 memcpy(key, dc_sess_key, 16);
214 if (lm_interactive_pwd)
215 memcpy(lm_pwd.hash, lm_interactive_pwd, sizeof(lm_pwd.hash));
217 if (nt_interactive_pwd)
218 memcpy(nt_pwd.hash, nt_interactive_pwd, sizeof(nt_pwd.hash));
220 #ifdef DEBUG_PASSWORD
221 DEBUG(100,("key:"));
222 dump_data(100, key, sizeof(key));
224 DEBUG(100,("lm owf password:"));
225 dump_data(100, lm_pwd.hash, sizeof(lm_pwd.hash));
227 DEBUG(100,("nt owf password:"));
228 dump_data(100, nt_pwd.hash, sizeof(nt_pwd.hash));
229 #endif
231 if (lm_interactive_pwd)
232 arcfour_crypt(lm_pwd.hash, key, sizeof(lm_pwd.hash));
234 if (nt_interactive_pwd)
235 arcfour_crypt(nt_pwd.hash, key, sizeof(nt_pwd.hash));
237 #ifdef DEBUG_PASSWORD
238 DEBUG(100,("decrypt of lm owf password:"));
239 dump_data(100, lm_pwd.hash, sizeof(lm_pwd));
241 DEBUG(100,("decrypt of nt owf password:"));
242 dump_data(100, nt_pwd.hash, sizeof(nt_pwd));
243 #endif
245 if (lm_interactive_pwd)
246 SMBOWFencrypt(lm_pwd.hash, chal,
247 local_lm_response);
249 if (nt_interactive_pwd)
250 SMBOWFencrypt(nt_pwd.hash, chal,
251 local_nt_response);
253 /* Password info paranoia */
254 ZERO_STRUCT(key);
257 bool ret;
258 NTSTATUS nt_status;
259 DATA_BLOB local_lm_blob;
260 DATA_BLOB local_nt_blob;
262 if (lm_interactive_pwd) {
263 local_lm_blob = data_blob(local_lm_response,
264 sizeof(local_lm_response));
267 if (nt_interactive_pwd) {
268 local_nt_blob = data_blob(local_nt_response,
269 sizeof(local_nt_response));
272 nt_status = make_user_info_map(
273 user_info,
274 smb_name, client_domain, workstation_name,
275 lm_interactive_pwd ? &local_lm_blob : NULL,
276 nt_interactive_pwd ? &local_nt_blob : NULL,
277 lm_interactive_pwd ? &lm_pwd : NULL,
278 nt_interactive_pwd ? &nt_pwd : NULL,
279 NULL, AUTH_PASSWORD_HASH);
281 if (NT_STATUS_IS_OK(nt_status)) {
282 (*user_info)->logon_parameters = logon_parameters;
285 ret = NT_STATUS_IS_OK(nt_status) ? True : False;
286 data_blob_free(&local_lm_blob);
287 data_blob_free(&local_nt_blob);
288 return ret;
293 /****************************************************************************
294 Create an auth_usersupplied_data structure
295 ****************************************************************************/
297 bool make_user_info_for_reply(struct auth_usersupplied_info **user_info,
298 const char *smb_name,
299 const char *client_domain,
300 const uint8 chal[8],
301 DATA_BLOB plaintext_password)
304 DATA_BLOB local_lm_blob;
305 DATA_BLOB local_nt_blob;
306 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
307 char *plaintext_password_string;
309 * Not encrypted - do so.
312 DEBUG(5,("make_user_info_for_reply: User passwords not in encrypted "
313 "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 plaintext_password_string = talloc_strndup(talloc_tos(),
337 (const char *)plaintext_password.data,
338 plaintext_password.length);
339 if (!plaintext_password_string) {
340 return False;
343 ret = make_user_info_map(
344 user_info, smb_name, client_domain,
345 get_remote_machine_name(),
346 local_lm_blob.data ? &local_lm_blob : NULL,
347 local_nt_blob.data ? &local_nt_blob : NULL,
348 NULL, NULL,
349 plaintext_password_string,
350 AUTH_PASSWORD_PLAIN);
352 if (plaintext_password_string) {
353 memset(plaintext_password_string, '\0', strlen(plaintext_password_string));
354 talloc_free(plaintext_password_string);
357 data_blob_free(&local_lm_blob);
358 return NT_STATUS_IS_OK(ret) ? True : False;
361 /****************************************************************************
362 Create an auth_usersupplied_data structure
363 ****************************************************************************/
365 NTSTATUS make_user_info_for_reply_enc(struct auth_usersupplied_info **user_info,
366 const char *smb_name,
367 const char *client_domain,
368 DATA_BLOB lm_resp, DATA_BLOB nt_resp)
370 return make_user_info_map(user_info, smb_name,
371 client_domain,
372 get_remote_machine_name(),
373 lm_resp.data && (lm_resp.length > 0) ? &lm_resp : NULL,
374 nt_resp.data && (nt_resp.length > 0) ? &nt_resp : NULL,
375 NULL, NULL, NULL,
376 AUTH_PASSWORD_RESPONSE);
379 /****************************************************************************
380 Create a guest user_info blob, for anonymous authenticaion.
381 ****************************************************************************/
383 bool make_user_info_guest(struct auth_usersupplied_info **user_info)
385 NTSTATUS nt_status;
387 nt_status = make_user_info(user_info,
388 "","",
389 "","",
390 "",
391 NULL, NULL,
392 NULL, NULL,
393 NULL,
394 AUTH_PASSWORD_RESPONSE);
396 return NT_STATUS_IS_OK(nt_status) ? True : False;
399 static NTSTATUS log_nt_token(struct security_token *token)
401 TALLOC_CTX *frame = talloc_stackframe();
402 char *command;
403 char *group_sidstr;
404 size_t i;
406 if ((lp_log_nt_token_command() == NULL) ||
407 (strlen(lp_log_nt_token_command()) == 0)) {
408 TALLOC_FREE(frame);
409 return NT_STATUS_OK;
412 group_sidstr = talloc_strdup(frame, "");
413 for (i=1; i<token->num_sids; i++) {
414 group_sidstr = talloc_asprintf(
415 frame, "%s %s", group_sidstr,
416 sid_string_talloc(frame, &token->sids[i]));
419 command = talloc_string_sub(
420 frame, lp_log_nt_token_command(),
421 "%s", sid_string_talloc(frame, &token->sids[0]));
422 command = talloc_string_sub(frame, command, "%t", group_sidstr);
424 if (command == NULL) {
425 TALLOC_FREE(frame);
426 return NT_STATUS_NO_MEMORY;
429 DEBUG(8, ("running command: [%s]\n", command));
430 if (smbrun(command, NULL) != 0) {
431 DEBUG(0, ("Could not log NT token\n"));
432 TALLOC_FREE(frame);
433 return NT_STATUS_ACCESS_DENIED;
436 TALLOC_FREE(frame);
437 return NT_STATUS_OK;
441 * Create the token to use from server_info->info3 and
442 * server_info->sids (the info3/sam groups). Find the unix gids.
445 NTSTATUS create_local_token(struct auth_serversupplied_info *server_info)
447 struct security_token *t;
448 NTSTATUS status;
449 size_t i;
450 struct dom_sid tmp_sid;
451 struct wbcUnixId *ids;
454 * If winbind is not around, we can not make much use of the SIDs the
455 * domain controller provided us with. Likewise if the user name was
456 * mapped to some local unix user.
459 if (((lp_server_role() == ROLE_DOMAIN_MEMBER) && !winbind_ping()) ||
460 (server_info->nss_token)) {
461 status = create_token_from_username(server_info,
462 server_info->unix_name,
463 server_info->guest,
464 &server_info->utok.uid,
465 &server_info->utok.gid,
466 &server_info->unix_name,
467 &server_info->security_token);
469 } else {
470 status = create_local_nt_token_from_info3(server_info,
471 server_info->guest,
472 server_info->info3,
473 &server_info->extra,
474 &server_info->security_token);
477 if (!NT_STATUS_IS_OK(status)) {
478 return status;
481 /* Convert the SIDs to gids. */
483 server_info->utok.ngroups = 0;
484 server_info->utok.groups = NULL;
486 t = server_info->security_token;
488 ids = TALLOC_ARRAY(talloc_tos(), struct wbcUnixId,
489 t->num_sids);
490 if (ids == NULL) {
491 return NT_STATUS_NO_MEMORY;
494 if (!sids_to_unix_ids(t->sids, t->num_sids, ids)) {
495 TALLOC_FREE(ids);
496 return NT_STATUS_NO_MEMORY;
499 /* Start at index 1, where the groups start. */
501 for (i=1; i<t->num_sids; i++) {
503 if (ids[i].type != WBC_ID_TYPE_GID) {
504 DEBUG(10, ("Could not convert SID %s to gid, "
505 "ignoring it\n",
506 sid_string_dbg(&t->sids[i])));
507 continue;
509 if (!add_gid_to_array_unique(server_info, ids[i].id.gid,
510 &server_info->utok.groups,
511 &server_info->utok.ngroups)) {
512 return NT_STATUS_NO_MEMORY;
517 * Add the "Unix Group" SID for each gid to catch mapped groups
518 * and their Unix equivalent. This is to solve the backwards
519 * compatibility problem of 'valid users = +ntadmin' where
520 * ntadmin has been paired with "Domain Admins" in the group
521 * mapping table. Otherwise smb.conf would need to be changed
522 * to 'valid user = "Domain Admins"'. --jerry
524 * For consistency we also add the "Unix User" SID,
525 * so that the complete unix token is represented within
526 * the nt token.
529 uid_to_unix_users_sid(server_info->utok.uid, &tmp_sid);
531 add_sid_to_array_unique(server_info->security_token, &tmp_sid,
532 &server_info->security_token->sids,
533 &server_info->security_token->num_sids);
535 for ( i=0; i<server_info->utok.ngroups; i++ ) {
536 gid_to_unix_groups_sid(server_info->utok.groups[i], &tmp_sid);
537 add_sid_to_array_unique(server_info->security_token, &tmp_sid,
538 &server_info->security_token->sids,
539 &server_info->security_token->num_sids);
542 security_token_debug(DBGC_AUTH, 10, server_info->security_token);
543 debug_unix_user_token(DBGC_AUTH, 10,
544 server_info->utok.uid,
545 server_info->utok.gid,
546 server_info->utok.ngroups,
547 server_info->utok.groups);
549 status = log_nt_token(server_info->security_token);
550 return status;
553 /***************************************************************************
554 Make (and fill) a server_info struct from a 'struct passwd' by conversion
555 to a struct samu
556 ***************************************************************************/
558 NTSTATUS make_server_info_pw(struct auth_serversupplied_info **server_info,
559 char *unix_username,
560 struct passwd *pwd)
562 NTSTATUS status;
563 struct samu *sampass = NULL;
564 char *qualified_name = NULL;
565 TALLOC_CTX *mem_ctx = NULL;
566 struct dom_sid u_sid;
567 enum lsa_SidType type;
568 struct auth_serversupplied_info *result;
571 * The SID returned in server_info->sam_account is based
572 * on our SAM sid even though for a pure UNIX account this should
573 * not be the case as it doesn't really exist in the SAM db.
574 * This causes lookups on "[in]valid users" to fail as they
575 * will lookup this name as a "Unix User" SID to check against
576 * the user token. Fix this by adding the "Unix User"\unix_username
577 * SID to the sid array. The correct fix should probably be
578 * changing the server_info->sam_account user SID to be a
579 * S-1-22 Unix SID, but this might break old configs where
580 * plaintext passwords were used with no SAM backend.
583 mem_ctx = talloc_init("make_server_info_pw_tmp");
584 if (!mem_ctx) {
585 return NT_STATUS_NO_MEMORY;
588 qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
589 unix_users_domain_name(),
590 unix_username );
591 if (!qualified_name) {
592 TALLOC_FREE(mem_ctx);
593 return NT_STATUS_NO_MEMORY;
596 if (!lookup_name(mem_ctx, qualified_name, LOOKUP_NAME_ALL,
597 NULL, NULL,
598 &u_sid, &type)) {
599 TALLOC_FREE(mem_ctx);
600 return NT_STATUS_NO_SUCH_USER;
603 TALLOC_FREE(mem_ctx);
605 if (type != SID_NAME_USER) {
606 return NT_STATUS_NO_SUCH_USER;
609 if ( !(sampass = samu_new( NULL )) ) {
610 return NT_STATUS_NO_MEMORY;
613 status = samu_set_unix( sampass, pwd );
614 if (!NT_STATUS_IS_OK(status)) {
615 return status;
618 /* In pathological cases the above call can set the account
619 * name to the DOMAIN\username form. Reset the account name
620 * using unix_username */
621 pdb_set_username(sampass, unix_username, PDB_SET);
623 /* set the user sid to be the calculated u_sid */
624 pdb_set_user_sid(sampass, &u_sid, PDB_SET);
626 result = make_server_info(NULL);
627 if (result == NULL) {
628 TALLOC_FREE(sampass);
629 return NT_STATUS_NO_MEMORY;
632 status = samu_to_SamInfo3(result, sampass, global_myname(),
633 &result->info3, &result->extra);
634 TALLOC_FREE(sampass);
635 if (!NT_STATUS_IS_OK(status)) {
636 DEBUG(10, ("Failed to convert samu to info3: %s\n",
637 nt_errstr(status)));
638 TALLOC_FREE(result);
639 return status;
642 result->unix_name = talloc_strdup(result, unix_username);
643 result->sanitized_username = sanitize_username(result, unix_username);
645 if ((result->unix_name == NULL)
646 || (result->sanitized_username == NULL)) {
647 TALLOC_FREE(result);
648 return NT_STATUS_NO_MEMORY;
651 result->utok.uid = pwd->pw_uid;
652 result->utok.gid = pwd->pw_gid;
654 *server_info = result;
656 return NT_STATUS_OK;
659 static NTSTATUS get_guest_info3(TALLOC_CTX *mem_ctx,
660 struct netr_SamInfo3 *info3)
662 const char *guest_account = lp_guestaccount();
663 struct dom_sid domain_sid;
664 struct passwd *pwd;
665 const char *tmp;
667 pwd = Get_Pwnam_alloc(mem_ctx, guest_account);
668 if (pwd == NULL) {
669 DEBUG(0,("SamInfo3_for_guest: Unable to locate guest "
670 "account [%s]!\n", guest_account));
671 return NT_STATUS_NO_SUCH_USER;
674 /* Set acount name */
675 tmp = talloc_strdup(mem_ctx, pwd->pw_name);
676 if (tmp == NULL) {
677 return NT_STATUS_NO_MEMORY;
679 init_lsa_String(&info3->base.account_name, tmp);
681 /* Set domain name */
682 tmp = talloc_strdup(mem_ctx, get_global_sam_name());
683 if (tmp == NULL) {
684 return NT_STATUS_NO_MEMORY;
686 init_lsa_StringLarge(&info3->base.domain, tmp);
688 /* Domain sid */
689 sid_copy(&domain_sid, get_global_sam_sid());
691 info3->base.domain_sid = dom_sid_dup(mem_ctx, &domain_sid);
692 if (info3->base.domain_sid == NULL) {
693 return NT_STATUS_NO_MEMORY;
696 /* Guest rid */
697 info3->base.rid = DOMAIN_RID_GUEST;
699 /* Primary gid */
700 info3->base.primary_gid = BUILTIN_RID_GUESTS;
702 TALLOC_FREE(pwd);
703 return NT_STATUS_OK;
706 /***************************************************************************
707 Make (and fill) a user_info struct for a guest login.
708 This *must* succeed for smbd to start. If there is no mapping entry for
709 the guest gid, then create one.
710 ***************************************************************************/
712 static NTSTATUS make_new_server_info_guest(struct auth_serversupplied_info **server_info)
714 static const char zeros[16] = {0};
715 const char *guest_account = lp_guestaccount();
716 const char *domain = global_myname();
717 struct netr_SamInfo3 info3;
718 TALLOC_CTX *tmp_ctx;
719 NTSTATUS status;
720 fstring tmp;
722 tmp_ctx = talloc_stackframe();
723 if (tmp_ctx == NULL) {
724 return NT_STATUS_NO_MEMORY;
727 ZERO_STRUCT(info3);
729 status = get_guest_info3(tmp_ctx, &info3);
730 if (!NT_STATUS_IS_OK(status)) {
731 goto done;
734 status = make_server_info_info3(tmp_ctx,
735 guest_account,
736 domain,
737 server_info,
738 &info3);
739 if (!NT_STATUS_IS_OK(status)) {
740 goto done;
743 (*server_info)->guest = True;
745 status = create_local_token(*server_info);
746 if (!NT_STATUS_IS_OK(status)) {
747 DEBUG(10, ("create_local_token failed: %s\n",
748 nt_errstr(status)));
749 goto done;
752 /* annoying, but the Guest really does have a session key, and it is
753 all zeros! */
754 (*server_info)->user_session_key = data_blob(zeros, sizeof(zeros));
755 (*server_info)->lm_session_key = data_blob(zeros, sizeof(zeros));
757 alpha_strcpy(tmp, (*server_info)->info3->base.account_name.string,
758 ". _-$", sizeof(tmp));
759 (*server_info)->sanitized_username = talloc_strdup(*server_info, tmp);
761 status = NT_STATUS_OK;
762 done:
763 TALLOC_FREE(tmp_ctx);
764 return NT_STATUS_OK;
767 /***************************************************************************
768 Make (and fill) a auth_session_info struct for a system user login.
769 This *must* succeed for smbd to start.
770 ***************************************************************************/
772 static NTSTATUS make_new_session_info_system(TALLOC_CTX *mem_ctx,
773 struct auth_serversupplied_info **session_info)
775 struct passwd *pwd;
776 NTSTATUS status;
778 pwd = getpwuid_alloc(mem_ctx, sec_initial_uid());
779 if (pwd == NULL) {
780 return NT_STATUS_NO_SUCH_USER;
783 status = make_serverinfo_from_username(mem_ctx,
784 pwd->pw_name,
785 false,
786 session_info);
787 TALLOC_FREE(pwd);
788 if (!NT_STATUS_IS_OK(status)) {
789 return status;
792 (*session_info)->system = true;
794 status = add_sid_to_array_unique((*session_info)->security_token->sids,
795 &global_sid_System,
796 &(*session_info)->security_token->sids,
797 &(*session_info)->security_token->num_sids);
798 if (!NT_STATUS_IS_OK(status)) {
799 TALLOC_FREE((*session_info));
800 return status;
803 return NT_STATUS_OK;
806 /****************************************************************************
807 Fake a auth_serversupplied_info just from a username
808 ****************************************************************************/
810 NTSTATUS make_serverinfo_from_username(TALLOC_CTX *mem_ctx,
811 const char *username,
812 bool is_guest,
813 struct auth_serversupplied_info **presult)
815 struct auth_serversupplied_info *result;
816 struct passwd *pwd;
817 NTSTATUS status;
819 pwd = Get_Pwnam_alloc(talloc_tos(), username);
820 if (pwd == NULL) {
821 return NT_STATUS_NO_SUCH_USER;
824 status = make_server_info_pw(&result, pwd->pw_name, pwd);
826 TALLOC_FREE(pwd);
828 if (!NT_STATUS_IS_OK(status)) {
829 return status;
832 result->nss_token = true;
833 result->guest = is_guest;
835 status = create_local_token(result);
837 if (!NT_STATUS_IS_OK(status)) {
838 TALLOC_FREE(result);
839 return status;
842 *presult = talloc_steal(mem_ctx, result);
843 return NT_STATUS_OK;
847 struct auth_serversupplied_info *copy_serverinfo(TALLOC_CTX *mem_ctx,
848 const struct auth_serversupplied_info *src)
850 struct auth_serversupplied_info *dst;
852 dst = make_server_info(mem_ctx);
853 if (dst == NULL) {
854 return NULL;
857 dst->guest = src->guest;
858 dst->system = src->system;
859 dst->utok.uid = src->utok.uid;
860 dst->utok.gid = src->utok.gid;
861 dst->utok.ngroups = src->utok.ngroups;
862 if (src->utok.ngroups != 0) {
863 dst->utok.groups = (gid_t *)TALLOC_MEMDUP(
864 dst, src->utok.groups,
865 sizeof(gid_t)*dst->utok.ngroups);
866 } else {
867 dst->utok.groups = NULL;
870 if (src->security_token) {
871 dst->security_token = dup_nt_token(dst, src->security_token);
872 if (!dst->security_token) {
873 TALLOC_FREE(dst);
874 return NULL;
878 dst->user_session_key = data_blob_talloc( dst, src->user_session_key.data,
879 src->user_session_key.length);
881 dst->lm_session_key = data_blob_talloc(dst, src->lm_session_key.data,
882 src->lm_session_key.length);
884 dst->info3 = copy_netr_SamInfo3(dst, src->info3);
885 if (!dst->info3) {
886 TALLOC_FREE(dst);
887 return NULL;
889 dst->extra = src->extra;
891 dst->unix_name = talloc_strdup(dst, src->unix_name);
892 if (!dst->unix_name) {
893 TALLOC_FREE(dst);
894 return NULL;
897 dst->sanitized_username = talloc_strdup(dst, src->sanitized_username);
898 if (!dst->sanitized_username) {
899 TALLOC_FREE(dst);
900 return NULL;
903 return dst;
907 * Set a new session key. Used in the rpc server where we have to override the
908 * SMB level session key with SystemLibraryDTC
911 bool session_info_set_session_key(struct auth_serversupplied_info *info,
912 DATA_BLOB session_key)
914 TALLOC_FREE(info->user_session_key.data);
916 info->user_session_key = data_blob_talloc(
917 info, session_key.data, session_key.length);
919 return (info->user_session_key.data != NULL);
922 static struct auth_serversupplied_info *guest_info = NULL;
924 bool init_guest_info(void)
926 if (guest_info != NULL)
927 return True;
929 return NT_STATUS_IS_OK(make_new_server_info_guest(&guest_info));
932 NTSTATUS make_server_info_guest(TALLOC_CTX *mem_ctx,
933 struct auth_serversupplied_info **server_info)
935 *server_info = copy_serverinfo(mem_ctx, guest_info);
936 return (*server_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
939 static struct auth_serversupplied_info *system_info = NULL;
941 NTSTATUS init_system_info(void)
943 if (system_info != NULL)
944 return NT_STATUS_OK;
946 return make_new_session_info_system(NULL, &system_info);
949 NTSTATUS make_session_info_system(TALLOC_CTX *mem_ctx,
950 struct auth_serversupplied_info **session_info)
952 if (system_info == NULL) return NT_STATUS_UNSUCCESSFUL;
953 *session_info = copy_serverinfo(mem_ctx, system_info);
954 return (*session_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
957 const struct auth_serversupplied_info *get_session_info_system(void)
959 return system_info;
962 bool copy_current_user(struct current_user *dst, struct current_user *src)
964 gid_t *groups;
965 struct security_token *nt_token;
967 groups = (gid_t *)memdup(src->ut.groups,
968 sizeof(gid_t) * src->ut.ngroups);
969 if ((src->ut.ngroups != 0) && (groups == NULL)) {
970 return False;
973 nt_token = dup_nt_token(NULL, src->nt_user_token);
974 if (nt_token == NULL) {
975 SAFE_FREE(groups);
976 return False;
979 dst->conn = src->conn;
980 dst->vuid = src->vuid;
981 dst->ut.uid = src->ut.uid;
982 dst->ut.gid = src->ut.gid;
983 dst->ut.ngroups = src->ut.ngroups;
984 dst->ut.groups = groups;
985 dst->nt_user_token = nt_token;
986 return True;
989 /***************************************************************************
990 Purely internal function for make_server_info_info3
991 ***************************************************************************/
993 static NTSTATUS check_account(TALLOC_CTX *mem_ctx, const char *domain,
994 const char *username, char **found_username,
995 struct passwd **pwd,
996 bool *username_was_mapped)
998 char *orig_dom_user = NULL;
999 char *dom_user = NULL;
1000 char *lower_username = NULL;
1001 char *real_username = NULL;
1002 struct passwd *passwd;
1004 lower_username = talloc_strdup(mem_ctx, username);
1005 if (!lower_username) {
1006 return NT_STATUS_NO_MEMORY;
1008 strlower_m( lower_username );
1010 orig_dom_user = talloc_asprintf(mem_ctx,
1011 "%s%c%s",
1012 domain,
1013 *lp_winbind_separator(),
1014 lower_username);
1015 if (!orig_dom_user) {
1016 return NT_STATUS_NO_MEMORY;
1019 /* Get the passwd struct. Try to create the account if necessary. */
1021 *username_was_mapped = map_username(mem_ctx, orig_dom_user, &dom_user);
1022 if (!dom_user) {
1023 return NT_STATUS_NO_MEMORY;
1026 passwd = smb_getpwnam(mem_ctx, dom_user, &real_username, True );
1027 if (!passwd) {
1028 DEBUG(3, ("Failed to find authenticated user %s via "
1029 "getpwnam(), denying access.\n", dom_user));
1030 return NT_STATUS_NO_SUCH_USER;
1033 if (!real_username) {
1034 return NT_STATUS_NO_MEMORY;
1037 *pwd = passwd;
1039 /* This is pointless -- there is no suport for differing
1040 unix and windows names. Make sure to always store the
1041 one we actually looked up and succeeded. Have I mentioned
1042 why I hate the 'winbind use default domain' parameter?
1043 --jerry */
1045 *found_username = talloc_strdup( mem_ctx, real_username );
1047 return NT_STATUS_OK;
1050 /****************************************************************************
1051 Wrapper to allow the getpwnam() call to strip the domain name and
1052 try again in case a local UNIX user is already there. Also run through
1053 the username if we fallback to the username only.
1054 ****************************************************************************/
1056 struct passwd *smb_getpwnam( TALLOC_CTX *mem_ctx, const char *domuser,
1057 char **p_save_username, bool create )
1059 struct passwd *pw = NULL;
1060 char *p = NULL;
1061 char *username = NULL;
1063 /* we only save a copy of the username it has been mangled
1064 by winbindd use default domain */
1065 *p_save_username = NULL;
1067 /* don't call map_username() here since it has to be done higher
1068 up the stack so we don't call it multiple times */
1070 username = talloc_strdup(mem_ctx, domuser);
1071 if (!username) {
1072 return NULL;
1075 p = strchr_m( username, *lp_winbind_separator() );
1077 /* code for a DOMAIN\user string */
1079 if ( p ) {
1080 pw = Get_Pwnam_alloc( mem_ctx, domuser );
1081 if ( pw ) {
1082 /* make sure we get the case of the username correct */
1083 /* work around 'winbind use default domain = yes' */
1085 if ( !strchr_m( pw->pw_name, *lp_winbind_separator() ) ) {
1086 char *domain;
1088 /* split the domain and username into 2 strings */
1089 *p = '\0';
1090 domain = username;
1092 *p_save_username = talloc_asprintf(mem_ctx,
1093 "%s%c%s",
1094 domain,
1095 *lp_winbind_separator(),
1096 pw->pw_name);
1097 if (!*p_save_username) {
1098 TALLOC_FREE(pw);
1099 return NULL;
1101 } else {
1102 *p_save_username = talloc_strdup(mem_ctx, pw->pw_name);
1105 /* whew -- done! */
1106 return pw;
1109 /* setup for lookup of just the username */
1110 /* remember that p and username are overlapping memory */
1112 p++;
1113 username = talloc_strdup(mem_ctx, p);
1114 if (!username) {
1115 return NULL;
1119 /* just lookup a plain username */
1121 pw = Get_Pwnam_alloc(mem_ctx, username);
1123 /* Create local user if requested but only if winbindd
1124 is not running. We need to protect against cases
1125 where winbindd is failing and then prematurely
1126 creating users in /etc/passwd */
1128 if ( !pw && create && !winbind_ping() ) {
1129 /* Don't add a machine account. */
1130 if (username[strlen(username)-1] == '$')
1131 return NULL;
1133 _smb_create_user(NULL, username, NULL);
1134 pw = Get_Pwnam_alloc(mem_ctx, username);
1137 /* one last check for a valid passwd struct */
1139 if (pw) {
1140 *p_save_username = talloc_strdup(mem_ctx, pw->pw_name);
1142 return pw;
1145 /***************************************************************************
1146 Make a server_info struct from the info3 returned by a domain logon
1147 ***************************************************************************/
1149 NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
1150 const char *sent_nt_username,
1151 const char *domain,
1152 struct auth_serversupplied_info **server_info,
1153 struct netr_SamInfo3 *info3)
1155 static const char zeros[16] = {0, };
1157 NTSTATUS nt_status = NT_STATUS_OK;
1158 char *found_username = NULL;
1159 const char *nt_domain;
1160 const char *nt_username;
1161 bool username_was_mapped;
1162 struct passwd *pwd;
1163 struct auth_serversupplied_info *result;
1164 struct dom_sid *group_sid;
1165 struct netr_SamInfo3 *i3;
1168 Here is where we should check the list of
1169 trusted domains, and verify that the SID
1170 matches.
1173 nt_username = talloc_strdup(mem_ctx, info3->base.account_name.string);
1174 if (!nt_username) {
1175 /* If the server didn't give us one, just use the one we sent
1176 * them */
1177 nt_username = sent_nt_username;
1180 nt_domain = talloc_strdup(mem_ctx, info3->base.domain.string);
1181 if (!nt_domain) {
1182 /* If the server didn't give us one, just use the one we sent
1183 * them */
1184 nt_domain = domain;
1187 /* If getpwnam() fails try the add user script (2.2.x behavior).
1189 We use the _unmapped_ username here in an attempt to provide
1190 consistent username mapping behavior between kerberos and NTLM[SSP]
1191 authentication in domain mode security. I.E. Username mapping
1192 should be applied to the fully qualified username
1193 (e.g. DOMAIN\user) and not just the login name. Yes this means we
1194 called map_username() unnecessarily in make_user_info_map() but
1195 that is how the current code is designed. Making the change here
1196 is the least disruptive place. -- jerry */
1198 /* this call will try to create the user if necessary */
1200 nt_status = check_account(mem_ctx, nt_domain, sent_nt_username,
1201 &found_username, &pwd,
1202 &username_was_mapped);
1204 if (!NT_STATUS_IS_OK(nt_status)) {
1205 return nt_status;
1208 result = make_server_info(NULL);
1209 if (result == NULL) {
1210 DEBUG(4, ("make_server_info failed!\n"));
1211 return NT_STATUS_NO_MEMORY;
1214 result->unix_name = talloc_strdup(result, found_username);
1216 result->sanitized_username = sanitize_username(result,
1217 result->unix_name);
1218 if (result->sanitized_username == NULL) {
1219 TALLOC_FREE(result);
1220 return NT_STATUS_NO_MEMORY;
1223 /* copy in the info3 */
1224 result->info3 = i3 = copy_netr_SamInfo3(result, info3);
1225 if (result->info3 == NULL) {
1226 TALLOC_FREE(result);
1227 return NT_STATUS_NO_MEMORY;
1230 /* Fill in the unix info we found on the way */
1231 result->utok.uid = pwd->pw_uid;
1232 result->utok.gid = pwd->pw_gid;
1234 /* We can't just trust that the primary group sid sent us is something
1235 * we can really use. Obtain the useable sid, and store the original
1236 * one as an additional group if it had to be replaced */
1237 nt_status = get_primary_group_sid(mem_ctx, found_username,
1238 &pwd, &group_sid);
1239 if (!NT_STATUS_IS_OK(nt_status)) {
1240 TALLOC_FREE(result);
1241 return nt_status;
1244 /* store and check if it is the same we got originally */
1245 sid_peek_rid(group_sid, &i3->base.primary_gid);
1246 if (i3->base.primary_gid != info3->base.primary_gid) {
1247 uint32_t n = i3->base.groups.count;
1248 /* not the same, store the original as an additional group */
1249 i3->base.groups.rids =
1250 talloc_realloc(i3, i3->base.groups.rids,
1251 struct samr_RidWithAttribute, n + 1);
1252 if (i3->base.groups.rids == NULL) {
1253 TALLOC_FREE(result);
1254 return NT_STATUS_NO_MEMORY;
1256 i3->base.groups.rids[n].rid = info3->base.primary_gid;
1257 i3->base.groups.rids[n].attributes = SE_GROUP_ENABLED;
1258 i3->base.groups.count = n + 1;
1261 /* ensure we are never given NULL session keys */
1263 if (memcmp(info3->base.key.key, zeros, sizeof(zeros)) == 0) {
1264 result->user_session_key = data_blob_null;
1265 } else {
1266 result->user_session_key = data_blob_talloc(
1267 result, info3->base.key.key,
1268 sizeof(info3->base.key.key));
1271 if (memcmp(info3->base.LMSessKey.key, zeros, 8) == 0) {
1272 result->lm_session_key = data_blob_null;
1273 } else {
1274 result->lm_session_key = data_blob_talloc(
1275 result, info3->base.LMSessKey.key,
1276 sizeof(info3->base.LMSessKey.key));
1279 result->nss_token |= username_was_mapped;
1281 *server_info = result;
1283 return NT_STATUS_OK;
1286 /*****************************************************************************
1287 Make a server_info struct from the wbcAuthUserInfo returned by a domain logon
1288 ******************************************************************************/
1290 NTSTATUS make_server_info_wbcAuthUserInfo(TALLOC_CTX *mem_ctx,
1291 const char *sent_nt_username,
1292 const char *domain,
1293 const struct wbcAuthUserInfo *info,
1294 struct auth_serversupplied_info **server_info)
1296 struct netr_SamInfo3 *info3;
1298 info3 = wbcAuthUserInfo_to_netr_SamInfo3(mem_ctx, info);
1299 if (!info3) {
1300 return NT_STATUS_NO_MEMORY;
1303 return make_server_info_info3(mem_ctx,
1304 sent_nt_username, domain,
1305 server_info, info3);
1309 * Verify whether or not given domain is trusted.
1311 * @param domain_name name of the domain to be verified
1312 * @return true if domain is one of the trusted ones or
1313 * false if otherwise
1316 bool is_trusted_domain(const char* dom_name)
1318 struct dom_sid trustdom_sid;
1319 bool ret;
1321 /* no trusted domains for a standalone server */
1323 if ( lp_server_role() == ROLE_STANDALONE )
1324 return False;
1326 if (dom_name == NULL || dom_name[0] == '\0') {
1327 return false;
1330 if (strequal(dom_name, get_global_sam_name())) {
1331 return false;
1334 /* if we are a DC, then check for a direct trust relationships */
1336 if ( IS_DC ) {
1337 become_root();
1338 DEBUG (5,("is_trusted_domain: Checking for domain trust with "
1339 "[%s]\n", dom_name ));
1340 ret = pdb_get_trusteddom_pw(dom_name, NULL, NULL, NULL);
1341 unbecome_root();
1342 if (ret)
1343 return True;
1345 else {
1346 wbcErr result;
1348 /* If winbind is around, ask it */
1350 result = wb_is_trusted_domain(dom_name);
1352 if (result == WBC_ERR_SUCCESS) {
1353 return True;
1356 if (result == WBC_ERR_DOMAIN_NOT_FOUND) {
1357 /* winbind could not find the domain */
1358 return False;
1361 /* The only other possible result is that winbind is not up
1362 and running. We need to update the trustdom_cache
1363 ourselves */
1365 update_trustdom_cache();
1368 /* now the trustdom cache should be available a DC could still
1369 * have a transitive trust so fall back to the cache of trusted
1370 * domains (like a domain member would use */
1372 if ( trustdom_cache_fetch(dom_name, &trustdom_sid) ) {
1373 return True;
1376 return False;