2 Unix SMB/Netbios implementation.
4 Password and authentication handling
5 Copyright (C) Andrew Tridgell 1992-1998
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 /* users from session setup */
27 static pstring session_users
="";
29 extern pstring global_myname
;
30 extern fstring global_myworkgroup
;
33 * track the machine trust account password timeout when
34 * in domain mode security
36 BOOL global_machine_password_needs_changing
= False
;
38 /* Data to do lanman1/2 password challenge. */
39 static unsigned char saved_challenge
[8];
40 static BOOL challenge_sent
=False
;
42 /*******************************************************************
43 Get the next challenge value - no repeats.
44 ********************************************************************/
46 void generate_next_challenge(char *challenge
)
50 generate_random_buffer(buf
,8,False
);
52 memcpy(saved_challenge
, buf
, 8);
53 memcpy(challenge
,buf
,8);
54 challenge_sent
= True
;
57 /*******************************************************************
58 Set the last challenge sent, usually from a password server.
59 ********************************************************************/
61 BOOL
set_challenge(unsigned char *challenge
)
63 memcpy(saved_challenge
,challenge
,8);
64 challenge_sent
= True
;
68 /*******************************************************************
69 Get the last challenge sent.
70 ********************************************************************/
72 static BOOL
last_challenge(unsigned char *challenge
)
76 memcpy(challenge
,saved_challenge
,8);
80 /* this holds info on user ids that are already validated for this VC */
81 static user_struct
*validated_users
;
82 static int next_vuid
= VUID_OFFSET
;
83 static int num_validated_vuids
;
85 /****************************************************************************
86 Check if a uid has been validated, and return an pointer to the user_struct
87 if it has. NULL if not. vuid is biased by an offset. This allows us to
88 tell random client vuid's (normally zero) from valid vuids.
89 ****************************************************************************/
91 user_struct
*get_valid_user_struct(uint16 vuid
)
96 if (vuid
== UID_FIELD_INVALID
)
99 for (usp
=validated_users
;usp
;usp
=usp
->next
,count
++) {
100 if (vuid
== usp
->vuid
) {
102 DLIST_PROMOTE(validated_users
, usp
);
111 /****************************************************************************
113 ****************************************************************************/
115 void invalidate_vuid(uint16 vuid
)
117 user_struct
*vuser
= get_valid_user_struct(vuid
);
124 DLIST_REMOVE(validated_users
, vuser
);
126 SAFE_FREE(vuser
->groups
);
127 delete_nt_token(&vuser
->nt_user_token
);
129 num_validated_vuids
--;
132 /****************************************************************************
133 Invalidate all vuid entries for this process.
134 ****************************************************************************/
136 void invalidate_all_vuids(void)
138 user_struct
*usp
, *next
=NULL
;
140 for (usp
=validated_users
;usp
;usp
=next
) {
143 invalidate_vuid(usp
->vuid
);
147 /****************************************************************************
148 Return a validated username.
149 ****************************************************************************/
151 char *validated_username(uint16 vuid
)
153 user_struct
*vuser
= get_valid_user_struct(vuid
);
156 return(vuser
->user
.unix_name
);
159 /****************************************************************************
160 Return a validated domain.
161 ****************************************************************************/
163 char *validated_domain(uint16 vuid
)
165 user_struct
*vuser
= get_valid_user_struct(vuid
);
168 return(vuser
->user
.domain
);
171 /****************************************************************************
172 Create the SID list for this user.
173 ****************************************************************************/
175 NT_USER_TOKEN
*create_nt_token(uid_t uid
, gid_t gid
, int ngroups
, gid_t
*groups
, BOOL is_guest
, NT_USER_TOKEN
*sup_tok
)
177 extern DOM_SID global_sid_World
;
178 extern DOM_SID global_sid_Network
;
179 extern DOM_SID global_sid_Builtin_Guests
;
180 extern DOM_SID global_sid_Authenticated_Users
;
181 NT_USER_TOKEN
*token
;
187 if ((token
= (NT_USER_TOKEN
*)malloc( sizeof(NT_USER_TOKEN
) ) ) == NULL
)
192 /* We always have uid/gid plus World and Network and Authenticated Users or Guest SIDs. */
193 num_sids
= 5 + ngroups
;
195 if (sup_tok
&& sup_tok
->num_sids
)
196 num_sids
+= sup_tok
->num_sids
;
198 if ((token
->user_sids
= (DOM_SID
*)malloc( num_sids
*sizeof(DOM_SID
))) == NULL
) {
203 psids
= token
->user_sids
;
206 * Note - user SID *MUST* be first in token !
207 * se_access_check depends on this.
210 uid_to_sid( &psids
[PRIMARY_USER_SID_INDEX
], uid
);
214 * Primary group SID is second in token. Convention.
217 gid_to_sid( &psids
[PRIMARY_GROUP_SID_INDEX
], gid
);
220 /* Now add the group SIDs. */
222 for (i
= 0; i
< ngroups
; i
++) {
223 if (groups
[i
] != gid
) {
224 gid_to_sid( &psids
[psid_ndx
++], groups
[i
]);
228 /* Now add the additional SIDs from the supplimentary token. */
230 for (i
= 0; i
< sup_tok
->num_sids
; i
++)
231 sid_copy( &psids
[psid_ndx
++], &sup_tok
->user_sids
[i
] );
235 * Finally add the "standard" SIDs.
236 * The only difference between guest and "anonymous" (which we
237 * don't really support) is the addition of Authenticated_Users.
240 sid_copy( &psids
[psid_ndx
++], &global_sid_World
);
241 sid_copy( &psids
[psid_ndx
++], &global_sid_Network
);
244 sid_copy( &psids
[psid_ndx
++], &global_sid_Builtin_Guests
);
246 sid_copy( &psids
[psid_ndx
++], &global_sid_Authenticated_Users
);
248 token
->num_sids
= psid_ndx
;
250 /* Dump list of sids in token */
252 for (i
= 0; i
< token
->num_sids
; i
++) {
253 DEBUG(5, ("user token sid %s\n",
254 sid_to_string(sid_str
, &token
->user_sids
[i
])));
260 /****************************************************************************
261 Register a uid/name pair as being valid and that a valid password
262 has been given. vuid is biased by an offset. This allows us to
263 tell random client vuid's (normally zero) from valid vuids.
264 ****************************************************************************/
266 int register_vuid(uid_t uid
,gid_t gid
, char *unix_name
, char *requested_name
,
267 char *domain
,BOOL guest
, NT_USER_TOKEN
**pptok
)
269 user_struct
*vuser
= NULL
;
270 struct passwd
*pwfile
; /* for getting real name from passwd file */
272 /* Ensure no vuid gets registered in share level security. */
273 if(lp_security() == SEC_SHARE
)
274 return UID_FIELD_INVALID
;
276 /* Limit allowed vuids to 16bits - VUID_OFFSET. */
277 if (num_validated_vuids
>= 0xFFFF-VUID_OFFSET
)
278 return UID_FIELD_INVALID
;
280 if((vuser
= (user_struct
*)malloc( sizeof(user_struct
) )) == NULL
) {
281 DEBUG(0,("Failed to malloc users struct!\n"));
282 return UID_FIELD_INVALID
;
287 DEBUG(10,("register_vuid: (%u,%u) %s %s %s guest=%d\n", (unsigned int)uid
, (unsigned int)gid
,
288 unix_name
, requested_name
, domain
, guest
));
290 /* Allocate a free vuid. Yes this is a linear search... :-) */
291 while( get_valid_user_struct(next_vuid
) != NULL
) {
293 /* Check for vuid wrap. */
294 if (next_vuid
== UID_FIELD_INVALID
)
295 next_vuid
= VUID_OFFSET
;
298 DEBUG(10,("register_vuid: allocated vuid = %u\n", (unsigned int)next_vuid
));
300 vuser
->vuid
= next_vuid
;
303 vuser
->guest
= guest
;
304 fstrcpy(vuser
->user
.unix_name
,unix_name
);
305 fstrcpy(vuser
->user
.smb_name
,requested_name
);
306 fstrcpy(vuser
->user
.domain
,domain
);
309 vuser
->groups
= NULL
;
311 /* Find all the groups this uid is in and store them.
312 Used by change_to_user() */
313 initialise_groups(unix_name
, uid
, gid
);
314 get_current_groups( vuser
->gid
, &vuser
->n_groups
, &vuser
->groups
);
316 #ifdef HAVE_GETGROUPS_TOO_MANY_EGIDS
318 * Under OSes to which this applies, we get GID 0 as the first
319 * element of vuser->groups, so we put GID back in there.
320 * It is ignored by setgroups
322 if (vuser
->n_groups
) vuser
->groups
[0] = gid
;
323 #endif /* HAVE_GETGROUPS_TOO_MANY_EGIDS */
326 add_supplementary_nt_login_groups(&vuser
->n_groups
, &vuser
->groups
, pptok
);
328 /* Create an NT_USER_TOKEN struct for this user. */
329 vuser
->nt_user_token
= create_nt_token(uid
,gid
, vuser
->n_groups
, vuser
->groups
, guest
, *pptok
);
332 num_validated_vuids
++;
334 DLIST_ADD(validated_users
, vuser
);
336 DEBUG(3,("uid %d registered to name %s\n",(int)uid
,unix_name
));
338 DEBUG(3, ("Clearing default real name\n"));
339 if ((pwfile
=sys_getpwnam(vuser
->user
.unix_name
))!= NULL
) {
340 DEBUG(3, ("User name: %s\tReal name: %s\n",vuser
->user
.unix_name
,pwfile
->pw_gecos
));
341 fstrcpy(vuser
->user
.full_name
, pwfile
->pw_gecos
);
344 if (!session_claim(vuser
->vuid
)) {
345 DEBUG(1,("Failed to claim session for vuid=%d\n", vuser
->vuid
));
346 invalidate_vuid(vuser
->vuid
);
353 /****************************************************************************
354 Add a name to the session users list.
355 ****************************************************************************/
357 void add_session_user(char *user
)
360 StrnCpy(suser
,user
,sizeof(suser
)-1);
362 if (!Get_Pwnam(suser
,True
))
365 if (suser
&& *suser
&& !in_list(suser
,session_users
,False
)) {
366 if (strlen(suser
) + strlen(session_users
) + 2 >= sizeof(pstring
))
367 DEBUG(1,("Too many session users??\n"));
369 pstrcat(session_users
," ");
370 pstrcat(session_users
,suser
);
375 /****************************************************************************
376 Update the encrypted smbpasswd file from the plaintext username and password.
377 *****************************************************************************/
379 static BOOL
update_smbpassword_file(char *user
, char *password
)
381 SAM_ACCOUNT
*sampass
= NULL
;
384 pdb_init_sam(&sampass
);
387 ret
= pdb_getsampwnam(sampass
, user
);
391 DEBUG(0,("update_smbpassword_file: pdb_getsampwnam failed to locate %s\n", user
));
396 * Remove the account disabled flag - we are updating the
397 * users password from a login.
399 pdb_set_acct_ctrl(sampass
, pdb_get_acct_ctrl(sampass
) & ~ACB_DISABLED
);
401 /* Here, the flag is one, because we want to ignore the
402 XXXXXXX'd out password */
403 ret
= change_oem_password( sampass
, password
, True
);
405 DEBUG(3,("change_oem_password returned False\n"));
409 pdb_free_sam(sampass
);
414 /****************************************************************************
415 Core of smb password checking routine.
416 ****************************************************************************/
418 BOOL
smb_password_check(char *password
, unsigned char *part_passwd
, unsigned char *c8
)
420 /* Finish the encryption of part_passwd. */
421 unsigned char p21
[21];
422 unsigned char p24
[24];
424 if (part_passwd
== NULL
)
425 DEBUG(10,("No password set - allowing access\n"));
427 /* No password set - always true ! */
428 if (part_passwd
== NULL
)
432 memcpy(p21
,part_passwd
,16);
437 DEBUG(100,("Part password (P16) was |"));
438 for(i
= 0; i
< 16; i
++)
439 DEBUG(100,("%X ", (unsigned char)part_passwd
[i
]));
441 DEBUG(100,("Password from client was |"));
442 for(i
= 0; i
< 24; i
++)
443 DEBUG(100,("%X ", (unsigned char)password
[i
]));
445 DEBUG(100,("Given challenge was |"));
446 for(i
= 0; i
< 8; i
++)
447 DEBUG(100,("%X ", (unsigned char)c8
[i
]));
449 DEBUG(100,("Value from encryption was |"));
450 for(i
= 0; i
< 24; i
++)
451 DEBUG(100,("%X ", (unsigned char)p24
[i
]));
455 return (memcmp(p24
, password
, 24) == 0);
458 /****************************************************************************
459 Do a specific test for an smb password being correct, given a smb_password and
460 the lanman and NT responses.
461 ****************************************************************************/
463 BOOL
smb_password_ok(SAM_ACCOUNT
*sampass
, uchar chal
[8],
464 uchar lm_pass
[24], uchar nt_pass
[24])
468 uint8
*nt_pw
, *lm_pw
;
470 if (!lm_pass
|| !sampass
)
473 user_name
= pdb_get_username(sampass
);
475 DEBUG(4,("smb_password_ok: Checking SMB password for user %s\n",user_name
));
477 if(pdb_get_acct_ctrl(sampass
) & ACB_DISABLED
) {
478 DEBUG(1,("smb_password_ok: account for user %s was disabled.\n", user_name
));
483 DEBUG(5,("smb_password_ok: use last SMBnegprot challenge\n"));
484 if (!last_challenge(challenge
)) {
485 DEBUG(1,("smb_password_ok: no challenge done - password failed\n"));
489 DEBUG(5,("smb_password_ok: challenge received\n"));
490 memcpy(challenge
, chal
, 8);
493 nt_pw
= pdb_get_nt_passwd(sampass
);
495 if ((Protocol
>= PROTOCOL_NT1
) && (nt_pw
!= NULL
)) {
496 /* We have the NT MD4 hash challenge available - see if we can
497 use it (ie. does it exist in the smbpasswd file).
499 DEBUG(4,("smb_password_ok: Checking NT MD4 password\n"));
500 if (smb_password_check((char *)nt_pass
, (uchar
*)nt_pw
, challenge
)) {
501 DEBUG(4,("smb_password_ok: NT MD4 password check succeeded\n"));
504 DEBUG(4,("smb_password_ok: NT MD4 password check failed\n"));
507 /* Try against the lanman password. pdb_get_lanman_passwd(sampass) == NULL
508 means no password, allow access. */
510 lm_pw
= pdb_get_lanman_passwd(sampass
);
512 if((lm_pw
== NULL
) && (pdb_get_acct_ctrl(sampass
) & ACB_PWNOTREQ
)) {
513 DEBUG(4,("smb_password_ok: no password required for user %s\n",user_name
));
517 if(lp_lanman_auth() && (lm_pw
!= NULL
)) {
518 DEBUG(4,("smb_password_ok: Checking LM password\n"));
519 if(smb_password_check((char *)lm_pass
,(uchar
*)lm_pw
, challenge
)) {
520 DEBUG(4,("smb_password_ok: LM password check succeeded\n"));
523 DEBUG(4,("smb_password_ok: LM password check failed\n"));
529 /****************************************************************************
530 Check if a username/password is OK assuming the password is a 24 byte
531 SMB hash. Return True if the password is correct, False otherwise.
532 ****************************************************************************/
534 BOOL
pass_check_smb(char *user
, char *domain
, uchar
*chal
,
535 uchar
*lm_pwd
, uchar
*nt_pwd
, struct passwd
*pwd
)
537 SAM_ACCOUNT
*sampass
= NULL
;
539 if (!lm_pwd
|| !nt_pwd
)
542 /* get the account information */
543 pdb_init_sam(&sampass
);
544 if (!pdb_getsampwnam(sampass
, user
)) {
545 DEBUG(1,("Couldn't find user '%s' in passdb.\n", user
));
546 pdb_free_sam(sampass
);
550 /* Quit if the account was disabled. */
551 if(pdb_get_acct_ctrl(sampass
) & ACB_DISABLED
) {
552 DEBUG(1,("Account for user '%s' was disabled.\n", user
));
553 pdb_free_sam(sampass
);
558 if (pdb_get_acct_ctrl(sampass
) & ACB_PWNOTREQ
) {
559 if (lp_null_passwords()) {
560 DEBUG(3,("Account for user '%s' has no password and null passwords are allowed.\n", user
));
561 pdb_free_sam(sampass
);
564 DEBUG(3,("Account for user '%s' has no password and null passwords are NOT allowed.\n", user
));
565 pdb_free_sam(sampass
);
570 if (smb_password_ok(sampass
, chal
, lm_pwd
, nt_pwd
)) {
571 pdb_free_sam(sampass
);
575 DEBUG(2,("pass_check_smb failed - invalid password for user [%s]\n", user
));
577 pdb_free_sam(sampass
);
581 /****************************************************************************
582 Check if a username/password pair is OK either via the system password
583 database or the encrypted SMB password database
584 return True if the password is correct, False otherwise.
585 ****************************************************************************/
587 BOOL
password_ok(char *user
, char *password
, int pwlen
, struct passwd
*pwd
)
592 if ((pwlen
== 0) && !lp_null_passwords()) {
593 DEBUG(4,("Null passwords not allowed.\n"));
597 if (pwlen
== 24 || (lp_encrypted_passwords() && (pwlen
== 0) && lp_null_passwords())) {
598 /* if 24 bytes long assume it is an encrypted password */
601 if (!last_challenge(challenge
)) {
602 DEBUG(0,("Error: challenge not done for user=%s\n", user
));
606 ret
= pass_check_smb(user
, global_myworkgroup
,
607 challenge
, (uchar
*)password
, (uchar
*)password
, pwd
);
610 * Try with PAM (may not be compiled in - returns True if not. JRA).
611 * FIXME ! Should this be called if we're using winbindd ? What about
612 * non-local accounts ? JRA.
616 return (NT_STATUS_V(smb_pam_accountcheck(user
)) == NT_STATUS_V(NT_STATUS_OK
));
621 return (pass_check(user
, password
, pwlen
, pwd
,
622 lp_update_encrypted() ?
623 update_smbpassword_file
: NULL
));
626 /****************************************************************************
627 Check if a username is valid
628 ****************************************************************************/
630 BOOL
user_ok(char *user
,int snum
)
632 pstring valid
, invalid
;
635 StrnCpy(valid
, lp_valid_users(snum
), sizeof(pstring
)-1);
636 StrnCpy(invalid
, lp_invalid_users(snum
), sizeof(pstring
)-1);
638 pstring_sub(valid
,"%S",lp_servicename(snum
));
639 pstring_sub(invalid
,"%S",lp_servicename(snum
));
641 ret
= !user_in_list(user
,invalid
);
643 if (ret
&& valid
&& *valid
)
644 ret
= user_in_list(user
,valid
);
646 if (ret
&& lp_onlyuser(snum
)) {
647 char *user_list
= lp_username(snum
);
648 pstring_sub(user_list
,"%S",lp_servicename(snum
));
649 ret
= user_in_list(user
,user_list
);
655 /****************************************************************************
656 Validate a group username entry. Return the username or NULL.
657 ****************************************************************************/
659 static char *validate_group(const char *group
,char *password
,int pwlen
,int snum
)
663 char *host
, *user
, *domain
;
665 while (getnetgrent(&host
, &user
, &domain
)) {
667 if (user_ok(user
, snum
) &&
668 password_ok(user
,password
,pwlen
,NULL
)) {
679 struct sys_userlist
*user_list
= get_users_in_group(group
);
680 struct sys_userlist
*member
;
682 for (member
= user_list
; member
; member
= member
->next
) {
684 fstrcpy(name
,member
->unix_name
);
685 if (user_ok(name
,snum
) &&
686 password_ok(name
,password
,pwlen
,NULL
)) {
687 free_userlist(user_list
);
691 DEBUG(10,("validate_group = member = %s\n", member
->unix_name
));
693 free_userlist(user_list
);
699 /****************************************************************************
700 Check for authority to login to a service with a given username/password.
701 Note this is *NOT* used when logging on using sessionsetup_and_X.
702 ****************************************************************************/
704 BOOL
authorise_login(int snum
,char *user
,char *password
, int pwlen
,
705 BOOL
*guest
,BOOL
*force
,uint16 vuid
)
708 user_struct
*vuser
= get_valid_user_struct(vuid
);
711 DEBUG(100,("authorise_login: checking authorisation on user=%s pass=%s\n",
717 if (GUEST_ONLY(snum
))
720 if (!GUEST_ONLY(snum
) && (lp_security() > SEC_SHARE
)) {
723 * We should just use the given vuid from a sessionsetup_and_X.
727 DEBUG(1,("authorise_login: refusing user %s with no session setup\n",
732 if (!vuser
->guest
&& user_ok(vuser
->user
.unix_name
,snum
)) {
733 fstrcpy(user
,vuser
->user
.unix_name
);
735 DEBUG(3,("authorise_login: ACCEPTED: validated uid ok as non-guest \
736 (user=%s)\n", user
));
741 /* there are several possibilities:
742 1) login as the given user with given password
743 2) login as a previously registered username with the given password
744 3) login as a session list username with the given password
745 4) login as a previously validated user/password pair
746 5) login as the "user =" user with given password
747 6) login as the "user =" user with no password (guest connection)
748 7) login as guest user with no password
750 if the service is guest_only then steps 1 to 5 are skipped
753 if (!(GUEST_ONLY(snum
) && GUEST_OK(snum
))) {
754 /* check the given username and password */
755 if (!ok
&& (*user
) && user_ok(user
,snum
)) {
756 ok
= password_ok(user
,password
, pwlen
, NULL
);
758 DEBUG(3,("authorise_login: ACCEPTED: given username (%s) password ok\n",
762 /* check for a previously registered guest username */
763 if (!ok
&& (vuser
!= 0) && vuser
->guest
) {
764 if (user_ok(vuser
->user
.unix_name
,snum
) &&
765 password_ok(vuser
->user
.unix_name
, password
, pwlen
, NULL
)) {
766 fstrcpy(user
, vuser
->user
.unix_name
);
767 vuser
->guest
= False
;
768 DEBUG(3,("authorise_login: ACCEPTED: given password with registered user %s\n", user
));
773 /* now check the list of session users */
776 char *user_list
= strdup(session_users
);
780 for (auser
=strtok(user_list
,LIST_SEP
); !ok
&& auser
;
781 auser
= strtok(NULL
,LIST_SEP
)) {
783 fstrcpy(user2
,auser
);
784 if (!user_ok(user2
,snum
))
787 if (password_ok(user2
,password
, pwlen
, NULL
)) {
790 DEBUG(3,("authorise_login: ACCEPTED: session list username (%s) \
791 and given password ok\n", user
));
795 SAFE_FREE(user_list
);
798 /* check for a previously validated username/password pair */
799 if (!ok
&& (lp_security() > SEC_SHARE
) && (vuser
!= 0) && !vuser
->guest
&&
800 user_ok(vuser
->user
.unix_name
,snum
)) {
801 fstrcpy(user
,vuser
->user
.unix_name
);
803 DEBUG(3,("authorise_login: ACCEPTED: validated uid (%s) as non-guest\n",
808 /* check for a rhosts entry */
809 if (!ok
&& user_ok(user
,snum
) && check_hosts_equiv(user
)) {
811 DEBUG(3,("authorise_login: ACCEPTED: hosts equiv or rhosts entry for %s\n",
815 /* check the user= fields and the given password */
816 if (!ok
&& lp_username(snum
)) {
819 StrnCpy(user_list
,lp_username(snum
),sizeof(pstring
)-1);
821 pstring_sub(user_list
,"%S",lp_servicename(snum
));
823 for (auser
=strtok(user_list
,LIST_SEP
); auser
&& !ok
;
824 auser
= strtok(NULL
,LIST_SEP
)) {
826 auser
= validate_group(auser
+1,password
,pwlen
,snum
);
830 DEBUG(3,("authorise_login: ACCEPTED: group username \
831 and given password ok (%s)\n", user
));
835 fstrcpy(user2
,auser
);
836 if (user_ok(user2
,snum
) && password_ok(user2
,password
,pwlen
,NULL
)) {
839 DEBUG(3,("authorise_login: ACCEPTED: user list username \
840 and given password ok (%s)\n", user
));
845 } /* not guest only */
847 /* check for a normal guest connection */
848 if (!ok
&& GUEST_OK(snum
)) {
850 StrnCpy(guestname
,lp_guestaccount(snum
),sizeof(guestname
)-1);
851 if (Get_Pwnam(guestname
,True
)) {
852 fstrcpy(user
,guestname
);
854 DEBUG(3,("authorise_login: ACCEPTED: guest account and guest ok (%s)\n",
857 DEBUG(0,("authorise_login: Invalid guest account %s??\n",guestname
));
862 if (ok
&& !user_ok(user
,snum
)) {
863 DEBUG(0,("authorise_login: rejected invalid user %s\n",user
));
870 /****************************************************************************
871 Read the a hosts.equiv or .rhosts file and check if it
872 allows this user from this machine.
873 ****************************************************************************/
875 static BOOL
check_user_equiv(char *user
, char *remote
, char *equiv_file
)
877 int plus_allowed
= 1;
880 char **lines
= file_lines_load(equiv_file
, NULL
, False
);
883 DEBUG(5, ("check_user_equiv %s %s %s\n", user
, remote
, equiv_file
));
888 for (i
=0; lines
[i
]; i
++) {
889 char *buf
= lines
[i
];
890 trim_string(buf
," "," ");
892 if (buf
[0] != '#' && buf
[0] != '\n') {
893 BOOL is_group
= False
;
896 if (strcmp(buf
, "NO_PLUS\n") == 0) {
897 DEBUG(6, ("check_user_equiv NO_PLUS\n"));
902 if (*bp
== '\n' && plus_allowed
) {
903 /* a bare plus means everbody allowed */
904 DEBUG(6, ("check_user_equiv everybody allowed\n"));
905 file_lines_free(lines
);
908 } else if (buf
[0] == '-') {
916 file_host
= strtok(bp
, " \t\n");
917 file_user
= strtok(NULL
, " \t\n");
918 DEBUG(7, ("check_user_equiv %s %s\n", file_host
? file_host
: "(null)",
919 file_user
? file_user
: "(null)" ));
920 if (file_host
&& *file_host
) {
921 BOOL host_ok
= False
;
923 #if defined(HAVE_NETGROUP) && defined(HAVE_YP_GET_DEFAULT_DOMAIN)
925 static char *mydomain
= NULL
;
927 yp_get_default_domain(&mydomain
);
928 if (mydomain
&& innetgr(file_host
,remote
,user
,mydomain
))
933 DEBUG(1,("Netgroups not configured\n"));
938 /* is it this host */
939 /* the fact that remote has come from a call of gethostbyaddr
940 * means that it may have the fully qualified domain name
941 * so we could look up the file version to get it into
942 * a canonical form, but I would rather just type it
943 * in full in the equiv file
945 if (!host_ok
&& !is_group
&& strequal(remote
, file_host
))
951 /* is it this user */
952 if (file_user
== 0 || strequal(user
, file_user
)) {
953 DEBUG(5, ("check_user_equiv matched %s%s %s\n",
954 (plus
? "+" : "-"), file_host
,
955 (file_user
? file_user
: "")));
956 file_lines_free(lines
);
957 return (plus
? True
: False
);
963 file_lines_free(lines
);
967 /****************************************************************************
968 Check for a possible hosts equiv or rhosts entry for the user.
969 ****************************************************************************/
971 BOOL
check_hosts_equiv(char *user
)
975 struct passwd
*pass
= Get_Pwnam(user
,True
);
980 fname
= lp_hosts_equiv();
982 /* note: don't allow hosts.equiv on root */
983 if (fname
&& *fname
&& (pass
->pw_uid
!= 0)) {
984 if (check_user_equiv(user
,client_name(),fname
))
988 if (lp_use_rhosts()) {
989 char *home
= get_user_service_home_dir(user
);
991 slprintf(rhostsfile
, sizeof(rhostsfile
)-1, "%s/.rhosts", home
);
992 if (check_user_equiv(user
,client_name(),rhostsfile
))
1000 /****************************************************************************
1001 Return the client state structure.
1002 ****************************************************************************/
1004 struct cli_state
*server_client(void)
1006 static struct cli_state pw_cli
;
1010 /****************************************************************************
1011 Support for server level security.
1012 ****************************************************************************/
1014 struct cli_state
*server_cryptkey(void)
1016 struct cli_state
*cli
;
1018 struct in_addr dest_ip
;
1021 BOOL connected_ok
= False
;
1023 cli
= server_client();
1025 if (!cli_initialise(cli
))
1028 pserver
= strdup(lp_passwordserver());
1031 while(next_token( &p
, desthost
, LIST_SEP
, sizeof(desthost
))) {
1032 standard_sub_basic(desthost
,sizeof(desthost
));
1035 if(!resolve_name( desthost
, &dest_ip
, 0x20)) {
1036 DEBUG(1,("server_cryptkey: Can't resolve address for %s\n",desthost
));
1040 if (ismyip(dest_ip
)) {
1041 DEBUG(1,("Password server loop - disabling password server %s\n",desthost
));
1045 if (cli_connect(cli
, desthost
, &dest_ip
)) {
1046 DEBUG(3,("connected to password server %s\n",desthost
));
1047 connected_ok
= True
;
1054 if (!connected_ok
) {
1055 DEBUG(0,("password server not available\n"));
1060 if (!attempt_netbios_session_request(cli
, global_myname
, desthost
, &dest_ip
)) {
1065 DEBUG(3,("got session\n"));
1067 if (!cli_negprot(cli
)) {
1068 DEBUG(1,("%s rejected the negprot\n",desthost
));
1073 if (cli
->protocol
< PROTOCOL_LANMAN2
||
1074 !(cli
->sec_mode
& 1)) {
1075 DEBUG(1,("%s isn't in user level security mode\n",desthost
));
1080 DEBUG(3,("password server OK\n"));
1085 /****************************************************************************
1086 Validate a password with the password server.
1087 ****************************************************************************/
1089 BOOL
server_validate(char *user
, char *domain
,
1090 char *pass
, int passlen
,
1091 char *ntpass
, int ntpasslen
)
1093 struct cli_state
*cli
;
1094 static unsigned char badpass
[24];
1095 static fstring baduser
;
1096 static BOOL tested_password_server
= False
;
1097 static BOOL bad_password_server
= False
;
1099 cli
= server_client();
1101 if (!cli
->initialised
) {
1102 DEBUG(1,("password server %s is not connected\n", cli
->desthost
));
1107 memset(badpass
, 0x1f, sizeof(badpass
));
1109 if((passlen
== sizeof(badpass
)) && !memcmp(badpass
, pass
, passlen
)) {
1111 * Very unlikely, our random bad password is the same as the users
1114 memset(badpass
, badpass
[0]+1, sizeof(badpass
));
1117 if(baduser
[0] == 0) {
1118 fstrcpy(baduser
, INVALID_USER_PREFIX
);
1119 fstrcat(baduser
, global_myname
);
1123 * Attempt a session setup with a totally incorrect password.
1124 * If this succeeds with the guest bit *NOT* set then the password
1125 * server is broken and is not correctly setting the guest bit. We
1126 * need to detect this as some versions of NT4.x are broken. JRA.
1129 if(!tested_password_server
) {
1130 if (cli_session_setup(cli
, baduser
, (char *)badpass
, sizeof(badpass
),
1131 (char *)badpass
, sizeof(badpass
), domain
)) {
1134 * We connected to the password server so we
1135 * can say we've tested it.
1137 tested_password_server
= True
;
1139 if ((SVAL(cli
->inbuf
,smb_vwv2
) & 1) == 0) {
1140 DEBUG(0,("server_validate: password server %s allows users as non-guest \
1141 with a bad password.\n", cli
->desthost
));
1142 DEBUG(0,("server_validate: This is broken (and insecure) behaviour. Please do not \
1143 use this machine as the password server.\n"));
1147 * Password server has the bug.
1149 bad_password_server
= True
;
1157 * We have already tested the password server.
1158 * Fail immediately if it has the bug.
1161 if(bad_password_server
) {
1162 DEBUG(0,("server_validate: [1] password server %s allows users as non-guest \
1163 with a bad password.\n", cli
->desthost
));
1164 DEBUG(0,("server_validate: [1] This is broken (and insecure) behaviour. Please do not \
1165 use this machine as the password server.\n"));
1171 * Now we know the password server will correctly set the guest bit, or is
1172 * not guest enabled, we can try with the real password.
1175 if (!cli_session_setup(cli
, user
, pass
, passlen
, ntpass
, ntpasslen
, domain
)) {
1176 DEBUG(1,("password server %s rejected the password\n", cli
->desthost
));
1180 /* if logged in as guest then reject */
1181 if ((SVAL(cli
->inbuf
,smb_vwv2
) & 1) != 0) {
1182 DEBUG(1,("password server %s gave us guest only\n", cli
->desthost
));
1192 static char *mutex_server_name
;
1194 static BOOL
grab_server_mutex(const char *name
)
1196 mutex_server_name
= strdup(name
);
1197 if (!mutex_server_name
) {
1198 DEBUG(0,("grab_server_mutex: malloc failed for %s\n", name
));
1201 if (!secrets_named_mutex(name
, 10)) {
1202 DEBUG(10,("grab_server_mutex: failed for %s\n", name
));
1203 SAFE_FREE(mutex_server_name
);
1210 static void release_server_mutex(void)
1212 if (mutex_server_name
) {
1213 secrets_named_mutex_release(mutex_server_name
);
1214 SAFE_FREE(mutex_server_name
);
1218 /***********************************************************************
1219 Connect to a remote machine for domain security authentication
1220 given a name or IP address.
1221 ************************************************************************/
1223 static BOOL
connect_to_domain_password_server(struct cli_state
**ppcli
,
1224 char *server
, unsigned char *trust_passwd
)
1226 struct in_addr dest_ip
;
1227 fstring remote_machine
;
1228 struct cli_state
*pcli
= NULL
;
1232 if(!(pcli
= cli_initialise(NULL
))) {
1233 DEBUG(0,("connect_to_domain_password_server: unable to initialize client connection.\n"));
1237 if (is_ipaddress(server
)) {
1238 struct in_addr to_ip
;
1240 /* we shouldn't have 255.255.255.255 forthe IP address of a password server anyways */
1241 if ((to_ip
.s_addr
=inet_addr(server
)) == 0xFFFFFFFF) {
1242 DEBUG (0,("connect_to_domain_password_server: inet_addr(%s) returned 0xFFFFFFFF!\n", server
));
1247 if (!name_status_find("*", 0, 0x20, to_ip
, remote_machine
)) {
1248 DEBUG(1, ("connect_to_domain_password_server: Can't " "resolve name for IP %s\n", server
));
1253 fstrcpy(remote_machine
, server
);
1256 standard_sub_basic(remote_machine
,sizeof(remote_machine
));
1257 strupper(remote_machine
);
1259 if(!resolve_name( remote_machine
, &dest_ip
, 0x20)) {
1260 DEBUG(1,("connect_to_domain_password_server: Can't resolve address for %s\n", remote_machine
));
1265 if (ismyip(dest_ip
)) {
1266 DEBUG(1,("connect_to_domain_password_server: Password server loop - not using password server %s\n",
1272 /* we use a mutex to prevent two connections at once - when a NT PDC gets
1273 two connections where one hasn't completed a negprot yet it will send a
1274 TCP reset to the first connection (tridge) */
1276 if (!grab_server_mutex(server
)) {
1281 if (!cli_connect(pcli
, remote_machine
, &dest_ip
)) {
1282 DEBUG(0,("connect_to_domain_password_server: unable to connect to SMB server on \
1283 machine %s. Error was : %s.\n", remote_machine
, cli_errstr(pcli
) ));
1285 release_server_mutex();
1289 if (!attempt_netbios_session_request(pcli
, global_myname
, remote_machine
, &dest_ip
)) {
1290 DEBUG(0,("connect_to_password_server: machine %s rejected the NetBIOS \
1291 session request. Error was : %s.\n", remote_machine
, cli_errstr(pcli
) ));
1293 release_server_mutex();
1297 pcli
->protocol
= PROTOCOL_NT1
;
1299 if (!cli_negprot(pcli
)) {
1300 DEBUG(0,("connect_to_domain_password_server: machine %s rejected the negotiate protocol. \
1301 Error was : %s.\n", remote_machine
, cli_errstr(pcli
) ));
1303 release_server_mutex();
1307 if (pcli
->protocol
!= PROTOCOL_NT1
) {
1308 DEBUG(0,("connect_to_domain_password_server: machine %s didn't negotiate NT protocol.\n",
1311 release_server_mutex();
1316 * Do an anonymous session setup.
1319 if (!cli_session_setup(pcli
, "", "", 0, "", 0, "")) {
1320 DEBUG(0,("connect_to_domain_password_server: machine %s rejected the session setup. \
1321 Error was : %s.\n", remote_machine
, cli_errstr(pcli
) ));
1323 release_server_mutex();
1327 if (!(pcli
->sec_mode
& 1)) {
1328 DEBUG(1,("connect_to_domain_password_server: machine %s isn't in user level security mode\n",
1331 release_server_mutex();
1335 if (!cli_send_tconX(pcli
, "IPC$", "IPC", "", 1)) {
1336 DEBUG(0,("connect_to_domain_password_server: machine %s rejected the tconX on the IPC$ share. \
1337 Error was : %s.\n", remote_machine
, cli_errstr(pcli
) ));
1339 release_server_mutex();
1344 * We now have an anonymous connection to IPC$ on the domain password server.
1348 * Even if the connect succeeds we need to setup the netlogon
1349 * pipe here. We do this as we may just have changed the domain
1350 * account password on the PDC and yet we may be talking to
1351 * a BDC that doesn't have this replicated yet. In this case
1352 * a successful connect to a DC needs to take the netlogon connect
1353 * into account also. This patch from "Bjart Kvarme" <bjart.kvarme@usit.uio.no>.
1356 if(cli_nt_session_open(pcli
, PIPE_NETLOGON
) == False
) {
1357 DEBUG(0,("connect_to_domain_password_server: unable to open the domain client session to \
1358 machine %s. Error was : %s.\n", remote_machine
, cli_errstr(pcli
)));
1359 cli_nt_session_close(pcli
);
1362 release_server_mutex();
1366 if (!NT_STATUS_IS_OK(cli_nt_setup_creds(pcli
, trust_passwd
))) {
1367 DEBUG(0,("connect_to_domain_password_server: unable to setup the PDC credentials to machine \
1368 %s. Error was : %s.\n", remote_machine
, cli_errstr(pcli
)));
1369 cli_nt_session_close(pcli
);
1372 release_server_mutex();
1378 /* We exit here with the mutex *locked*. JRA */
1382 /***********************************************************************
1383 Utility function to attempt a connection to an IP address of a DC.
1384 ************************************************************************/
1386 static BOOL
attempt_connect_to_dc(struct cli_state
**ppcli
, struct in_addr
*ip
, unsigned char *trust_passwd
)
1391 * Ignore addresses we have already tried.
1394 if (is_zero_ip(*ip
))
1397 if (!lookup_dc_name(global_myname
, lp_workgroup(), ip
, dc_name
))
1400 return connect_to_domain_password_server(ppcli
, dc_name
, trust_passwd
);
1403 /***********************************************************************
1404 We have been asked to dynamcially determine the IP addresses of
1405 the PDC and BDC's for this DOMAIN, and query them in turn.
1406 ************************************************************************/
1408 static BOOL
find_connect_pdc(struct cli_state
**ppcli
, unsigned char *trust_passwd
, time_t last_change_time
)
1410 struct in_addr
*ip_list
= NULL
;
1413 BOOL connected_ok
= False
;
1414 time_t time_now
= time(NULL
);
1415 BOOL use_pdc_only
= False
;
1418 * If the time the machine password has changed
1419 * was less than an hour ago then we need to contact
1420 * the PDC only, as we cannot be sure domain replication
1421 * has yet taken place. Bug found by Gerald (way to go
1425 if (time_now
- last_change_time
< 3600)
1426 use_pdc_only
= True
;
1428 if (!get_dc_list(use_pdc_only
, lp_workgroup(), &ip_list
, &count
))
1432 * Firstly try and contact a PDC/BDC who has the same
1433 * network address as any of our interfaces.
1435 for(i
= 0; i
< count
; i
++) {
1436 if(!is_local_net(ip_list
[i
]))
1439 if((connected_ok
= attempt_connect_to_dc(ppcli
, &ip_list
[i
], trust_passwd
)))
1442 zero_ip(&ip_list
[i
]); /* Tried and failed. */
1446 * Secondly try and contact a random PDC/BDC.
1449 i
= (sys_random() % count
);
1451 if (!is_zero_ip(ip_list
[i
])) {
1452 if (!(connected_ok
= attempt_connect_to_dc(ppcli
, &ip_list
[i
], trust_passwd
)))
1453 zero_ip(&ip_list
[i
]); /* Tried and failed. */
1458 * Finally go through the IP list in turn, ignoring any addresses
1459 * we have already tried.
1463 * Try and connect to any of the other IP addresses in the PDC/BDC list.
1464 * Note that from a WINS server the #1 IP address is the PDC.
1466 for(i
= 0; i
< count
; i
++) {
1467 if (is_zero_ip(ip_list
[i
]))
1470 if((connected_ok
= attempt_connect_to_dc(ppcli
, &ip_list
[i
], trust_passwd
)))
1476 return connected_ok
;
1479 /***********************************************************************
1480 Do the same as security=server, but using NT Domain calls and a session
1481 key from the machine password.
1482 ************************************************************************/
1484 BOOL
domain_client_validate( char *user
, char *domain
,
1485 char *smb_apasswd
, int smb_apasslen
,
1486 char *smb_ntpasswd
, int smb_ntpasslen
,
1487 BOOL
*user_exists
, NT_USER_TOKEN
**pptoken
)
1489 unsigned char local_challenge
[8];
1490 unsigned char local_lm_response
[24];
1491 unsigned char local_nt_response
[24];
1492 unsigned char trust_passwd
[16];
1493 fstring remote_machine
;
1495 const char *pserver
;
1496 NET_ID_INFO_CTR ctr
;
1497 NET_USER_INFO_3 info3
;
1498 struct cli_state
*pcli
= NULL
;
1500 BOOL connected_ok
= False
;
1501 time_t last_change_time
;
1507 if(user_exists
!= NULL
)
1508 *user_exists
= True
; /* Only set false on a very specific error. */
1511 * Check that the requested domain is not our own machine name.
1512 * If it is, we should never check the PDC here, we use our own local
1516 if(strequal( domain
, global_myname
)) {
1517 DEBUG(3,("domain_client_validate: Requested domain was for this machine.\n"));
1522 * Next, check that the passwords given were encrypted.
1525 if(((smb_apasslen
!= 24) && (smb_apasslen
!= 0)) ||
1526 ((smb_ntpasslen
!= 24) && (smb_ntpasslen
!= 0))) {
1529 * Not encrypted - do so.
1532 DEBUG(3,("domain_client_validate: User passwords not in encrypted format.\n"));
1533 generate_random_buffer( local_challenge
, 8, False
);
1534 SMBencrypt( (uchar
*)smb_apasswd
, local_challenge
, local_lm_response
);
1535 SMBNTencrypt((uchar
*)smb_ntpasswd
, local_challenge
, local_nt_response
);
1538 smb_apasswd
= (char *)local_lm_response
;
1539 smb_ntpasswd
= (char *)local_nt_response
;
1543 * Encrypted - get the challenge we sent for these
1547 if (!last_challenge(local_challenge
)) {
1548 DEBUG(0,("domain_client_validate: no challenge done - password failed\n"));
1554 * Get the machine account password for our primary domain
1557 if (!secrets_fetch_trust_account_password(global_myworkgroup
, trust_passwd
, &last_change_time
)) {
1558 DEBUG(0, ("domain_client_validate: could not fetch trust account password for domain %s\n", global_myworkgroup
));
1562 /* Test if machine password is expired and need to be changed */
1563 if (lp_machine_password_timeout()) {
1564 if (time(NULL
) > last_change_time
+ lp_machine_password_timeout()) {
1565 DEBUG(10,("domain_client_validate: machine account password needs changing. \
1566 Last change time = (%u) %s. Machine password timeout = %u seconds\n",
1567 (unsigned int)last_change_time
, http_timestring(last_change_time
),
1568 (unsigned int)lp_machine_password_timeout() ));
1569 global_machine_password_needs_changing
= True
;
1574 * At this point, smb_apasswd points to the lanman response to
1575 * the challenge in local_challenge, and smb_ntpasswd points to
1576 * the NT response to the challenge in local_challenge. Ship
1577 * these over the secure channel to a domain controller and
1578 * see if they were valid.
1582 * Treat each name in the 'password server =' line as a potential
1583 * PDC/BDC. Contact each in turn and try and authenticate.
1586 pserver
= lp_passwordserver();
1591 while (!connected_ok
&&
1592 next_token(&p
,remote_machine
,LIST_SEP
,sizeof(remote_machine
))) {
1593 if(strequal(remote_machine
, "*")) {
1594 connected_ok
= find_connect_pdc(&pcli
, trust_passwd
, last_change_time
);
1596 connected_ok
= connect_to_domain_password_server(&pcli
, remote_machine
, trust_passwd
);
1600 if (!connected_ok
) {
1601 DEBUG(0,("domain_client_validate: Domain password server not available.\n"));
1604 release_server_mutex();
1608 /* We really don't care what LUID we give the user. */
1609 generate_random_buffer( (unsigned char *)&smb_uid_low
, 4, False
);
1613 status
= cli_nt_login_network(pcli
, domain
, user
, smb_uid_low
, (char *)local_challenge
,
1614 ((smb_apasslen
!= 0) ? smb_apasswd
: NULL
),
1615 ((smb_ntpasslen
!= 0) ? smb_ntpasswd
: NULL
),
1618 if (!NT_STATUS_IS_OK(status
)) {
1620 DEBUG(0,("domain_client_validate: unable to validate password for user %s in domain \
1621 %s to Domain controller %s. Error was %s.\n", user
, domain
, remote_machine
, get_nt_error_msg(status
) ));
1622 cli_nt_session_close(pcli
);
1625 release_server_mutex();
1627 if((NT_STATUS_V(status
) == NT_STATUS_V(NT_STATUS_NO_SUCH_USER
)) && (user_exists
!= NULL
))
1628 *user_exists
= False
;
1634 * Here, if we really want it, we have lots of info about the user in info3.
1637 /* Return group membership as returned by NT. This contains group
1638 membership in nested groups which doesn't seem to be accessible by any
1639 other means. We merge this into the NT_USER_TOKEN associated with the vuid
1642 if (pptoken
&& (info3
.num_groups2
!= 0)) {
1643 NT_USER_TOKEN
*ptok
;
1648 if ((ptok
= (NT_USER_TOKEN
*)malloc( sizeof(NT_USER_TOKEN
) ) ) == NULL
) {
1649 DEBUG(0, ("domain_client_validate: Out of memory allocating NT_USER_TOKEN\n"));
1650 release_server_mutex();
1654 ptok
->num_sids
= (size_t)info3
.num_groups2
+ info3
.num_other_sids
;
1655 if ((ptok
->user_sids
= (DOM_SID
*)malloc( sizeof(DOM_SID
) * ptok
->num_sids
)) == NULL
) {
1656 DEBUG(0, ("domain_client_validate: Out of memory allocating group SIDS\n"));
1658 release_server_mutex();
1662 /* Group membership (including nested groups) is
1665 for (i
= 0; i
< info3
.num_groups2
; i
++) {
1666 sid_copy(&ptok
->user_sids
[i
], &info3
.dom_sid
.sid
);
1667 sid_append_rid(&ptok
->user_sids
[i
], info3
.gids
[i
].g_rid
);
1670 /* Universal group memberships for other domains are
1671 stored in the info3.other_sids field. We also need to
1672 do sid filtering here. */
1674 for (i
= 0; i
< info3
.num_other_sids
; i
++)
1675 sid_copy(&ptok
->user_sids
[info3
.num_groups2
+ i
],
1676 &info3
.other_sids
[i
].sid
);
1683 * We don't actually need to do this - plus it fails currently with
1684 * NT_STATUS_INVALID_INFO_CLASS - we need to know *exactly* what to
1688 if(cli_nt_logoff(pcli
, &ctr
) == False
) {
1689 DEBUG(0,("domain_client_validate: unable to log off user %s in domain \
1690 %s to Domain controller %s. Error was %s.\n", user
, domain
, remote_machine
, cli_errstr(pcli
)));
1691 cli_nt_session_close(pcli
);
1694 release_server_mutex();
1699 /* Note - once the cli stream is shutdown the mem_ctx used
1700 to allocate the other_sids and gids structures has been deleted - so
1701 these pointers are no longer valid..... */
1703 cli_nt_session_close(pcli
);
1706 release_server_mutex();