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
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 #define DBGC_CLASS DBGC_AUTH
29 extern DOM_SID global_sid_World
;
30 extern DOM_SID global_sid_Network
;
31 extern DOM_SID global_sid_Builtin_Guests
;
32 extern DOM_SID global_sid_Authenticated_Users
;
35 /****************************************************************************
36 Create a UNIX user on demand.
37 ****************************************************************************/
39 static int smb_create_user(const char *unix_user
, const char *homedir
)
44 pstrcpy(add_script
, lp_adduser_script());
47 all_string_sub(add_script
, "%u", unix_user
, sizeof(pstring
));
49 all_string_sub(add_script
, "%H", homedir
, sizeof(pstring
));
50 ret
= smbrun(add_script
,NULL
);
51 DEBUG(3,("smb_create_user: Running the command `%s' gave %d\n",add_script
,ret
));
55 /****************************************************************************
56 Add and Delete UNIX users on demand, based on NTSTATUS codes.
57 ****************************************************************************/
59 void smb_user_control(const auth_usersupplied_info
*user_info
, auth_serversupplied_info
*server_info
, NTSTATUS nt_status
)
61 struct passwd
*pwd
=NULL
;
63 if (NT_STATUS_IS_OK(nt_status
)) {
65 if (!(server_info
->sam_fill_level
& SAM_FILL_UNIX
)) {
68 * User validated ok against Domain controller.
69 * If the admin wants us to try and create a UNIX
70 * user on the fly, do so.
73 if(lp_adduser_script() && !(pwd
= Get_Pwnam(user_info
->internal_username
.str
))) {
74 smb_create_user(user_info
->internal_username
.str
, NULL
);
80 /****************************************************************************
81 Create an auth_usersupplied_data structure
82 ****************************************************************************/
84 static NTSTATUS
make_user_info(auth_usersupplied_info
**user_info
,
86 const char *internal_username
,
87 const char *client_domain
,
89 const char *wksta_name
,
90 DATA_BLOB lm_pwd
, DATA_BLOB nt_pwd
,
92 uint32 auth_flags
, BOOL encrypted
)
95 DEBUG(5,("attempting to make a user_info for %s (%s)\n", internal_username
, smb_name
));
97 *user_info
= malloc(sizeof(**user_info
));
99 DEBUG(0,("malloc failed for user_info (size %d)\n", sizeof(*user_info
)));
100 return NT_STATUS_NO_MEMORY
;
103 ZERO_STRUCTP(*user_info
);
105 DEBUG(5,("making strings for %s's user_info struct\n", internal_username
));
107 (*user_info
)->smb_name
.str
= strdup(smb_name
);
108 if ((*user_info
)->smb_name
.str
) {
109 (*user_info
)->smb_name
.len
= strlen(smb_name
);
111 free_user_info(user_info
);
112 return NT_STATUS_NO_MEMORY
;
115 (*user_info
)->internal_username
.str
= strdup(internal_username
);
116 if ((*user_info
)->internal_username
.str
) {
117 (*user_info
)->internal_username
.len
= strlen(internal_username
);
119 free_user_info(user_info
);
120 return NT_STATUS_NO_MEMORY
;
123 (*user_info
)->domain
.str
= strdup(domain
);
124 if ((*user_info
)->domain
.str
) {
125 (*user_info
)->domain
.len
= strlen(domain
);
127 free_user_info(user_info
);
128 return NT_STATUS_NO_MEMORY
;
131 (*user_info
)->client_domain
.str
= strdup(client_domain
);
132 if ((*user_info
)->client_domain
.str
) {
133 (*user_info
)->client_domain
.len
= strlen(client_domain
);
135 free_user_info(user_info
);
136 return NT_STATUS_NO_MEMORY
;
139 (*user_info
)->wksta_name
.str
= strdup(wksta_name
);
140 if ((*user_info
)->wksta_name
.str
) {
141 (*user_info
)->wksta_name
.len
= strlen(wksta_name
);
143 free_user_info(user_info
);
144 return NT_STATUS_NO_MEMORY
;
147 DEBUG(5,("making blobs for %s's user_info struct\n", internal_username
));
149 (*user_info
)->lm_resp
= data_blob(lm_pwd
.data
, lm_pwd
.length
);
150 (*user_info
)->nt_resp
= data_blob(nt_pwd
.data
, nt_pwd
.length
);
151 (*user_info
)->plaintext_password
= data_blob(plaintext
.data
, plaintext
.length
);
153 (*user_info
)->encrypted
= encrypted
;
154 (*user_info
)->auth_flags
= auth_flags
;
156 DEBUG(10,("made an %sencrypted user_info for %s (%s)\n", encrypted
? "":"un" , internal_username
, smb_name
));
161 /****************************************************************************
162 Create an auth_usersupplied_data structure after appropriate mapping.
163 ****************************************************************************/
165 NTSTATUS
make_user_info_map(auth_usersupplied_info
**user_info
,
166 const char *smb_name
,
167 const char *client_domain
,
168 const char *wksta_name
,
169 DATA_BLOB lm_pwd
, DATA_BLOB nt_pwd
,
171 uint32 ntlmssp_flags
, BOOL encrypted
)
174 fstring internal_username
;
175 fstrcpy(internal_username
, smb_name
);
176 map_username(internal_username
);
178 DEBUG(5, ("make_user_info_map: Mapping user [%s]\\[%s] from workstation [%s]\n",
179 client_domain
, smb_name
, wksta_name
));
181 if (lp_allow_trusted_domains() && *client_domain
) {
183 /* the client could have given us a workstation name
184 or other crap for the workgroup - we really need a
185 way of telling if this domain name is one of our
188 Also don't allow "" as a domain, fixes a Win9X bug
189 where it doens't supply a domain for logon script
192 The way I do it here is by checking if the fully
193 qualified username exists. This is rather reliant
194 on winbind, but until we have a better method this
198 domain
= client_domain
;
200 if ((smb_name
) && (*smb_name
)) { /* Don't do this for guests */
202 if (asprintf(&user
, "%s%s%s",
203 client_domain
, lp_winbind_separator(),
205 DEBUG(0, ("make_user_info_map: asprintf() failed!\n"));
206 return NT_STATUS_NO_MEMORY
;
209 DEBUG(5, ("make_user_info_map: testing for user %s\n", user
));
211 if (Get_Pwnam(user
) == NULL
) {
212 DEBUG(5, ("make_user_info_map: test for user %s failed\n", user
));
213 domain
= lp_workgroup();
214 DEBUG(5, ("make_user_info_map: trusted domain %s doesn't appear to exist, using %s\n",
215 client_domain
, domain
));
217 DEBUG(5, ("make_user_info_map: using trusted domain %s\n", domain
));
222 domain
= lp_workgroup();
225 return make_user_info(user_info
,
226 smb_name
, internal_username
,
227 client_domain
, domain
,
231 ntlmssp_flags
, encrypted
);
235 /****************************************************************************
236 Create an auth_usersupplied_data, making the DATA_BLOBs here.
237 Decrypt and encrypt the passwords.
238 ****************************************************************************/
240 BOOL
make_user_info_netlogon_network(auth_usersupplied_info
**user_info
,
241 const char *smb_name
,
242 const char *client_domain
,
243 const char *wksta_name
,
244 const uchar
*lm_network_pwd
, int lm_pwd_len
,
245 const uchar
*nt_network_pwd
, int nt_pwd_len
)
249 DATA_BLOB lm_blob
= data_blob(lm_network_pwd
, lm_pwd_len
);
250 DATA_BLOB nt_blob
= data_blob(nt_network_pwd
, nt_pwd_len
);
251 DATA_BLOB plaintext_blob
= data_blob(NULL
, 0);
252 uint32 auth_flags
= AUTH_FLAG_NONE
;
255 auth_flags
|= AUTH_FLAG_LM_RESP
;
256 if (nt_pwd_len
== 24) {
257 auth_flags
|= AUTH_FLAG_NTLM_RESP
;
258 } else if (nt_pwd_len
!= 0) {
259 auth_flags
|= AUTH_FLAG_NTLMv2_RESP
;
262 nt_status
= make_user_info_map(user_info
,
263 smb_name
, client_domain
,
269 ret
= NT_STATUS_IS_OK(nt_status
) ? True
: False
;
271 data_blob_free(&lm_blob
);
272 data_blob_free(&nt_blob
);
276 /****************************************************************************
277 Create an auth_usersupplied_data, making the DATA_BLOBs here.
278 Decrypt and encrypt the passwords.
279 ****************************************************************************/
281 BOOL
make_user_info_netlogon_interactive(auth_usersupplied_info
**user_info
,
282 const char *smb_name
,
283 const char *client_domain
,
284 const char *wksta_name
,
286 const uchar lm_interactive_pwd
[16],
287 const uchar nt_interactive_pwd
[16],
288 const uchar
*dc_sess_key
)
292 unsigned char local_lm_response
[24];
293 unsigned char local_nt_response
[24];
294 unsigned char key
[16];
295 uint32 auth_flags
= AUTH_FLAG_NONE
;
298 memcpy(key
, dc_sess_key
, 8);
300 if (lm_interactive_pwd
) memcpy(lm_pwd
, lm_interactive_pwd
, sizeof(lm_pwd
));
301 if (nt_interactive_pwd
) memcpy(nt_pwd
, nt_interactive_pwd
, sizeof(nt_pwd
));
303 #ifdef DEBUG_PASSWORD
305 dump_data(100, (char *)key
, sizeof(key
));
307 DEBUG(100,("lm owf password:"));
308 dump_data(100, lm_pwd
, sizeof(lm_pwd
));
310 DEBUG(100,("nt owf password:"));
311 dump_data(100, nt_pwd
, sizeof(nt_pwd
));
314 SamOEMhash((uchar
*)lm_pwd
, key
, sizeof(lm_pwd
));
315 SamOEMhash((uchar
*)nt_pwd
, key
, sizeof(nt_pwd
));
317 #ifdef DEBUG_PASSWORD
318 DEBUG(100,("decrypt of lm owf password:"));
319 dump_data(100, lm_pwd
, sizeof(lm_pwd
));
321 DEBUG(100,("decrypt of nt owf password:"));
322 dump_data(100, nt_pwd
, sizeof(nt_pwd
));
325 SMBOWFencrypt((const unsigned char *)lm_pwd
, chal
, local_lm_response
);
326 SMBOWFencrypt((const unsigned char *)nt_pwd
, chal
, local_nt_response
);
328 /* Password info paranoia */
336 DATA_BLOB local_lm_blob
= data_blob(local_lm_response
, sizeof(local_lm_response
));
337 DATA_BLOB local_nt_blob
= data_blob(local_nt_response
, sizeof(local_nt_response
));
338 DATA_BLOB plaintext_blob
= data_blob(NULL
, 0);
340 if (lm_interactive_pwd
)
341 auth_flags
|= AUTH_FLAG_LM_RESP
;
342 if (nt_interactive_pwd
)
343 auth_flags
|= AUTH_FLAG_NTLM_RESP
;
345 nt_status
= make_user_info_map(user_info
,
346 smb_name
, client_domain
,
353 ret
= NT_STATUS_IS_OK(nt_status
) ? True
: False
;
354 data_blob_free(&local_lm_blob
);
355 data_blob_free(&local_nt_blob
);
361 /****************************************************************************
362 Create an auth_usersupplied_data structure
363 ****************************************************************************/
365 BOOL
make_user_info_for_reply(auth_usersupplied_info
**user_info
,
366 const char *smb_name
,
367 const char *client_domain
,
369 DATA_BLOB plaintext_password
)
372 DATA_BLOB local_lm_blob
;
373 DATA_BLOB local_nt_blob
;
374 NTSTATUS ret
= NT_STATUS_UNSUCCESSFUL
;
375 uint32 auth_flags
= AUTH_FLAG_NONE
;
378 * Not encrypted - do so.
381 DEBUG(5,("make_user_info_for_reply: User passwords not in encrypted format.\n"));
383 if (plaintext_password
.data
) {
384 unsigned char local_lm_response
[24];
386 #ifdef DEBUG_PASSWORD
387 DEBUG(10,("Unencrypted password (len %d):\n",plaintext_password
.length
));
388 dump_data(100, plaintext_password
.data
, plaintext_password
.length
);
391 SMBencrypt( (const uchar
*)plaintext_password
.data
, (const uchar
*)chal
, local_lm_response
);
392 local_lm_blob
= data_blob(local_lm_response
, 24);
394 /* We can't do an NT hash here, as the password needs to be
396 local_nt_blob
= data_blob(NULL
, 0);
398 auth_flags
= (AUTH_FLAG_PLAINTEXT
| AUTH_FLAG_LM_RESP
);
400 local_lm_blob
= data_blob(NULL
, 0);
401 local_nt_blob
= data_blob(NULL
, 0);
404 ret
= make_user_info_map(user_info
, smb_name
,
406 get_remote_machine_name(),
412 data_blob_free(&local_lm_blob
);
413 return NT_STATUS_IS_OK(ret
) ? True
: False
;
416 /****************************************************************************
417 Create an auth_usersupplied_data structure
418 ****************************************************************************/
420 NTSTATUS
make_user_info_for_reply_enc(auth_usersupplied_info
**user_info
,
421 const char *smb_name
,
422 const char *client_domain
,
423 DATA_BLOB lm_resp
, DATA_BLOB nt_resp
)
425 uint32 auth_flags
= AUTH_FLAG_NONE
;
427 DATA_BLOB no_plaintext_blob
= data_blob(NULL
, 0);
429 if (lm_resp
.length
== 24) {
430 auth_flags
|= AUTH_FLAG_LM_RESP
;
432 if (nt_resp
.length
== 0) {
433 } else if (nt_resp
.length
== 24) {
434 auth_flags
|= AUTH_FLAG_NTLM_RESP
;
436 auth_flags
|= AUTH_FLAG_NTLMv2_RESP
;
439 return make_user_info_map(user_info
, smb_name
,
441 get_remote_machine_name(),
448 /****************************************************************************
449 Create a guest user_info blob, for anonymous authenticaion.
450 ****************************************************************************/
452 BOOL
make_user_info_guest(auth_usersupplied_info
**user_info
)
454 DATA_BLOB lm_blob
= data_blob(NULL
, 0);
455 DATA_BLOB nt_blob
= data_blob(NULL
, 0);
456 DATA_BLOB plaintext_blob
= data_blob(NULL
, 0);
457 uint32 auth_flags
= AUTH_FLAG_NONE
;
460 nt_status
= make_user_info(user_info
,
468 return NT_STATUS_IS_OK(nt_status
) ? True
: False
;
471 /****************************************************************************
472 prints a NT_USER_TOKEN to debug output.
473 ****************************************************************************/
475 void debug_nt_user_token(int dbg_class
, int dbg_lev
, NT_USER_TOKEN
*token
)
481 DEBUGC(dbg_class
, dbg_lev
, ("NT user token: (NULL)\n"));
485 DEBUGC(dbg_class
, dbg_lev
, ("NT user token of user %s\n",
486 sid_to_string(sid_str
, &token
->user_sids
[0]) ));
487 DEBUGADDC(dbg_class
, dbg_lev
, ("contains %i SIDs\n", token
->num_sids
));
488 for (i
= 0; i
< token
->num_sids
; i
++)
489 DEBUGADDC(dbg_class
, dbg_lev
, ("SID[%3i]: %s\n", i
,
490 sid_to_string(sid_str
, &token
->user_sids
[i
])));
493 /****************************************************************************
494 prints a UNIX 'token' to debug output.
495 ****************************************************************************/
497 void debug_unix_user_token(int dbg_class
, int dbg_lev
, uid_t uid
, gid_t gid
, int n_groups
, gid_t
*groups
)
500 DEBUGC(dbg_class
, dbg_lev
, ("UNIX token of user %ld\n", (long int)uid
));
502 DEBUGADDC(dbg_class
, dbg_lev
, ("Primary group is %ld and contains %i supplementary groups\n", (long int)gid
, n_groups
));
503 for (i
= 0; i
< n_groups
; i
++)
504 DEBUGADDC(dbg_class
, dbg_lev
, ("Group[%3i]: %ld\n", i
,
505 (long int)groups
[i
]));
508 /****************************************************************************
509 Create the SID list for this user.
510 ****************************************************************************/
512 static NTSTATUS
create_nt_user_token(const DOM_SID
*user_sid
, const DOM_SID
*group_sid
,
513 int n_groupSIDs
, DOM_SID
*groupSIDs
,
514 BOOL is_guest
, NT_USER_TOKEN
**token
)
516 NTSTATUS nt_status
= NT_STATUS_OK
;
517 NT_USER_TOKEN
*ptoken
;
521 if ((ptoken
= malloc( sizeof(NT_USER_TOKEN
) ) ) == NULL
) {
522 DEBUG(0, ("create_nt_token: Out of memory allocating token\n"));
523 nt_status
= NT_STATUS_NO_MEMORY
;
527 ZERO_STRUCTP(ptoken
);
529 ptoken
->num_sids
= n_groupSIDs
+ 5;
531 if ((ptoken
->user_sids
= (DOM_SID
*)malloc( sizeof(DOM_SID
) * ptoken
->num_sids
)) == NULL
) {
532 DEBUG(0, ("create_nt_token: Out of memory allocating SIDs\n"));
533 nt_status
= NT_STATUS_NO_MEMORY
;
537 memset((char*)ptoken
->user_sids
,0,sizeof(DOM_SID
) * ptoken
->num_sids
);
540 * Note - user SID *MUST* be first in token !
541 * se_access_check depends on this.
543 * Primary group SID is second in token. Convention.
546 sid_copy(&ptoken
->user_sids
[PRIMARY_USER_SID_INDEX
], user_sid
);
548 sid_copy(&ptoken
->user_sids
[PRIMARY_GROUP_SID_INDEX
], group_sid
);
551 * Finally add the "standard" SIDs.
552 * The only difference between guest and "anonymous" (which we
553 * don't really support) is the addition of Authenticated_Users.
556 sid_copy(&ptoken
->user_sids
[2], &global_sid_World
);
557 sid_copy(&ptoken
->user_sids
[3], &global_sid_Network
);
560 sid_copy(&ptoken
->user_sids
[4], &global_sid_Builtin_Guests
);
562 sid_copy(&ptoken
->user_sids
[4], &global_sid_Authenticated_Users
);
564 sid_ndx
= 5; /* next available spot */
566 for (i
= 0; i
< n_groupSIDs
; i
++) {
567 size_t check_sid_idx
;
568 for (check_sid_idx
= 1; check_sid_idx
< ptoken
->num_sids
; check_sid_idx
++) {
569 if (sid_equal(&ptoken
->user_sids
[check_sid_idx
],
575 if (check_sid_idx
>= ptoken
->num_sids
) /* Not found already */ {
576 sid_copy(&ptoken
->user_sids
[sid_ndx
++], &groupSIDs
[i
]);
582 debug_nt_user_token(DBGC_AUTH
, 10, ptoken
);
589 /****************************************************************************
590 Create the SID list for this user.
591 ****************************************************************************/
593 NT_USER_TOKEN
*create_nt_token(uid_t uid
, gid_t gid
, int ngroups
, gid_t
*groups
, BOOL is_guest
)
598 NT_USER_TOKEN
*token
;
601 if (!uid_to_sid(&user_sid
, uid
)) {
604 if (!gid_to_sid(&group_sid
, gid
)) {
608 group_sids
= malloc(sizeof(DOM_SID
) * ngroups
);
610 DEBUG(0, ("create_nt_token: malloc() failed for DOM_SID list!\n"));
614 for (i
= 0; i
< ngroups
; i
++) {
615 if (!gid_to_sid(&(group_sids
)[i
], (groups
)[i
])) {
616 DEBUG(1, ("create_nt_token: failed to convert gid %ld to a sid!\n", (long int)groups
[i
]));
617 SAFE_FREE(group_sids
);
622 if (!NT_STATUS_IS_OK(create_nt_user_token(&user_sid
, &group_sid
,
623 ngroups
, group_sids
, is_guest
, &token
))) {
624 SAFE_FREE(group_sids
);
628 SAFE_FREE(group_sids
);
633 /******************************************************************************
634 * this function returns the groups (SIDs) of the local SAM the user is in.
635 * If this samba server is a DC of the domain the user belongs to, it returns
636 * both domain groups and local / builtin groups. If the user is in a trusted
637 * domain, or samba is a member server of a domain, then this function returns
638 * local and builtin groups the user is a member of.
640 * currently this is a hack, as there is no sam implementation that is capable
642 ******************************************************************************/
644 static NTSTATUS
get_user_groups_from_local_sam(const DOM_SID
*user_sid
,
645 int *n_groups
, DOM_SID
**groups
, gid_t
**unix_groups
)
648 enum SID_NAME_USE snu
;
657 if (!sid_to_uid(user_sid
, &uid
, &snu
)) {
658 DEBUG(2, ("get_user_groups_from_local_sam: Failed to convert user SID %s to a uid!\n",
659 sid_to_string(str
, user_sid
)));
660 /* This might be a non-unix account */
665 * This is _essential_ to prevent occasional segfaults when
666 * winbind can't find uid -> username mapping
668 if (!(usr
= getpwuid_alloc(uid
))) {
669 DEBUG(0, ("Couldn't find passdb structure for UID = %d ! Aborting.\n", uid
));
670 return NT_STATUS_NO_SUCH_USER
;
673 n_unix_groups
= groups_max();
674 if ((*unix_groups
= malloc( sizeof(gid_t
) * groups_max() ) ) == NULL
) {
675 DEBUG(0, ("get_user_groups_from_local_sam: Out of memory allocating unix group list\n"));
677 return NT_STATUS_NO_MEMORY
;
680 if (sys_getgrouplist(usr
->pw_name
, usr
->pw_gid
, *unix_groups
, &n_unix_groups
) == -1) {
681 *unix_groups
= Realloc(*unix_groups
, sizeof(gid_t
) * n_unix_groups
);
682 if (sys_getgrouplist(usr
->pw_name
, usr
->pw_gid
, *unix_groups
, &n_unix_groups
) == -1) {
683 DEBUG(0, ("get_user_groups_from_local_sam: failed to get the unix group list\n"));
684 SAFE_FREE(*unix_groups
);
686 return NT_STATUS_NO_SUCH_USER
; /* what should this return value be? */
690 debug_unix_user_token(DBGC_CLASS
, 5, usr
->pw_uid
, usr
->pw_gid
, n_unix_groups
, *unix_groups
);
694 if (n_unix_groups
> 0) {
695 *groups
= malloc(sizeof(DOM_SID
) * n_unix_groups
);
697 DEBUG(0, ("get_user_group_from_local_sam: malloc() failed for DOM_SID list!\n"));
698 SAFE_FREE(*unix_groups
);
699 return NT_STATUS_NO_MEMORY
;
703 *n_groups
= n_unix_groups
;
705 for (i
= 0; i
< *n_groups
; i
++) {
706 if (!gid_to_sid(&(*groups
)[i
], (*unix_groups
)[i
])) {
707 DEBUG(1, ("get_user_groups_from_local_sam: failed to convert gid %ld to a sid!\n", (long int)(*unix_groups
)[i
+1]));
709 SAFE_FREE(*unix_groups
);
710 return NT_STATUS_NO_SUCH_USER
;
717 /***************************************************************************
718 Make a user_info struct
719 ***************************************************************************/
721 static NTSTATUS
make_server_info(auth_serversupplied_info
**server_info
, SAM_ACCOUNT
*sampass
)
723 *server_info
= malloc(sizeof(**server_info
));
725 DEBUG(0,("make_server_info: malloc failed!\n"));
726 return NT_STATUS_NO_MEMORY
;
728 ZERO_STRUCTP(*server_info
);
730 (*server_info
)->sam_fill_level
= SAM_FILL_ALL
;
731 (*server_info
)->sam_account
= sampass
;
736 /***************************************************************************
737 Make (and fill) a user_info struct from a SAM_ACCOUNT
738 ***************************************************************************/
740 NTSTATUS
make_server_info_sam(auth_serversupplied_info
**server_info
,
741 SAM_ACCOUNT
*sampass
)
743 NTSTATUS nt_status
= NT_STATUS_OK
;
744 const DOM_SID
*user_sid
= pdb_get_user_sid(sampass
);
745 const DOM_SID
*group_sid
= pdb_get_group_sid(sampass
);
747 DOM_SID
*groupSIDs
= NULL
;
748 gid_t
*unix_groups
= NULL
;
749 NT_USER_TOKEN
*token
;
753 if (!NT_STATUS_IS_OK(nt_status
= make_server_info(server_info
, sampass
))) {
757 if (!NT_STATUS_IS_OK(nt_status
758 = get_user_groups_from_local_sam(pdb_get_user_sid(sampass
),
759 &n_groupSIDs
, &groupSIDs
, &unix_groups
)))
761 DEBUG(4,("get_user_groups_from_local_sam failed\n"));
762 free_server_info(server_info
);
766 is_guest
= (sid_peek_rid(user_sid
, &rid
) && rid
== DOMAIN_USER_RID_GUEST
);
768 if (!NT_STATUS_IS_OK(nt_status
= create_nt_user_token(user_sid
, group_sid
,
769 n_groupSIDs
, groupSIDs
, is_guest
,
772 DEBUG(4,("create_nt_user_token failed\n"));
773 SAFE_FREE(groupSIDs
);
774 SAFE_FREE(unix_groups
);
775 free_server_info(server_info
);
779 SAFE_FREE(groupSIDs
);
781 (*server_info
)->n_groups
= n_groupSIDs
;
782 (*server_info
)->groups
= unix_groups
;
784 (*server_info
)->ptok
= token
;
786 DEBUG(5,("make_server_info_sam: made server info for user %s\n",
787 pdb_get_username((*server_info
)->sam_account
)));
792 /***************************************************************************
793 Make (and fill) a user_info struct from a 'struct passwd' by conversion
795 ***************************************************************************/
797 NTSTATUS
make_server_info_pw(auth_serversupplied_info
**server_info
, const struct passwd
*pwd
)
800 SAM_ACCOUNT
*sampass
= NULL
;
801 if (!NT_STATUS_IS_OK(nt_status
= pdb_init_sam_pw(&sampass
, pwd
))) {
804 return make_server_info_sam(server_info
, sampass
);
807 /***************************************************************************
808 Make (and fill) a user_info struct for a guest login.
809 ***************************************************************************/
811 NTSTATUS
make_server_info_guest(auth_serversupplied_info
**server_info
)
814 SAM_ACCOUNT
*sampass
= NULL
;
817 if (!NT_STATUS_IS_OK(nt_status
= pdb_init_sam(&sampass
))) {
821 sid_copy(&guest_sid
, get_global_sam_sid());
822 sid_append_rid(&guest_sid
, DOMAIN_USER_RID_GUEST
);
825 if (!pdb_getsampwsid(sampass
, &guest_sid
)) {
827 return NT_STATUS_NO_SUCH_USER
;
831 nt_status
= make_server_info_sam(server_info
, sampass
);
833 (*server_info
)->guest
= True
;
838 /***************************************************************************
839 Make a server_info struct from the info3 returned by a domain logon
840 ***************************************************************************/
842 NTSTATUS
make_server_info_info3(TALLOC_CTX
*mem_ctx
,
843 const char *internal_username
,
844 const char *sent_nt_username
,
846 auth_serversupplied_info
**server_info
,
847 NET_USER_INFO_3
*info3
)
849 NTSTATUS nt_status
= NT_STATUS_OK
;
851 const char *nt_domain
;
852 const char *nt_username
;
854 SAM_ACCOUNT
*sam_account
= NULL
;
858 struct passwd
*passwd
;
864 DOM_SID
*lgroupSIDs
= NULL
;
866 gid_t
*unix_groups
= NULL
;
867 NT_USER_TOKEN
*token
;
869 DOM_SID
*all_group_SIDs
;
873 Here is where we should check the list of
874 trusted domains, and verify that the SID
878 sid_copy(&user_sid
, &info3
->dom_sid
.sid
);
879 if (!sid_append_rid(&user_sid
, info3
->user_rid
)) {
880 return NT_STATUS_INVALID_PARAMETER
;
883 sid_copy(&group_sid
, &info3
->dom_sid
.sid
);
884 if (!sid_append_rid(&group_sid
, info3
->group_rid
)) {
885 return NT_STATUS_INVALID_PARAMETER
;
888 if (!(nt_username
= unistr2_tdup(mem_ctx
, &(info3
->uni_user_name
)))) {
889 /* If the server didn't give us one, just use the one we sent them */
890 nt_username
= sent_nt_username
;
893 if (!(nt_domain
= unistr2_tdup(mem_ctx
, &(info3
->uni_logon_dom
)))) {
894 /* If the server didn't give us one, just use the one we sent them */
898 if (winbind_sid_to_uid(&uid
, &user_sid
)
899 && winbind_sid_to_gid(&gid
, &group_sid
)
900 && ((passwd
= getpwuid_alloc(uid
)))) {
901 nt_status
= pdb_init_sam_pw(&sam_account
, passwd
);
902 passwd_free(&passwd
);
905 dom_user
= talloc_asprintf(mem_ctx
, "%s%s%s",
907 lp_winbind_separator(),
911 DEBUG(0, ("talloc_asprintf failed!\n"));
912 return NT_STATUS_NO_MEMORY
;
915 if (!(passwd
= Get_Pwnam(dom_user
))
916 /* Only lookup local for the local
917 domain, we don't want this for
919 && strequal(nt_domain
, lp_workgroup())) {
920 passwd
= Get_Pwnam(internal_username
);
924 return NT_STATUS_NO_SUCH_USER
;
926 nt_status
= pdb_init_sam_pw(&sam_account
, passwd
);
931 if (!NT_STATUS_IS_OK(nt_status
)) {
932 DEBUG(0, ("make_server_info_info3: pdb_init_sam failed!\n"));
936 if (!pdb_set_user_sid(sam_account
, &user_sid
, PDB_CHANGED
)) {
937 pdb_free_sam(&sam_account
);
938 return NT_STATUS_UNSUCCESSFUL
;
941 if (!pdb_set_group_sid(sam_account
, &group_sid
, PDB_CHANGED
)) {
942 pdb_free_sam(&sam_account
);
943 return NT_STATUS_UNSUCCESSFUL
;
946 if (!pdb_set_nt_username(sam_account
, nt_username
, PDB_CHANGED
)) {
947 pdb_free_sam(&sam_account
);
948 return NT_STATUS_NO_MEMORY
;
951 if (!pdb_set_domain(sam_account
, nt_domain
, PDB_CHANGED
)) {
952 pdb_free_sam(&sam_account
);
953 return NT_STATUS_NO_MEMORY
;
956 if (!pdb_set_fullname(sam_account
, unistr2_static(&(info3
->uni_full_name
)), PDB_CHANGED
)) {
957 pdb_free_sam(&sam_account
);
958 return NT_STATUS_NO_MEMORY
;
961 if (!pdb_set_logon_script(sam_account
, unistr2_static(&(info3
->uni_logon_script
)), PDB_CHANGED
)) {
962 pdb_free_sam(&sam_account
);
963 return NT_STATUS_NO_MEMORY
;
966 if (!pdb_set_profile_path(sam_account
, unistr2_static(&(info3
->uni_profile_path
)), PDB_CHANGED
)) {
967 pdb_free_sam(&sam_account
);
968 return NT_STATUS_NO_MEMORY
;
971 if (!pdb_set_homedir(sam_account
, unistr2_static(&(info3
->uni_home_dir
)), PDB_CHANGED
)) {
972 pdb_free_sam(&sam_account
);
973 return NT_STATUS_NO_MEMORY
;
976 if (!pdb_set_dir_drive(sam_account
, unistr2_static(&(info3
->uni_dir_drive
)), PDB_CHANGED
)) {
977 pdb_free_sam(&sam_account
);
978 return NT_STATUS_NO_MEMORY
;
981 if (!NT_STATUS_IS_OK(nt_status
= make_server_info(server_info
, sam_account
))) {
982 DEBUG(4, ("make_server_info failed!\n"));
983 pdb_free_sam(&sam_account
);
987 /* Store the user group information in the server_info
988 returned to the caller. */
990 if (!NT_STATUS_IS_OK(nt_status
991 = get_user_groups_from_local_sam(&user_sid
,
996 DEBUG(4,("get_user_groups_from_local_sam failed\n"));
1000 (*server_info
)->groups
= unix_groups
;
1001 (*server_info
)->n_groups
= n_lgroupSIDs
;
1003 /* Create a 'combined' list of all SIDs we might want in the SD */
1004 all_group_SIDs
= malloc(sizeof(DOM_SID
) *
1005 (n_lgroupSIDs
+ info3
->num_groups2
+
1006 info3
->num_other_sids
));
1007 if (!all_group_SIDs
) {
1008 DEBUG(0, ("create_nt_token_info3: malloc() failed for DOM_SID list!\n"));
1009 SAFE_FREE(lgroupSIDs
);
1010 return NT_STATUS_NO_MEMORY
;
1013 /* Copy the 'local' sids */
1014 memcpy(all_group_SIDs
, lgroupSIDs
, sizeof(DOM_SID
) * n_lgroupSIDs
);
1015 SAFE_FREE(lgroupSIDs
);
1017 /* and create (by appending rids) the 'domain' sids */
1018 for (i
= 0; i
< info3
->num_groups2
; i
++) {
1019 sid_copy(&all_group_SIDs
[i
+n_lgroupSIDs
], &(info3
->dom_sid
.sid
));
1020 if (!sid_append_rid(&all_group_SIDs
[i
+n_lgroupSIDs
], info3
->gids
[i
].g_rid
)) {
1021 nt_status
= NT_STATUS_INVALID_PARAMETER
;
1022 DEBUG(3,("create_nt_token_info3: could not append additional group rid 0x%x\n",
1023 info3
->gids
[i
].g_rid
));
1024 SAFE_FREE(lgroupSIDs
);
1029 /* Copy 'other' sids. We need to do sid filtering here to
1030 prevent possible elevation of privileges. See:
1032 http://www.microsoft.com/windows2000/techinfo/administration/security/sidfilter.asp
1035 for (i
= 0; i
< info3
->num_other_sids
; i
++)
1036 sid_copy(&all_group_SIDs
[
1037 n_lgroupSIDs
+ info3
->num_groups2
+ i
],
1038 &info3
->other_sids
[i
].sid
);
1040 /* Where are the 'global' sids... */
1042 /* can the user be guest? if yes, where is it stored? */
1043 if (!NT_STATUS_IS_OK(
1044 nt_status
= create_nt_user_token(
1045 &user_sid
, &group_sid
,
1046 n_lgroupSIDs
+ info3
->num_groups2
+ info3
->num_other_sids
,
1047 all_group_SIDs
, False
, &token
))) {
1048 DEBUG(4,("create_nt_user_token failed\n"));
1049 SAFE_FREE(all_group_SIDs
);
1053 (*server_info
)->ptok
= token
;
1055 SAFE_FREE(all_group_SIDs
);
1057 return NT_STATUS_OK
;
1060 /***************************************************************************
1061 Free a user_info struct
1062 ***************************************************************************/
1064 void free_user_info(auth_usersupplied_info
**user_info
)
1066 DEBUG(5,("attempting to free (and zero) a user_info structure\n"));
1067 if (*user_info
!= NULL
) {
1068 if ((*user_info
)->smb_name
.str
) {
1069 DEBUG(10,("structure was created for %s\n", (*user_info
)->smb_name
.str
));
1071 SAFE_FREE((*user_info
)->smb_name
.str
);
1072 SAFE_FREE((*user_info
)->internal_username
.str
);
1073 SAFE_FREE((*user_info
)->client_domain
.str
);
1074 SAFE_FREE((*user_info
)->domain
.str
);
1075 SAFE_FREE((*user_info
)->wksta_name
.str
);
1076 data_blob_free(&(*user_info
)->lm_resp
);
1077 data_blob_free(&(*user_info
)->nt_resp
);
1078 SAFE_FREE((*user_info
)->interactive_password
);
1079 data_blob_clear_free(&(*user_info
)->plaintext_password
);
1080 ZERO_STRUCT(**user_info
);
1082 SAFE_FREE(*user_info
);
1085 /***************************************************************************
1086 Clear out a server_info struct that has been allocated
1087 ***************************************************************************/
1089 void free_server_info(auth_serversupplied_info
**server_info
)
1091 DEBUG(5,("attempting to free (and zero) a server_info structure\n"));
1092 if (*server_info
!= NULL
) {
1093 pdb_free_sam(&(*server_info
)->sam_account
);
1095 /* call pam_end here, unless we know we are keeping it */
1096 delete_nt_token( &(*server_info
)->ptok
);
1097 SAFE_FREE((*server_info
)->groups
);
1098 ZERO_STRUCT(**server_info
);
1100 SAFE_FREE(*server_info
);
1103 /***************************************************************************
1104 Make an auth_methods struct
1105 ***************************************************************************/
1107 BOOL
make_auth_methods(struct auth_context
*auth_context
, auth_methods
**auth_method
)
1109 if (!auth_context
) {
1110 smb_panic("no auth_context supplied to make_auth_methods()!\n");
1114 smb_panic("make_auth_methods: pointer to auth_method pointer is NULL!\n");
1117 *auth_method
= talloc(auth_context
->mem_ctx
, sizeof(**auth_method
));
1118 if (!*auth_method
) {
1119 DEBUG(0,("make_auth_method: malloc failed!\n"));
1122 ZERO_STRUCTP(*auth_method
);
1127 /****************************************************************************
1129 ****************************************************************************/
1131 void delete_nt_token(NT_USER_TOKEN
**pptoken
)
1134 NT_USER_TOKEN
*ptoken
= *pptoken
;
1135 SAFE_FREE( ptoken
->user_sids
);
1136 ZERO_STRUCTP(ptoken
);
1138 SAFE_FREE(*pptoken
);
1141 /****************************************************************************
1142 Duplicate a SID token.
1143 ****************************************************************************/
1145 NT_USER_TOKEN
*dup_nt_token(NT_USER_TOKEN
*ptoken
)
1147 NT_USER_TOKEN
*token
;
1152 if ((token
= (NT_USER_TOKEN
*)malloc( sizeof(NT_USER_TOKEN
) ) ) == NULL
)
1155 ZERO_STRUCTP(token
);
1157 if ((token
->user_sids
= (DOM_SID
*)memdup( ptoken
->user_sids
, sizeof(DOM_SID
) * ptoken
->num_sids
)) == NULL
) {
1162 token
->num_sids
= ptoken
->num_sids
;
1168 * Squash an NT_STATUS in line with security requirements.
1169 * In an attempt to avoid giving the whole game away when users
1170 * are authenticating, NT replaces both NT_STATUS_NO_SUCH_USER and
1171 * NT_STATUS_WRONG_PASSWORD with NT_STATUS_LOGON_FAILURE in certain situations
1172 * (session setups in particular).
1174 * @param nt_status NTSTATUS input for squashing.
1175 * @return the 'squashed' nt_status
1178 NTSTATUS
nt_status_squash(NTSTATUS nt_status
)
1180 if NT_STATUS_IS_OK(nt_status
) {
1182 } else if NT_STATUS_EQUAL(nt_status
, NT_STATUS_NO_SUCH_USER
) {
1183 /* Match WinXP and don't give the game away */
1184 return NT_STATUS_LOGON_FAILURE
;
1186 } else if NT_STATUS_EQUAL(nt_status
, NT_STATUS_WRONG_PASSWORD
) {
1187 /* Match WinXP and don't give the game away */
1188 return NT_STATUS_LOGON_FAILURE
;