Make use of ZERO_STRUCT instead of memset in namequery.c
[Samba.git] / source / auth / auth_util.c
blob7013285809c1e4d32f379c10747f1c74c405328b
1 /*
2 Unix SMB/CIFS implementation.
3 Authentication utility functions
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 2000-2001
7 Copyright (C) Rafal Szczesniak 2002
8 Copyright (C) Volker Lendecke 2006
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "includes.h"
26 #undef DBGC_CLASS
27 #define DBGC_CLASS DBGC_AUTH
29 /****************************************************************************
30 Create a UNIX user on demand.
31 ****************************************************************************/
33 static int smb_create_user(const char *domain, const char *unix_username, const char *homedir)
35 TALLOC_CTX *ctx = talloc_tos();
36 char *add_script;
37 int ret;
39 add_script = talloc_strdup(ctx, lp_adduser_script());
40 if (!add_script || !*add_script) {
41 return -1;
43 add_script = talloc_all_string_sub(ctx,
44 add_script,
45 "%u",
46 unix_username);
47 if (!add_script) {
48 return -1;
50 if (domain) {
51 add_script = talloc_all_string_sub(ctx,
52 add_script,
53 "%D",
54 domain);
55 if (!add_script) {
56 return -1;
59 if (homedir) {
60 add_script = talloc_all_string_sub(ctx,
61 add_script,
62 "%H",
63 homedir);
64 if (!add_script) {
65 return -1;
68 ret = smbrun(add_script,NULL);
69 flush_pwnam_cache();
70 DEBUG(ret ? 0 : 3,
71 ("smb_create_user: Running the command `%s' gave %d\n",
72 add_script,ret));
73 return ret;
76 /****************************************************************************
77 Create an auth_usersupplied_data structure
78 ****************************************************************************/
80 static NTSTATUS make_user_info(auth_usersupplied_info **user_info,
81 const char *smb_name,
82 const char *internal_username,
83 const char *client_domain,
84 const char *domain,
85 const char *wksta_name,
86 DATA_BLOB *lm_pwd, DATA_BLOB *nt_pwd,
87 DATA_BLOB *lm_interactive_pwd, DATA_BLOB *nt_interactive_pwd,
88 DATA_BLOB *plaintext,
89 bool encrypted)
92 DEBUG(5,("attempting to make a user_info for %s (%s)\n", internal_username, smb_name));
94 *user_info = SMB_MALLOC_P(auth_usersupplied_info);
95 if (*user_info == NULL) {
96 DEBUG(0,("malloc failed for user_info (size %lu)\n", (unsigned long)sizeof(*user_info)));
97 return NT_STATUS_NO_MEMORY;
100 ZERO_STRUCTP(*user_info);
102 DEBUG(5,("making strings for %s's user_info struct\n", internal_username));
104 (*user_info)->smb_name = SMB_STRDUP(smb_name);
105 if ((*user_info)->smb_name == NULL) {
106 free_user_info(user_info);
107 return NT_STATUS_NO_MEMORY;
110 (*user_info)->internal_username = SMB_STRDUP(internal_username);
111 if ((*user_info)->internal_username == NULL) {
112 free_user_info(user_info);
113 return NT_STATUS_NO_MEMORY;
116 (*user_info)->domain = SMB_STRDUP(domain);
117 if ((*user_info)->domain == NULL) {
118 free_user_info(user_info);
119 return NT_STATUS_NO_MEMORY;
122 (*user_info)->client_domain = SMB_STRDUP(client_domain);
123 if ((*user_info)->client_domain == NULL) {
124 free_user_info(user_info);
125 return NT_STATUS_NO_MEMORY;
128 (*user_info)->wksta_name = SMB_STRDUP(wksta_name);
129 if ((*user_info)->wksta_name == NULL) {
130 free_user_info(user_info);
131 return NT_STATUS_NO_MEMORY;
134 DEBUG(5,("making blobs for %s's user_info struct\n", internal_username));
136 if (lm_pwd)
137 (*user_info)->lm_resp = data_blob(lm_pwd->data, lm_pwd->length);
138 if (nt_pwd)
139 (*user_info)->nt_resp = data_blob(nt_pwd->data, nt_pwd->length);
140 if (lm_interactive_pwd)
141 (*user_info)->lm_interactive_pwd = data_blob(lm_interactive_pwd->data, lm_interactive_pwd->length);
142 if (nt_interactive_pwd)
143 (*user_info)->nt_interactive_pwd = data_blob(nt_interactive_pwd->data, nt_interactive_pwd->length);
145 if (plaintext)
146 (*user_info)->plaintext_password = data_blob(plaintext->data, plaintext->length);
148 (*user_info)->encrypted = encrypted;
150 (*user_info)->logon_parameters = 0;
152 DEBUG(10,("made an %sencrypted user_info for %s (%s)\n", encrypted ? "":"un" , internal_username, smb_name));
154 return NT_STATUS_OK;
157 /****************************************************************************
158 Create an auth_usersupplied_data structure after appropriate mapping.
159 ****************************************************************************/
161 NTSTATUS make_user_info_map(auth_usersupplied_info **user_info,
162 const char *smb_name,
163 const char *client_domain,
164 const char *wksta_name,
165 DATA_BLOB *lm_pwd, DATA_BLOB *nt_pwd,
166 DATA_BLOB *lm_interactive_pwd, DATA_BLOB *nt_interactive_pwd,
167 DATA_BLOB *plaintext,
168 bool encrypted)
170 const char *domain;
171 NTSTATUS result;
172 bool was_mapped;
173 fstring internal_username;
174 fstrcpy(internal_username, smb_name);
175 was_mapped = map_username(internal_username);
177 DEBUG(5, ("make_user_info_map: Mapping user [%s]\\[%s] from workstation [%s]\n",
178 client_domain, smb_name, wksta_name));
180 /* don't allow "" as a domain, fixes a Win9X bug
181 where it doens't supply a domain for logon script
182 'net use' commands. */
184 if ( *client_domain )
185 domain = client_domain;
186 else
187 domain = lp_workgroup();
189 /* do what win2k does. Always map unknown domains to our own
190 and let the "passdb backend" handle unknown users. */
192 if ( !is_trusted_domain(domain) && !strequal(domain, get_global_sam_name()) )
193 domain = my_sam_name();
195 /* we know that it is a trusted domain (and we are allowing them) or it is our domain */
197 result = make_user_info(user_info, smb_name, internal_username,
198 client_domain, domain, wksta_name,
199 lm_pwd, nt_pwd,
200 lm_interactive_pwd, nt_interactive_pwd,
201 plaintext, encrypted);
202 if (NT_STATUS_IS_OK(result)) {
203 (*user_info)->was_mapped = was_mapped;
205 return result;
208 /****************************************************************************
209 Create an auth_usersupplied_data, making the DATA_BLOBs here.
210 Decrypt and encrypt the passwords.
211 ****************************************************************************/
213 bool make_user_info_netlogon_network(auth_usersupplied_info **user_info,
214 const char *smb_name,
215 const char *client_domain,
216 const char *wksta_name,
217 uint32 logon_parameters,
218 const uchar *lm_network_pwd,
219 int lm_pwd_len,
220 const uchar *nt_network_pwd,
221 int nt_pwd_len)
223 bool ret;
224 NTSTATUS status;
225 DATA_BLOB lm_blob = data_blob(lm_network_pwd, lm_pwd_len);
226 DATA_BLOB nt_blob = data_blob(nt_network_pwd, nt_pwd_len);
228 status = make_user_info_map(user_info,
229 smb_name, client_domain,
230 wksta_name,
231 lm_pwd_len ? &lm_blob : NULL,
232 nt_pwd_len ? &nt_blob : NULL,
233 NULL, NULL, NULL,
234 True);
236 if (NT_STATUS_IS_OK(status)) {
237 (*user_info)->logon_parameters = logon_parameters;
239 ret = NT_STATUS_IS_OK(status) ? True : False;
241 data_blob_free(&lm_blob);
242 data_blob_free(&nt_blob);
243 return ret;
246 /****************************************************************************
247 Create an auth_usersupplied_data, making the DATA_BLOBs here.
248 Decrypt and encrypt the passwords.
249 ****************************************************************************/
251 bool make_user_info_netlogon_interactive(auth_usersupplied_info **user_info,
252 const char *smb_name,
253 const char *client_domain,
254 const char *wksta_name,
255 uint32 logon_parameters,
256 const uchar chal[8],
257 const uchar lm_interactive_pwd[16],
258 const uchar nt_interactive_pwd[16],
259 const uchar *dc_sess_key)
261 unsigned char lm_pwd[16];
262 unsigned char nt_pwd[16];
263 unsigned char local_lm_response[24];
264 unsigned char local_nt_response[24];
265 unsigned char key[16];
267 ZERO_STRUCT(key);
268 memcpy(key, dc_sess_key, 8);
270 if (lm_interactive_pwd)
271 memcpy(lm_pwd, lm_interactive_pwd, sizeof(lm_pwd));
273 if (nt_interactive_pwd)
274 memcpy(nt_pwd, nt_interactive_pwd, sizeof(nt_pwd));
276 #ifdef DEBUG_PASSWORD
277 DEBUG(100,("key:"));
278 dump_data(100, key, sizeof(key));
280 DEBUG(100,("lm owf password:"));
281 dump_data(100, lm_pwd, sizeof(lm_pwd));
283 DEBUG(100,("nt owf password:"));
284 dump_data(100, nt_pwd, sizeof(nt_pwd));
285 #endif
287 if (lm_interactive_pwd)
288 SamOEMhash(lm_pwd, key, sizeof(lm_pwd));
290 if (nt_interactive_pwd)
291 SamOEMhash(nt_pwd, key, sizeof(nt_pwd));
293 #ifdef DEBUG_PASSWORD
294 DEBUG(100,("decrypt of lm owf password:"));
295 dump_data(100, lm_pwd, sizeof(lm_pwd));
297 DEBUG(100,("decrypt of nt owf password:"));
298 dump_data(100, nt_pwd, sizeof(nt_pwd));
299 #endif
301 if (lm_interactive_pwd)
302 SMBOWFencrypt(lm_pwd, chal,
303 local_lm_response);
305 if (nt_interactive_pwd)
306 SMBOWFencrypt(nt_pwd, chal,
307 local_nt_response);
309 /* Password info paranoia */
310 ZERO_STRUCT(key);
313 bool ret;
314 NTSTATUS nt_status;
315 DATA_BLOB local_lm_blob;
316 DATA_BLOB local_nt_blob;
318 DATA_BLOB lm_interactive_blob;
319 DATA_BLOB nt_interactive_blob;
321 if (lm_interactive_pwd) {
322 local_lm_blob = data_blob(local_lm_response,
323 sizeof(local_lm_response));
324 lm_interactive_blob = data_blob(lm_pwd,
325 sizeof(lm_pwd));
326 ZERO_STRUCT(lm_pwd);
329 if (nt_interactive_pwd) {
330 local_nt_blob = data_blob(local_nt_response,
331 sizeof(local_nt_response));
332 nt_interactive_blob = data_blob(nt_pwd,
333 sizeof(nt_pwd));
334 ZERO_STRUCT(nt_pwd);
337 nt_status = make_user_info_map(
338 user_info,
339 smb_name, client_domain, wksta_name,
340 lm_interactive_pwd ? &local_lm_blob : NULL,
341 nt_interactive_pwd ? &local_nt_blob : NULL,
342 lm_interactive_pwd ? &lm_interactive_blob : NULL,
343 nt_interactive_pwd ? &nt_interactive_blob : NULL,
344 NULL, True);
346 if (NT_STATUS_IS_OK(nt_status)) {
347 (*user_info)->logon_parameters = logon_parameters;
350 ret = NT_STATUS_IS_OK(nt_status) ? True : False;
351 data_blob_free(&local_lm_blob);
352 data_blob_free(&local_nt_blob);
353 data_blob_free(&lm_interactive_blob);
354 data_blob_free(&nt_interactive_blob);
355 return ret;
360 /****************************************************************************
361 Create an auth_usersupplied_data structure
362 ****************************************************************************/
364 bool make_user_info_for_reply(auth_usersupplied_info **user_info,
365 const char *smb_name,
366 const char *client_domain,
367 const uint8 chal[8],
368 DATA_BLOB plaintext_password)
371 DATA_BLOB local_lm_blob;
372 DATA_BLOB local_nt_blob;
373 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
376 * Not encrypted - do so.
379 DEBUG(5,("make_user_info_for_reply: User passwords not in encrypted "
380 "format.\n"));
382 if (plaintext_password.data) {
383 unsigned char local_lm_response[24];
385 #ifdef DEBUG_PASSWORD
386 DEBUG(10,("Unencrypted password (len %d):\n",
387 (int)plaintext_password.length));
388 dump_data(100, plaintext_password.data,
389 plaintext_password.length);
390 #endif
392 SMBencrypt( (const char *)plaintext_password.data,
393 (const uchar*)chal, local_lm_response);
394 local_lm_blob = data_blob(local_lm_response, 24);
396 /* We can't do an NT hash here, as the password needs to be
397 case insensitive */
398 local_nt_blob = data_blob_null;
400 } else {
401 local_lm_blob = data_blob_null;
402 local_nt_blob = data_blob_null;
405 ret = make_user_info_map(
406 user_info, smb_name, client_domain,
407 get_remote_machine_name(),
408 local_lm_blob.data ? &local_lm_blob : NULL,
409 local_nt_blob.data ? &local_nt_blob : NULL,
410 NULL, NULL,
411 plaintext_password.data ? &plaintext_password : NULL,
412 False);
414 data_blob_free(&local_lm_blob);
415 return NT_STATUS_IS_OK(ret) ? True : False;
418 /****************************************************************************
419 Create an auth_usersupplied_data structure
420 ****************************************************************************/
422 NTSTATUS make_user_info_for_reply_enc(auth_usersupplied_info **user_info,
423 const char *smb_name,
424 const char *client_domain,
425 DATA_BLOB lm_resp, DATA_BLOB nt_resp)
427 return make_user_info_map(user_info, smb_name,
428 client_domain,
429 get_remote_machine_name(),
430 lm_resp.data ? &lm_resp : NULL,
431 nt_resp.data ? &nt_resp : NULL,
432 NULL, NULL, NULL,
433 True);
436 /****************************************************************************
437 Create a guest user_info blob, for anonymous authenticaion.
438 ****************************************************************************/
440 bool make_user_info_guest(auth_usersupplied_info **user_info)
442 NTSTATUS nt_status;
444 nt_status = make_user_info(user_info,
445 "","",
446 "","",
447 "",
448 NULL, NULL,
449 NULL, NULL,
450 NULL,
451 True);
453 return NT_STATUS_IS_OK(nt_status) ? True : False;
456 static int server_info_dtor(auth_serversupplied_info *server_info)
458 TALLOC_FREE(server_info->sam_account);
459 ZERO_STRUCTP(server_info);
460 return 0;
463 /***************************************************************************
464 Make a server_info struct. Free with TALLOC_FREE().
465 ***************************************************************************/
467 static auth_serversupplied_info *make_server_info(TALLOC_CTX *mem_ctx)
469 struct auth_serversupplied_info *result;
471 result = TALLOC_ZERO_P(mem_ctx, auth_serversupplied_info);
472 if (result == NULL) {
473 DEBUG(0, ("talloc failed\n"));
474 return NULL;
477 talloc_set_destructor(result, server_info_dtor);
479 /* Initialise the uid and gid values to something non-zero
480 which may save us from giving away root access if there
481 is a bug in allocating these fields. */
483 result->uid = -1;
484 result->gid = -1;
485 return result;
488 /***************************************************************************
489 Make (and fill) a user_info struct from a struct samu
490 ***************************************************************************/
492 NTSTATUS make_server_info_sam(auth_serversupplied_info **server_info,
493 struct samu *sampass)
495 NTSTATUS status;
496 struct passwd *pwd;
497 gid_t *gids;
498 auth_serversupplied_info *result;
499 int i;
500 size_t num_gids;
501 DOM_SID unix_group_sid;
504 if ( !(result = make_server_info(NULL)) ) {
505 return NT_STATUS_NO_MEMORY;
508 if ( !(pwd = getpwnam_alloc(result, pdb_get_username(sampass))) ) {
509 DEBUG(1, ("User %s in passdb, but getpwnam() fails!\n",
510 pdb_get_username(sampass)));
511 TALLOC_FREE(result);
512 return NT_STATUS_NO_SUCH_USER;
515 result->sam_account = sampass;
516 /* Ensure thaat the sampass will be freed with the result */
517 talloc_steal(result, sampass);
518 result->unix_name = pwd->pw_name;
519 /* Ensure that we keep pwd->pw_name, because we will free pwd below */
520 talloc_steal(result, pwd->pw_name);
521 result->gid = pwd->pw_gid;
522 result->uid = pwd->pw_uid;
524 TALLOC_FREE(pwd);
526 status = pdb_enum_group_memberships(result, sampass,
527 &result->sids, &gids,
528 &result->num_sids);
530 if (!NT_STATUS_IS_OK(status)) {
531 DEBUG(10, ("pdb_enum_group_memberships failed: %s\n",
532 nt_errstr(status)));
533 result->sam_account = NULL; /* Don't free on error exit. */
534 TALLOC_FREE(result);
535 return status;
538 /* Add the "Unix Group" SID for each gid to catch mapped groups
539 and their Unix equivalent. This is to solve the backwards
540 compatibility problem of 'valid users = +ntadmin' where
541 ntadmin has been paired with "Domain Admins" in the group
542 mapping table. Otherwise smb.conf would need to be changed
543 to 'valid user = "Domain Admins"'. --jerry */
545 num_gids = result->num_sids;
546 for ( i=0; i<num_gids; i++ ) {
547 if ( !gid_to_unix_groups_sid( gids[i], &unix_group_sid ) ) {
548 DEBUG(1,("make_server_info_sam: Failed to create SID "
549 "for gid %d!\n", gids[i]));
550 continue;
552 status = add_sid_to_array_unique(result, &unix_group_sid,
553 &result->sids,
554 &result->num_sids);
555 if (!NT_STATUS_IS_OK(status)) {
556 result->sam_account = NULL; /* Don't free on error exit. */
557 TALLOC_FREE(result);
558 return status;
562 /* For now we throw away the gids and convert via sid_to_gid
563 * later. This needs fixing, but I'd like to get the code straight and
564 * simple first. */
566 TALLOC_FREE(gids);
568 DEBUG(5,("make_server_info_sam: made server info for user %s -> %s\n",
569 pdb_get_username(sampass), result->unix_name));
571 *server_info = result;
573 return NT_STATUS_OK;
576 static NTSTATUS log_nt_token(TALLOC_CTX *tmp_ctx, NT_USER_TOKEN *token)
578 char *command;
579 char *group_sidstr;
580 size_t i;
582 if ((lp_log_nt_token_command() == NULL) ||
583 (strlen(lp_log_nt_token_command()) == 0)) {
584 return NT_STATUS_OK;
587 group_sidstr = talloc_strdup(tmp_ctx, "");
588 for (i=1; i<token->num_sids; i++) {
589 group_sidstr = talloc_asprintf(
590 tmp_ctx, "%s %s", group_sidstr,
591 sid_string_talloc(tmp_ctx, &token->user_sids[i]));
594 command = talloc_string_sub(
595 tmp_ctx, lp_log_nt_token_command(),
596 "%s", sid_string_talloc(tmp_ctx, &token->user_sids[0]));
597 command = talloc_string_sub(tmp_ctx, command, "%t", group_sidstr);
599 if (command == NULL) {
600 return NT_STATUS_NO_MEMORY;
603 DEBUG(8, ("running command: [%s]\n", command));
604 if (smbrun(command, NULL) != 0) {
605 DEBUG(0, ("Could not log NT token\n"));
606 return NT_STATUS_ACCESS_DENIED;
609 return NT_STATUS_OK;
613 * Create the token to use from server_info->sam_account and
614 * server_info->sids (the info3/sam groups). Find the unix gids.
617 NTSTATUS create_local_token(auth_serversupplied_info *server_info)
619 TALLOC_CTX *mem_ctx;
620 NTSTATUS status;
621 size_t i;
624 mem_ctx = talloc_new(NULL);
625 if (mem_ctx == NULL) {
626 DEBUG(0, ("talloc_new failed\n"));
627 return NT_STATUS_NO_MEMORY;
631 * If winbind is not around, we can not make much use of the SIDs the
632 * domain controller provided us with. Likewise if the user name was
633 * mapped to some local unix user.
636 if (((lp_server_role() == ROLE_DOMAIN_MEMBER) && !winbind_ping()) ||
637 (server_info->was_mapped)) {
638 status = create_token_from_username(server_info,
639 server_info->unix_name,
640 server_info->guest,
641 &server_info->uid,
642 &server_info->gid,
643 &server_info->unix_name,
644 &server_info->ptok);
646 } else {
647 server_info->ptok = create_local_nt_token(
648 server_info,
649 pdb_get_user_sid(server_info->sam_account),
650 server_info->guest,
651 server_info->num_sids, server_info->sids);
652 status = server_info->ptok ?
653 NT_STATUS_OK : NT_STATUS_NO_SUCH_USER;
656 if (!NT_STATUS_IS_OK(status)) {
657 TALLOC_FREE(mem_ctx);
658 return status;
661 /* Convert the SIDs to gids. */
663 server_info->n_groups = 0;
664 server_info->groups = NULL;
666 /* Start at index 1, where the groups start. */
668 for (i=1; i<server_info->ptok->num_sids; i++) {
669 gid_t gid;
670 DOM_SID *sid = &server_info->ptok->user_sids[i];
672 if (!sid_to_gid(sid, &gid)) {
673 DEBUG(10, ("Could not convert SID %s to gid, "
674 "ignoring it\n", sid_string_dbg(sid)));
675 continue;
677 add_gid_to_array_unique(server_info, gid, &server_info->groups,
678 &server_info->n_groups);
681 debug_nt_user_token(DBGC_AUTH, 10, server_info->ptok);
683 status = log_nt_token(mem_ctx, server_info->ptok);
685 TALLOC_FREE(mem_ctx);
686 return status;
690 * Create an artificial NT token given just a username. (Initially indended
691 * for force user)
693 * We go through lookup_name() to avoid problems we had with 'winbind use
694 * default domain'.
696 * We have 3 cases:
698 * unmapped unix users: Go directly to nss to find the user's group.
700 * A passdb user: The list of groups is provided by pdb_enum_group_memberships.
702 * If the user is provided by winbind, the primary gid is set to "domain
703 * users" of the user's domain. For an explanation why this is necessary, see
704 * the thread starting at
705 * http://lists.samba.org/archive/samba-technical/2006-January/044803.html.
708 NTSTATUS create_token_from_username(TALLOC_CTX *mem_ctx, const char *username,
709 bool is_guest,
710 uid_t *uid, gid_t *gid,
711 char **found_username,
712 struct nt_user_token **token)
714 NTSTATUS result = NT_STATUS_NO_SUCH_USER;
715 TALLOC_CTX *tmp_ctx;
716 DOM_SID user_sid;
717 enum lsa_SidType type;
718 gid_t *gids;
719 DOM_SID *group_sids;
720 DOM_SID unix_group_sid;
721 size_t num_group_sids;
722 size_t num_gids;
723 size_t i;
725 tmp_ctx = talloc_new(NULL);
726 if (tmp_ctx == NULL) {
727 DEBUG(0, ("talloc_new failed\n"));
728 return NT_STATUS_NO_MEMORY;
731 if (!lookup_name_smbconf(tmp_ctx, username, LOOKUP_NAME_ALL,
732 NULL, NULL, &user_sid, &type)) {
733 DEBUG(1, ("lookup_name_smbconf for %s failed\n", username));
734 goto done;
737 if (type != SID_NAME_USER) {
738 DEBUG(1, ("%s is a %s, not a user\n", username,
739 sid_type_lookup(type)));
740 goto done;
743 if (!sid_to_uid(&user_sid, uid)) {
744 DEBUG(1, ("sid_to_uid for %s (%s) failed\n",
745 username, sid_string_dbg(&user_sid)));
746 goto done;
749 if (sid_check_is_in_our_domain(&user_sid)) {
750 bool ret;
752 /* This is a passdb user, so ask passdb */
754 struct samu *sam_acct = NULL;
756 if ( !(sam_acct = samu_new( tmp_ctx )) ) {
757 result = NT_STATUS_NO_MEMORY;
758 goto done;
761 become_root();
762 ret = pdb_getsampwsid(sam_acct, &user_sid);
763 unbecome_root();
765 if (!ret) {
766 DEBUG(1, ("pdb_getsampwsid(%s) for user %s failed\n",
767 sid_string_dbg(&user_sid), username));
768 DEBUGADD(1, ("Fall back to unix user %s\n", username));
769 goto unix_user;
772 result = pdb_enum_group_memberships(tmp_ctx, sam_acct,
773 &group_sids, &gids,
774 &num_group_sids);
775 if (!NT_STATUS_IS_OK(result)) {
776 DEBUG(10, ("enum_group_memberships failed for %s\n",
777 username));
778 DEBUGADD(1, ("Fall back to unix user %s\n", username));
779 goto unix_user;
782 /* see the smb_panic() in pdb_default_enum_group_memberships */
783 SMB_ASSERT(num_group_sids > 0);
785 *gid = gids[0];
787 /* Ensure we're returning the found_username on the right context. */
788 *found_username = talloc_strdup(mem_ctx,
789 pdb_get_username(sam_acct));
791 } else if (sid_check_is_in_unix_users(&user_sid)) {
793 /* This is a unix user not in passdb. We need to ask nss
794 * directly, without consulting passdb */
796 struct passwd *pass;
799 * This goto target is used as a fallback for the passdb
800 * case. The concrete bug report is when passdb gave us an
801 * unmapped gid.
804 unix_user:
806 uid_to_unix_users_sid(*uid, &user_sid);
808 pass = getpwuid_alloc(tmp_ctx, *uid);
809 if (pass == NULL) {
810 DEBUG(1, ("getpwuid(%d) for user %s failed\n",
811 *uid, username));
812 goto done;
815 if (!getgroups_unix_user(tmp_ctx, username, pass->pw_gid,
816 &gids, &num_group_sids)) {
817 DEBUG(1, ("getgroups_unix_user for user %s failed\n",
818 username));
819 goto done;
822 if (num_group_sids) {
823 group_sids = TALLOC_ARRAY(tmp_ctx, DOM_SID, num_group_sids);
824 if (group_sids == NULL) {
825 DEBUG(1, ("TALLOC_ARRAY failed\n"));
826 result = NT_STATUS_NO_MEMORY;
827 goto done;
829 } else {
830 group_sids = NULL;
833 for (i=0; i<num_group_sids; i++) {
834 gid_to_sid(&group_sids[i], gids[i]);
837 /* In getgroups_unix_user we always set the primary gid */
838 SMB_ASSERT(num_group_sids > 0);
840 *gid = gids[0];
842 /* Ensure we're returning the found_username on the right context. */
843 *found_username = talloc_strdup(mem_ctx, pass->pw_name);
844 } else {
846 /* This user is from winbind, force the primary gid to the
847 * user's "domain users" group. Under certain circumstances
848 * (user comes from NT4), this might be a loss of
849 * information. But we can not rely on winbind getting the
850 * correct info. AD might prohibit winbind looking up that
851 * information. */
853 uint32 dummy;
855 num_group_sids = 1;
856 group_sids = TALLOC_ARRAY(tmp_ctx, DOM_SID, num_group_sids);
857 if (group_sids == NULL) {
858 DEBUG(1, ("TALLOC_ARRAY failed\n"));
859 result = NT_STATUS_NO_MEMORY;
860 goto done;
863 sid_copy(&group_sids[0], &user_sid);
864 sid_split_rid(&group_sids[0], &dummy);
865 sid_append_rid(&group_sids[0], DOMAIN_GROUP_RID_USERS);
867 if (!sid_to_gid(&group_sids[0], gid)) {
868 DEBUG(1, ("sid_to_gid(%s) failed\n",
869 sid_string_dbg(&group_sids[0])));
870 goto done;
873 gids = gid;
875 /* Ensure we're returning the found_username on the right context. */
876 *found_username = talloc_strdup(mem_ctx, username);
879 /* Add the "Unix Group" SID for each gid to catch mapped groups
880 and their Unix equivalent. This is to solve the backwards
881 compatibility problem of 'valid users = +ntadmin' where
882 ntadmin has been paired with "Domain Admins" in the group
883 mapping table. Otherwise smb.conf would need to be changed
884 to 'valid user = "Domain Admins"'. --jerry */
886 num_gids = num_group_sids;
887 for ( i=0; i<num_gids; i++ ) {
888 gid_t high, low;
890 /* don't pickup anything managed by Winbind */
892 if ( lp_idmap_gid(&low, &high) && (gids[i] >= low) && (gids[i] <= high) )
893 continue;
895 if ( !gid_to_unix_groups_sid( gids[i], &unix_group_sid ) ) {
896 DEBUG(1,("create_token_from_username: Failed to create SID "
897 "for gid %d!\n", gids[i]));
898 continue;
900 result = add_sid_to_array_unique(tmp_ctx, &unix_group_sid,
901 &group_sids, &num_group_sids);
902 if (!NT_STATUS_IS_OK(result)) {
903 goto done;
907 /* Ensure we're creating the nt_token on the right context. */
908 *token = create_local_nt_token(mem_ctx, &user_sid,
909 is_guest, num_group_sids, group_sids);
911 if ((*token == NULL) || (*found_username == NULL)) {
912 result = NT_STATUS_NO_MEMORY;
913 goto done;
916 result = NT_STATUS_OK;
917 done:
918 TALLOC_FREE(tmp_ctx);
919 return result;
922 /***************************************************************************
923 Build upon create_token_from_username:
925 Expensive helper function to figure out whether a user given its name is
926 member of a particular group.
927 ***************************************************************************/
929 bool user_in_group_sid(const char *username, const DOM_SID *group_sid)
931 NTSTATUS status;
932 uid_t uid;
933 gid_t gid;
934 char *found_username;
935 struct nt_user_token *token;
936 bool result;
938 TALLOC_CTX *mem_ctx;
940 mem_ctx = talloc_new(NULL);
941 if (mem_ctx == NULL) {
942 DEBUG(0, ("talloc_new failed\n"));
943 return False;
946 status = create_token_from_username(mem_ctx, username, False,
947 &uid, &gid, &found_username,
948 &token);
950 if (!NT_STATUS_IS_OK(status)) {
951 DEBUG(10, ("could not create token for %s\n", username));
952 return False;
955 result = nt_token_check_sid(group_sid, token);
957 TALLOC_FREE(mem_ctx);
958 return result;
962 bool user_in_group(const char *username, const char *groupname)
964 TALLOC_CTX *mem_ctx;
965 DOM_SID group_sid;
966 bool ret;
968 mem_ctx = talloc_new(NULL);
969 if (mem_ctx == NULL) {
970 DEBUG(0, ("talloc_new failed\n"));
971 return False;
974 ret = lookup_name(mem_ctx, groupname, LOOKUP_NAME_ALL,
975 NULL, NULL, &group_sid, NULL);
976 TALLOC_FREE(mem_ctx);
978 if (!ret) {
979 DEBUG(10, ("lookup_name for (%s) failed.\n", groupname));
980 return False;
983 return user_in_group_sid(username, &group_sid);
987 /***************************************************************************
988 Make (and fill) a user_info struct from a 'struct passwd' by conversion
989 to a struct samu
990 ***************************************************************************/
992 NTSTATUS make_server_info_pw(auth_serversupplied_info **server_info,
993 char *unix_username,
994 struct passwd *pwd)
996 NTSTATUS status;
997 struct samu *sampass = NULL;
998 gid_t *gids;
999 char *qualified_name = NULL;
1000 TALLOC_CTX *mem_ctx = NULL;
1001 DOM_SID u_sid;
1002 enum lsa_SidType type;
1003 auth_serversupplied_info *result;
1005 if ( !(sampass = samu_new( NULL )) ) {
1006 return NT_STATUS_NO_MEMORY;
1009 status = samu_set_unix( sampass, pwd );
1010 if (!NT_STATUS_IS_OK(status)) {
1011 return status;
1014 result = make_server_info(NULL);
1015 if (result == NULL) {
1016 TALLOC_FREE(sampass);
1017 return NT_STATUS_NO_MEMORY;
1020 result->sam_account = sampass;
1021 result->unix_name = talloc_strdup(result, unix_username);
1022 result->uid = pwd->pw_uid;
1023 result->gid = pwd->pw_gid;
1025 status = pdb_enum_group_memberships(result, sampass,
1026 &result->sids, &gids,
1027 &result->num_sids);
1029 if (!NT_STATUS_IS_OK(status)) {
1030 DEBUG(10, ("pdb_enum_group_memberships failed: %s\n",
1031 nt_errstr(status)));
1032 TALLOC_FREE(result);
1033 return status;
1037 * The SID returned in server_info->sam_account is based
1038 * on our SAM sid even though for a pure UNIX account this should
1039 * not be the case as it doesn't really exist in the SAM db.
1040 * This causes lookups on "[in]valid users" to fail as they
1041 * will lookup this name as a "Unix User" SID to check against
1042 * the user token. Fix this by adding the "Unix User"\unix_username
1043 * SID to the sid array. The correct fix should probably be
1044 * changing the server_info->sam_account user SID to be a
1045 * S-1-22 Unix SID, but this might break old configs where
1046 * plaintext passwords were used with no SAM backend.
1049 mem_ctx = talloc_init("make_server_info_pw_tmp");
1050 if (!mem_ctx) {
1051 TALLOC_FREE(result);
1052 return NT_STATUS_NO_MEMORY;
1055 qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
1056 unix_users_domain_name(),
1057 unix_username );
1058 if (!qualified_name) {
1059 TALLOC_FREE(result);
1060 TALLOC_FREE(mem_ctx);
1061 return NT_STATUS_NO_MEMORY;
1064 if (!lookup_name(mem_ctx, qualified_name, LOOKUP_NAME_ALL,
1065 NULL, NULL,
1066 &u_sid, &type)) {
1067 TALLOC_FREE(result);
1068 TALLOC_FREE(mem_ctx);
1069 return NT_STATUS_NO_SUCH_USER;
1072 TALLOC_FREE(mem_ctx);
1074 if (type != SID_NAME_USER) {
1075 TALLOC_FREE(result);
1076 return NT_STATUS_NO_SUCH_USER;
1079 status = add_sid_to_array_unique(result, &u_sid,
1080 &result->sids,
1081 &result->num_sids);
1082 if (!NT_STATUS_IS_OK(status)) {
1083 TALLOC_FREE(result);
1084 return status;
1087 /* For now we throw away the gids and convert via sid_to_gid
1088 * later. This needs fixing, but I'd like to get the code straight and
1089 * simple first. */
1090 TALLOC_FREE(gids);
1092 *server_info = result;
1094 return NT_STATUS_OK;
1097 /***************************************************************************
1098 Make (and fill) a user_info struct for a guest login.
1099 This *must* succeed for smbd to start. If there is no mapping entry for
1100 the guest gid, then create one.
1101 ***************************************************************************/
1103 static NTSTATUS make_new_server_info_guest(auth_serversupplied_info **server_info)
1105 NTSTATUS status;
1106 struct samu *sampass = NULL;
1107 DOM_SID guest_sid;
1108 bool ret;
1109 char zeros[16];
1111 if ( !(sampass = samu_new( NULL )) ) {
1112 return NT_STATUS_NO_MEMORY;
1115 sid_copy(&guest_sid, get_global_sam_sid());
1116 sid_append_rid(&guest_sid, DOMAIN_USER_RID_GUEST);
1118 become_root();
1119 ret = pdb_getsampwsid(sampass, &guest_sid);
1120 unbecome_root();
1122 if (!ret) {
1123 TALLOC_FREE(sampass);
1124 return NT_STATUS_NO_SUCH_USER;
1127 status = make_server_info_sam(server_info, sampass);
1128 if (!NT_STATUS_IS_OK(status)) {
1129 TALLOC_FREE(sampass);
1130 return status;
1133 (*server_info)->guest = True;
1135 status = create_local_token(*server_info);
1136 if (!NT_STATUS_IS_OK(status)) {
1137 DEBUG(10, ("create_local_token failed: %s\n",
1138 nt_errstr(status)));
1139 return status;
1142 /* annoying, but the Guest really does have a session key, and it is
1143 all zeros! */
1144 ZERO_STRUCT(zeros);
1145 (*server_info)->user_session_key = data_blob(zeros, sizeof(zeros));
1146 (*server_info)->lm_session_key = data_blob(zeros, sizeof(zeros));
1148 return NT_STATUS_OK;
1151 static auth_serversupplied_info *copy_serverinfo(auth_serversupplied_info *src)
1153 auth_serversupplied_info *dst;
1155 dst = make_server_info(NULL);
1156 if (dst == NULL) {
1157 return NULL;
1160 dst->guest = src->guest;
1161 dst->uid = src->uid;
1162 dst->gid = src->gid;
1163 dst->n_groups = src->n_groups;
1164 if (src->n_groups != 0) {
1165 dst->groups = (gid_t *)TALLOC_MEMDUP(
1166 dst, src->groups, sizeof(gid_t)*dst->n_groups);
1167 } else {
1168 dst->groups = NULL;
1171 if (src->ptok) {
1172 dst->ptok = dup_nt_token(dst, src->ptok);
1173 if (!dst->ptok) {
1174 TALLOC_FREE(dst);
1175 return NULL;
1179 dst->user_session_key = data_blob_talloc( dst, src->user_session_key.data,
1180 src->user_session_key.length);
1182 dst->lm_session_key = data_blob_talloc(dst, src->lm_session_key.data,
1183 src->lm_session_key.length);
1185 dst->sam_account = samu_new(NULL);
1186 if (!dst->sam_account) {
1187 TALLOC_FREE(dst);
1188 return NULL;
1191 if (!pdb_copy_sam_account(dst->sam_account, src->sam_account)) {
1192 TALLOC_FREE(dst);
1193 return NULL;
1196 dst->pam_handle = NULL;
1197 dst->unix_name = talloc_strdup(dst, src->unix_name);
1198 if (!dst->unix_name) {
1199 TALLOC_FREE(dst);
1200 return NULL;
1203 return dst;
1206 static auth_serversupplied_info *guest_info = NULL;
1208 bool init_guest_info(void)
1210 if (guest_info != NULL)
1211 return True;
1213 return NT_STATUS_IS_OK(make_new_server_info_guest(&guest_info));
1216 NTSTATUS make_server_info_guest(auth_serversupplied_info **server_info)
1218 *server_info = copy_serverinfo(guest_info);
1219 return (*server_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1222 bool copy_current_user(struct current_user *dst, struct current_user *src)
1224 gid_t *groups;
1225 NT_USER_TOKEN *nt_token;
1227 groups = (gid_t *)memdup(src->ut.groups,
1228 sizeof(gid_t) * src->ut.ngroups);
1229 if ((src->ut.ngroups != 0) && (groups == NULL)) {
1230 return False;
1233 nt_token = dup_nt_token(NULL, src->nt_user_token);
1234 if (nt_token == NULL) {
1235 SAFE_FREE(groups);
1236 return False;
1239 dst->conn = src->conn;
1240 dst->vuid = src->vuid;
1241 dst->ut.uid = src->ut.uid;
1242 dst->ut.gid = src->ut.gid;
1243 dst->ut.ngroups = src->ut.ngroups;
1244 dst->ut.groups = groups;
1245 dst->nt_user_token = nt_token;
1246 return True;
1249 bool set_current_user_guest(struct current_user *dst)
1251 gid_t *groups;
1252 NT_USER_TOKEN *nt_token;
1254 groups = (gid_t *)memdup(guest_info->groups,
1255 sizeof(gid_t) * guest_info->n_groups);
1256 if (groups == NULL) {
1257 return False;
1260 nt_token = dup_nt_token(NULL, guest_info->ptok);
1261 if (nt_token == NULL) {
1262 SAFE_FREE(groups);
1263 return False;
1266 TALLOC_FREE(dst->nt_user_token);
1267 SAFE_FREE(dst->ut.groups);
1269 /* dst->conn is never really dereferenced, it's only tested for
1270 * equality in uid.c */
1271 dst->conn = NULL;
1273 dst->vuid = UID_FIELD_INVALID;
1274 dst->ut.uid = guest_info->uid;
1275 dst->ut.gid = guest_info->gid;
1276 dst->ut.ngroups = guest_info->n_groups;
1277 dst->ut.groups = groups;
1278 dst->nt_user_token = nt_token;
1279 return True;
1282 /***************************************************************************
1283 Purely internal function for make_server_info_info3
1284 Fill the sam account from getpwnam
1285 ***************************************************************************/
1286 static NTSTATUS fill_sam_account(TALLOC_CTX *mem_ctx,
1287 const char *domain,
1288 const char *username,
1289 char **found_username,
1290 uid_t *uid, gid_t *gid,
1291 struct samu *account,
1292 bool *username_was_mapped)
1294 NTSTATUS nt_status;
1295 fstring dom_user, lower_username;
1296 fstring real_username;
1297 struct passwd *passwd;
1299 fstrcpy( lower_username, username );
1300 strlower_m( lower_username );
1302 fstr_sprintf(dom_user, "%s%c%s", domain, *lp_winbind_separator(),
1303 lower_username);
1305 /* Get the passwd struct. Try to create the account is necessary. */
1307 *username_was_mapped = map_username( dom_user );
1309 if ( !(passwd = smb_getpwnam( NULL, dom_user, real_username, True )) )
1310 return NT_STATUS_NO_SUCH_USER;
1312 *uid = passwd->pw_uid;
1313 *gid = passwd->pw_gid;
1315 /* This is pointless -- there is no suport for differing
1316 unix and windows names. Make sure to always store the
1317 one we actually looked up and succeeded. Have I mentioned
1318 why I hate the 'winbind use default domain' parameter?
1319 --jerry */
1321 *found_username = talloc_strdup( mem_ctx, real_username );
1323 DEBUG(5,("fill_sam_account: located username was [%s]\n", *found_username));
1325 nt_status = samu_set_unix( account, passwd );
1327 TALLOC_FREE(passwd);
1329 return nt_status;
1332 /****************************************************************************
1333 Wrapper to allow the getpwnam() call to strip the domain name and
1334 try again in case a local UNIX user is already there. Also run through
1335 the username if we fallback to the username only.
1336 ****************************************************************************/
1338 struct passwd *smb_getpwnam( TALLOC_CTX *mem_ctx, char *domuser,
1339 fstring save_username, bool create )
1341 struct passwd *pw = NULL;
1342 char *p;
1343 fstring username;
1345 /* we only save a copy of the username it has been mangled
1346 by winbindd use default domain */
1348 save_username[0] = '\0';
1350 /* don't call map_username() here since it has to be done higher
1351 up the stack so we don't call it mutliple times */
1353 fstrcpy( username, domuser );
1355 p = strchr_m( username, *lp_winbind_separator() );
1357 /* code for a DOMAIN\user string */
1359 if ( p ) {
1360 fstring strip_username;
1362 pw = Get_Pwnam_alloc( mem_ctx, domuser );
1363 if ( pw ) {
1364 /* make sure we get the case of the username correct */
1365 /* work around 'winbind use default domain = yes' */
1367 if ( !strchr_m( pw->pw_name, *lp_winbind_separator() ) ) {
1368 char *domain;
1370 /* split the domain and username into 2 strings */
1371 *p = '\0';
1372 domain = username;
1374 fstr_sprintf(save_username, "%s%c%s", domain, *lp_winbind_separator(), pw->pw_name);
1376 else
1377 fstrcpy( save_username, pw->pw_name );
1379 /* whew -- done! */
1380 return pw;
1383 /* setup for lookup of just the username */
1384 /* remember that p and username are overlapping memory */
1386 p++;
1387 fstrcpy( strip_username, p );
1388 fstrcpy( username, strip_username );
1391 /* just lookup a plain username */
1393 pw = Get_Pwnam_alloc(mem_ctx, username);
1395 /* Create local user if requested but only if winbindd
1396 is not running. We need to protect against cases
1397 where winbindd is failing and then prematurely
1398 creating users in /etc/passwd */
1400 if ( !pw && create && !winbind_ping() ) {
1401 /* Don't add a machine account. */
1402 if (username[strlen(username)-1] == '$')
1403 return NULL;
1405 smb_create_user(NULL, username, NULL);
1406 pw = Get_Pwnam_alloc(mem_ctx, username);
1409 /* one last check for a valid passwd struct */
1411 if ( pw )
1412 fstrcpy( save_username, pw->pw_name );
1414 return pw;
1417 /***************************************************************************
1418 Make a server_info struct from the info3 returned by a domain logon
1419 ***************************************************************************/
1421 NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
1422 const char *sent_nt_username,
1423 const char *domain,
1424 auth_serversupplied_info **server_info,
1425 struct netr_SamInfo3 *info3)
1427 char zeros[16];
1429 NTSTATUS nt_status = NT_STATUS_OK;
1430 char *found_username = NULL;
1431 const char *nt_domain;
1432 const char *nt_username;
1433 struct samu *sam_account = NULL;
1434 DOM_SID user_sid;
1435 DOM_SID group_sid;
1436 bool username_was_mapped;
1438 uid_t uid = (uid_t)-1;
1439 gid_t gid = (gid_t)-1;
1441 auth_serversupplied_info *result;
1444 Here is where we should check the list of
1445 trusted domains, and verify that the SID
1446 matches.
1449 sid_copy(&user_sid, info3->base.domain_sid);
1450 if (!sid_append_rid(&user_sid, info3->base.rid)) {
1451 return NT_STATUS_INVALID_PARAMETER;
1454 sid_copy(&group_sid, info3->base.domain_sid);
1455 if (!sid_append_rid(&group_sid, info3->base.primary_gid)) {
1456 return NT_STATUS_INVALID_PARAMETER;
1459 nt_username = talloc_strdup(mem_ctx, info3->base.account_name.string);
1460 if (!nt_username) {
1461 /* If the server didn't give us one, just use the one we sent
1462 * them */
1463 nt_username = sent_nt_username;
1466 nt_domain = talloc_strdup(mem_ctx, info3->base.domain.string);
1467 if (!nt_domain) {
1468 /* If the server didn't give us one, just use the one we sent
1469 * them */
1470 nt_domain = domain;
1473 /* try to fill the SAM account.. If getpwnam() fails, then try the
1474 add user script (2.2.x behavior).
1476 We use the _unmapped_ username here in an attempt to provide
1477 consistent username mapping behavior between kerberos and NTLM[SSP]
1478 authentication in domain mode security. I.E. Username mapping
1479 should be applied to the fully qualified username
1480 (e.g. DOMAIN\user) and not just the login name. Yes this means we
1481 called map_username() unnecessarily in make_user_info_map() but
1482 that is how the current code is designed. Making the change here
1483 is the least disruptive place. -- jerry */
1485 if ( !(sam_account = samu_new( NULL )) ) {
1486 return NT_STATUS_NO_MEMORY;
1489 /* this call will try to create the user if necessary */
1491 nt_status = fill_sam_account(mem_ctx, nt_domain, sent_nt_username,
1492 &found_username, &uid, &gid, sam_account,
1493 &username_was_mapped);
1496 /* if we still don't have a valid unix account check for
1497 'map to guest = bad uid' */
1499 if (!NT_STATUS_IS_OK(nt_status)) {
1500 TALLOC_FREE( sam_account );
1501 if ( lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID ) {
1502 make_server_info_guest(server_info);
1503 return NT_STATUS_OK;
1505 return nt_status;
1508 if (!pdb_set_nt_username(sam_account, nt_username, PDB_CHANGED)) {
1509 TALLOC_FREE(sam_account);
1510 return NT_STATUS_NO_MEMORY;
1513 if (!pdb_set_username(sam_account, nt_username, PDB_CHANGED)) {
1514 TALLOC_FREE(sam_account);
1515 return NT_STATUS_NO_MEMORY;
1518 if (!pdb_set_domain(sam_account, nt_domain, PDB_CHANGED)) {
1519 TALLOC_FREE(sam_account);
1520 return NT_STATUS_NO_MEMORY;
1523 if (!pdb_set_user_sid(sam_account, &user_sid, PDB_CHANGED)) {
1524 TALLOC_FREE(sam_account);
1525 return NT_STATUS_UNSUCCESSFUL;
1528 if (!pdb_set_group_sid(sam_account, &group_sid, PDB_CHANGED)) {
1529 TALLOC_FREE(sam_account);
1530 return NT_STATUS_UNSUCCESSFUL;
1533 if (!pdb_set_fullname(sam_account,
1534 info3->base.full_name.string,
1535 PDB_CHANGED)) {
1536 TALLOC_FREE(sam_account);
1537 return NT_STATUS_NO_MEMORY;
1540 if (!pdb_set_logon_script(sam_account,
1541 info3->base.logon_script.string,
1542 PDB_CHANGED)) {
1543 TALLOC_FREE(sam_account);
1544 return NT_STATUS_NO_MEMORY;
1547 if (!pdb_set_profile_path(sam_account,
1548 info3->base.profile_path.string,
1549 PDB_CHANGED)) {
1550 TALLOC_FREE(sam_account);
1551 return NT_STATUS_NO_MEMORY;
1554 if (!pdb_set_homedir(sam_account,
1555 info3->base.home_directory.string,
1556 PDB_CHANGED)) {
1557 TALLOC_FREE(sam_account);
1558 return NT_STATUS_NO_MEMORY;
1561 if (!pdb_set_dir_drive(sam_account,
1562 info3->base.home_drive.string,
1563 PDB_CHANGED)) {
1564 TALLOC_FREE(sam_account);
1565 return NT_STATUS_NO_MEMORY;
1568 if (!pdb_set_acct_ctrl(sam_account, info3->base.acct_flags, PDB_CHANGED)) {
1569 TALLOC_FREE(sam_account);
1570 return NT_STATUS_NO_MEMORY;
1573 if (!pdb_set_pass_last_set_time(
1574 sam_account,
1575 nt_time_to_unix(info3->base.last_password_change),
1576 PDB_CHANGED)) {
1577 TALLOC_FREE(sam_account);
1578 return NT_STATUS_NO_MEMORY;
1581 if (!pdb_set_pass_can_change_time(
1582 sam_account,
1583 nt_time_to_unix(info3->base.allow_password_change),
1584 PDB_CHANGED)) {
1585 TALLOC_FREE(sam_account);
1586 return NT_STATUS_NO_MEMORY;
1589 if (!pdb_set_pass_must_change_time(
1590 sam_account,
1591 nt_time_to_unix(info3->base.force_password_change),
1592 PDB_CHANGED)) {
1593 TALLOC_FREE(sam_account);
1594 return NT_STATUS_NO_MEMORY;
1597 result = make_server_info(NULL);
1598 if (result == NULL) {
1599 DEBUG(4, ("make_server_info failed!\n"));
1600 TALLOC_FREE(sam_account);
1601 return NT_STATUS_NO_MEMORY;
1604 /* save this here to _net_sam_logon() doesn't fail (it assumes a
1605 valid struct samu) */
1607 result->sam_account = sam_account;
1608 result->unix_name = talloc_strdup(result, found_username);
1610 /* Fill in the unix info we found on the way */
1612 result->uid = uid;
1613 result->gid = gid;
1615 /* Create a 'combined' list of all SIDs we might want in the SD */
1617 result->num_sids = 0;
1618 result->sids = NULL;
1620 nt_status = sid_array_from_info3(result, info3,
1621 &result->sids,
1622 &result->num_sids,
1623 false, false);
1624 if (!NT_STATUS_IS_OK(nt_status)) {
1625 TALLOC_FREE(result);
1626 return nt_status;
1629 result->login_server = talloc_strdup(result,
1630 info3->base.logon_server.string);
1632 /* ensure we are never given NULL session keys */
1634 ZERO_STRUCT(zeros);
1636 if (memcmp(info3->base.key.key, zeros, sizeof(zeros)) == 0) {
1637 result->user_session_key = data_blob_null;
1638 } else {
1639 result->user_session_key = data_blob_talloc(
1640 result, info3->base.key.key,
1641 sizeof(info3->base.key.key));
1644 if (memcmp(info3->base.LMSessKey.key, zeros, 8) == 0) {
1645 result->lm_session_key = data_blob_null;
1646 } else {
1647 result->lm_session_key = data_blob_talloc(
1648 result, info3->base.LMSessKey.key,
1649 sizeof(info3->base.LMSessKey.key));
1652 result->was_mapped = username_was_mapped;
1654 *server_info = result;
1656 return NT_STATUS_OK;
1659 /*****************************************************************************
1660 Make a server_info struct from the wbcAuthUserInfo returned by a domain logon
1661 ******************************************************************************/
1663 NTSTATUS make_server_info_wbcAuthUserInfo(TALLOC_CTX *mem_ctx,
1664 const char *sent_nt_username,
1665 const char *domain,
1666 const struct wbcAuthUserInfo *info,
1667 auth_serversupplied_info **server_info)
1669 char zeros[16];
1671 NTSTATUS nt_status = NT_STATUS_OK;
1672 char *found_username = NULL;
1673 const char *nt_domain;
1674 const char *nt_username;
1675 struct samu *sam_account = NULL;
1676 DOM_SID user_sid;
1677 DOM_SID group_sid;
1678 bool username_was_mapped;
1679 uint32_t i;
1681 uid_t uid = (uid_t)-1;
1682 gid_t gid = (gid_t)-1;
1684 auth_serversupplied_info *result;
1686 result = make_server_info(NULL);
1687 if (result == NULL) {
1688 DEBUG(4, ("make_server_info failed!\n"));
1689 return NT_STATUS_NO_MEMORY;
1693 Here is where we should check the list of
1694 trusted domains, and verify that the SID
1695 matches.
1698 memcpy(&user_sid, &info->sids[0].sid, sizeof(user_sid));
1699 memcpy(&group_sid, &info->sids[1].sid, sizeof(group_sid));
1701 if (info->account_name) {
1702 nt_username = talloc_strdup(result, info->account_name);
1703 } else {
1704 /* If the server didn't give us one, just use the one we sent
1705 * them */
1706 nt_username = talloc_strdup(result, sent_nt_username);
1708 if (!nt_username) {
1709 TALLOC_FREE(result);
1710 return NT_STATUS_NO_MEMORY;
1713 if (info->domain_name) {
1714 nt_domain = talloc_strdup(result, info->domain_name);
1715 } else {
1716 /* If the server didn't give us one, just use the one we sent
1717 * them */
1718 nt_domain = talloc_strdup(result, domain);
1720 if (!nt_domain) {
1721 TALLOC_FREE(result);
1722 return NT_STATUS_NO_MEMORY;
1725 /* try to fill the SAM account.. If getpwnam() fails, then try the
1726 add user script (2.2.x behavior).
1728 We use the _unmapped_ username here in an attempt to provide
1729 consistent username mapping behavior between kerberos and NTLM[SSP]
1730 authentication in domain mode security. I.E. Username mapping
1731 should be applied to the fully qualified username
1732 (e.g. DOMAIN\user) and not just the login name. Yes this means we
1733 called map_username() unnecessarily in make_user_info_map() but
1734 that is how the current code is designed. Making the change here
1735 is the least disruptive place. -- jerry */
1737 if ( !(sam_account = samu_new( result )) ) {
1738 TALLOC_FREE(result);
1739 return NT_STATUS_NO_MEMORY;
1742 /* this call will try to create the user if necessary */
1744 nt_status = fill_sam_account(result, nt_domain, sent_nt_username,
1745 &found_username, &uid, &gid, sam_account,
1746 &username_was_mapped);
1748 /* if we still don't have a valid unix account check for
1749 'map to guest = bad uid' */
1751 if (!NT_STATUS_IS_OK(nt_status)) {
1752 TALLOC_FREE( result );
1753 if ( lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID ) {
1754 make_server_info_guest(server_info);
1755 return NT_STATUS_OK;
1757 return nt_status;
1760 if (!pdb_set_nt_username(sam_account, nt_username, PDB_CHANGED)) {
1761 TALLOC_FREE(result);
1762 return NT_STATUS_NO_MEMORY;
1765 if (!pdb_set_username(sam_account, nt_username, PDB_CHANGED)) {
1766 TALLOC_FREE(result);
1767 return NT_STATUS_NO_MEMORY;
1770 if (!pdb_set_domain(sam_account, nt_domain, PDB_CHANGED)) {
1771 TALLOC_FREE(result);
1772 return NT_STATUS_NO_MEMORY;
1775 if (!pdb_set_user_sid(sam_account, &user_sid, PDB_CHANGED)) {
1776 TALLOC_FREE(result);
1777 return NT_STATUS_UNSUCCESSFUL;
1780 if (!pdb_set_group_sid(sam_account, &group_sid, PDB_CHANGED)) {
1781 TALLOC_FREE(result);
1782 return NT_STATUS_UNSUCCESSFUL;
1785 if (!pdb_set_fullname(sam_account, info->full_name, PDB_CHANGED)) {
1786 TALLOC_FREE(result);
1787 return NT_STATUS_NO_MEMORY;
1790 if (!pdb_set_logon_script(sam_account, info->logon_script, PDB_CHANGED)) {
1791 TALLOC_FREE(result);
1792 return NT_STATUS_NO_MEMORY;
1795 if (!pdb_set_profile_path(sam_account, info->profile_path, PDB_CHANGED)) {
1796 TALLOC_FREE(result);
1797 return NT_STATUS_NO_MEMORY;
1800 if (!pdb_set_homedir(sam_account, info->home_directory, PDB_CHANGED)) {
1801 TALLOC_FREE(result);
1802 return NT_STATUS_NO_MEMORY;
1805 if (!pdb_set_dir_drive(sam_account, info->home_drive, PDB_CHANGED)) {
1806 TALLOC_FREE(result);
1807 return NT_STATUS_NO_MEMORY;
1810 if (!pdb_set_acct_ctrl(sam_account, info->acct_flags, PDB_CHANGED)) {
1811 TALLOC_FREE(result);
1812 return NT_STATUS_NO_MEMORY;
1815 if (!pdb_set_pass_last_set_time(
1816 sam_account,
1817 nt_time_to_unix(info->pass_last_set_time),
1818 PDB_CHANGED)) {
1819 TALLOC_FREE(result);
1820 return NT_STATUS_NO_MEMORY;
1823 if (!pdb_set_pass_can_change_time(
1824 sam_account,
1825 nt_time_to_unix(info->pass_can_change_time),
1826 PDB_CHANGED)) {
1827 TALLOC_FREE(result);
1828 return NT_STATUS_NO_MEMORY;
1831 if (!pdb_set_pass_must_change_time(
1832 sam_account,
1833 nt_time_to_unix(info->pass_must_change_time),
1834 PDB_CHANGED)) {
1835 TALLOC_FREE(result);
1836 return NT_STATUS_NO_MEMORY;
1839 /* save this here to _net_sam_logon() doesn't fail (it assumes a
1840 valid struct samu) */
1842 result->sam_account = sam_account;
1843 result->unix_name = talloc_strdup(result, found_username);
1845 result->login_server = talloc_strdup(result, info->logon_server);
1847 /* Fill in the unix info we found on the way */
1849 result->uid = uid;
1850 result->gid = gid;
1852 /* Create a 'combined' list of all SIDs we might want in the SD */
1854 result->num_sids = info->num_sids - 2;
1855 result->sids = talloc_array(result, DOM_SID, result->num_sids);
1856 if (result->sids == NULL) {
1857 TALLOC_FREE(result);
1858 return NT_STATUS_NO_MEMORY;
1861 for (i=0; i < result->num_sids; i++) {
1862 memcpy(&result->sids[i], &info->sids[i+2].sid, sizeof(result->sids[i]));
1865 /* ensure we are never given NULL session keys */
1867 ZERO_STRUCT(zeros);
1869 if (memcmp(info->user_session_key, zeros, sizeof(zeros)) == 0) {
1870 result->user_session_key = data_blob_null;
1871 } else {
1872 result->user_session_key = data_blob_talloc(
1873 result, info->user_session_key,
1874 sizeof(info->user_session_key));
1877 if (memcmp(info->lm_session_key, zeros, 8) == 0) {
1878 result->lm_session_key = data_blob_null;
1879 } else {
1880 result->lm_session_key = data_blob_talloc(
1881 result, info->lm_session_key,
1882 sizeof(info->lm_session_key));
1885 result->was_mapped = username_was_mapped;
1887 *server_info = result;
1889 return NT_STATUS_OK;
1892 /***************************************************************************
1893 Free a user_info struct
1894 ***************************************************************************/
1896 void free_user_info(auth_usersupplied_info **user_info)
1898 DEBUG(5,("attempting to free (and zero) a user_info structure\n"));
1899 if (*user_info != NULL) {
1900 if ((*user_info)->smb_name) {
1901 DEBUG(10,("structure was created for %s\n",
1902 (*user_info)->smb_name));
1904 SAFE_FREE((*user_info)->smb_name);
1905 SAFE_FREE((*user_info)->internal_username);
1906 SAFE_FREE((*user_info)->client_domain);
1907 SAFE_FREE((*user_info)->domain);
1908 SAFE_FREE((*user_info)->wksta_name);
1909 data_blob_free(&(*user_info)->lm_resp);
1910 data_blob_free(&(*user_info)->nt_resp);
1911 data_blob_clear_free(&(*user_info)->lm_interactive_pwd);
1912 data_blob_clear_free(&(*user_info)->nt_interactive_pwd);
1913 data_blob_clear_free(&(*user_info)->plaintext_password);
1914 ZERO_STRUCT(**user_info);
1916 SAFE_FREE(*user_info);
1919 /***************************************************************************
1920 Make an auth_methods struct
1921 ***************************************************************************/
1923 bool make_auth_methods(struct auth_context *auth_context, auth_methods **auth_method)
1925 if (!auth_context) {
1926 smb_panic("no auth_context supplied to "
1927 "make_auth_methods()!\n");
1930 if (!auth_method) {
1931 smb_panic("make_auth_methods: pointer to auth_method pointer "
1932 "is NULL!\n");
1935 *auth_method = TALLOC_P(auth_context->mem_ctx, auth_methods);
1936 if (!*auth_method) {
1937 DEBUG(0,("make_auth_method: malloc failed!\n"));
1938 return False;
1940 ZERO_STRUCTP(*auth_method);
1942 return True;
1946 * Verify whether or not given domain is trusted.
1948 * @param domain_name name of the domain to be verified
1949 * @return true if domain is one of the trusted once or
1950 * false if otherwise
1953 bool is_trusted_domain(const char* dom_name)
1955 DOM_SID trustdom_sid;
1956 bool ret;
1958 /* no trusted domains for a standalone server */
1960 if ( lp_server_role() == ROLE_STANDALONE )
1961 return False;
1963 /* if we are a DC, then check for a direct trust relationships */
1965 if ( IS_DC ) {
1966 become_root();
1967 DEBUG (5,("is_trusted_domain: Checking for domain trust with "
1968 "[%s]\n", dom_name ));
1969 ret = pdb_get_trusteddom_pw(dom_name, NULL, NULL, NULL);
1970 unbecome_root();
1971 if (ret)
1972 return True;
1974 else {
1975 wbcErr result;
1977 /* If winbind is around, ask it */
1979 result = wb_is_trusted_domain(dom_name);
1981 if (result == WBC_ERR_SUCCESS) {
1982 return True;
1985 if (result == WBC_ERR_DOMAIN_NOT_FOUND) {
1986 /* winbind could not find the domain */
1987 return False;
1990 /* The only other possible result is that winbind is not up
1991 and running. We need to update the trustdom_cache
1992 ourselves */
1994 update_trustdom_cache();
1997 /* now the trustdom cache should be available a DC could still
1998 * have a transitive trust so fall back to the cache of trusted
1999 * domains (like a domain member would use */
2001 if ( trustdom_cache_fetch(dom_name, &trustdom_sid) ) {
2002 return True;
2005 return False;