s4-scripting: allow to specify the number max of iteration around getNcChanges
[Samba/gbeck.git] / source3 / auth / auth_util.c
blobf41809d58d10a5ed898a1effa0de8ac52555d77b
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"
34 #include "../auth/auth_sam_reply.h"
36 #undef DBGC_CLASS
37 #define DBGC_CLASS DBGC_AUTH
39 /****************************************************************************
40 Create a UNIX user on demand.
41 ****************************************************************************/
43 static int _smb_create_user(const char *domain, const char *unix_username, const char *homedir)
45 TALLOC_CTX *ctx = talloc_tos();
46 char *add_script;
47 int ret;
49 add_script = talloc_strdup(ctx, lp_adduser_script());
50 if (!add_script || !*add_script) {
51 return -1;
53 add_script = talloc_all_string_sub(ctx,
54 add_script,
55 "%u",
56 unix_username);
57 if (!add_script) {
58 return -1;
60 if (domain) {
61 add_script = talloc_all_string_sub(ctx,
62 add_script,
63 "%D",
64 domain);
65 if (!add_script) {
66 return -1;
69 if (homedir) {
70 add_script = talloc_all_string_sub(ctx,
71 add_script,
72 "%H",
73 homedir);
74 if (!add_script) {
75 return -1;
78 ret = smbrun(add_script,NULL);
79 flush_pwnam_cache();
80 DEBUG(ret ? 0 : 3,
81 ("smb_create_user: Running the command `%s' gave %d\n",
82 add_script,ret));
83 return ret;
86 /****************************************************************************
87 Create an auth_usersupplied_data structure after appropriate mapping.
88 ****************************************************************************/
90 NTSTATUS make_user_info_map(struct auth_usersupplied_info **user_info,
91 const char *smb_name,
92 const char *client_domain,
93 const char *workstation_name,
94 const struct tsocket_address *remote_address,
95 DATA_BLOB *lm_pwd,
96 DATA_BLOB *nt_pwd,
97 const struct samr_Password *lm_interactive_pwd,
98 const struct samr_Password *nt_interactive_pwd,
99 const char *plaintext,
100 enum auth_password_state password_state)
102 const char *domain;
103 NTSTATUS result;
104 bool was_mapped;
105 char *internal_username = NULL;
107 was_mapped = map_username(talloc_tos(), smb_name, &internal_username);
108 if (!internal_username) {
109 return NT_STATUS_NO_MEMORY;
112 DEBUG(5, ("Mapping user [%s]\\[%s] from workstation [%s]\n",
113 client_domain, smb_name, workstation_name));
115 domain = client_domain;
117 /* If you connect to a Windows domain member using a bogus domain name,
118 * the Windows box will map the BOGUS\user to SAMNAME\user. Thus, if
119 * the Windows box is a DC the name will become DOMAIN\user and be
120 * authenticated against AD, if the Windows box is a member server but
121 * not a DC the name will become WORKSTATION\user. A standalone
122 * non-domain member box will also map to WORKSTATION\user.
123 * This also deals with the client passing in a "" domain */
125 if (!is_trusted_domain(domain) &&
126 !strequal(domain, my_sam_name()))
128 if (lp_map_untrusted_to_domain())
129 domain = my_sam_name();
130 else
131 domain = get_global_sam_name();
132 DEBUG(5, ("Mapped domain from [%s] to [%s] for user [%s] from "
133 "workstation [%s]\n",
134 client_domain, domain, smb_name, workstation_name));
137 /* We know that the given domain is trusted (and we are allowing them),
138 * it is our global SAM name, or for legacy behavior it is our
139 * primary domain name */
141 result = make_user_info(user_info, smb_name, internal_username,
142 client_domain, domain, workstation_name,
143 remote_address, lm_pwd, nt_pwd,
144 lm_interactive_pwd, nt_interactive_pwd,
145 plaintext, password_state);
146 if (NT_STATUS_IS_OK(result)) {
147 /* We have tried mapping */
148 (*user_info)->mapped_state = true;
149 /* did we actually map the user to a different name? */
150 (*user_info)->was_mapped = was_mapped;
152 return result;
155 /****************************************************************************
156 Create an auth_usersupplied_data, making the DATA_BLOBs here.
157 Decrypt and encrypt the passwords.
158 ****************************************************************************/
160 bool make_user_info_netlogon_network(struct auth_usersupplied_info **user_info,
161 const char *smb_name,
162 const char *client_domain,
163 const char *workstation_name,
164 const struct tsocket_address *remote_address,
165 uint32 logon_parameters,
166 const uchar *lm_network_pwd,
167 int lm_pwd_len,
168 const uchar *nt_network_pwd,
169 int nt_pwd_len)
171 bool ret;
172 NTSTATUS status;
173 DATA_BLOB lm_blob = data_blob(lm_network_pwd, lm_pwd_len);
174 DATA_BLOB nt_blob = data_blob(nt_network_pwd, nt_pwd_len);
176 status = make_user_info_map(user_info,
177 smb_name, client_domain,
178 workstation_name,
179 remote_address,
180 lm_pwd_len ? &lm_blob : NULL,
181 nt_pwd_len ? &nt_blob : NULL,
182 NULL, NULL, NULL,
183 AUTH_PASSWORD_RESPONSE);
185 if (NT_STATUS_IS_OK(status)) {
186 (*user_info)->logon_parameters = logon_parameters;
188 ret = NT_STATUS_IS_OK(status) ? true : false;
190 data_blob_free(&lm_blob);
191 data_blob_free(&nt_blob);
192 return ret;
195 /****************************************************************************
196 Create an auth_usersupplied_data, making the DATA_BLOBs here.
197 Decrypt and encrypt the passwords.
198 ****************************************************************************/
200 bool make_user_info_netlogon_interactive(struct auth_usersupplied_info **user_info,
201 const char *smb_name,
202 const char *client_domain,
203 const char *workstation_name,
204 const struct tsocket_address *remote_address,
205 uint32 logon_parameters,
206 const uchar chal[8],
207 const uchar lm_interactive_pwd[16],
208 const uchar nt_interactive_pwd[16],
209 const uchar *dc_sess_key)
211 struct samr_Password lm_pwd;
212 struct samr_Password nt_pwd;
213 unsigned char local_lm_response[24];
214 unsigned char local_nt_response[24];
215 unsigned char key[16];
217 memcpy(key, dc_sess_key, 16);
219 if (lm_interactive_pwd)
220 memcpy(lm_pwd.hash, lm_interactive_pwd, sizeof(lm_pwd.hash));
222 if (nt_interactive_pwd)
223 memcpy(nt_pwd.hash, nt_interactive_pwd, sizeof(nt_pwd.hash));
225 #ifdef DEBUG_PASSWORD
226 DEBUG(100,("key:"));
227 dump_data(100, key, sizeof(key));
229 DEBUG(100,("lm owf password:"));
230 dump_data(100, lm_pwd.hash, sizeof(lm_pwd.hash));
232 DEBUG(100,("nt owf password:"));
233 dump_data(100, nt_pwd.hash, sizeof(nt_pwd.hash));
234 #endif
236 if (lm_interactive_pwd)
237 arcfour_crypt(lm_pwd.hash, key, sizeof(lm_pwd.hash));
239 if (nt_interactive_pwd)
240 arcfour_crypt(nt_pwd.hash, key, sizeof(nt_pwd.hash));
242 #ifdef DEBUG_PASSWORD
243 DEBUG(100,("decrypt of lm owf password:"));
244 dump_data(100, lm_pwd.hash, sizeof(lm_pwd));
246 DEBUG(100,("decrypt of nt owf password:"));
247 dump_data(100, nt_pwd.hash, sizeof(nt_pwd));
248 #endif
250 if (lm_interactive_pwd)
251 SMBOWFencrypt(lm_pwd.hash, chal,
252 local_lm_response);
254 if (nt_interactive_pwd)
255 SMBOWFencrypt(nt_pwd.hash, chal,
256 local_nt_response);
258 /* Password info paranoia */
259 ZERO_STRUCT(key);
262 bool ret;
263 NTSTATUS nt_status;
264 DATA_BLOB local_lm_blob;
265 DATA_BLOB local_nt_blob;
267 if (lm_interactive_pwd) {
268 local_lm_blob = data_blob(local_lm_response,
269 sizeof(local_lm_response));
272 if (nt_interactive_pwd) {
273 local_nt_blob = data_blob(local_nt_response,
274 sizeof(local_nt_response));
277 nt_status = make_user_info_map(
278 user_info,
279 smb_name, client_domain, workstation_name,
280 remote_address,
281 lm_interactive_pwd ? &local_lm_blob : NULL,
282 nt_interactive_pwd ? &local_nt_blob : NULL,
283 lm_interactive_pwd ? &lm_pwd : NULL,
284 nt_interactive_pwd ? &nt_pwd : NULL,
285 NULL, AUTH_PASSWORD_HASH);
287 if (NT_STATUS_IS_OK(nt_status)) {
288 (*user_info)->logon_parameters = logon_parameters;
291 ret = NT_STATUS_IS_OK(nt_status) ? true : false;
292 data_blob_free(&local_lm_blob);
293 data_blob_free(&local_nt_blob);
294 return ret;
299 /****************************************************************************
300 Create an auth_usersupplied_data structure
301 ****************************************************************************/
303 bool make_user_info_for_reply(struct auth_usersupplied_info **user_info,
304 const char *smb_name,
305 const char *client_domain,
306 const struct tsocket_address *remote_address,
307 const uint8 chal[8],
308 DATA_BLOB plaintext_password)
311 DATA_BLOB local_lm_blob;
312 DATA_BLOB local_nt_blob;
313 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
314 char *plaintext_password_string;
316 * Not encrypted - do so.
319 DEBUG(5,("make_user_info_for_reply: User passwords not in encrypted "
320 "format.\n"));
321 if (plaintext_password.data && plaintext_password.length) {
322 unsigned char local_lm_response[24];
324 #ifdef DEBUG_PASSWORD
325 DEBUG(10,("Unencrypted password (len %d):\n",
326 (int)plaintext_password.length));
327 dump_data(100, plaintext_password.data,
328 plaintext_password.length);
329 #endif
331 SMBencrypt( (const char *)plaintext_password.data,
332 (const uchar*)chal, local_lm_response);
333 local_lm_blob = data_blob(local_lm_response, 24);
335 /* We can't do an NT hash here, as the password needs to be
336 case insensitive */
337 local_nt_blob = data_blob_null;
338 } else {
339 local_lm_blob = data_blob_null;
340 local_nt_blob = data_blob_null;
343 plaintext_password_string = talloc_strndup(talloc_tos(),
344 (const char *)plaintext_password.data,
345 plaintext_password.length);
346 if (!plaintext_password_string) {
347 return false;
350 ret = make_user_info_map(
351 user_info, smb_name, client_domain,
352 get_remote_machine_name(),
353 remote_address,
354 local_lm_blob.data ? &local_lm_blob : NULL,
355 local_nt_blob.data ? &local_nt_blob : NULL,
356 NULL, NULL,
357 plaintext_password_string,
358 AUTH_PASSWORD_PLAIN);
360 if (plaintext_password_string) {
361 memset(plaintext_password_string, '\0', strlen(plaintext_password_string));
362 talloc_free(plaintext_password_string);
365 data_blob_free(&local_lm_blob);
366 return NT_STATUS_IS_OK(ret) ? true : false;
369 /****************************************************************************
370 Create an auth_usersupplied_data structure
371 ****************************************************************************/
373 NTSTATUS make_user_info_for_reply_enc(struct auth_usersupplied_info **user_info,
374 const char *smb_name,
375 const char *client_domain,
376 const struct tsocket_address *remote_address,
377 DATA_BLOB lm_resp, DATA_BLOB nt_resp)
379 return make_user_info_map(user_info, smb_name,
380 client_domain,
381 get_remote_machine_name(),
382 remote_address,
383 lm_resp.data && (lm_resp.length > 0) ? &lm_resp : NULL,
384 nt_resp.data && (nt_resp.length > 0) ? &nt_resp : NULL,
385 NULL, NULL, NULL,
386 AUTH_PASSWORD_RESPONSE);
389 /****************************************************************************
390 Create a guest user_info blob, for anonymous authentication.
391 ****************************************************************************/
393 bool make_user_info_guest(const struct tsocket_address *remote_address,
394 struct auth_usersupplied_info **user_info)
396 NTSTATUS nt_status;
398 nt_status = make_user_info(user_info,
399 "","",
400 "","",
401 "",
402 remote_address,
403 NULL, NULL,
404 NULL, NULL,
405 NULL,
406 AUTH_PASSWORD_RESPONSE);
408 return NT_STATUS_IS_OK(nt_status) ? true : false;
411 static NTSTATUS log_nt_token(struct security_token *token)
413 TALLOC_CTX *frame = talloc_stackframe();
414 char *command;
415 char *group_sidstr;
416 size_t i;
418 if ((lp_log_nt_token_command() == NULL) ||
419 (strlen(lp_log_nt_token_command()) == 0)) {
420 TALLOC_FREE(frame);
421 return NT_STATUS_OK;
424 group_sidstr = talloc_strdup(frame, "");
425 for (i=1; i<token->num_sids; i++) {
426 group_sidstr = talloc_asprintf(
427 frame, "%s %s", group_sidstr,
428 sid_string_talloc(frame, &token->sids[i]));
431 command = talloc_string_sub(
432 frame, lp_log_nt_token_command(),
433 "%s", sid_string_talloc(frame, &token->sids[0]));
434 command = talloc_string_sub(frame, command, "%t", group_sidstr);
436 if (command == NULL) {
437 TALLOC_FREE(frame);
438 return NT_STATUS_NO_MEMORY;
441 DEBUG(8, ("running command: [%s]\n", command));
442 if (smbrun(command, NULL) != 0) {
443 DEBUG(0, ("Could not log NT token\n"));
444 TALLOC_FREE(frame);
445 return NT_STATUS_ACCESS_DENIED;
448 TALLOC_FREE(frame);
449 return NT_STATUS_OK;
453 * Create the token to use from server_info->info3 and
454 * server_info->sids (the info3/sam groups). Find the unix gids.
457 NTSTATUS create_local_token(TALLOC_CTX *mem_ctx,
458 const struct auth_serversupplied_info *server_info,
459 DATA_BLOB *session_key,
460 const char *smb_username, /* for ->sanitized_username, for %U subs */
461 struct auth_session_info **session_info_out)
463 struct security_token *t;
464 NTSTATUS status;
465 size_t i;
466 struct dom_sid tmp_sid;
467 struct auth_session_info *session_info;
468 struct wbcUnixId *ids;
469 fstring tmp;
471 /* Ensure we can't possible take a code path leading to a
472 * null defref. */
473 if (!server_info) {
474 return NT_STATUS_LOGON_FAILURE;
477 session_info = talloc_zero(mem_ctx, struct auth_session_info);
478 if (!session_info) {
479 return NT_STATUS_NO_MEMORY;
482 session_info->unix_token = talloc_zero(session_info, struct security_unix_token);
483 if (!session_info->unix_token) {
484 TALLOC_FREE(session_info);
485 return NT_STATUS_NO_MEMORY;
488 session_info->unix_token->uid = server_info->utok.uid;
489 session_info->unix_token->gid = server_info->utok.gid;
491 session_info->unix_info = talloc_zero(session_info, struct auth_user_info_unix);
492 if (!session_info->unix_info) {
493 TALLOC_FREE(session_info);
494 return NT_STATUS_NO_MEMORY;
497 session_info->unix_info->unix_name = talloc_strdup(session_info, server_info->unix_name);
498 if (!session_info->unix_info->unix_name) {
499 TALLOC_FREE(session_info);
500 return NT_STATUS_NO_MEMORY;
503 /* This is a potentially untrusted username for use in %U */
504 alpha_strcpy(tmp, smb_username, ". _-$", sizeof(tmp));
505 session_info->unix_info->sanitized_username =
506 talloc_strdup(session_info->unix_info, tmp);
508 session_info->unix_info->system = server_info->system;
510 if (session_key) {
511 data_blob_free(&session_info->session_key);
512 session_info->session_key = data_blob_talloc(session_info,
513 session_key->data,
514 session_key->length);
515 if (!session_info->session_key.data && session_key->length) {
516 return NT_STATUS_NO_MEMORY;
518 } else {
519 session_info->session_key = data_blob_talloc( session_info, server_info->session_key.data,
520 server_info->session_key.length);
523 if (session_info->security_token) {
524 /* Just copy the token, it has already been finalised
525 * (nasty hack to support a cached guest session_info,
526 * and a possible strategy for auth_samba4 to pass in
527 * a finalised session) */
529 session_info->security_token = dup_nt_token(session_info, server_info->security_token);
530 if (!session_info->security_token) {
531 TALLOC_FREE(session_info);
532 return NT_STATUS_NO_MEMORY;
535 session_info->unix_token->ngroups = server_info->utok.ngroups;
536 if (server_info->utok.ngroups != 0) {
537 session_info->unix_token->groups = (gid_t *)talloc_memdup(
538 session_info->unix_token, server_info->utok.groups,
539 sizeof(gid_t)*session_info->unix_token->ngroups);
540 } else {
541 session_info->unix_token->groups = NULL;
544 *session_info_out = session_info;
545 return NT_STATUS_OK;
548 /* We need to populate session_info->info with the information found in server_info->info3 */
549 status = make_user_info_SamBaseInfo(session_info, "", &server_info->info3->base,
550 server_info->guest == false,
551 &session_info->info);
552 if (!NT_STATUS_IS_OK(status)) {
553 DEBUG(0, ("conversion of info3 into auth_user_info failed!\n"));
554 TALLOC_FREE(session_info);
555 return status;
559 * If winbind is not around, we can not make much use of the SIDs the
560 * domain controller provided us with. Likewise if the user name was
561 * mapped to some local unix user.
564 if (((lp_server_role() == ROLE_DOMAIN_MEMBER) && !winbind_ping()) ||
565 (server_info->nss_token)) {
566 char *found_username = NULL;
567 status = create_token_from_username(session_info,
568 server_info->unix_name,
569 server_info->guest,
570 &session_info->unix_token->uid,
571 &session_info->unix_token->gid,
572 &found_username,
573 &session_info->security_token);
574 if (NT_STATUS_IS_OK(status)) {
575 session_info->unix_info->unix_name = found_username;
577 } else {
578 status = create_local_nt_token_from_info3(session_info,
579 server_info->guest,
580 server_info->info3,
581 &server_info->extra,
582 &session_info->security_token);
585 if (!NT_STATUS_IS_OK(status)) {
586 return status;
589 /* Convert the SIDs to gids. */
591 session_info->unix_token->ngroups = 0;
592 session_info->unix_token->groups = NULL;
594 t = session_info->security_token;
596 ids = talloc_array(talloc_tos(), struct wbcUnixId,
597 t->num_sids);
598 if (ids == NULL) {
599 return NT_STATUS_NO_MEMORY;
602 if (!sids_to_unix_ids(t->sids, t->num_sids, ids)) {
603 TALLOC_FREE(ids);
604 return NT_STATUS_NO_MEMORY;
607 /* Start at index 1, where the groups start. */
609 for (i=1; i<t->num_sids; i++) {
611 if (ids[i].type != WBC_ID_TYPE_GID) {
612 DEBUG(10, ("Could not convert SID %s to gid, "
613 "ignoring it\n",
614 sid_string_dbg(&t->sids[i])));
615 continue;
617 if (!add_gid_to_array_unique(session_info, ids[i].id.gid,
618 &session_info->unix_token->groups,
619 &session_info->unix_token->ngroups)) {
620 return NT_STATUS_NO_MEMORY;
625 * Add the "Unix Group" SID for each gid to catch mapped groups
626 * and their Unix equivalent. This is to solve the backwards
627 * compatibility problem of 'valid users = +ntadmin' where
628 * ntadmin has been paired with "Domain Admins" in the group
629 * mapping table. Otherwise smb.conf would need to be changed
630 * to 'valid user = "Domain Admins"'. --jerry
632 * For consistency we also add the "Unix User" SID,
633 * so that the complete unix token is represented within
634 * the nt token.
637 uid_to_unix_users_sid(session_info->unix_token->uid, &tmp_sid);
639 add_sid_to_array_unique(session_info->security_token, &tmp_sid,
640 &session_info->security_token->sids,
641 &session_info->security_token->num_sids);
643 for ( i=0; i<session_info->unix_token->ngroups; i++ ) {
644 gid_to_unix_groups_sid(session_info->unix_token->groups[i], &tmp_sid);
645 add_sid_to_array_unique(session_info->security_token, &tmp_sid,
646 &session_info->security_token->sids,
647 &session_info->security_token->num_sids);
650 security_token_debug(DBGC_AUTH, 10, session_info->security_token);
651 debug_unix_user_token(DBGC_AUTH, 10,
652 session_info->unix_token->uid,
653 session_info->unix_token->gid,
654 session_info->unix_token->ngroups,
655 session_info->unix_token->groups);
657 status = log_nt_token(session_info->security_token);
658 if (!NT_STATUS_IS_OK(status)) {
659 return status;
662 *session_info_out = session_info;
663 return NT_STATUS_OK;
666 /***************************************************************************
667 Make (and fill) a server_info struct from a 'struct passwd' by conversion
668 to a struct samu
669 ***************************************************************************/
671 NTSTATUS make_server_info_pw(struct auth_serversupplied_info **server_info,
672 char *unix_username,
673 struct passwd *pwd)
675 NTSTATUS status;
676 struct samu *sampass = NULL;
677 char *qualified_name = NULL;
678 TALLOC_CTX *mem_ctx = NULL;
679 struct dom_sid u_sid;
680 enum lsa_SidType type;
681 struct auth_serversupplied_info *result;
684 * The SID returned in server_info->sam_account is based
685 * on our SAM sid even though for a pure UNIX account this should
686 * not be the case as it doesn't really exist in the SAM db.
687 * This causes lookups on "[in]valid users" to fail as they
688 * will lookup this name as a "Unix User" SID to check against
689 * the user token. Fix this by adding the "Unix User"\unix_username
690 * SID to the sid array. The correct fix should probably be
691 * changing the server_info->sam_account user SID to be a
692 * S-1-22 Unix SID, but this might break old configs where
693 * plaintext passwords were used with no SAM backend.
696 mem_ctx = talloc_init("make_server_info_pw_tmp");
697 if (!mem_ctx) {
698 return NT_STATUS_NO_MEMORY;
701 qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
702 unix_users_domain_name(),
703 unix_username );
704 if (!qualified_name) {
705 TALLOC_FREE(mem_ctx);
706 return NT_STATUS_NO_MEMORY;
709 if (!lookup_name(mem_ctx, qualified_name, LOOKUP_NAME_ALL,
710 NULL, NULL,
711 &u_sid, &type)) {
712 TALLOC_FREE(mem_ctx);
713 return NT_STATUS_NO_SUCH_USER;
716 TALLOC_FREE(mem_ctx);
718 if (type != SID_NAME_USER) {
719 return NT_STATUS_NO_SUCH_USER;
722 if ( !(sampass = samu_new( NULL )) ) {
723 return NT_STATUS_NO_MEMORY;
726 status = samu_set_unix( sampass, pwd );
727 if (!NT_STATUS_IS_OK(status)) {
728 return status;
731 /* In pathological cases the above call can set the account
732 * name to the DOMAIN\username form. Reset the account name
733 * using unix_username */
734 pdb_set_username(sampass, unix_username, PDB_SET);
736 /* set the user sid to be the calculated u_sid */
737 pdb_set_user_sid(sampass, &u_sid, PDB_SET);
739 result = make_server_info(NULL);
740 if (result == NULL) {
741 TALLOC_FREE(sampass);
742 return NT_STATUS_NO_MEMORY;
745 status = samu_to_SamInfo3(result, sampass, lp_netbios_name(),
746 &result->info3, &result->extra);
747 TALLOC_FREE(sampass);
748 if (!NT_STATUS_IS_OK(status)) {
749 DEBUG(10, ("Failed to convert samu to info3: %s\n",
750 nt_errstr(status)));
751 TALLOC_FREE(result);
752 return status;
755 result->unix_name = talloc_strdup(result, unix_username);
757 if (result->unix_name == NULL) {
758 TALLOC_FREE(result);
759 return NT_STATUS_NO_MEMORY;
762 result->utok.uid = pwd->pw_uid;
763 result->utok.gid = pwd->pw_gid;
765 *server_info = result;
767 return NT_STATUS_OK;
770 static NTSTATUS get_guest_info3(TALLOC_CTX *mem_ctx,
771 struct netr_SamInfo3 *info3)
773 const char *guest_account = lp_guestaccount();
774 struct dom_sid domain_sid;
775 struct passwd *pwd;
776 const char *tmp;
778 pwd = Get_Pwnam_alloc(mem_ctx, guest_account);
779 if (pwd == NULL) {
780 DEBUG(0,("SamInfo3_for_guest: Unable to locate guest "
781 "account [%s]!\n", guest_account));
782 return NT_STATUS_NO_SUCH_USER;
785 /* Set account name */
786 tmp = talloc_strdup(mem_ctx, pwd->pw_name);
787 if (tmp == NULL) {
788 return NT_STATUS_NO_MEMORY;
790 init_lsa_String(&info3->base.account_name, tmp);
792 /* Set domain name */
793 tmp = talloc_strdup(mem_ctx, get_global_sam_name());
794 if (tmp == NULL) {
795 return NT_STATUS_NO_MEMORY;
797 init_lsa_StringLarge(&info3->base.domain, tmp);
799 /* Domain sid */
800 sid_copy(&domain_sid, get_global_sam_sid());
802 info3->base.domain_sid = dom_sid_dup(mem_ctx, &domain_sid);
803 if (info3->base.domain_sid == NULL) {
804 return NT_STATUS_NO_MEMORY;
807 /* Guest rid */
808 info3->base.rid = DOMAIN_RID_GUEST;
810 /* Primary gid */
811 info3->base.primary_gid = BUILTIN_RID_GUESTS;
813 /* Set as guest */
814 info3->base.user_flags = NETLOGON_GUEST;
816 TALLOC_FREE(pwd);
817 return NT_STATUS_OK;
820 /***************************************************************************
821 Make (and fill) a user_info struct for a guest login.
822 This *must* succeed for smbd to start. If there is no mapping entry for
823 the guest gid, then create one.
825 The resulting structure is a 'session_info' because
826 create_local_token() has already been called on it. This is quite
827 nasty, as the auth subsystem isn't expect this, but the behavior is
828 left as-is for now.
829 ***************************************************************************/
831 static NTSTATUS make_new_session_info_guest(struct auth_session_info **session_info, struct auth_serversupplied_info **server_info)
833 static const char zeros[16] = {0};
834 const char *guest_account = lp_guestaccount();
835 const char *domain = lp_netbios_name();
836 struct netr_SamInfo3 info3;
837 TALLOC_CTX *tmp_ctx;
838 NTSTATUS status;
840 tmp_ctx = talloc_stackframe();
841 if (tmp_ctx == NULL) {
842 return NT_STATUS_NO_MEMORY;
845 ZERO_STRUCT(info3);
847 status = get_guest_info3(tmp_ctx, &info3);
848 if (!NT_STATUS_IS_OK(status)) {
849 DEBUG(0, ("get_guest_info3 failed with %s\n",
850 nt_errstr(status)));
851 goto done;
854 status = make_server_info_info3(tmp_ctx,
855 guest_account,
856 domain,
857 server_info,
858 &info3);
859 if (!NT_STATUS_IS_OK(status)) {
860 DEBUG(0, ("make_server_info_info3 failed with %s\n",
861 nt_errstr(status)));
862 goto done;
865 (*server_info)->guest = true;
867 /* This should not be done here (we should produce a server
868 * info, and later construct a session info from it), but for
869 * now this does not change the previous behavior */
870 status = create_local_token(tmp_ctx, *server_info, NULL,
871 (*server_info)->info3->base.account_name.string,
872 session_info);
873 if (!NT_STATUS_IS_OK(status)) {
874 DEBUG(0, ("create_local_token failed: %s\n",
875 nt_errstr(status)));
876 goto done;
878 talloc_steal(NULL, *session_info);
879 talloc_steal(NULL, *server_info);
881 /* annoying, but the Guest really does have a session key, and it is
882 all zeros! */
883 (*session_info)->session_key = data_blob(zeros, sizeof(zeros));
885 status = NT_STATUS_OK;
886 done:
887 TALLOC_FREE(tmp_ctx);
888 return status;
891 /***************************************************************************
892 Make (and fill) a auth_session_info struct for a system user login.
893 This *must* succeed for smbd to start.
894 ***************************************************************************/
896 static NTSTATUS make_new_session_info_system(TALLOC_CTX *mem_ctx,
897 struct auth_session_info **session_info)
899 struct passwd *pwd;
900 NTSTATUS status;
902 pwd = getpwuid_alloc(mem_ctx, sec_initial_uid());
903 if (pwd == NULL) {
904 return NT_STATUS_NO_SUCH_USER;
907 status = make_session_info_from_username(mem_ctx,
908 pwd->pw_name,
909 false,
910 session_info);
911 TALLOC_FREE(pwd);
912 if (!NT_STATUS_IS_OK(status)) {
913 return status;
916 (*session_info)->unix_info->system = true;
918 status = add_sid_to_array_unique((*session_info)->security_token->sids,
919 &global_sid_System,
920 &(*session_info)->security_token->sids,
921 &(*session_info)->security_token->num_sids);
922 if (!NT_STATUS_IS_OK(status)) {
923 TALLOC_FREE((*session_info));
924 return status;
927 return NT_STATUS_OK;
930 /****************************************************************************
931 Fake a auth_session_info just from a username (as a
932 session_info structure, with create_local_token() already called on
934 ****************************************************************************/
936 NTSTATUS make_session_info_from_username(TALLOC_CTX *mem_ctx,
937 const char *username,
938 bool is_guest,
939 struct auth_session_info **session_info)
941 struct auth_serversupplied_info *result;
942 struct passwd *pwd;
943 NTSTATUS status;
945 pwd = Get_Pwnam_alloc(talloc_tos(), username);
946 if (pwd == NULL) {
947 return NT_STATUS_NO_SUCH_USER;
950 status = make_server_info_pw(&result, pwd->pw_name, pwd);
952 if (!NT_STATUS_IS_OK(status)) {
953 TALLOC_FREE(pwd);
954 return status;
957 result->nss_token = true;
958 result->guest = is_guest;
960 /* Now turn the server_info into a session_info with the full token etc */
961 status = create_local_token(mem_ctx, result, NULL, pwd->pw_name, session_info);
962 TALLOC_FREE(pwd);
963 talloc_free(result);
964 return status;
967 /* This function MUST only used to create the cached server_info for
968 * guest.
970 * This is a lossy conversion. Variables known to be lost so far
971 * include:
973 * - nss_token (not needed because the only read doesn't happen
974 * for the GUEST user, as this routine populates ->security_token
976 * - extra (not needed because the guest account must have valid RIDs per the output of get_guest_info3())
978 * - The 'server_info' parameter allows the missing 'info3' to be copied across.
980 static struct auth_serversupplied_info *copy_session_info_serverinfo_guest(TALLOC_CTX *mem_ctx,
981 const struct auth_session_info *src,
982 struct auth_serversupplied_info *server_info)
984 struct auth_serversupplied_info *dst;
986 dst = make_server_info(mem_ctx);
987 if (dst == NULL) {
988 return NULL;
991 /* This element must be provided to convert back to an auth_serversupplied_info */
992 SMB_ASSERT(src->unix_info);
994 dst->guest = true;
995 dst->system = false;
997 /* This element must be provided to convert back to an
998 * auth_serversupplied_info. This needs to be from the
999 * auth_session_info because the group values in particular
1000 * may change during create_local_token() processing */
1001 SMB_ASSERT(src->unix_token);
1002 dst->utok.uid = src->unix_token->uid;
1003 dst->utok.gid = src->unix_token->gid;
1004 dst->utok.ngroups = src->unix_token->ngroups;
1005 if (src->unix_token->ngroups != 0) {
1006 dst->utok.groups = (gid_t *)talloc_memdup(
1007 dst, src->unix_token->groups,
1008 sizeof(gid_t)*dst->utok.ngroups);
1009 } else {
1010 dst->utok.groups = NULL;
1013 /* We must have a security_token as otherwise the lossy
1014 * conversion without nss_token would cause create_local_token
1015 * to take the wrong path */
1016 SMB_ASSERT(src->security_token);
1018 dst->security_token = dup_nt_token(dst, src->security_token);
1019 if (!dst->security_token) {
1020 TALLOC_FREE(dst);
1021 return NULL;
1024 dst->session_key = data_blob_talloc( dst, src->session_key.data,
1025 src->session_key.length);
1027 /* This is OK because this functions is only used for the
1028 * GUEST account, which has all-zero keys for both values */
1029 dst->lm_session_key = data_blob_talloc(dst, src->session_key.data,
1030 src->session_key.length);
1032 dst->info3 = copy_netr_SamInfo3(dst, server_info->info3);
1033 if (!dst->info3) {
1034 TALLOC_FREE(dst);
1035 return NULL;
1038 dst->unix_name = talloc_strdup(dst, src->unix_info->unix_name);
1039 if (!dst->unix_name) {
1040 TALLOC_FREE(dst);
1041 return NULL;
1044 return dst;
1047 struct auth_session_info *copy_session_info(TALLOC_CTX *mem_ctx,
1048 const struct auth_session_info *src)
1050 struct auth_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_auth_session_info);
1057 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1058 DEBUG(0, ("copy_session_info(): ndr_push_auth_session_info failed: "
1059 "%s\n", ndr_errstr(ndr_err)));
1060 return NULL;
1063 dst = talloc(mem_ctx, struct auth_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_auth_session_info);
1073 TALLOC_FREE(blob.data);
1075 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1076 DEBUG(0, ("copy_session_info(): ndr_pull_auth_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 auth_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 auth_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 'auth_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 auth_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 auth_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 auth_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 auth_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 support 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 /* copy in the info3 */
1409 result->info3 = i3 = copy_netr_SamInfo3(result, info3);
1410 if (result->info3 == NULL) {
1411 TALLOC_FREE(result);
1412 return NT_STATUS_NO_MEMORY;
1415 /* Fill in the unix info we found on the way */
1416 result->utok.uid = pwd->pw_uid;
1417 result->utok.gid = pwd->pw_gid;
1419 /* We can't just trust that the primary group sid sent us is something
1420 * we can really use. Obtain the usable sid, and store the original
1421 * one as an additional group if it had to be replaced */
1422 nt_status = get_primary_group_sid(mem_ctx, found_username,
1423 &pwd, &group_sid);
1424 if (!NT_STATUS_IS_OK(nt_status)) {
1425 TALLOC_FREE(result);
1426 return nt_status;
1429 /* store and check if it is the same we got originally */
1430 sid_peek_rid(group_sid, &i3->base.primary_gid);
1431 if (i3->base.primary_gid != info3->base.primary_gid) {
1432 uint32_t n = i3->base.groups.count;
1433 /* not the same, store the original as an additional group */
1434 i3->base.groups.rids =
1435 talloc_realloc(i3, i3->base.groups.rids,
1436 struct samr_RidWithAttribute, n + 1);
1437 if (i3->base.groups.rids == NULL) {
1438 TALLOC_FREE(result);
1439 return NT_STATUS_NO_MEMORY;
1441 i3->base.groups.rids[n].rid = info3->base.primary_gid;
1442 i3->base.groups.rids[n].attributes = SE_GROUP_ENABLED;
1443 i3->base.groups.count = n + 1;
1446 /* ensure we are never given NULL session keys */
1448 if (memcmp(info3->base.key.key, zeros, sizeof(zeros)) == 0) {
1449 result->session_key = data_blob_null;
1450 } else {
1451 result->session_key = data_blob_talloc(
1452 result, info3->base.key.key,
1453 sizeof(info3->base.key.key));
1456 if (memcmp(info3->base.LMSessKey.key, zeros, 8) == 0) {
1457 result->lm_session_key = data_blob_null;
1458 } else {
1459 result->lm_session_key = data_blob_talloc(
1460 result, info3->base.LMSessKey.key,
1461 sizeof(info3->base.LMSessKey.key));
1464 result->nss_token |= username_was_mapped;
1466 result->guest = (info3->base.user_flags & NETLOGON_GUEST);
1468 *server_info = result;
1470 return NT_STATUS_OK;
1473 /*****************************************************************************
1474 Make a server_info struct from the wbcAuthUserInfo returned by a domain logon
1475 ******************************************************************************/
1477 NTSTATUS make_server_info_wbcAuthUserInfo(TALLOC_CTX *mem_ctx,
1478 const char *sent_nt_username,
1479 const char *domain,
1480 const struct wbcAuthUserInfo *info,
1481 struct auth_serversupplied_info **server_info)
1483 struct netr_SamInfo3 *info3;
1485 info3 = wbcAuthUserInfo_to_netr_SamInfo3(mem_ctx, info);
1486 if (!info3) {
1487 return NT_STATUS_NO_MEMORY;
1490 return make_server_info_info3(mem_ctx,
1491 sent_nt_username, domain,
1492 server_info, info3);
1496 * Verify whether or not given domain is trusted.
1498 * @param domain_name name of the domain to be verified
1499 * @return true if domain is one of the trusted ones or
1500 * false if otherwise
1503 bool is_trusted_domain(const char* dom_name)
1505 struct dom_sid trustdom_sid;
1506 bool ret;
1508 /* no trusted domains for a standalone server */
1510 if ( lp_server_role() == ROLE_STANDALONE )
1511 return false;
1513 if (dom_name == NULL || dom_name[0] == '\0') {
1514 return false;
1517 if (strequal(dom_name, get_global_sam_name())) {
1518 return false;
1521 /* if we are a DC, then check for a direct trust relationships */
1523 if ( IS_DC ) {
1524 become_root();
1525 DEBUG (5,("is_trusted_domain: Checking for domain trust with "
1526 "[%s]\n", dom_name ));
1527 ret = pdb_get_trusteddom_pw(dom_name, NULL, NULL, NULL);
1528 unbecome_root();
1529 if (ret)
1530 return true;
1532 else {
1533 wbcErr result;
1535 /* If winbind is around, ask it */
1537 result = wb_is_trusted_domain(dom_name);
1539 if (result == WBC_ERR_SUCCESS) {
1540 return true;
1543 if (result == WBC_ERR_DOMAIN_NOT_FOUND) {
1544 /* winbind could not find the domain */
1545 return false;
1548 /* The only other possible result is that winbind is not up
1549 and running. We need to update the trustdom_cache
1550 ourselves */
1552 update_trustdom_cache();
1555 /* now the trustdom cache should be available a DC could still
1556 * have a transitive trust so fall back to the cache of trusted
1557 * domains (like a domain member would use */
1559 if ( trustdom_cache_fetch(dom_name, &trustdom_sid) ) {
1560 return true;
1563 return false;
1569 on a logon error possibly map the error to success if "map to guest"
1570 is set approriately
1572 NTSTATUS do_map_to_guest_server_info(NTSTATUS status,
1573 struct auth_serversupplied_info **server_info,
1574 const char *user, const char *domain)
1576 user = user ? user : "";
1577 domain = domain ? domain : "";
1579 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
1580 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
1581 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
1582 DEBUG(3,("No such user %s [%s] - using guest account\n",
1583 user, domain));
1584 return make_server_info_guest(NULL, server_info);
1586 } else if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1587 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
1588 DEBUG(3,("Registered username %s for guest access\n",
1589 user));
1590 return make_server_info_guest(NULL, server_info);
1594 return status;