s4/test: Run DrsDeleteObjectTestCase as part of S4 testing
[Samba.git] / source3 / auth / auth_util.c
blob837e58bb84a0689fffdcf6f96eaa9df1fae455b1
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 if (!uid_to_unix_users_sid(server_info->utok.uid, &tmp_sid)) {
502 DEBUG(1,("create_local_token: Failed to create SID "
503 "for uid %u!\n", (unsigned int)server_info->utok.uid));
505 add_sid_to_array_unique(server_info->ptok, &tmp_sid,
506 &server_info->ptok->user_sids,
507 &server_info->ptok->num_sids);
509 for ( i=0; i<server_info->utok.ngroups; i++ ) {
510 if (!gid_to_unix_groups_sid( server_info->utok.groups[i], &tmp_sid ) ) {
511 DEBUG(1,("create_local_token: Failed to create SID "
512 "for gid %u!\n", (unsigned int)server_info->utok.groups[i]));
513 continue;
515 add_sid_to_array_unique(server_info->ptok, &tmp_sid,
516 &server_info->ptok->user_sids,
517 &server_info->ptok->num_sids);
520 debug_nt_user_token(DBGC_AUTH, 10, server_info->ptok);
521 debug_unix_user_token(DBGC_AUTH, 10,
522 server_info->utok.uid,
523 server_info->utok.gid,
524 server_info->utok.ngroups,
525 server_info->utok.groups);
527 status = log_nt_token(server_info->ptok);
528 return status;
531 /***************************************************************************
532 Make (and fill) a server_info struct from a 'struct passwd' by conversion
533 to a struct samu
534 ***************************************************************************/
536 NTSTATUS make_server_info_pw(struct auth_serversupplied_info **server_info,
537 char *unix_username,
538 struct passwd *pwd)
540 NTSTATUS status;
541 struct samu *sampass = NULL;
542 char *qualified_name = NULL;
543 TALLOC_CTX *mem_ctx = NULL;
544 struct dom_sid u_sid;
545 enum lsa_SidType type;
546 struct auth_serversupplied_info *result;
549 * The SID returned in server_info->sam_account is based
550 * on our SAM sid even though for a pure UNIX account this should
551 * not be the case as it doesn't really exist in the SAM db.
552 * This causes lookups on "[in]valid users" to fail as they
553 * will lookup this name as a "Unix User" SID to check against
554 * the user token. Fix this by adding the "Unix User"\unix_username
555 * SID to the sid array. The correct fix should probably be
556 * changing the server_info->sam_account user SID to be a
557 * S-1-22 Unix SID, but this might break old configs where
558 * plaintext passwords were used with no SAM backend.
561 mem_ctx = talloc_init("make_server_info_pw_tmp");
562 if (!mem_ctx) {
563 return NT_STATUS_NO_MEMORY;
566 qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
567 unix_users_domain_name(),
568 unix_username );
569 if (!qualified_name) {
570 TALLOC_FREE(mem_ctx);
571 return NT_STATUS_NO_MEMORY;
574 if (!lookup_name(mem_ctx, qualified_name, LOOKUP_NAME_ALL,
575 NULL, NULL,
576 &u_sid, &type)) {
577 TALLOC_FREE(mem_ctx);
578 return NT_STATUS_NO_SUCH_USER;
581 TALLOC_FREE(mem_ctx);
583 if (type != SID_NAME_USER) {
584 return NT_STATUS_NO_SUCH_USER;
587 if ( !(sampass = samu_new( NULL )) ) {
588 return NT_STATUS_NO_MEMORY;
591 status = samu_set_unix( sampass, pwd );
592 if (!NT_STATUS_IS_OK(status)) {
593 return status;
596 /* In pathological cases the above call can set the account
597 * name to the DOMAIN\username form. Reset the account name
598 * using unix_username */
599 pdb_set_username(sampass, unix_username, PDB_SET);
601 /* set the user sid to be the calculated u_sid */
602 pdb_set_user_sid(sampass, &u_sid, PDB_SET);
604 result = make_server_info(NULL);
605 if (result == NULL) {
606 TALLOC_FREE(sampass);
607 return NT_STATUS_NO_MEMORY;
610 status = samu_to_SamInfo3(result, sampass, global_myname(),
611 &result->info3, &result->extra);
612 if (!NT_STATUS_IS_OK(status)) {
613 DEBUG(10, ("Failed to convert samu to info3: %s\n",
614 nt_errstr(status)));
615 TALLOC_FREE(sampass);
616 TALLOC_FREE(result);
617 return status;
620 TALLOC_FREE(sampass);
622 result->unix_name = talloc_strdup(result, unix_username);
623 result->sanitized_username = sanitize_username(result, unix_username);
625 if ((result->unix_name == NULL)
626 || (result->sanitized_username == NULL)) {
627 TALLOC_FREE(result);
628 return NT_STATUS_NO_MEMORY;
631 result->utok.uid = pwd->pw_uid;
632 result->utok.gid = pwd->pw_gid;
634 *server_info = result;
636 return NT_STATUS_OK;
639 /***************************************************************************
640 Make (and fill) a user_info struct for a guest login.
641 This *must* succeed for smbd to start. If there is no mapping entry for
642 the guest gid, then create one.
643 ***************************************************************************/
645 static NTSTATUS make_new_server_info_guest(struct auth_serversupplied_info **server_info)
647 NTSTATUS status;
648 struct samu *sampass = NULL;
649 struct dom_sid guest_sid;
650 bool ret;
651 static const char zeros[16] = {0, };
652 fstring tmp;
654 if ( !(sampass = samu_new( NULL )) ) {
655 return NT_STATUS_NO_MEMORY;
658 sid_compose(&guest_sid, get_global_sam_sid(), DOMAIN_RID_GUEST);
660 become_root();
661 ret = pdb_getsampwsid(sampass, &guest_sid);
662 unbecome_root();
664 if (!ret) {
665 TALLOC_FREE(sampass);
666 return NT_STATUS_NO_SUCH_USER;
669 status = make_server_info_sam(server_info, sampass);
670 if (!NT_STATUS_IS_OK(status)) {
671 TALLOC_FREE(sampass);
672 return status;
675 TALLOC_FREE(sampass);
677 (*server_info)->guest = True;
679 status = create_local_token(*server_info);
680 if (!NT_STATUS_IS_OK(status)) {
681 DEBUG(10, ("create_local_token failed: %s\n",
682 nt_errstr(status)));
683 return status;
686 /* annoying, but the Guest really does have a session key, and it is
687 all zeros! */
688 (*server_info)->user_session_key = data_blob(zeros, sizeof(zeros));
689 (*server_info)->lm_session_key = data_blob(zeros, sizeof(zeros));
691 alpha_strcpy(tmp, (*server_info)->info3->base.account_name.string,
692 ". _-$", sizeof(tmp));
693 (*server_info)->sanitized_username = talloc_strdup(*server_info, tmp);
695 return NT_STATUS_OK;
698 /***************************************************************************
699 Make (and fill) a user_info struct for a system user login.
700 This *must* succeed for smbd to start.
701 ***************************************************************************/
703 static NTSTATUS make_new_server_info_system(TALLOC_CTX *mem_ctx,
704 struct auth_serversupplied_info **server_info)
706 struct passwd *pwd;
707 NTSTATUS status;
709 pwd = getpwuid_alloc(mem_ctx, sec_initial_uid());
710 if (pwd == NULL) {
711 return NT_STATUS_NO_MEMORY;
714 status = make_serverinfo_from_username(mem_ctx,
715 pwd->pw_name,
716 false,
717 server_info);
718 if (!NT_STATUS_IS_OK(status)) {
719 return status;
722 (*server_info)->system = true;
724 return NT_STATUS_OK;
727 /****************************************************************************
728 Fake a auth_serversupplied_info just from a username
729 ****************************************************************************/
731 NTSTATUS make_serverinfo_from_username(TALLOC_CTX *mem_ctx,
732 const char *username,
733 bool is_guest,
734 struct auth_serversupplied_info **presult)
736 struct auth_serversupplied_info *result;
737 struct passwd *pwd;
738 NTSTATUS status;
740 pwd = getpwnam_alloc(talloc_tos(), username);
741 if (pwd == NULL) {
742 return NT_STATUS_NO_SUCH_USER;
745 status = make_server_info_pw(&result, pwd->pw_name, pwd);
747 TALLOC_FREE(pwd);
749 if (!NT_STATUS_IS_OK(status)) {
750 return status;
753 result->nss_token = true;
754 result->guest = is_guest;
756 status = create_local_token(result);
758 if (!NT_STATUS_IS_OK(status)) {
759 TALLOC_FREE(result);
760 return status;
763 *presult = result;
764 return NT_STATUS_OK;
768 struct auth_serversupplied_info *copy_serverinfo(TALLOC_CTX *mem_ctx,
769 const struct auth_serversupplied_info *src)
771 struct auth_serversupplied_info *dst;
773 dst = make_server_info(mem_ctx);
774 if (dst == NULL) {
775 return NULL;
778 dst->guest = src->guest;
779 dst->system = src->system;
780 dst->utok.uid = src->utok.uid;
781 dst->utok.gid = src->utok.gid;
782 dst->utok.ngroups = src->utok.ngroups;
783 if (src->utok.ngroups != 0) {
784 dst->utok.groups = (gid_t *)TALLOC_MEMDUP(
785 dst, src->utok.groups,
786 sizeof(gid_t)*dst->utok.ngroups);
787 } else {
788 dst->utok.groups = NULL;
791 if (src->ptok) {
792 dst->ptok = dup_nt_token(dst, src->ptok);
793 if (!dst->ptok) {
794 TALLOC_FREE(dst);
795 return NULL;
799 dst->user_session_key = data_blob_talloc( dst, src->user_session_key.data,
800 src->user_session_key.length);
802 dst->lm_session_key = data_blob_talloc(dst, src->lm_session_key.data,
803 src->lm_session_key.length);
805 dst->info3 = copy_netr_SamInfo3(dst, src->info3);
806 if (!dst->info3) {
807 TALLOC_FREE(dst);
808 return NULL;
810 dst->extra = src->extra;
812 dst->pam_handle = NULL;
813 dst->unix_name = talloc_strdup(dst, src->unix_name);
814 if (!dst->unix_name) {
815 TALLOC_FREE(dst);
816 return NULL;
819 dst->sanitized_username = talloc_strdup(dst, src->sanitized_username);
820 if (!dst->sanitized_username) {
821 TALLOC_FREE(dst);
822 return NULL;
825 return dst;
829 * Set a new session key. Used in the rpc server where we have to override the
830 * SMB level session key with SystemLibraryDTC
833 bool server_info_set_session_key(struct auth_serversupplied_info *info,
834 DATA_BLOB session_key)
836 TALLOC_FREE(info->user_session_key.data);
838 info->user_session_key = data_blob_talloc(
839 info, session_key.data, session_key.length);
841 return (info->user_session_key.data != NULL);
844 static struct auth_serversupplied_info *guest_info = NULL;
846 bool init_guest_info(void)
848 if (guest_info != NULL)
849 return True;
851 return NT_STATUS_IS_OK(make_new_server_info_guest(&guest_info));
854 NTSTATUS make_server_info_guest(TALLOC_CTX *mem_ctx,
855 struct auth_serversupplied_info **server_info)
857 *server_info = copy_serverinfo(mem_ctx, guest_info);
858 return (*server_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
861 static struct auth_serversupplied_info *system_info = NULL;
863 bool init_system_info(void)
865 if (system_info != NULL)
866 return True;
868 return NT_STATUS_IS_OK(make_new_server_info_system(talloc_autofree_context(), &system_info));
871 NTSTATUS make_server_info_system(TALLOC_CTX *mem_ctx,
872 struct auth_serversupplied_info **server_info)
874 if (system_info == NULL) return NT_STATUS_UNSUCCESSFUL;
875 *server_info = copy_serverinfo(mem_ctx, system_info);
876 return (*server_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
879 bool copy_current_user(struct current_user *dst, struct current_user *src)
881 gid_t *groups;
882 NT_USER_TOKEN *nt_token;
884 groups = (gid_t *)memdup(src->ut.groups,
885 sizeof(gid_t) * src->ut.ngroups);
886 if ((src->ut.ngroups != 0) && (groups == NULL)) {
887 return False;
890 nt_token = dup_nt_token(NULL, src->nt_user_token);
891 if (nt_token == NULL) {
892 SAFE_FREE(groups);
893 return False;
896 dst->conn = src->conn;
897 dst->vuid = src->vuid;
898 dst->ut.uid = src->ut.uid;
899 dst->ut.gid = src->ut.gid;
900 dst->ut.ngroups = src->ut.ngroups;
901 dst->ut.groups = groups;
902 dst->nt_user_token = nt_token;
903 return True;
906 /***************************************************************************
907 Purely internal function for make_server_info_info3
908 ***************************************************************************/
910 static NTSTATUS check_account(TALLOC_CTX *mem_ctx, const char *domain,
911 const char *username, char **found_username,
912 struct passwd **pwd,
913 bool *username_was_mapped)
915 fstring dom_user, lower_username;
916 fstring real_username;
917 struct passwd *passwd;
919 fstrcpy( lower_username, username );
920 strlower_m( lower_username );
922 fstr_sprintf(dom_user, "%s%c%s", domain, *lp_winbind_separator(),
923 lower_username);
925 /* Get the passwd struct. Try to create the account if necessary. */
927 *username_was_mapped = map_username(dom_user);
929 passwd = smb_getpwnam( NULL, dom_user, real_username, True );
930 if (!passwd) {
931 DEBUG(3, ("Failed to find authenticated user %s via "
932 "getpwnam(), denying access.\n", dom_user));
933 return NT_STATUS_NO_SUCH_USER;
936 *pwd = passwd;
938 /* This is pointless -- there is no suport for differing
939 unix and windows names. Make sure to always store the
940 one we actually looked up and succeeded. Have I mentioned
941 why I hate the 'winbind use default domain' parameter?
942 --jerry */
944 *found_username = talloc_strdup( mem_ctx, real_username );
946 return NT_STATUS_OK;
949 /****************************************************************************
950 Wrapper to allow the getpwnam() call to strip the domain name and
951 try again in case a local UNIX user is already there. Also run through
952 the username if we fallback to the username only.
953 ****************************************************************************/
955 struct passwd *smb_getpwnam( TALLOC_CTX *mem_ctx, char *domuser,
956 fstring save_username, bool create )
958 struct passwd *pw = NULL;
959 char *p;
960 fstring username;
962 /* we only save a copy of the username it has been mangled
963 by winbindd use default domain */
965 save_username[0] = '\0';
967 /* don't call map_username() here since it has to be done higher
968 up the stack so we don't call it multiple times */
970 fstrcpy( username, domuser );
972 p = strchr_m( username, *lp_winbind_separator() );
974 /* code for a DOMAIN\user string */
976 if ( p ) {
977 fstring strip_username;
979 pw = Get_Pwnam_alloc( mem_ctx, domuser );
980 if ( pw ) {
981 /* make sure we get the case of the username correct */
982 /* work around 'winbind use default domain = yes' */
984 if ( !strchr_m( pw->pw_name, *lp_winbind_separator() ) ) {
985 char *domain;
987 /* split the domain and username into 2 strings */
988 *p = '\0';
989 domain = username;
991 fstr_sprintf(save_username, "%s%c%s", domain, *lp_winbind_separator(), pw->pw_name);
993 else
994 fstrcpy( save_username, pw->pw_name );
996 /* whew -- done! */
997 return pw;
1000 /* setup for lookup of just the username */
1001 /* remember that p and username are overlapping memory */
1003 p++;
1004 fstrcpy( strip_username, p );
1005 fstrcpy( username, strip_username );
1008 /* just lookup a plain username */
1010 pw = Get_Pwnam_alloc(mem_ctx, username);
1012 /* Create local user if requested but only if winbindd
1013 is not running. We need to protect against cases
1014 where winbindd is failing and then prematurely
1015 creating users in /etc/passwd */
1017 if ( !pw && create && !winbind_ping() ) {
1018 /* Don't add a machine account. */
1019 if (username[strlen(username)-1] == '$')
1020 return NULL;
1022 _smb_create_user(NULL, username, NULL);
1023 pw = Get_Pwnam_alloc(mem_ctx, username);
1026 /* one last check for a valid passwd struct */
1028 if ( pw )
1029 fstrcpy( save_username, pw->pw_name );
1031 return pw;
1034 /***************************************************************************
1035 Make a server_info struct from the info3 returned by a domain logon
1036 ***************************************************************************/
1038 NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
1039 const char *sent_nt_username,
1040 const char *domain,
1041 struct auth_serversupplied_info **server_info,
1042 struct netr_SamInfo3 *info3)
1044 static const char zeros[16] = {0, };
1046 NTSTATUS nt_status = NT_STATUS_OK;
1047 char *found_username = NULL;
1048 const char *nt_domain;
1049 const char *nt_username;
1050 bool username_was_mapped;
1051 struct passwd *pwd;
1052 struct auth_serversupplied_info *result;
1053 struct dom_sid *group_sid;
1054 struct netr_SamInfo3 *i3;
1057 Here is where we should check the list of
1058 trusted domains, and verify that the SID
1059 matches.
1062 nt_username = talloc_strdup(mem_ctx, info3->base.account_name.string);
1063 if (!nt_username) {
1064 /* If the server didn't give us one, just use the one we sent
1065 * them */
1066 nt_username = sent_nt_username;
1069 nt_domain = talloc_strdup(mem_ctx, info3->base.domain.string);
1070 if (!nt_domain) {
1071 /* If the server didn't give us one, just use the one we sent
1072 * them */
1073 nt_domain = domain;
1076 /* If getpwnam() fails try the add user script (2.2.x behavior).
1078 We use the _unmapped_ username here in an attempt to provide
1079 consistent username mapping behavior between kerberos and NTLM[SSP]
1080 authentication in domain mode security. I.E. Username mapping
1081 should be applied to the fully qualified username
1082 (e.g. DOMAIN\user) and not just the login name. Yes this means we
1083 called map_username() unnecessarily in make_user_info_map() but
1084 that is how the current code is designed. Making the change here
1085 is the least disruptive place. -- jerry */
1087 /* this call will try to create the user if necessary */
1089 nt_status = check_account(mem_ctx, nt_domain, sent_nt_username,
1090 &found_username, &pwd,
1091 &username_was_mapped);
1093 if (!NT_STATUS_IS_OK(nt_status)) {
1094 return nt_status;
1097 result = make_server_info(NULL);
1098 if (result == NULL) {
1099 DEBUG(4, ("make_server_info failed!\n"));
1100 return NT_STATUS_NO_MEMORY;
1103 result->unix_name = talloc_strdup(result, found_username);
1105 result->sanitized_username = sanitize_username(result,
1106 result->unix_name);
1107 if (result->sanitized_username == NULL) {
1108 TALLOC_FREE(result);
1109 return NT_STATUS_NO_MEMORY;
1112 /* copy in the info3 */
1113 result->info3 = i3 = copy_netr_SamInfo3(result, info3);
1114 if (result->info3 == NULL) {
1115 TALLOC_FREE(result);
1116 return NT_STATUS_NO_MEMORY;
1119 /* Fill in the unix info we found on the way */
1120 result->utok.uid = pwd->pw_uid;
1121 result->utok.gid = pwd->pw_gid;
1123 /* We can't just trust that the primary group sid sent us is something
1124 * we can really use. Obtain the useable sid, and store the original
1125 * one as an additional group if it had to be replaced */
1126 nt_status = get_primary_group_sid(mem_ctx, found_username,
1127 &pwd, &group_sid);
1128 if (!NT_STATUS_IS_OK(nt_status)) {
1129 TALLOC_FREE(result);
1130 return nt_status;
1133 /* store and check if it is the same we got originally */
1134 sid_peek_rid(group_sid, &i3->base.primary_gid);
1135 if (i3->base.primary_gid != info3->base.primary_gid) {
1136 uint32_t n = i3->base.groups.count;
1137 /* not the same, store the original as an additional group */
1138 i3->base.groups.rids =
1139 talloc_realloc(i3, i3->base.groups.rids,
1140 struct samr_RidWithAttribute, n + 1);
1141 if (i3->base.groups.rids == NULL) {
1142 TALLOC_FREE(result);
1143 return NT_STATUS_NO_MEMORY;
1145 i3->base.groups.rids[n].rid = info3->base.primary_gid;
1146 i3->base.groups.rids[n].attributes = SE_GROUP_ENABLED;
1147 i3->base.groups.count = n + 1;
1150 /* ensure we are never given NULL session keys */
1152 if (memcmp(info3->base.key.key, zeros, sizeof(zeros)) == 0) {
1153 result->user_session_key = data_blob_null;
1154 } else {
1155 result->user_session_key = data_blob_talloc(
1156 result, info3->base.key.key,
1157 sizeof(info3->base.key.key));
1160 if (memcmp(info3->base.LMSessKey.key, zeros, 8) == 0) {
1161 result->lm_session_key = data_blob_null;
1162 } else {
1163 result->lm_session_key = data_blob_talloc(
1164 result, info3->base.LMSessKey.key,
1165 sizeof(info3->base.LMSessKey.key));
1168 result->nss_token |= username_was_mapped;
1170 *server_info = result;
1172 return NT_STATUS_OK;
1175 /*****************************************************************************
1176 Make a server_info struct from the wbcAuthUserInfo returned by a domain logon
1177 ******************************************************************************/
1179 NTSTATUS make_server_info_wbcAuthUserInfo(TALLOC_CTX *mem_ctx,
1180 const char *sent_nt_username,
1181 const char *domain,
1182 const struct wbcAuthUserInfo *info,
1183 struct auth_serversupplied_info **server_info)
1185 struct netr_SamInfo3 *info3;
1187 info3 = wbcAuthUserInfo_to_netr_SamInfo3(mem_ctx, info);
1188 if (!info3) {
1189 return NT_STATUS_NO_MEMORY;
1192 return make_server_info_info3(mem_ctx,
1193 sent_nt_username, domain,
1194 server_info, info3);
1198 * Verify whether or not given domain is trusted.
1200 * @param domain_name name of the domain to be verified
1201 * @return true if domain is one of the trusted ones or
1202 * false if otherwise
1205 bool is_trusted_domain(const char* dom_name)
1207 struct dom_sid trustdom_sid;
1208 bool ret;
1210 /* no trusted domains for a standalone server */
1212 if ( lp_server_role() == ROLE_STANDALONE )
1213 return False;
1215 if (dom_name == NULL || dom_name[0] == '\0') {
1216 return false;
1219 if (strequal(dom_name, get_global_sam_name())) {
1220 return false;
1223 /* if we are a DC, then check for a direct trust relationships */
1225 if ( IS_DC ) {
1226 become_root();
1227 DEBUG (5,("is_trusted_domain: Checking for domain trust with "
1228 "[%s]\n", dom_name ));
1229 ret = pdb_get_trusteddom_pw(dom_name, NULL, NULL, NULL);
1230 unbecome_root();
1231 if (ret)
1232 return True;
1234 else {
1235 wbcErr result;
1237 /* If winbind is around, ask it */
1239 result = wb_is_trusted_domain(dom_name);
1241 if (result == WBC_ERR_SUCCESS) {
1242 return True;
1245 if (result == WBC_ERR_DOMAIN_NOT_FOUND) {
1246 /* winbind could not find the domain */
1247 return False;
1250 /* The only other possible result is that winbind is not up
1251 and running. We need to update the trustdom_cache
1252 ourselves */
1254 update_trustdom_cache();
1257 /* now the trustdom cache should be available a DC could still
1258 * have a transitive trust so fall back to the cache of trusted
1259 * domains (like a domain member would use */
1261 if ( trustdom_cache_fetch(dom_name, &trustdom_sid) ) {
1262 return True;
1265 return False;