Fix bug #9637 - Renaming directories as guest user in security share mode doesn't...
[Samba.git] / source3 / auth / auth_util.c
blob0e1f4379f9d860c2dd6dde611c31539cf1e92875
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 "../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"
34 #undef DBGC_CLASS
35 #define DBGC_CLASS DBGC_AUTH
37 /****************************************************************************
38 Create a UNIX user on demand.
39 ****************************************************************************/
41 static int _smb_create_user(const char *domain, const char *unix_username, const char *homedir)
43 TALLOC_CTX *ctx = talloc_tos();
44 char *add_script;
45 int ret;
47 add_script = talloc_strdup(ctx, lp_adduser_script());
48 if (!add_script || !*add_script) {
49 return -1;
51 add_script = talloc_all_string_sub(ctx,
52 add_script,
53 "%u",
54 unix_username);
55 if (!add_script) {
56 return -1;
58 if (domain) {
59 add_script = talloc_all_string_sub(ctx,
60 add_script,
61 "%D",
62 domain);
63 if (!add_script) {
64 return -1;
67 if (homedir) {
68 add_script = talloc_all_string_sub(ctx,
69 add_script,
70 "%H",
71 homedir);
72 if (!add_script) {
73 return -1;
76 ret = smbrun(add_script,NULL);
77 flush_pwnam_cache();
78 DEBUG(ret ? 0 : 3,
79 ("smb_create_user: Running the command `%s' gave %d\n",
80 add_script,ret));
81 return ret;
84 /****************************************************************************
85 Create an auth_usersupplied_data structure after appropriate mapping.
86 ****************************************************************************/
88 NTSTATUS make_user_info_map(struct auth_usersupplied_info **user_info,
89 const char *smb_name,
90 const char *client_domain,
91 const char *workstation_name,
92 DATA_BLOB *lm_pwd,
93 DATA_BLOB *nt_pwd,
94 const struct samr_Password *lm_interactive_pwd,
95 const struct samr_Password *nt_interactive_pwd,
96 const char *plaintext,
97 enum auth_password_state password_state)
99 const char *domain;
100 NTSTATUS result;
101 bool was_mapped;
102 char *internal_username = NULL;
104 was_mapped = map_username(talloc_tos(), smb_name, &internal_username);
105 if (!internal_username) {
106 return NT_STATUS_NO_MEMORY;
109 DEBUG(5, ("Mapping user [%s]\\[%s] from workstation [%s]\n",
110 client_domain, smb_name, workstation_name));
112 domain = client_domain;
114 /* If you connect to a Windows domain member using a bogus domain name,
115 * the Windows box will map the BOGUS\user to SAMNAME\user. Thus, if
116 * the Windows box is a DC the name will become DOMAIN\user and be
117 * authenticated against AD, if the Windows box is a member server but
118 * not a DC the name will become WORKSTATION\user. A standalone
119 * non-domain member box will also map to WORKSTATION\user.
120 * This also deals with the client passing in a "" domain */
122 if (!is_trusted_domain(domain) &&
123 !strequal(domain, my_sam_name()) &&
124 !strequal(domain, get_global_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_system_info3(TALLOC_CTX *mem_ctx,
660 struct passwd *pwd,
661 struct netr_SamInfo3 *info3)
663 struct dom_sid domain_sid;
664 const char *tmp;
666 /* Set account name */
667 tmp = talloc_strdup(mem_ctx, pwd->pw_name);
668 if (tmp == NULL) {
669 return NT_STATUS_NO_MEMORY;
671 init_lsa_String(&info3->base.account_name, tmp);
673 /* Set domain name */
674 tmp = talloc_strdup(mem_ctx, get_global_sam_name());
675 if (tmp == NULL) {
676 return NT_STATUS_NO_MEMORY;
678 init_lsa_StringLarge(&info3->base.domain, tmp);
680 /* Domain sid */
681 sid_copy(&domain_sid, get_global_sam_sid());
683 info3->base.domain_sid = dom_sid_dup(mem_ctx, &domain_sid);
684 if (info3->base.domain_sid == NULL) {
685 return NT_STATUS_NO_MEMORY;
688 /* Admin rid */
689 info3->base.rid = DOMAIN_RID_ADMINISTRATOR;
691 /* Primary gid */
692 info3->base.primary_gid = BUILTIN_RID_ADMINISTRATORS;
694 return NT_STATUS_OK;
697 static NTSTATUS get_guest_info3(TALLOC_CTX *mem_ctx,
698 struct netr_SamInfo3 *info3)
700 const char *guest_account = lp_guestaccount();
701 struct dom_sid domain_sid;
702 struct passwd *pwd;
703 const char *tmp;
705 pwd = Get_Pwnam_alloc(mem_ctx, guest_account);
706 if (pwd == NULL) {
707 DEBUG(0,("SamInfo3_for_guest: Unable to locate guest "
708 "account [%s]!\n", guest_account));
709 return NT_STATUS_NO_SUCH_USER;
712 /* Set acount name */
713 tmp = talloc_strdup(mem_ctx, pwd->pw_name);
714 if (tmp == NULL) {
715 return NT_STATUS_NO_MEMORY;
717 init_lsa_String(&info3->base.account_name, tmp);
719 /* Set domain name */
720 tmp = talloc_strdup(mem_ctx, get_global_sam_name());
721 if (tmp == NULL) {
722 return NT_STATUS_NO_MEMORY;
724 init_lsa_StringLarge(&info3->base.domain, tmp);
726 /* Domain sid */
727 sid_copy(&domain_sid, get_global_sam_sid());
729 info3->base.domain_sid = dom_sid_dup(mem_ctx, &domain_sid);
730 if (info3->base.domain_sid == NULL) {
731 return NT_STATUS_NO_MEMORY;
734 /* Guest rid */
735 info3->base.rid = DOMAIN_RID_GUEST;
737 /* Primary gid */
738 info3->base.primary_gid = DOMAIN_RID_GUESTS;
740 TALLOC_FREE(pwd);
741 return NT_STATUS_OK;
744 /***************************************************************************
745 Make (and fill) a user_info struct for a guest login.
746 This *must* succeed for smbd to start. If there is no mapping entry for
747 the guest gid, then create one.
748 ***************************************************************************/
750 static NTSTATUS make_new_server_info_guest(struct auth_serversupplied_info **server_info)
752 static const char zeros[16] = {0};
753 const char *guest_account = lp_guestaccount();
754 const char *domain = global_myname();
755 struct netr_SamInfo3 info3;
756 TALLOC_CTX *tmp_ctx;
757 NTSTATUS status;
758 fstring tmp;
760 tmp_ctx = talloc_stackframe();
761 if (tmp_ctx == NULL) {
762 return NT_STATUS_NO_MEMORY;
765 ZERO_STRUCT(info3);
767 status = get_guest_info3(tmp_ctx, &info3);
768 if (!NT_STATUS_IS_OK(status)) {
769 goto done;
772 status = make_server_info_info3(tmp_ctx,
773 guest_account,
774 domain,
775 server_info,
776 &info3);
777 if (!NT_STATUS_IS_OK(status)) {
778 goto done;
781 (*server_info)->guest = True;
783 status = create_local_token(*server_info);
784 if (!NT_STATUS_IS_OK(status)) {
785 DEBUG(10, ("create_local_token failed: %s\n",
786 nt_errstr(status)));
787 goto done;
790 /* annoying, but the Guest really does have a session key, and it is
791 all zeros! */
792 (*server_info)->user_session_key = data_blob(zeros, sizeof(zeros));
793 (*server_info)->lm_session_key = data_blob(zeros, sizeof(zeros));
795 alpha_strcpy(tmp, (*server_info)->info3->base.account_name.string,
796 ". _-$", sizeof(tmp));
797 (*server_info)->sanitized_username = talloc_strdup(*server_info, tmp);
799 status = NT_STATUS_OK;
800 done:
801 TALLOC_FREE(tmp_ctx);
802 return status;
805 /****************************************************************************
806 Fake a auth_session_info just from a username (as a
807 session_info structure, with create_local_token() already called on
809 ****************************************************************************/
811 static NTSTATUS make_system_session_info_from_pw(TALLOC_CTX *mem_ctx,
812 struct passwd *pwd,
813 struct auth_serversupplied_info **server_info)
815 const char *domain = global_myname();
816 struct netr_SamInfo3 info3;
817 TALLOC_CTX *tmp_ctx;
818 NTSTATUS status;
820 tmp_ctx = talloc_stackframe();
821 if (tmp_ctx == NULL) {
822 return NT_STATUS_NO_MEMORY;
825 ZERO_STRUCT(info3);
827 status = get_system_info3(tmp_ctx, pwd, &info3);
828 if (!NT_STATUS_IS_OK(status)) {
829 DEBUG(0, ("Failed creating system info3 with %s\n",
830 nt_errstr(status)));
831 goto done;
834 status = make_server_info_info3(mem_ctx,
835 pwd->pw_name,
836 domain,
837 server_info,
838 &info3);
839 if (!NT_STATUS_IS_OK(status)) {
840 DEBUG(0, ("make_server_info_info3 failed with %s\n",
841 nt_errstr(status)));
842 goto done;
845 (*server_info)->nss_token = true;
847 /* Now turn the server_info into a session_info with the full token etc */
848 status = create_local_token(*server_info);
849 if (!NT_STATUS_IS_OK(status)) {
850 DEBUG(0, ("create_local_token failed: %s\n",
851 nt_errstr(status)));
852 goto done;
855 status = NT_STATUS_OK;
856 done:
857 TALLOC_FREE(tmp_ctx);
858 return status;
861 /***************************************************************************
862 Make (and fill) a auth_session_info struct for a system user login.
863 This *must* succeed for smbd to start.
864 ***************************************************************************/
866 static NTSTATUS make_new_session_info_system(TALLOC_CTX *mem_ctx,
867 struct auth_serversupplied_info **session_info)
869 struct passwd *pwd;
870 NTSTATUS status;
872 pwd = getpwuid_alloc(mem_ctx, sec_initial_uid());
873 if (pwd == NULL) {
874 return NT_STATUS_NO_SUCH_USER;
877 status = make_system_session_info_from_pw(mem_ctx,
878 pwd,
879 session_info);
880 TALLOC_FREE(pwd);
881 if (!NT_STATUS_IS_OK(status)) {
882 return status;
885 (*session_info)->system = true;
887 status = add_sid_to_array_unique((*session_info)->security_token->sids,
888 &global_sid_System,
889 &(*session_info)->security_token->sids,
890 &(*session_info)->security_token->num_sids);
891 if (!NT_STATUS_IS_OK(status)) {
892 TALLOC_FREE((*session_info));
893 return status;
896 return NT_STATUS_OK;
899 /****************************************************************************
900 Fake a auth_serversupplied_info just from a username
901 ****************************************************************************/
903 NTSTATUS make_serverinfo_from_username(TALLOC_CTX *mem_ctx,
904 const char *username,
905 bool is_guest,
906 struct auth_serversupplied_info **presult)
908 struct auth_serversupplied_info *result;
909 struct passwd *pwd;
910 NTSTATUS status;
912 pwd = Get_Pwnam_alloc(talloc_tos(), username);
913 if (pwd == NULL) {
914 return NT_STATUS_NO_SUCH_USER;
917 status = make_server_info_pw(&result, pwd->pw_name, pwd);
919 TALLOC_FREE(pwd);
921 if (!NT_STATUS_IS_OK(status)) {
922 return status;
925 result->nss_token = true;
926 result->guest = is_guest;
928 if (is_guest) {
929 status = make_server_info_guest(mem_ctx, &result);
930 } else {
931 status = create_local_token(result);
934 if (!NT_STATUS_IS_OK(status)) {
935 TALLOC_FREE(result);
936 return status;
939 *presult = talloc_steal(mem_ctx, result);
940 return NT_STATUS_OK;
944 struct auth_serversupplied_info *copy_serverinfo(TALLOC_CTX *mem_ctx,
945 const struct auth_serversupplied_info *src)
947 struct auth_serversupplied_info *dst;
949 dst = make_server_info(mem_ctx);
950 if (dst == NULL) {
951 return NULL;
954 dst->guest = src->guest;
955 dst->system = src->system;
956 dst->utok.uid = src->utok.uid;
957 dst->utok.gid = src->utok.gid;
958 dst->utok.ngroups = src->utok.ngroups;
959 if (src->utok.ngroups != 0) {
960 dst->utok.groups = (gid_t *)TALLOC_MEMDUP(
961 dst, src->utok.groups,
962 sizeof(gid_t)*dst->utok.ngroups);
963 } else {
964 dst->utok.groups = NULL;
967 if (src->security_token) {
968 dst->security_token = dup_nt_token(dst, src->security_token);
969 if (!dst->security_token) {
970 TALLOC_FREE(dst);
971 return NULL;
975 dst->user_session_key = data_blob_talloc( dst, src->user_session_key.data,
976 src->user_session_key.length);
978 dst->lm_session_key = data_blob_talloc(dst, src->lm_session_key.data,
979 src->lm_session_key.length);
981 dst->info3 = copy_netr_SamInfo3(dst, src->info3);
982 if (!dst->info3) {
983 TALLOC_FREE(dst);
984 return NULL;
986 dst->extra = src->extra;
988 dst->unix_name = talloc_strdup(dst, src->unix_name);
989 if (!dst->unix_name) {
990 TALLOC_FREE(dst);
991 return NULL;
994 dst->sanitized_username = talloc_strdup(dst, src->sanitized_username);
995 if (!dst->sanitized_username) {
996 TALLOC_FREE(dst);
997 return NULL;
1000 return dst;
1004 * Set a new session key. Used in the rpc server where we have to override the
1005 * SMB level session key with SystemLibraryDTC
1008 bool session_info_set_session_key(struct auth_serversupplied_info *info,
1009 DATA_BLOB session_key)
1011 TALLOC_FREE(info->user_session_key.data);
1013 info->user_session_key = data_blob_talloc(
1014 info, session_key.data, session_key.length);
1016 return (info->user_session_key.data != NULL);
1019 static struct auth_serversupplied_info *guest_info = NULL;
1021 bool init_guest_info(void)
1023 if (guest_info != NULL)
1024 return True;
1026 return NT_STATUS_IS_OK(make_new_server_info_guest(&guest_info));
1029 NTSTATUS make_server_info_guest(TALLOC_CTX *mem_ctx,
1030 struct auth_serversupplied_info **server_info)
1032 *server_info = copy_serverinfo(mem_ctx, guest_info);
1033 return (*server_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1036 static struct auth_serversupplied_info *system_info = NULL;
1038 NTSTATUS init_system_info(void)
1040 if (system_info != NULL)
1041 return NT_STATUS_OK;
1043 return make_new_session_info_system(NULL, &system_info);
1046 NTSTATUS make_session_info_system(TALLOC_CTX *mem_ctx,
1047 struct auth_serversupplied_info **session_info)
1049 if (system_info == NULL) return NT_STATUS_UNSUCCESSFUL;
1050 *session_info = copy_serverinfo(mem_ctx, system_info);
1051 return (*session_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1054 const struct auth_serversupplied_info *get_session_info_system(void)
1056 return system_info;
1059 bool copy_current_user(struct current_user *dst, struct current_user *src)
1061 gid_t *groups;
1062 struct security_token *nt_token;
1064 groups = (gid_t *)memdup(src->ut.groups,
1065 sizeof(gid_t) * src->ut.ngroups);
1066 if ((src->ut.ngroups != 0) && (groups == NULL)) {
1067 return False;
1070 nt_token = dup_nt_token(NULL, src->nt_user_token);
1071 if (nt_token == NULL) {
1072 SAFE_FREE(groups);
1073 return False;
1076 dst->conn = src->conn;
1077 dst->vuid = src->vuid;
1078 dst->ut.uid = src->ut.uid;
1079 dst->ut.gid = src->ut.gid;
1080 dst->ut.ngroups = src->ut.ngroups;
1081 dst->ut.groups = groups;
1082 dst->nt_user_token = nt_token;
1083 return True;
1086 /***************************************************************************
1087 Purely internal function for make_server_info_info3
1088 ***************************************************************************/
1090 static NTSTATUS check_account(TALLOC_CTX *mem_ctx, const char *domain,
1091 const char *username, char **found_username,
1092 struct passwd **pwd,
1093 bool *username_was_mapped)
1095 char *orig_dom_user = NULL;
1096 char *dom_user = NULL;
1097 char *lower_username = NULL;
1098 char *real_username = NULL;
1099 struct passwd *passwd;
1101 lower_username = talloc_strdup(mem_ctx, username);
1102 if (!lower_username) {
1103 return NT_STATUS_NO_MEMORY;
1105 strlower_m( lower_username );
1107 orig_dom_user = talloc_asprintf(mem_ctx,
1108 "%s%c%s",
1109 domain,
1110 *lp_winbind_separator(),
1111 lower_username);
1112 if (!orig_dom_user) {
1113 return NT_STATUS_NO_MEMORY;
1116 /* Get the passwd struct. Try to create the account if necessary. */
1118 *username_was_mapped = map_username(mem_ctx, orig_dom_user, &dom_user);
1119 if (!dom_user) {
1120 return NT_STATUS_NO_MEMORY;
1123 passwd = smb_getpwnam(mem_ctx, dom_user, &real_username, True );
1124 if (!passwd) {
1125 DEBUG(3, ("Failed to find authenticated user %s via "
1126 "getpwnam(), denying access.\n", dom_user));
1127 return NT_STATUS_NO_SUCH_USER;
1130 if (!real_username) {
1131 return NT_STATUS_NO_MEMORY;
1134 *pwd = passwd;
1136 /* This is pointless -- there is no suport for differing
1137 unix and windows names. Make sure to always store the
1138 one we actually looked up and succeeded. Have I mentioned
1139 why I hate the 'winbind use default domain' parameter?
1140 --jerry */
1142 *found_username = talloc_strdup( mem_ctx, real_username );
1144 return NT_STATUS_OK;
1147 /****************************************************************************
1148 Wrapper to allow the getpwnam() call to strip the domain name and
1149 try again in case a local UNIX user is already there. Also run through
1150 the username if we fallback to the username only.
1151 ****************************************************************************/
1153 struct passwd *smb_getpwnam( TALLOC_CTX *mem_ctx, const char *domuser,
1154 char **p_save_username, bool create )
1156 struct passwd *pw = NULL;
1157 char *p = NULL;
1158 char *username = NULL;
1160 /* we only save a copy of the username it has been mangled
1161 by winbindd use default domain */
1162 *p_save_username = NULL;
1164 /* don't call map_username() here since it has to be done higher
1165 up the stack so we don't call it multiple times */
1167 username = talloc_strdup(mem_ctx, domuser);
1168 if (!username) {
1169 return NULL;
1172 p = strchr_m( username, *lp_winbind_separator() );
1174 /* code for a DOMAIN\user string */
1176 if ( p ) {
1177 pw = Get_Pwnam_alloc( mem_ctx, domuser );
1178 if ( pw ) {
1179 /* make sure we get the case of the username correct */
1180 /* work around 'winbind use default domain = yes' */
1182 if ( lp_winbind_use_default_domain() &&
1183 !strchr_m( pw->pw_name, *lp_winbind_separator() ) ) {
1184 char *domain;
1186 /* split the domain and username into 2 strings */
1187 *p = '\0';
1188 domain = username;
1190 *p_save_username = talloc_asprintf(mem_ctx,
1191 "%s%c%s",
1192 domain,
1193 *lp_winbind_separator(),
1194 pw->pw_name);
1195 if (!*p_save_username) {
1196 TALLOC_FREE(pw);
1197 return NULL;
1199 } else {
1200 *p_save_username = talloc_strdup(mem_ctx, pw->pw_name);
1203 /* whew -- done! */
1204 return pw;
1207 /* setup for lookup of just the username */
1208 /* remember that p and username are overlapping memory */
1210 p++;
1211 username = talloc_strdup(mem_ctx, p);
1212 if (!username) {
1213 return NULL;
1217 /* just lookup a plain username */
1219 pw = Get_Pwnam_alloc(mem_ctx, username);
1221 /* Create local user if requested but only if winbindd
1222 is not running. We need to protect against cases
1223 where winbindd is failing and then prematurely
1224 creating users in /etc/passwd */
1226 if ( !pw && create && !winbind_ping() ) {
1227 /* Don't add a machine account. */
1228 if (username[strlen(username)-1] == '$')
1229 return NULL;
1231 _smb_create_user(NULL, username, NULL);
1232 pw = Get_Pwnam_alloc(mem_ctx, username);
1235 /* one last check for a valid passwd struct */
1237 if (pw) {
1238 *p_save_username = talloc_strdup(mem_ctx, pw->pw_name);
1240 return pw;
1243 /***************************************************************************
1244 Make a server_info struct from the info3 returned by a domain logon
1245 ***************************************************************************/
1247 NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
1248 const char *sent_nt_username,
1249 const char *domain,
1250 struct auth_serversupplied_info **server_info,
1251 struct netr_SamInfo3 *info3)
1253 static const char zeros[16] = {0, };
1255 NTSTATUS nt_status = NT_STATUS_OK;
1256 char *found_username = NULL;
1257 const char *nt_domain;
1258 const char *nt_username;
1259 struct dom_sid user_sid;
1260 struct dom_sid group_sid;
1261 bool username_was_mapped;
1262 struct passwd *pwd;
1263 struct auth_serversupplied_info *result;
1266 Here is where we should check the list of
1267 trusted domains, and verify that the SID
1268 matches.
1271 if (!sid_compose(&user_sid, info3->base.domain_sid, info3->base.rid)) {
1272 return NT_STATUS_INVALID_PARAMETER;
1275 if (!sid_compose(&group_sid, info3->base.domain_sid,
1276 info3->base.primary_gid)) {
1277 return NT_STATUS_INVALID_PARAMETER;
1280 nt_username = talloc_strdup(mem_ctx, info3->base.account_name.string);
1281 if (!nt_username) {
1282 /* If the server didn't give us one, just use the one we sent
1283 * them */
1284 nt_username = sent_nt_username;
1287 nt_domain = talloc_strdup(mem_ctx, info3->base.domain.string);
1288 if (!nt_domain) {
1289 /* If the server didn't give us one, just use the one we sent
1290 * them */
1291 nt_domain = domain;
1294 /* If getpwnam() fails try the add user script (2.2.x behavior).
1296 We use the _unmapped_ username here in an attempt to provide
1297 consistent username mapping behavior between kerberos and NTLM[SSP]
1298 authentication in domain mode security. I.E. Username mapping
1299 should be applied to the fully qualified username
1300 (e.g. DOMAIN\user) and not just the login name. Yes this means we
1301 called map_username() unnecessarily in make_user_info_map() but
1302 that is how the current code is designed. Making the change here
1303 is the least disruptive place. -- jerry */
1305 /* this call will try to create the user if necessary */
1307 nt_status = check_account(mem_ctx, nt_domain, sent_nt_username,
1308 &found_username, &pwd,
1309 &username_was_mapped);
1311 if (!NT_STATUS_IS_OK(nt_status)) {
1312 return nt_status;
1315 result = make_server_info(NULL);
1316 if (result == NULL) {
1317 DEBUG(4, ("make_server_info failed!\n"));
1318 return NT_STATUS_NO_MEMORY;
1321 result->unix_name = talloc_strdup(result, found_username);
1323 result->sanitized_username = sanitize_username(result,
1324 result->unix_name);
1325 if (result->sanitized_username == NULL) {
1326 TALLOC_FREE(result);
1327 return NT_STATUS_NO_MEMORY;
1330 /* copy in the info3 */
1331 result->info3 = copy_netr_SamInfo3(result, info3);
1332 if (result->info3 == NULL) {
1333 TALLOC_FREE(result);
1334 return NT_STATUS_NO_MEMORY;
1337 /* Fill in the unix info we found on the way */
1339 result->utok.uid = pwd->pw_uid;
1340 result->utok.gid = pwd->pw_gid;
1342 /* ensure we are never given NULL session keys */
1344 if (memcmp(info3->base.key.key, zeros, sizeof(zeros)) == 0) {
1345 result->user_session_key = data_blob_null;
1346 } else {
1347 result->user_session_key = data_blob_talloc(
1348 result, info3->base.key.key,
1349 sizeof(info3->base.key.key));
1352 if (memcmp(info3->base.LMSessKey.key, zeros, 8) == 0) {
1353 result->lm_session_key = data_blob_null;
1354 } else {
1355 result->lm_session_key = data_blob_talloc(
1356 result, info3->base.LMSessKey.key,
1357 sizeof(info3->base.LMSessKey.key));
1360 result->nss_token |= username_was_mapped;
1362 *server_info = result;
1364 return NT_STATUS_OK;
1367 /*****************************************************************************
1368 Make a server_info struct from the wbcAuthUserInfo returned by a domain logon
1369 ******************************************************************************/
1371 NTSTATUS make_server_info_wbcAuthUserInfo(TALLOC_CTX *mem_ctx,
1372 const char *sent_nt_username,
1373 const char *domain,
1374 const struct wbcAuthUserInfo *info,
1375 struct auth_serversupplied_info **server_info)
1377 struct netr_SamInfo3 *info3;
1379 info3 = wbcAuthUserInfo_to_netr_SamInfo3(mem_ctx, info);
1380 if (!info3) {
1381 return NT_STATUS_NO_MEMORY;
1384 return make_server_info_info3(mem_ctx,
1385 sent_nt_username, domain,
1386 server_info, info3);
1390 * Verify whether or not given domain is trusted.
1392 * @param domain_name name of the domain to be verified
1393 * @return true if domain is one of the trusted ones or
1394 * false if otherwise
1397 bool is_trusted_domain(const char* dom_name)
1399 struct dom_sid trustdom_sid;
1400 bool ret;
1402 /* no trusted domains for a standalone server */
1404 if ( lp_server_role() == ROLE_STANDALONE )
1405 return False;
1407 if (dom_name == NULL || dom_name[0] == '\0') {
1408 return false;
1411 if (strequal(dom_name, get_global_sam_name())) {
1412 return false;
1415 /* if we are a DC, then check for a direct trust relationships */
1417 if ( IS_DC ) {
1418 become_root();
1419 DEBUG (5,("is_trusted_domain: Checking for domain trust with "
1420 "[%s]\n", dom_name ));
1421 ret = pdb_get_trusteddom_pw(dom_name, NULL, NULL, NULL);
1422 unbecome_root();
1423 if (ret)
1424 return True;
1426 else {
1427 wbcErr result;
1429 /* If winbind is around, ask it */
1431 result = wb_is_trusted_domain(dom_name);
1433 if (result == WBC_ERR_SUCCESS) {
1434 return True;
1437 if (result == WBC_ERR_DOMAIN_NOT_FOUND) {
1438 /* winbind could not find the domain */
1439 return False;
1442 /* The only other possible result is that winbind is not up
1443 and running. We need to update the trustdom_cache
1444 ourselves */
1446 update_trustdom_cache();
1449 /* now the trustdom cache should be available a DC could still
1450 * have a transitive trust so fall back to the cache of trusted
1451 * domains (like a domain member would use */
1453 if ( trustdom_cache_fetch(dom_name, &trustdom_sid) ) {
1454 return True;
1457 return False;