s3-auth reimplement copy_session_info via NDR pull/push
[Samba/gebeck_regimport.git] / source3 / auth / auth_util.c
blobeb804c5f13b5985281d8b6e1ab23b2b9b9d5a875
1 /*
2 Unix SMB/CIFS implementation.
3 Authentication utility functions
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001-2011
6 Copyright (C) Jeremy Allison 2000-2001
7 Copyright (C) Rafal Szczesniak 2002
8 Copyright (C) Volker Lendecke 2006-2008
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "includes.h"
25 #include "auth.h"
26 #include "../libcli/auth/libcli_auth.h"
27 #include "../lib/crypto/arcfour.h"
28 #include "rpc_client/init_lsa.h"
29 #include "../libcli/security/security.h"
30 #include "../lib/util/util_pw.h"
31 #include "lib/winbind_util.h"
32 #include "passdb.h"
33 #include "../librpc/gen_ndr/ndr_auth.h"
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 const struct tsocket_address *remote_address,
94 DATA_BLOB *lm_pwd,
95 DATA_BLOB *nt_pwd,
96 const struct samr_Password *lm_interactive_pwd,
97 const struct samr_Password *nt_interactive_pwd,
98 const char *plaintext,
99 enum auth_password_state password_state)
101 const char *domain;
102 NTSTATUS result;
103 bool was_mapped;
104 char *internal_username = NULL;
106 was_mapped = map_username(talloc_tos(), smb_name, &internal_username);
107 if (!internal_username) {
108 return NT_STATUS_NO_MEMORY;
111 DEBUG(5, ("Mapping user [%s]\\[%s] from workstation [%s]\n",
112 client_domain, smb_name, workstation_name));
114 domain = client_domain;
116 /* If you connect to a Windows domain member using a bogus domain name,
117 * the Windows box will map the BOGUS\user to SAMNAME\user. Thus, if
118 * the Windows box is a DC the name will become DOMAIN\user and be
119 * authenticated against AD, if the Windows box is a member server but
120 * not a DC the name will become WORKSTATION\user. A standalone
121 * non-domain member box will also map to WORKSTATION\user.
122 * This also deals with the client passing in a "" domain */
124 if (!is_trusted_domain(domain) &&
125 !strequal(domain, my_sam_name()))
127 if (lp_map_untrusted_to_domain())
128 domain = my_sam_name();
129 else
130 domain = get_global_sam_name();
131 DEBUG(5, ("Mapped domain from [%s] to [%s] for user [%s] from "
132 "workstation [%s]\n",
133 client_domain, domain, smb_name, workstation_name));
136 /* We know that the given domain is trusted (and we are allowing them),
137 * it is our global SAM name, or for legacy behavior it is our
138 * primary domain name */
140 result = make_user_info(user_info, smb_name, internal_username,
141 client_domain, domain, workstation_name,
142 remote_address, lm_pwd, nt_pwd,
143 lm_interactive_pwd, nt_interactive_pwd,
144 plaintext, password_state);
145 if (NT_STATUS_IS_OK(result)) {
146 /* We have tried mapping */
147 (*user_info)->mapped_state = True;
148 /* did we actually map the user to a different name? */
149 (*user_info)->was_mapped = was_mapped;
151 return result;
154 /****************************************************************************
155 Create an auth_usersupplied_data, making the DATA_BLOBs here.
156 Decrypt and encrypt the passwords.
157 ****************************************************************************/
159 bool make_user_info_netlogon_network(struct auth_usersupplied_info **user_info,
160 const char *smb_name,
161 const char *client_domain,
162 const char *workstation_name,
163 const struct tsocket_address *remote_address,
164 uint32 logon_parameters,
165 const uchar *lm_network_pwd,
166 int lm_pwd_len,
167 const uchar *nt_network_pwd,
168 int nt_pwd_len)
170 bool ret;
171 NTSTATUS status;
172 DATA_BLOB lm_blob = data_blob(lm_network_pwd, lm_pwd_len);
173 DATA_BLOB nt_blob = data_blob(nt_network_pwd, nt_pwd_len);
175 status = make_user_info_map(user_info,
176 smb_name, client_domain,
177 workstation_name,
178 remote_address,
179 lm_pwd_len ? &lm_blob : NULL,
180 nt_pwd_len ? &nt_blob : NULL,
181 NULL, NULL, NULL,
182 AUTH_PASSWORD_RESPONSE);
184 if (NT_STATUS_IS_OK(status)) {
185 (*user_info)->logon_parameters = logon_parameters;
187 ret = NT_STATUS_IS_OK(status) ? True : False;
189 data_blob_free(&lm_blob);
190 data_blob_free(&nt_blob);
191 return ret;
194 /****************************************************************************
195 Create an auth_usersupplied_data, making the DATA_BLOBs here.
196 Decrypt and encrypt the passwords.
197 ****************************************************************************/
199 bool make_user_info_netlogon_interactive(struct auth_usersupplied_info **user_info,
200 const char *smb_name,
201 const char *client_domain,
202 const char *workstation_name,
203 const struct tsocket_address *remote_address,
204 uint32 logon_parameters,
205 const uchar chal[8],
206 const uchar lm_interactive_pwd[16],
207 const uchar nt_interactive_pwd[16],
208 const uchar *dc_sess_key)
210 struct samr_Password lm_pwd;
211 struct samr_Password nt_pwd;
212 unsigned char local_lm_response[24];
213 unsigned char local_nt_response[24];
214 unsigned char key[16];
216 memcpy(key, dc_sess_key, 16);
218 if (lm_interactive_pwd)
219 memcpy(lm_pwd.hash, lm_interactive_pwd, sizeof(lm_pwd.hash));
221 if (nt_interactive_pwd)
222 memcpy(nt_pwd.hash, nt_interactive_pwd, sizeof(nt_pwd.hash));
224 #ifdef DEBUG_PASSWORD
225 DEBUG(100,("key:"));
226 dump_data(100, key, sizeof(key));
228 DEBUG(100,("lm owf password:"));
229 dump_data(100, lm_pwd.hash, sizeof(lm_pwd.hash));
231 DEBUG(100,("nt owf password:"));
232 dump_data(100, nt_pwd.hash, sizeof(nt_pwd.hash));
233 #endif
235 if (lm_interactive_pwd)
236 arcfour_crypt(lm_pwd.hash, key, sizeof(lm_pwd.hash));
238 if (nt_interactive_pwd)
239 arcfour_crypt(nt_pwd.hash, key, sizeof(nt_pwd.hash));
241 #ifdef DEBUG_PASSWORD
242 DEBUG(100,("decrypt of lm owf password:"));
243 dump_data(100, lm_pwd.hash, sizeof(lm_pwd));
245 DEBUG(100,("decrypt of nt owf password:"));
246 dump_data(100, nt_pwd.hash, sizeof(nt_pwd));
247 #endif
249 if (lm_interactive_pwd)
250 SMBOWFencrypt(lm_pwd.hash, chal,
251 local_lm_response);
253 if (nt_interactive_pwd)
254 SMBOWFencrypt(nt_pwd.hash, chal,
255 local_nt_response);
257 /* Password info paranoia */
258 ZERO_STRUCT(key);
261 bool ret;
262 NTSTATUS nt_status;
263 DATA_BLOB local_lm_blob;
264 DATA_BLOB local_nt_blob;
266 if (lm_interactive_pwd) {
267 local_lm_blob = data_blob(local_lm_response,
268 sizeof(local_lm_response));
271 if (nt_interactive_pwd) {
272 local_nt_blob = data_blob(local_nt_response,
273 sizeof(local_nt_response));
276 nt_status = make_user_info_map(
277 user_info,
278 smb_name, client_domain, workstation_name,
279 remote_address,
280 lm_interactive_pwd ? &local_lm_blob : NULL,
281 nt_interactive_pwd ? &local_nt_blob : NULL,
282 lm_interactive_pwd ? &lm_pwd : NULL,
283 nt_interactive_pwd ? &nt_pwd : NULL,
284 NULL, AUTH_PASSWORD_HASH);
286 if (NT_STATUS_IS_OK(nt_status)) {
287 (*user_info)->logon_parameters = logon_parameters;
290 ret = NT_STATUS_IS_OK(nt_status) ? True : False;
291 data_blob_free(&local_lm_blob);
292 data_blob_free(&local_nt_blob);
293 return ret;
298 /****************************************************************************
299 Create an auth_usersupplied_data structure
300 ****************************************************************************/
302 bool make_user_info_for_reply(struct auth_usersupplied_info **user_info,
303 const char *smb_name,
304 const char *client_domain,
305 const struct tsocket_address *remote_address,
306 const uint8 chal[8],
307 DATA_BLOB plaintext_password)
310 DATA_BLOB local_lm_blob;
311 DATA_BLOB local_nt_blob;
312 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
313 char *plaintext_password_string;
315 * Not encrypted - do so.
318 DEBUG(5,("make_user_info_for_reply: User passwords not in encrypted "
319 "format.\n"));
320 if (plaintext_password.data && plaintext_password.length) {
321 unsigned char local_lm_response[24];
323 #ifdef DEBUG_PASSWORD
324 DEBUG(10,("Unencrypted password (len %d):\n",
325 (int)plaintext_password.length));
326 dump_data(100, plaintext_password.data,
327 plaintext_password.length);
328 #endif
330 SMBencrypt( (const char *)plaintext_password.data,
331 (const uchar*)chal, local_lm_response);
332 local_lm_blob = data_blob(local_lm_response, 24);
334 /* We can't do an NT hash here, as the password needs to be
335 case insensitive */
336 local_nt_blob = data_blob_null;
337 } else {
338 local_lm_blob = data_blob_null;
339 local_nt_blob = data_blob_null;
342 plaintext_password_string = talloc_strndup(talloc_tos(),
343 (const char *)plaintext_password.data,
344 plaintext_password.length);
345 if (!plaintext_password_string) {
346 return False;
349 ret = make_user_info_map(
350 user_info, smb_name, client_domain,
351 get_remote_machine_name(),
352 remote_address,
353 local_lm_blob.data ? &local_lm_blob : NULL,
354 local_nt_blob.data ? &local_nt_blob : NULL,
355 NULL, NULL,
356 plaintext_password_string,
357 AUTH_PASSWORD_PLAIN);
359 if (plaintext_password_string) {
360 memset(plaintext_password_string, '\0', strlen(plaintext_password_string));
361 talloc_free(plaintext_password_string);
364 data_blob_free(&local_lm_blob);
365 return NT_STATUS_IS_OK(ret) ? True : False;
368 /****************************************************************************
369 Create an auth_usersupplied_data structure
370 ****************************************************************************/
372 NTSTATUS make_user_info_for_reply_enc(struct auth_usersupplied_info **user_info,
373 const char *smb_name,
374 const char *client_domain,
375 const struct tsocket_address *remote_address,
376 DATA_BLOB lm_resp, DATA_BLOB nt_resp)
378 return make_user_info_map(user_info, smb_name,
379 client_domain,
380 get_remote_machine_name(),
381 remote_address,
382 lm_resp.data && (lm_resp.length > 0) ? &lm_resp : NULL,
383 nt_resp.data && (nt_resp.length > 0) ? &nt_resp : NULL,
384 NULL, NULL, NULL,
385 AUTH_PASSWORD_RESPONSE);
388 /****************************************************************************
389 Create a guest user_info blob, for anonymous authenticaion.
390 ****************************************************************************/
392 bool make_user_info_guest(const struct tsocket_address *remote_address,
393 struct auth_usersupplied_info **user_info)
395 NTSTATUS nt_status;
397 nt_status = make_user_info(user_info,
398 "","",
399 "","",
400 "",
401 remote_address,
402 NULL, NULL,
403 NULL, NULL,
404 NULL,
405 AUTH_PASSWORD_RESPONSE);
407 return NT_STATUS_IS_OK(nt_status) ? True : False;
410 static NTSTATUS log_nt_token(struct security_token *token)
412 TALLOC_CTX *frame = talloc_stackframe();
413 char *command;
414 char *group_sidstr;
415 size_t i;
417 if ((lp_log_nt_token_command() == NULL) ||
418 (strlen(lp_log_nt_token_command()) == 0)) {
419 TALLOC_FREE(frame);
420 return NT_STATUS_OK;
423 group_sidstr = talloc_strdup(frame, "");
424 for (i=1; i<token->num_sids; i++) {
425 group_sidstr = talloc_asprintf(
426 frame, "%s %s", group_sidstr,
427 sid_string_talloc(frame, &token->sids[i]));
430 command = talloc_string_sub(
431 frame, lp_log_nt_token_command(),
432 "%s", sid_string_talloc(frame, &token->sids[0]));
433 command = talloc_string_sub(frame, command, "%t", group_sidstr);
435 if (command == NULL) {
436 TALLOC_FREE(frame);
437 return NT_STATUS_NO_MEMORY;
440 DEBUG(8, ("running command: [%s]\n", command));
441 if (smbrun(command, NULL) != 0) {
442 DEBUG(0, ("Could not log NT token\n"));
443 TALLOC_FREE(frame);
444 return NT_STATUS_ACCESS_DENIED;
447 TALLOC_FREE(frame);
448 return NT_STATUS_OK;
452 * Create the token to use from server_info->info3 and
453 * server_info->sids (the info3/sam groups). Find the unix gids.
456 NTSTATUS create_local_token(TALLOC_CTX *mem_ctx,
457 const struct auth_serversupplied_info *server_info,
458 DATA_BLOB *session_key,
459 struct auth3_session_info **session_info_out)
461 struct security_token *t;
462 NTSTATUS status;
463 size_t i;
464 struct dom_sid tmp_sid;
465 struct auth3_session_info *session_info;
466 struct wbcUnixId *ids;
468 /* Ensure we can't possible take a code path leading to a
469 * null defref. */
470 if (!server_info) {
471 return NT_STATUS_LOGON_FAILURE;
474 session_info = make_auth3_session_info(mem_ctx);
475 if (!session_info) {
476 return NT_STATUS_NO_MEMORY;
479 session_info->unix_token = talloc_zero(session_info, struct security_unix_token);
480 if (!session_info->unix_token) {
481 TALLOC_FREE(session_info);
482 return NT_STATUS_NO_MEMORY;
485 session_info->unix_token->uid = server_info->utok.uid;
486 session_info->unix_token->gid = server_info->utok.gid;
488 session_info->info3 = copy_netr_SamInfo3(session_info, server_info->info3);
489 if (!session_info->info3) {
490 TALLOC_FREE(session_info);
491 return NT_STATUS_NO_MEMORY;
494 session_info->unix_info = talloc_zero(session_info, struct auth_user_info_unix);
495 if (!session_info->unix_info) {
496 TALLOC_FREE(session_info);
497 return NT_STATUS_NO_MEMORY;
500 session_info->unix_info->unix_name = talloc_strdup(session_info, server_info->unix_name);
501 if (!session_info->unix_info->unix_name) {
502 TALLOC_FREE(session_info);
503 return NT_STATUS_NO_MEMORY;
506 session_info->unix_info->sanitized_username = talloc_strdup(session_info, server_info->sanitized_username);
507 if (!session_info->unix_info->sanitized_username) {
508 TALLOC_FREE(session_info);
509 return NT_STATUS_NO_MEMORY;
512 session_info->unix_info->guest = server_info->guest;
513 session_info->unix_info->system = server_info->system;
515 if (session_key) {
516 data_blob_free(&session_info->session_key);
517 session_info->session_key = data_blob_talloc(session_info,
518 session_key->data,
519 session_key->length);
520 if (!session_info->session_key.data && session_key->length) {
521 return NT_STATUS_NO_MEMORY;
523 } else {
524 session_info->session_key = data_blob_talloc( session_info, server_info->session_key.data,
525 server_info->session_key.length);
528 if (session_info->security_token) {
529 /* Just copy the token, it has already been finalised
530 * (nasty hack to support a cached guest session_info,
531 * and a possible strategy for auth_samba4 to pass in
532 * a finalised session) */
534 session_info->security_token = dup_nt_token(session_info, server_info->security_token);
535 if (!session_info->security_token) {
536 TALLOC_FREE(session_info);
537 return NT_STATUS_NO_MEMORY;
540 session_info->unix_token->ngroups = server_info->utok.ngroups;
541 if (server_info->utok.ngroups != 0) {
542 session_info->unix_token->groups = (gid_t *)talloc_memdup(
543 session_info->unix_token, server_info->utok.groups,
544 sizeof(gid_t)*session_info->unix_token->ngroups);
545 } else {
546 session_info->unix_token->groups = NULL;
549 *session_info_out = session_info;
550 return NT_STATUS_OK;
554 * If winbind is not around, we can not make much use of the SIDs the
555 * domain controller provided us with. Likewise if the user name was
556 * mapped to some local unix user.
559 if (((lp_server_role() == ROLE_DOMAIN_MEMBER) && !winbind_ping()) ||
560 (server_info->nss_token)) {
561 status = create_token_from_username(session_info,
562 server_info->unix_name,
563 server_info->guest,
564 &session_info->unix_token->uid,
565 &session_info->unix_token->gid,
566 &session_info->unix_info->unix_name,
567 &session_info->security_token);
569 } else {
570 status = create_local_nt_token_from_info3(session_info,
571 server_info->guest,
572 server_info->info3,
573 &server_info->extra,
574 &session_info->security_token);
577 if (!NT_STATUS_IS_OK(status)) {
578 return status;
581 /* Convert the SIDs to gids. */
583 session_info->unix_token->ngroups = 0;
584 session_info->unix_token->groups = NULL;
586 t = session_info->security_token;
588 ids = talloc_array(talloc_tos(), struct wbcUnixId,
589 t->num_sids);
590 if (ids == NULL) {
591 return NT_STATUS_NO_MEMORY;
594 if (!sids_to_unix_ids(t->sids, t->num_sids, ids)) {
595 TALLOC_FREE(ids);
596 return NT_STATUS_NO_MEMORY;
599 /* Start at index 1, where the groups start. */
601 for (i=1; i<t->num_sids; i++) {
603 if (ids[i].type != WBC_ID_TYPE_GID) {
604 DEBUG(10, ("Could not convert SID %s to gid, "
605 "ignoring it\n",
606 sid_string_dbg(&t->sids[i])));
607 continue;
609 if (!add_gid_to_array_unique(session_info, ids[i].id.gid,
610 &session_info->unix_token->groups,
611 &session_info->unix_token->ngroups)) {
612 return NT_STATUS_NO_MEMORY;
617 * Add the "Unix Group" SID for each gid to catch mapped groups
618 * and their Unix equivalent. This is to solve the backwards
619 * compatibility problem of 'valid users = +ntadmin' where
620 * ntadmin has been paired with "Domain Admins" in the group
621 * mapping table. Otherwise smb.conf would need to be changed
622 * to 'valid user = "Domain Admins"'. --jerry
624 * For consistency we also add the "Unix User" SID,
625 * so that the complete unix token is represented within
626 * the nt token.
629 uid_to_unix_users_sid(session_info->unix_token->uid, &tmp_sid);
631 add_sid_to_array_unique(session_info->security_token, &tmp_sid,
632 &session_info->security_token->sids,
633 &session_info->security_token->num_sids);
635 for ( i=0; i<session_info->unix_token->ngroups; i++ ) {
636 gid_to_unix_groups_sid(session_info->unix_token->groups[i], &tmp_sid);
637 add_sid_to_array_unique(session_info->security_token, &tmp_sid,
638 &session_info->security_token->sids,
639 &session_info->security_token->num_sids);
642 security_token_debug(DBGC_AUTH, 10, session_info->security_token);
643 debug_unix_user_token(DBGC_AUTH, 10,
644 session_info->unix_token->uid,
645 session_info->unix_token->gid,
646 session_info->unix_token->ngroups,
647 session_info->unix_token->groups);
649 status = log_nt_token(session_info->security_token);
650 if (!NT_STATUS_IS_OK(status)) {
651 return status;
654 *session_info_out = session_info;
655 return NT_STATUS_OK;
658 /***************************************************************************
659 Make (and fill) a server_info struct from a 'struct passwd' by conversion
660 to a struct samu
661 ***************************************************************************/
663 NTSTATUS make_server_info_pw(struct auth_serversupplied_info **server_info,
664 char *unix_username,
665 struct passwd *pwd)
667 NTSTATUS status;
668 struct samu *sampass = NULL;
669 char *qualified_name = NULL;
670 TALLOC_CTX *mem_ctx = NULL;
671 struct dom_sid u_sid;
672 enum lsa_SidType type;
673 struct auth_serversupplied_info *result;
676 * The SID returned in server_info->sam_account is based
677 * on our SAM sid even though for a pure UNIX account this should
678 * not be the case as it doesn't really exist in the SAM db.
679 * This causes lookups on "[in]valid users" to fail as they
680 * will lookup this name as a "Unix User" SID to check against
681 * the user token. Fix this by adding the "Unix User"\unix_username
682 * SID to the sid array. The correct fix should probably be
683 * changing the server_info->sam_account user SID to be a
684 * S-1-22 Unix SID, but this might break old configs where
685 * plaintext passwords were used with no SAM backend.
688 mem_ctx = talloc_init("make_server_info_pw_tmp");
689 if (!mem_ctx) {
690 return NT_STATUS_NO_MEMORY;
693 qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
694 unix_users_domain_name(),
695 unix_username );
696 if (!qualified_name) {
697 TALLOC_FREE(mem_ctx);
698 return NT_STATUS_NO_MEMORY;
701 if (!lookup_name(mem_ctx, qualified_name, LOOKUP_NAME_ALL,
702 NULL, NULL,
703 &u_sid, &type)) {
704 TALLOC_FREE(mem_ctx);
705 return NT_STATUS_NO_SUCH_USER;
708 TALLOC_FREE(mem_ctx);
710 if (type != SID_NAME_USER) {
711 return NT_STATUS_NO_SUCH_USER;
714 if ( !(sampass = samu_new( NULL )) ) {
715 return NT_STATUS_NO_MEMORY;
718 status = samu_set_unix( sampass, pwd );
719 if (!NT_STATUS_IS_OK(status)) {
720 return status;
723 /* In pathological cases the above call can set the account
724 * name to the DOMAIN\username form. Reset the account name
725 * using unix_username */
726 pdb_set_username(sampass, unix_username, PDB_SET);
728 /* set the user sid to be the calculated u_sid */
729 pdb_set_user_sid(sampass, &u_sid, PDB_SET);
731 result = make_server_info(NULL);
732 if (result == NULL) {
733 TALLOC_FREE(sampass);
734 return NT_STATUS_NO_MEMORY;
737 status = samu_to_SamInfo3(result, sampass, lp_netbios_name(),
738 &result->info3, &result->extra);
739 TALLOC_FREE(sampass);
740 if (!NT_STATUS_IS_OK(status)) {
741 DEBUG(10, ("Failed to convert samu to info3: %s\n",
742 nt_errstr(status)));
743 TALLOC_FREE(result);
744 return status;
747 result->unix_name = talloc_strdup(result, unix_username);
748 result->sanitized_username = sanitize_username(result, unix_username);
750 if ((result->unix_name == NULL)
751 || (result->sanitized_username == NULL)) {
752 TALLOC_FREE(result);
753 return NT_STATUS_NO_MEMORY;
756 result->utok.uid = pwd->pw_uid;
757 result->utok.gid = pwd->pw_gid;
759 *server_info = result;
761 return NT_STATUS_OK;
764 static NTSTATUS get_guest_info3(TALLOC_CTX *mem_ctx,
765 struct netr_SamInfo3 *info3)
767 const char *guest_account = lp_guestaccount();
768 struct dom_sid domain_sid;
769 struct passwd *pwd;
770 const char *tmp;
772 pwd = Get_Pwnam_alloc(mem_ctx, guest_account);
773 if (pwd == NULL) {
774 DEBUG(0,("SamInfo3_for_guest: Unable to locate guest "
775 "account [%s]!\n", guest_account));
776 return NT_STATUS_NO_SUCH_USER;
779 /* Set acount name */
780 tmp = talloc_strdup(mem_ctx, pwd->pw_name);
781 if (tmp == NULL) {
782 return NT_STATUS_NO_MEMORY;
784 init_lsa_String(&info3->base.account_name, tmp);
786 /* Set domain name */
787 tmp = talloc_strdup(mem_ctx, get_global_sam_name());
788 if (tmp == NULL) {
789 return NT_STATUS_NO_MEMORY;
791 init_lsa_StringLarge(&info3->base.domain, tmp);
793 /* Domain sid */
794 sid_copy(&domain_sid, get_global_sam_sid());
796 info3->base.domain_sid = dom_sid_dup(mem_ctx, &domain_sid);
797 if (info3->base.domain_sid == NULL) {
798 return NT_STATUS_NO_MEMORY;
801 /* Guest rid */
802 info3->base.rid = DOMAIN_RID_GUEST;
804 /* Primary gid */
805 info3->base.primary_gid = BUILTIN_RID_GUESTS;
807 TALLOC_FREE(pwd);
808 return NT_STATUS_OK;
811 /***************************************************************************
812 Make (and fill) a user_info struct for a guest login.
813 This *must* succeed for smbd to start. If there is no mapping entry for
814 the guest gid, then create one.
816 The resulting structure is a 'session_info' because
817 create_local_token() has already been called on it. This is quite
818 nasty, as the auth subsystem isn't expect this, but the behaviour is
819 left as-is for now.
820 ***************************************************************************/
822 static NTSTATUS make_new_session_info_guest(struct auth3_session_info **session_info, struct auth_serversupplied_info **server_info)
824 static const char zeros[16] = {0};
825 const char *guest_account = lp_guestaccount();
826 const char *domain = lp_netbios_name();
827 struct netr_SamInfo3 info3;
828 TALLOC_CTX *tmp_ctx;
829 NTSTATUS status;
830 fstring tmp;
832 tmp_ctx = talloc_stackframe();
833 if (tmp_ctx == NULL) {
834 return NT_STATUS_NO_MEMORY;
837 ZERO_STRUCT(info3);
839 status = get_guest_info3(tmp_ctx, &info3);
840 if (!NT_STATUS_IS_OK(status)) {
841 DEBUG(0, ("get_guest_info3 failed with %s\n",
842 nt_errstr(status)));
843 goto done;
846 status = make_server_info_info3(tmp_ctx,
847 guest_account,
848 domain,
849 server_info,
850 &info3);
851 if (!NT_STATUS_IS_OK(status)) {
852 DEBUG(0, ("make_server_info_info3 failed with %s\n",
853 nt_errstr(status)));
854 goto done;
857 (*server_info)->guest = True;
859 /* This should not be done here (we should produce a server
860 * info, and later construct a session info from it), but for
861 * now this does not change the previous behaviours */
862 status = create_local_token(tmp_ctx, *server_info, NULL, session_info);
863 if (!NT_STATUS_IS_OK(status)) {
864 DEBUG(0, ("create_local_token failed: %s\n",
865 nt_errstr(status)));
866 goto done;
868 talloc_steal(NULL, *session_info);
869 talloc_steal(NULL, *server_info);
871 /* annoying, but the Guest really does have a session key, and it is
872 all zeros! */
873 (*session_info)->session_key = data_blob(zeros, sizeof(zeros));
875 alpha_strcpy(tmp, (*session_info)->info3->base.account_name.string,
876 ". _-$", sizeof(tmp));
877 (*session_info)->unix_info->sanitized_username = talloc_strdup(*session_info, tmp);
879 status = NT_STATUS_OK;
880 done:
881 TALLOC_FREE(tmp_ctx);
882 return status;
885 /***************************************************************************
886 Make (and fill) a auth_session_info struct for a system user login.
887 This *must* succeed for smbd to start.
888 ***************************************************************************/
890 static NTSTATUS make_new_session_info_system(TALLOC_CTX *mem_ctx,
891 struct auth3_session_info **session_info)
893 struct passwd *pwd;
894 NTSTATUS status;
896 pwd = getpwuid_alloc(mem_ctx, sec_initial_uid());
897 if (pwd == NULL) {
898 return NT_STATUS_NO_SUCH_USER;
901 status = make_session_info_from_username(mem_ctx,
902 pwd->pw_name,
903 false,
904 session_info);
905 TALLOC_FREE(pwd);
906 if (!NT_STATUS_IS_OK(status)) {
907 return status;
910 (*session_info)->unix_info->system = true;
912 status = add_sid_to_array_unique((*session_info)->security_token->sids,
913 &global_sid_System,
914 &(*session_info)->security_token->sids,
915 &(*session_info)->security_token->num_sids);
916 if (!NT_STATUS_IS_OK(status)) {
917 TALLOC_FREE((*session_info));
918 return status;
921 return NT_STATUS_OK;
924 /****************************************************************************
925 Fake a auth3_session_info just from a username (as a
926 session_info structure, with create_local_token() already called on
928 ****************************************************************************/
930 NTSTATUS make_session_info_from_username(TALLOC_CTX *mem_ctx,
931 const char *username,
932 bool is_guest,
933 struct auth3_session_info **session_info)
935 struct auth_serversupplied_info *result;
936 struct passwd *pwd;
937 NTSTATUS status;
939 pwd = Get_Pwnam_alloc(talloc_tos(), username);
940 if (pwd == NULL) {
941 return NT_STATUS_NO_SUCH_USER;
944 status = make_server_info_pw(&result, pwd->pw_name, pwd);
946 TALLOC_FREE(pwd);
948 if (!NT_STATUS_IS_OK(status)) {
949 return status;
952 result->nss_token = true;
953 result->guest = is_guest;
955 /* Now turn the server_info into a session_info with the full token etc */
956 status = create_local_token(mem_ctx, result, NULL, session_info);
957 talloc_free(result);
958 return status;
961 /* This function MUST only used to create the cached server_info for
962 * guest.
964 * This is a lossy conversion. Variables known to be lost so far
965 * include:
967 * - nss_token (not needed because the only read doesn't happen
968 * for the GUEST user, as this routine populates ->security_token
970 * - extra (not needed because the guest account must have valid RIDs per the output of get_guest_info3())
972 * - The 'server_info' parameter allows the missing 'info3' to be copied across.
974 static struct auth_serversupplied_info *copy_session_info_serverinfo_guest(TALLOC_CTX *mem_ctx,
975 const struct auth3_session_info *src,
976 struct auth_serversupplied_info *server_info)
978 struct auth_serversupplied_info *dst;
980 dst = make_server_info(mem_ctx);
981 if (dst == NULL) {
982 return NULL;
985 /* This element must be provided to convert back to an auth_serversupplied_info */
986 SMB_ASSERT(src->unix_info);
988 dst->guest = src->unix_info->guest;
989 dst->system = src->unix_info->system;
991 /* This element must be provided to convert back to an
992 * auth_serversupplied_info. This needs to be from hte
993 * auth3_session_info because the group values in particular
994 * may change during create_local_token() processing */
995 SMB_ASSERT(src->unix_token);
996 dst->utok.uid = src->unix_token->uid;
997 dst->utok.gid = src->unix_token->gid;
998 dst->utok.ngroups = src->unix_token->ngroups;
999 if (src->unix_token->ngroups != 0) {
1000 dst->utok.groups = (gid_t *)talloc_memdup(
1001 dst, src->unix_token->groups,
1002 sizeof(gid_t)*dst->utok.ngroups);
1003 } else {
1004 dst->utok.groups = NULL;
1007 /* We must have a security_token as otherwise the lossy
1008 * conversion without nss_token would cause create_local_token
1009 * to take the wrong path */
1010 SMB_ASSERT(src->security_token);
1012 dst->security_token = dup_nt_token(dst, src->security_token);
1013 if (!dst->security_token) {
1014 TALLOC_FREE(dst);
1015 return NULL;
1018 dst->session_key = data_blob_talloc( dst, src->session_key.data,
1019 src->session_key.length);
1021 /* This is OK because this functions is only used for the
1022 * GUEST account, which has all-zero keys for both values */
1023 dst->lm_session_key = data_blob_talloc(dst, src->session_key.data,
1024 src->session_key.length);
1026 dst->info3 = copy_netr_SamInfo3(dst, server_info->info3);
1027 if (!dst->info3) {
1028 TALLOC_FREE(dst);
1029 return NULL;
1032 dst->unix_name = talloc_strdup(dst, src->unix_info->unix_name);
1033 if (!dst->unix_name) {
1034 TALLOC_FREE(dst);
1035 return NULL;
1038 dst->sanitized_username = talloc_strdup(dst, src->unix_info->sanitized_username);
1039 if (!dst->sanitized_username) {
1040 TALLOC_FREE(dst);
1041 return NULL;
1044 return dst;
1047 struct auth3_session_info *copy_session_info(TALLOC_CTX *mem_ctx,
1048 const struct auth3_session_info *src)
1050 struct auth3_session_info *dst;
1051 DATA_BLOB blob;
1052 enum ndr_err_code ndr_err;
1054 ndr_err = ndr_push_struct_blob(
1055 &blob, talloc_tos(), src,
1056 (ndr_push_flags_fn_t)ndr_push_auth3_session_info);
1057 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1058 DEBUG(0, ("copy_session_info(): ndr_push_auth3_session_info failed: "
1059 "%s\n", ndr_errstr(ndr_err)));
1060 return NULL;
1063 dst = talloc(mem_ctx, struct auth3_session_info);
1064 if (dst == NULL) {
1065 DEBUG(0, ("talloc failed\n"));
1066 TALLOC_FREE(blob.data);
1067 return NULL;
1070 ndr_err = ndr_pull_struct_blob(
1071 &blob, dst, dst,
1072 (ndr_pull_flags_fn_t)ndr_pull_auth3_session_info);
1073 TALLOC_FREE(blob.data);
1075 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1076 DEBUG(0, ("copy_session_info(): ndr_pull_auth3_session_info failed: "
1077 "%s\n", ndr_errstr(ndr_err)));
1078 TALLOC_FREE(dst);
1079 return NULL;
1082 return dst;
1086 * Set a new session key. Used in the rpc server where we have to override the
1087 * SMB level session key with SystemLibraryDTC
1090 bool session_info_set_session_key(struct auth3_session_info *info,
1091 DATA_BLOB session_key)
1093 TALLOC_FREE(info->session_key.data);
1095 info->session_key = data_blob_talloc(
1096 info, session_key.data, session_key.length);
1098 return (info->session_key.data != NULL);
1101 static struct auth3_session_info *guest_info = NULL;
1103 static struct auth_serversupplied_info *guest_server_info = NULL;
1105 bool init_guest_info(void)
1107 if (guest_info != NULL)
1108 return True;
1110 return NT_STATUS_IS_OK(make_new_session_info_guest(&guest_info, &guest_server_info));
1113 NTSTATUS make_server_info_guest(TALLOC_CTX *mem_ctx,
1114 struct auth_serversupplied_info **server_info)
1116 /* This is trickier than it would appear to need to be because
1117 * we are trying to avoid certain costly operations when the
1118 * structure is converted to a 'auth3_session_info' again in
1119 * create_local_token() */
1120 *server_info = copy_session_info_serverinfo_guest(mem_ctx, guest_info, guest_server_info);
1121 return (*server_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1124 NTSTATUS make_session_info_guest(TALLOC_CTX *mem_ctx,
1125 struct auth3_session_info **session_info)
1127 *session_info = copy_session_info(mem_ctx, guest_info);
1128 return (*session_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1131 static struct auth3_session_info *system_info = NULL;
1133 NTSTATUS init_system_info(void)
1135 if (system_info != NULL)
1136 return NT_STATUS_OK;
1138 return make_new_session_info_system(NULL, &system_info);
1141 NTSTATUS make_session_info_system(TALLOC_CTX *mem_ctx,
1142 struct auth3_session_info **session_info)
1144 if (system_info == NULL) return NT_STATUS_UNSUCCESSFUL;
1145 *session_info = copy_session_info(mem_ctx, system_info);
1146 return (*session_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1149 const struct auth3_session_info *get_session_info_system(void)
1151 return system_info;
1154 bool copy_current_user(struct current_user *dst, struct current_user *src)
1156 gid_t *groups;
1157 struct security_token *nt_token;
1159 groups = (gid_t *)memdup(src->ut.groups,
1160 sizeof(gid_t) * src->ut.ngroups);
1161 if ((src->ut.ngroups != 0) && (groups == NULL)) {
1162 return False;
1165 nt_token = dup_nt_token(NULL, src->nt_user_token);
1166 if (nt_token == NULL) {
1167 SAFE_FREE(groups);
1168 return False;
1171 dst->conn = src->conn;
1172 dst->vuid = src->vuid;
1173 dst->ut.uid = src->ut.uid;
1174 dst->ut.gid = src->ut.gid;
1175 dst->ut.ngroups = src->ut.ngroups;
1176 dst->ut.groups = groups;
1177 dst->nt_user_token = nt_token;
1178 return True;
1181 /***************************************************************************
1182 Purely internal function for make_server_info_info3
1183 ***************************************************************************/
1185 static NTSTATUS check_account(TALLOC_CTX *mem_ctx, const char *domain,
1186 const char *username, char **found_username,
1187 struct passwd **pwd,
1188 bool *username_was_mapped)
1190 char *orig_dom_user = NULL;
1191 char *dom_user = NULL;
1192 char *lower_username = NULL;
1193 char *real_username = NULL;
1194 struct passwd *passwd;
1196 lower_username = talloc_strdup(mem_ctx, username);
1197 if (!lower_username) {
1198 return NT_STATUS_NO_MEMORY;
1200 strlower_m( lower_username );
1202 orig_dom_user = talloc_asprintf(mem_ctx,
1203 "%s%c%s",
1204 domain,
1205 *lp_winbind_separator(),
1206 lower_username);
1207 if (!orig_dom_user) {
1208 return NT_STATUS_NO_MEMORY;
1211 /* Get the passwd struct. Try to create the account if necessary. */
1213 *username_was_mapped = map_username(mem_ctx, orig_dom_user, &dom_user);
1214 if (!dom_user) {
1215 return NT_STATUS_NO_MEMORY;
1218 passwd = smb_getpwnam(mem_ctx, dom_user, &real_username, True );
1219 if (!passwd) {
1220 DEBUG(3, ("Failed to find authenticated user %s via "
1221 "getpwnam(), denying access.\n", dom_user));
1222 return NT_STATUS_NO_SUCH_USER;
1225 if (!real_username) {
1226 return NT_STATUS_NO_MEMORY;
1229 *pwd = passwd;
1231 /* This is pointless -- there is no suport for differing
1232 unix and windows names. Make sure to always store the
1233 one we actually looked up and succeeded. Have I mentioned
1234 why I hate the 'winbind use default domain' parameter?
1235 --jerry */
1237 *found_username = talloc_strdup( mem_ctx, real_username );
1239 return NT_STATUS_OK;
1242 /****************************************************************************
1243 Wrapper to allow the getpwnam() call to strip the domain name and
1244 try again in case a local UNIX user is already there. Also run through
1245 the username if we fallback to the username only.
1246 ****************************************************************************/
1248 struct passwd *smb_getpwnam( TALLOC_CTX *mem_ctx, const char *domuser,
1249 char **p_save_username, bool create )
1251 struct passwd *pw = NULL;
1252 char *p = NULL;
1253 char *username = NULL;
1255 /* we only save a copy of the username it has been mangled
1256 by winbindd use default domain */
1257 *p_save_username = NULL;
1259 /* don't call map_username() here since it has to be done higher
1260 up the stack so we don't call it multiple times */
1262 username = talloc_strdup(mem_ctx, domuser);
1263 if (!username) {
1264 return NULL;
1267 p = strchr_m( username, *lp_winbind_separator() );
1269 /* code for a DOMAIN\user string */
1271 if ( p ) {
1272 pw = Get_Pwnam_alloc( mem_ctx, domuser );
1273 if ( pw ) {
1274 /* make sure we get the case of the username correct */
1275 /* work around 'winbind use default domain = yes' */
1277 if ( !strchr_m( pw->pw_name, *lp_winbind_separator() ) ) {
1278 char *domain;
1280 /* split the domain and username into 2 strings */
1281 *p = '\0';
1282 domain = username;
1284 *p_save_username = talloc_asprintf(mem_ctx,
1285 "%s%c%s",
1286 domain,
1287 *lp_winbind_separator(),
1288 pw->pw_name);
1289 if (!*p_save_username) {
1290 TALLOC_FREE(pw);
1291 return NULL;
1293 } else {
1294 *p_save_username = talloc_strdup(mem_ctx, pw->pw_name);
1297 /* whew -- done! */
1298 return pw;
1301 /* setup for lookup of just the username */
1302 /* remember that p and username are overlapping memory */
1304 p++;
1305 username = talloc_strdup(mem_ctx, p);
1306 if (!username) {
1307 return NULL;
1311 /* just lookup a plain username */
1313 pw = Get_Pwnam_alloc(mem_ctx, username);
1315 /* Create local user if requested but only if winbindd
1316 is not running. We need to protect against cases
1317 where winbindd is failing and then prematurely
1318 creating users in /etc/passwd */
1320 if ( !pw && create && !winbind_ping() ) {
1321 /* Don't add a machine account. */
1322 if (username[strlen(username)-1] == '$')
1323 return NULL;
1325 _smb_create_user(NULL, username, NULL);
1326 pw = Get_Pwnam_alloc(mem_ctx, username);
1329 /* one last check for a valid passwd struct */
1331 if (pw) {
1332 *p_save_username = talloc_strdup(mem_ctx, pw->pw_name);
1334 return pw;
1337 /***************************************************************************
1338 Make a server_info struct from the info3 returned by a domain logon
1339 ***************************************************************************/
1341 NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
1342 const char *sent_nt_username,
1343 const char *domain,
1344 struct auth_serversupplied_info **server_info,
1345 struct netr_SamInfo3 *info3)
1347 static const char zeros[16] = {0, };
1349 NTSTATUS nt_status = NT_STATUS_OK;
1350 char *found_username = NULL;
1351 const char *nt_domain;
1352 const char *nt_username;
1353 bool username_was_mapped;
1354 struct passwd *pwd;
1355 struct auth_serversupplied_info *result;
1356 struct dom_sid *group_sid;
1357 struct netr_SamInfo3 *i3;
1360 Here is where we should check the list of
1361 trusted domains, and verify that the SID
1362 matches.
1365 nt_username = talloc_strdup(mem_ctx, info3->base.account_name.string);
1366 if (!nt_username) {
1367 /* If the server didn't give us one, just use the one we sent
1368 * them */
1369 nt_username = sent_nt_username;
1372 nt_domain = talloc_strdup(mem_ctx, info3->base.domain.string);
1373 if (!nt_domain) {
1374 /* If the server didn't give us one, just use the one we sent
1375 * them */
1376 nt_domain = domain;
1379 /* If getpwnam() fails try the add user script (2.2.x behavior).
1381 We use the _unmapped_ username here in an attempt to provide
1382 consistent username mapping behavior between kerberos and NTLM[SSP]
1383 authentication in domain mode security. I.E. Username mapping
1384 should be applied to the fully qualified username
1385 (e.g. DOMAIN\user) and not just the login name. Yes this means we
1386 called map_username() unnecessarily in make_user_info_map() but
1387 that is how the current code is designed. Making the change here
1388 is the least disruptive place. -- jerry */
1390 /* this call will try to create the user if necessary */
1392 nt_status = check_account(mem_ctx, nt_domain, sent_nt_username,
1393 &found_username, &pwd,
1394 &username_was_mapped);
1396 if (!NT_STATUS_IS_OK(nt_status)) {
1397 return nt_status;
1400 result = make_server_info(NULL);
1401 if (result == NULL) {
1402 DEBUG(4, ("make_server_info failed!\n"));
1403 return NT_STATUS_NO_MEMORY;
1406 result->unix_name = talloc_strdup(result, found_username);
1408 result->sanitized_username = sanitize_username(result,
1409 result->unix_name);
1410 if (result->sanitized_username == NULL) {
1411 TALLOC_FREE(result);
1412 return NT_STATUS_NO_MEMORY;
1415 /* copy in the info3 */
1416 result->info3 = i3 = copy_netr_SamInfo3(result, info3);
1417 if (result->info3 == NULL) {
1418 TALLOC_FREE(result);
1419 return NT_STATUS_NO_MEMORY;
1422 /* Fill in the unix info we found on the way */
1423 result->utok.uid = pwd->pw_uid;
1424 result->utok.gid = pwd->pw_gid;
1426 /* We can't just trust that the primary group sid sent us is something
1427 * we can really use. Obtain the useable sid, and store the original
1428 * one as an additional group if it had to be replaced */
1429 nt_status = get_primary_group_sid(mem_ctx, found_username,
1430 &pwd, &group_sid);
1431 if (!NT_STATUS_IS_OK(nt_status)) {
1432 TALLOC_FREE(result);
1433 return nt_status;
1436 /* store and check if it is the same we got originally */
1437 sid_peek_rid(group_sid, &i3->base.primary_gid);
1438 if (i3->base.primary_gid != info3->base.primary_gid) {
1439 uint32_t n = i3->base.groups.count;
1440 /* not the same, store the original as an additional group */
1441 i3->base.groups.rids =
1442 talloc_realloc(i3, i3->base.groups.rids,
1443 struct samr_RidWithAttribute, n + 1);
1444 if (i3->base.groups.rids == NULL) {
1445 TALLOC_FREE(result);
1446 return NT_STATUS_NO_MEMORY;
1448 i3->base.groups.rids[n].rid = info3->base.primary_gid;
1449 i3->base.groups.rids[n].attributes = SE_GROUP_ENABLED;
1450 i3->base.groups.count = n + 1;
1453 /* ensure we are never given NULL session keys */
1455 if (memcmp(info3->base.key.key, zeros, sizeof(zeros)) == 0) {
1456 result->session_key = data_blob_null;
1457 } else {
1458 result->session_key = data_blob_talloc(
1459 result, info3->base.key.key,
1460 sizeof(info3->base.key.key));
1463 if (memcmp(info3->base.LMSessKey.key, zeros, 8) == 0) {
1464 result->lm_session_key = data_blob_null;
1465 } else {
1466 result->lm_session_key = data_blob_talloc(
1467 result, info3->base.LMSessKey.key,
1468 sizeof(info3->base.LMSessKey.key));
1471 result->nss_token |= username_was_mapped;
1473 result->guest = (info3->base.user_flags & NETLOGON_GUEST);
1475 *server_info = result;
1477 return NT_STATUS_OK;
1480 /*****************************************************************************
1481 Make a server_info struct from the wbcAuthUserInfo returned by a domain logon
1482 ******************************************************************************/
1484 NTSTATUS make_server_info_wbcAuthUserInfo(TALLOC_CTX *mem_ctx,
1485 const char *sent_nt_username,
1486 const char *domain,
1487 const struct wbcAuthUserInfo *info,
1488 struct auth_serversupplied_info **server_info)
1490 struct netr_SamInfo3 *info3;
1492 info3 = wbcAuthUserInfo_to_netr_SamInfo3(mem_ctx, info);
1493 if (!info3) {
1494 return NT_STATUS_NO_MEMORY;
1497 return make_server_info_info3(mem_ctx,
1498 sent_nt_username, domain,
1499 server_info, info3);
1503 * Verify whether or not given domain is trusted.
1505 * @param domain_name name of the domain to be verified
1506 * @return true if domain is one of the trusted ones or
1507 * false if otherwise
1510 bool is_trusted_domain(const char* dom_name)
1512 struct dom_sid trustdom_sid;
1513 bool ret;
1515 /* no trusted domains for a standalone server */
1517 if ( lp_server_role() == ROLE_STANDALONE )
1518 return False;
1520 if (dom_name == NULL || dom_name[0] == '\0') {
1521 return false;
1524 if (strequal(dom_name, get_global_sam_name())) {
1525 return false;
1528 /* if we are a DC, then check for a direct trust relationships */
1530 if ( IS_DC ) {
1531 become_root();
1532 DEBUG (5,("is_trusted_domain: Checking for domain trust with "
1533 "[%s]\n", dom_name ));
1534 ret = pdb_get_trusteddom_pw(dom_name, NULL, NULL, NULL);
1535 unbecome_root();
1536 if (ret)
1537 return True;
1539 else {
1540 wbcErr result;
1542 /* If winbind is around, ask it */
1544 result = wb_is_trusted_domain(dom_name);
1546 if (result == WBC_ERR_SUCCESS) {
1547 return True;
1550 if (result == WBC_ERR_DOMAIN_NOT_FOUND) {
1551 /* winbind could not find the domain */
1552 return False;
1555 /* The only other possible result is that winbind is not up
1556 and running. We need to update the trustdom_cache
1557 ourselves */
1559 update_trustdom_cache();
1562 /* now the trustdom cache should be available a DC could still
1563 * have a transitive trust so fall back to the cache of trusted
1564 * domains (like a domain member would use */
1566 if ( trustdom_cache_fetch(dom_name, &trustdom_sid) ) {
1567 return True;
1570 return False;