2 Unix SMB/Netbios implementation.
4 Password and authentication handling
5 Copyright (C) Andrew Tridgell 1992-1995
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.
25 extern int DEBUGLEVEL;
28 /* users from session setup */
29 static pstring session_users="";
31 /* these are kept here to keep the string_combinations function simple */
32 static char this_user[100]="";
33 static char this_salt[100]="";
34 static char this_crypted[100]="";
37 /* Data to do lanman1/2 password challenge. */
38 static unsigned char saved_challenge[8];
39 static BOOL challenge_sent=False;
41 /*******************************************************************
42 Get the next challenge value - no repeats.
43 ********************************************************************/
44 void generate_next_challenge(char *challenge)
46 extern void E1(char *,char *,char *);
47 static int counter = 0;
51 v1 = (counter++) + getpid() + tval.tv_sec;
52 v2 = (counter++) * getpid() + tval.tv_usec;
53 SIVAL(challenge,0,v1);
54 SIVAL(challenge,4,v2);
55 E1(challenge,"SAMBA",saved_challenge);
56 memcpy(challenge,saved_challenge,8);
57 challenge_sent = True;
60 /*******************************************************************
61 set the last challenge sent, usually from a password server
62 ********************************************************************/
63 BOOL set_challenge(char *challenge)
65 memcpy(saved_challenge,challenge,8);
66 challenge_sent = True;
70 /*******************************************************************
71 get the last challenge sent
72 ********************************************************************/
73 BOOL last_challenge(char *challenge)
75 if (!challenge_sent) return(False);
76 memcpy(challenge,saved_challenge,8);
81 /* this holds info on user ids that are already validated for this VC */
82 static user_struct *validated_users = NULL;
83 static int num_validated_users = 0;
85 /****************************************************************************
86 check if a uid has been validated, and return an index if it has. -1 if not
87 ****************************************************************************/
88 int valid_uid(int uid)
91 if (uid == -1) return(-1);
93 for (i=0;i<num_validated_users;i++)
94 if (validated_users[i].uid == uid)
96 DEBUG(3,("valid uid %d mapped to vuid %d (user=%s)\n",
97 uid,i,validated_users[i].name));
103 /****************************************************************************
104 check if a uid has been validated, and return an pointer to the user_struct
105 if it has. NULL if not
106 ****************************************************************************/
107 user_struct *get_valid_user_struct(int uid)
109 int vuid = valid_uid(uid);
110 if(vuid == -1 || validated_users[vuid].guest)
112 return &validated_users[vuid];
115 /****************************************************************************
117 ****************************************************************************/
118 void invalidate_uid(int uid)
121 for (i=0;i<num_validated_users;i++)
122 if (validated_users[i].uid == uid)
124 user_struct *vuser = &validated_users[i];
127 vuser->user_ngroups = 0;
128 if(vuser->user_groups &&
129 (vuser->user_groups != (gid_t *)vuser->user_igroups))
130 free(vuser->user_groups);
131 vuser->user_groups = NULL;
132 if(vuser->user_igroups)
133 free(vuser->user_igroups);
134 vuser->user_igroups = NULL;
139 /****************************************************************************
140 return a validated username
141 ****************************************************************************/
142 char *validated_username(int vuid)
144 return(validated_users[vuid].name);
147 /****************************************************************************
148 register a uid/name pair as being valid and that a valid password
150 ****************************************************************************/
151 void register_uid(int uid,int gid, char *name,BOOL guest)
155 if (valid_uid(uid) >= 0)
157 validated_users = (user_struct *)Realloc(validated_users,
159 (num_validated_users+1));
161 if (!validated_users)
163 DEBUG(0,("Failed to realloc users struct!\n"));
167 vuser = &validated_users[num_validated_users];
170 vuser->guest = guest;
171 strcpy(vuser->name,name);
173 vuser->user_ngroups = 0;
174 vuser->user_groups = NULL;
175 vuser->user_igroups = NULL;
177 /* Find all the groups this uid is in and store them.
178 Used by become_user() */
179 setup_groups(name,uid,gid,
180 &vuser->user_ngroups,
181 &vuser->user_igroups,
182 &vuser->user_groups);
184 DEBUG(3,("uid %d registered to name %s\n",uid,name));
186 num_validated_users++;
190 /****************************************************************************
191 add a name to the session users list
192 ****************************************************************************/
193 void add_session_user(char *user)
196 StrnCpy(suser,user,sizeof(suser)-1);
198 if (!Get_Pwnam(suser,True)) return;
200 if (suser && *suser && !in_list(suser,session_users,False))
202 if (strlen(suser) + strlen(session_users) + 2 >= sizeof(pstring))
203 DEBUG(1,("Too many session users??\n"));
206 strcat(session_users," ");
207 strcat(session_users,suser);
214 /* a fake shadow password routine which just fills a fake spwd struct
215 * with the sp_pwdp field. (sreiz@aie.nl)
217 static struct spwd *getspnam(char *username) /* fake shadow password routine */
222 static struct spwd static_spwd;
224 static_spwd.sp_pwdp=0;
225 if (!(f=fopen("/etc/master.passwd", "r")))
227 while (fgets(line, 1024, f)) {
228 if (!strncmp(line, username, strlen(username)) &&
229 line[strlen(username)]==':') { /* found entry */
232 p=line+strlen(username)+1;
233 if ((q=strchr(p, ':'))) {
238 static_spwd.sp_pwdp=pw;
244 if (static_spwd.sp_pwdp)
252 /****************************************************************************
253 an enhanced crypt for OSF1
254 ****************************************************************************/
255 static char *osf1_bigcrypt(char *password,char *salt1)
257 static char result[AUTH_MAX_PASSWD_LENGTH] = "";
262 int parts = strlen(password) / AUTH_CLEARTEXT_SEG_CHARS;
263 if (strlen(password)%AUTH_CLEARTEXT_SEG_CHARS)
266 StrnCpy(salt,salt1,2);
267 StrnCpy(result,salt1,2);
269 for (i=0; i<parts;i++)
273 StrnCpy(salt,&result[2+i*AUTH_CIPHERTEXT_SEG_CHARS],2);
274 p2 += AUTH_CLEARTEXT_SEG_CHARS;
282 /****************************************************************************
283 update the enhanced security database. Only relevant for OSF1 at the moment.
284 ****************************************************************************/
285 static void update_protected_database( char *user, BOOL result)
288 struct pr_passwd *mypasswd;
292 mypasswd = getprpwnam (user);
293 starttime = time (NULL);
294 tz = mktime ( localtime ( &starttime ) );
298 mypasswd->ufld.fd_slogin = tz;
299 mypasswd->ufld.fd_nlogins = 0;
301 putprpwnam(user,mypasswd);
303 DEBUG(3,("Update protected database for Account %s after succesful connection\n",user));
307 mypasswd->ufld.fd_ulogin = tz;
308 mypasswd->ufld.fd_nlogins = mypasswd->ufld.fd_nlogins + 1;
309 if ( mypasswd->ufld.fd_max_tries != 0 && mypasswd->ufld.fd_nlogins > mypasswd->ufld.fd_max_tries )
311 mypasswd->uflg.fg_lock = 0;
312 DEBUG(3,("Account is disabled -- see Account Administrator.\n"));
314 putprpwnam ( user , mypasswd );
315 DEBUG(3,("Update protected database for Account %s after refusing connection\n",user));
318 DEBUG(6,("Updated database with %s %s\n",user,BOOLSTR(result)));
324 /*******************************************************************
325 check on AFS authentication
326 ********************************************************************/
327 static BOOL afs_auth(char *this_user,char *password)
329 long password_expires = 0;
332 /* For versions of AFS prior to 3.3, this routine has few arguments, */
333 /* but since I can't find the old documentation... :-) */
335 if (ka_UserAuthenticateGeneral(KA_USERAUTH_VERSION+KA_USERAUTH_DOSETPAG,
337 (char *) 0, /* instance */
338 (char *) 0, /* cell */
340 0, /* lifetime, default */
341 &password_expires, /*days 'til it expires */
352 sec_login_handle_t my_dce_sec_context;
353 int dcelogin_atmost_once = 0;
355 /*******************************************************************
356 check on a DCE/DFS authentication
357 ********************************************************************/
358 static BOOL dfs_auth(char *this_user,char *password)
363 boolean32 password_reset;
364 sec_passwd_rec_t my_dce_password;
365 sec_login_auth_src_t auth_src = sec_login_auth_src_network;
366 unsigned char dce_errstr[dce_c_error_string_len];
369 * We only go for a DCE login context if the given password
370 * matches that stored in the local password file..
371 * Assumes local passwd file is kept in sync w/ DCE RGY!
374 if (!strcmp((char *)crypt(password,this_salt),this_crypted) ||
375 dcelogin_atmost_once)
378 if (sec_login_setup_identity(
379 (unsigned char *)this_user,
384 dce_error_inq_text(err, dce_errstr, &err2);
385 DEBUG(0,("DCE Setup Identity for %s failed: %s\n",
386 this_user,dce_errstr));
390 my_dce_password.version_number = sec_passwd_c_version_none;
391 my_dce_password.pepper = NULL;
392 my_dce_password.key.key_type = sec_passwd_plain;
393 my_dce_password.key.tagged_union.plain = (idl_char *)password;
395 if (sec_login_valid_and_cert_ident(my_dce_sec_context,
401 dce_error_inq_text(err, dce_errstr, &err2);
402 DEBUG(0,("DCE Identity Validation failed for principal %s: %s\n",
403 this_user,dce_errstr));
408 sec_login_set_context(my_dce_sec_context, &err);
409 if (err != error_status_ok )
411 dce_error_inq_text(err, dce_errstr, &err2);
412 DEBUG(0,("DCE login failed for principal %s, cant set context: %s\n",
413 this_user,dce_errstr));
414 sec_login_purge_context(my_dce_sec_context, &err);
419 DEBUG(0,("DCE login succeeded for principal %s on pid %d\n",
420 this_user, getpid()));
423 dcelogin_atmost_once = 1;
427 void dfs_unlogin(void)
431 unsigned char dce_errstr[dce_c_error_string_len];
433 sec_login_purge_context(my_dce_sec_context, &err);
434 if (err != error_status_ok )
436 dce_error_inq_text(err, dce_errstr, &err2);
437 DEBUG(0,("DCE purge login context failed for server instance %d: %s\n",
438 getpid(), dce_errstr));
445 #ifdef LINUX_BIGCRYPT
446 /****************************************************************************
447 an enhanced crypt for Linux to handle password longer than 8 characters
448 ****************************************************************************/
449 static int linux_bigcrypt(char *password,char *salt1, char *crypted)
451 #define LINUX_PASSWORD_SEG_CHARS 8
455 StrnCpy(salt,salt1,2);
458 for ( i=strlen(password); i > 0; i -= LINUX_PASSWORD_SEG_CHARS) {
459 char * p = crypt(password,salt) + 2;
460 if(strncmp(p, crypted, LINUX_PASSWORD_SEG_CHARS) != 0)
462 password += LINUX_PASSWORD_SEG_CHARS;
463 crypted += strlen(p);
471 /****************************************************************************
472 apply a function to upper/lower case combinations
473 of a string and return true if one of them returns true.
474 try all combinations with N uppercase letters.
475 offset is the first char to try and change (start with 0)
476 it assumes the string starts lowercased
477 ****************************************************************************/
478 static BOOL string_combinations2(char *s,int offset,BOOL (*fn)(),int N)
483 #ifdef PASSWORD_LENGTH
484 len = MIN(len,PASSWORD_LENGTH);
487 if (N <= 0 || offset >= len)
490 for (i=offset;i<(len-(N-1));i++)
493 if (!islower(c)) continue;
495 if (string_combinations2(s,i+1,fn,N-1))
502 /****************************************************************************
503 apply a function to upper/lower case combinations
504 of a string and return true if one of them returns true.
505 try all combinations with up to N uppercase letters.
506 offset is the first char to try and change (start with 0)
507 it assumes the string starts lowercased
508 ****************************************************************************/
509 static BOOL string_combinations(char *s,BOOL (*fn)(),int N)
513 if (string_combinations2(s,0,fn,n)) return(True);
519 /****************************************************************************
520 core of password checking routine
521 ****************************************************************************/
522 BOOL password_check(char *password)
525 if (afs_auth(this_user,password)) return(True);
529 if (dfs_auth(this_user,password)) return(True);
533 if (pwdauth(this_user,password) == 0)
538 return(strcmp(osf1_bigcrypt(password,this_salt),this_crypted) == 0);
542 return (strcmp((char *)crypt16(password, this_salt ),this_crypted) == 0);
545 #ifdef LINUX_BIGCRYPT
546 return(linux_bigcrypt(password,this_salt,this_crypted));
550 DEBUG(1,("Warning - no crypt available\n"));
553 return(strcmp((char *)crypt(password,this_salt),this_crypted) == 0);
558 /****************************************************************************
559 core of smb password checking routine.
560 ****************************************************************************/
561 BOOL smb_password_check(char *password, unsigned char *part_passwd, unsigned char *c8)
563 /* Finish the encryption of part_passwd. */
564 unsigned char p21[21];
565 unsigned char p24[24];
567 if(part_passwd == NULL)
568 DEBUG(10,("No password set - allowing access\n"));
569 /* No password set - always true ! */
570 if(part_passwd == NULL)
574 memcpy(p21,part_passwd,16);
579 DEBUG(100,("Part password (P16) was |"));
580 for(i = 0; i < 16; i++)
581 DEBUG(100,("%X ", (unsigned char)part_passwd[i]));
583 DEBUG(100,("Password from client was |"));
584 for(i = 0; i < 24; i++)
585 DEBUG(100,("%X ", (unsigned char)password[i]));
587 DEBUG(100,("Given challenge was |"));
588 for(i = 0; i < 8; i++)
589 DEBUG(100,("%X ", (unsigned char)c8[i]));
591 DEBUG(100,("Value from encryption was |"));
592 for(i = 0; i < 24; i++)
593 DEBUG(100,("%X ", (unsigned char)p24[i]));
597 return (memcmp(p24, password, 24) == 0);
601 /****************************************************************************
602 check if a username/password is OK
603 ****************************************************************************/
604 BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd, BOOL is_nt_password)
607 int level = lp_passwordlevel();
611 struct smb_passwd *smb_pass;
612 BOOL challenge_done = False;
615 if (password) password[pwlen] = 0;
619 challenge_done = last_challenge(challenge);
627 DEBUG(100,("checking user=[%s] pass=[",user));
628 for( i = 0; i < 24; i++)
629 DEBUG(100,("%0x ", (unsigned char)password[i]));
634 DEBUG(100,("checking user=[%s] pass=[%s]\n",user,password));
640 if (((!*password) || (!pwlen)) && !lp_null_passwords())
645 pass = (struct passwd *) pwd;
646 user = pass->pw_name;
649 pass = Get_Pwnam(user,True);
653 DEBUG(4,("SMB Password - pwlen = %d, challenge_done = %d\n", pwlen, challenge_done));
655 if((pwlen == 24) && challenge_done)
657 DEBUG(4,("Checking SMB password for user %s (l=24)\n",user));
661 DEBUG(3,("Couldn't find user %s\n",user));
665 smb_pass = get_smbpwnam(user);
668 DEBUG(3,("Couldn't find user %s in smb_passwd file.\n", user));
672 /* Ensure the uid's match */
673 if(smb_pass->smb_userid != pass->pw_uid)
675 DEBUG(3,("Error : UNIX and SMB uids in password files do not match !\n"));
679 if(Protocol >= PROTOCOL_NT1 && is_nt_password)
681 /* We have the NT MD4 hash challenge available - see if we can
682 use it (ie. does it exist in the smbpasswd file).
684 if(smb_pass->smb_nt_passwd != NULL)
686 DEBUG(4,("Checking NT MD4 password\n"));
687 if(smb_password_check(password, smb_pass->smb_nt_passwd, challenge))
689 update_protected_database(user,True);
692 DEBUG(4,("NT MD4 password check failed\n"));
697 /* Try against the lanman password */
699 if(smb_password_check(password, smb_pass->smb_passwd, challenge))
701 update_protected_database(user,True);
705 DEBUG(3,("Error smb_password_check failed\n"));
709 DEBUG(4,("Checking password for user %s (l=%d)\n",user,pwlen));
713 DEBUG(3,("Couldn't find user %s\n",user));
721 /* many shadow systems require you to be root to get the password,
722 in most cases this should already be the case when this
723 function is called, except perhaps for IPC password changing
726 spass = getspnam(pass->pw_name);
727 if (spass && spass->sp_pwdp)
728 pass->pw_passwd = spass->sp_pwdp;
734 struct pr_passwd *pr_pw = getprpwnam(pass->pw_name);
735 if (pr_pw && pr_pw->ufld.fd_encrypt)
736 pass->pw_passwd = pr_pw->ufld.fd_encrypt;
740 #ifdef HPUX_10_TRUSTED
742 struct pr_passwd *pr_pw = getprpwnam(pass->pw_name);
743 if (pr_pw && pr_pw->ufld.fd_encrypt)
744 pass->pw_passwd = pr_pw->ufld.fd_encrypt;
750 struct pr_passwd *mypasswd;
751 DEBUG(5,("Checking password for user %s in OSF1_ENH_SEC\n",user));
752 mypasswd = getprpwnam (user);
755 strcpy(pass->pw_name,mypasswd->ufld.fd_name);
756 strcpy(pass->pw_passwd,mypasswd->ufld.fd_encrypt);
760 DEBUG(5,("No entry for user %s in protected database !\n",user));
768 AUTHORIZATION *ap = getauthuid( pass->pw_uid );
771 strcpy( pass->pw_passwd, ap->a_password );
777 /* extract relevant info */
778 strcpy(this_user,pass->pw_name);
779 strcpy(this_salt,pass->pw_passwd);
780 strcpy(this_crypted,pass->pw_passwd);
782 if (!*this_crypted) {
783 if (!lp_null_passwords()) {
784 DEBUG(2,("Disallowing access to %s due to null password\n",this_user));
789 DEBUG(3,("Allowing access to %s with null password\n",this_user));
795 /* try it as it came to us */
796 if (password_check(password))
798 update_protected_database(user,True);
802 /* if the password was given to us with mixed case then we don't
803 need to proceed as we know it hasn't been case modified by the
805 if (strhasupper(password) && strhaslower(password))
808 /* make a copy of it */
809 StrnCpy(pass2,password,sizeof(pstring)-1);
811 /* try all lowercase */
813 if (password_check(password))
815 update_protected_database(user,True);
822 update_protected_database(user,False);
825 strcpy(password,pass2);
830 /* last chance - all combinations of up to level chars upper! */
833 if (string_combinations(password,password_check,level))
835 update_protected_database(user,True);
839 update_protected_database(user,False);
842 strcpy(password,pass2);
849 /****************************************************************************
850 check if a username is valid
851 ****************************************************************************/
852 BOOL user_ok(char *user,int snum)
854 pstring valid, invalid;
857 StrnCpy(valid, lp_valid_users(snum), sizeof(pstring));
858 StrnCpy(invalid, lp_invalid_users(snum), sizeof(pstring));
860 string_sub(valid,"%S",lp_servicename(snum));
861 string_sub(invalid,"%S",lp_servicename(snum));
863 ret = !user_in_list(user,invalid);
865 if (ret && valid && *valid)
866 ret = user_in_list(user,valid);
868 if (ret && lp_onlyuser(snum)) {
869 char *user_list = lp_username(snum);
870 string_sub(user_list,"%S",lp_servicename(snum));
871 ret = user_in_list(user,user_list);
880 /****************************************************************************
881 validate a group username entry. Return the username or NULL
882 ****************************************************************************/
883 static char *validate_group(char *group,char *password,int pwlen,int snum)
887 char *host, *user, *domain;
889 while (getnetgrent(&host, &user, &domain)) {
891 if (user_ok(user, snum) &&
892 password_ok(user,password,pwlen,NULL,False)) {
904 struct group *gptr = (struct group *)getgrnam(group);
908 member = gptr->gr_mem;
909 while (member && *member)
912 strcpy(name,*member);
913 if (user_ok(name,snum) &&
914 password_ok(name,password,pwlen,NULL,False))
918 #ifdef GROUP_CHECK_PWENT
924 while (pwd = getpwent ()) {
925 if (*(pwd->pw_passwd) && pwd->pw_gid == gptr->gr_gid) {
926 /* This Entry have PASSWORD and same GID then check pwd */
927 if (password_ok(NULL, password, pwlen, pwd,False)) {
928 strcpy(tm, pwd->pw_name);
936 #endif /* GROUP_CHECK_PWENT */
945 /****************************************************************************
946 check for authority to login to a service with a given username/password
947 ****************************************************************************/
948 BOOL authorise_login(int snum,char *user,char *password, int pwlen,
949 BOOL *guest,BOOL *force,int vuid)
956 DEBUG(100,("checking authorisation on user=%s pass=%s\n",user,password));
959 /* there are several possabilities:
960 1) login as the given user with given password
961 2) login as a previously registered username with the given password
962 3) login as a session list username with the given password
963 4) login as a previously validated user/password pair
964 5) login as the "user =" user with given password
965 6) login as the "user =" user with no password (guest connection)
966 7) login as guest user with no password
968 if the service is guest_only then steps 1 to 5 are skipped
971 if (GUEST_ONLY(snum)) *force = True;
973 if (!(GUEST_ONLY(snum) && GUEST_OK(snum)))
976 /* check the given username and password */
977 if (!ok && (*user) && user_ok(user,snum)) {
978 ok = password_ok(user,password, pwlen, NULL, False);
979 if (ok) DEBUG(3,("ACCEPTED: given username password ok\n"));
982 /* check for a previously registered guest username */
983 if (!ok && (vuid >= 0) && validated_users[vuid].guest) {
984 if (user_ok(validated_users[vuid].name,snum) &&
985 password_ok(validated_users[vuid].name, password, pwlen, NULL, False)) {
986 strcpy(user, validated_users[vuid].name);
987 validated_users[vuid].guest = False;
988 DEBUG(3,("ACCEPTED: given password with registered user %s\n", user));
994 /* now check the list of session users */
998 char *user_list = strdup(session_users);
999 if (!user_list) return(False);
1001 for (auser=strtok(user_list,LIST_SEP);
1003 auser = strtok(NULL,LIST_SEP))
1006 strcpy(user2,auser);
1007 if (!user_ok(user2,snum)) continue;
1009 if (password_ok(user2,password, pwlen, NULL, False)) {
1012 DEBUG(3,("ACCEPTED: session list username and given password ok\n"));
1018 /* check for a previously validated username/password pair */
1019 if (!ok && !lp_revalidate(snum) &&
1020 (vuid >= 0) && !validated_users[vuid].guest &&
1021 user_ok(validated_users[vuid].name,snum)) {
1022 strcpy(user,validated_users[vuid].name);
1024 DEBUG(3,("ACCEPTED: validated uid ok as non-guest\n"));
1028 /* check for a rhosts entry */
1029 if (!ok && user_ok(user,snum) && check_hosts_equiv(user)) {
1031 DEBUG(3,("ACCEPTED: hosts equiv or rhosts entry\n"));
1034 /* check the user= fields and the given password */
1035 if (!ok && lp_username(snum)) {
1038 StrnCpy(user_list,lp_username(snum),sizeof(pstring));
1040 string_sub(user_list,"%S",lp_servicename(snum));
1042 for (auser=strtok(user_list,LIST_SEP);
1044 auser = strtok(NULL,LIST_SEP))
1048 auser = validate_group(auser+1,password,pwlen,snum);
1053 DEBUG(3,("ACCEPTED: group username and given password ok\n"));
1059 strcpy(user2,auser);
1060 if (user_ok(user2,snum) &&
1061 password_ok(user2,password,pwlen,NULL, False))
1065 DEBUG(3,("ACCEPTED: user list username and given password ok\n"));
1070 } /* not guest only */
1072 /* check for a normal guest connection */
1073 if (!ok && GUEST_OK(snum))
1076 StrnCpy(guestname,lp_guestaccount(snum),sizeof(guestname)-1);
1077 if (Get_Pwnam(guestname,True))
1079 strcpy(user,guestname);
1081 DEBUG(3,("ACCEPTED: guest account and guest ok\n"));
1084 DEBUG(0,("Invalid guest account %s??\n",guestname));
1089 if (ok && !user_ok(user,snum))
1091 DEBUG(0,("rejected invalid user %s\n",user));
1099 /****************************************************************************
1100 read the a hosts.equiv or .rhosts file and check if it
1101 allows this user from this machine
1102 ****************************************************************************/
1103 static BOOL check_user_equiv(char *user, char *remote, char *equiv_file)
1106 int plus_allowed = 1;
1109 FILE *fp = fopen(equiv_file, "r");
1110 DEBUG(5, ("check_user_equiv %s %s %s\n", user, remote, equiv_file));
1111 if (! fp) return False;
1112 while(fgets(buf, sizeof(buf), fp))
1114 trim_string(buf," "," ");
1116 if (buf[0] != '#' && buf[0] != '\n')
1118 BOOL is_group = False;
1121 if (strcmp(buf, "NO_PLUS\n") == 0)
1123 DEBUG(6, ("check_user_equiv NO_PLUS\n"));
1130 if (*bp == '\n' && plus_allowed)
1132 /* a bare plus means everbody allowed */
1133 DEBUG(6, ("check_user_equiv everybody allowed\n"));
1138 else if (buf[0] == '-')
1148 file_host = strtok(bp, " \t\n");
1149 file_user = strtok(NULL, " \t\n");
1150 DEBUG(7, ("check_user_equiv %s %s\n", file_host, file_user));
1151 if (file_host && *file_host)
1153 BOOL host_ok = False;
1158 static char *mydomain = NULL;
1160 yp_get_default_domain(&mydomain);
1161 if (mydomain && innetgr(file_host,remote,user,mydomain))
1167 DEBUG(1,("Netgroups not configured - add -DNETGROUP and recompile\n"));
1172 /* is it this host */
1173 /* the fact that remote has come from a call of gethostbyaddr
1174 * means that it may have the fully qualified domain name
1175 * so we could look up the file version to get it into
1176 * a canonical form, but I would rather just type it
1177 * in full in the equiv file
1179 if (!host_ok && !is_group && strequal(remote, file_host))
1185 /* is it this user */
1186 if (file_user == 0 || strequal(user, file_user))
1189 DEBUG(5, ("check_user_equiv matched %s%s %s\n",
1190 (plus ? "+" : "-"), file_host,
1191 (file_user ? file_user : "")));
1192 return (plus ? True : False);
1203 /****************************************************************************
1204 check for a possible hosts equiv or rhosts entry for the user
1205 ****************************************************************************/
1206 BOOL check_hosts_equiv(char *user)
1210 struct passwd *pass = Get_Pwnam(user,True);
1212 extern struct from_host Client_info;
1218 fromhost(Client,&Client_info);
1220 fname = lp_hosts_equiv();
1222 /* note: don't allow hosts.equiv on root */
1223 if (fname && *fname && (pass->pw_uid != 0))
1225 if (check_user_equiv(user,Client_info.name,fname))
1229 if (lp_use_rhosts())
1231 char *home = get_home_dir(user);
1234 sprintf(rhostsfile, "%s/.rhosts", home);
1235 if (check_user_equiv(user,Client_info.name,rhostsfile))
1244 static int password_client = -1;
1245 static fstring pserver;
1247 /****************************************************************************
1248 attempted support for server level security
1249 ****************************************************************************/
1250 BOOL server_cryptkey(char *buf)
1252 pstring inbuf,outbuf;
1253 fstring pass_protocol;
1254 extern fstring remote_machine;
1258 struct in_addr dest_ip;
1259 extern struct in_addr myip;
1263 if (password_client >= 0)
1264 close(password_client);
1265 password_client = -1;
1267 if (Protocol < PROTOCOL_NT1) {
1268 strcpy(pass_protocol,"LM1.2X002");
1270 strcpy(pass_protocol,"NT LM 0.12");
1273 bzero(inbuf,sizeof(inbuf));
1274 bzero(outbuf,sizeof(outbuf));
1276 for (p=strtok(lp_passwordserver(),LIST_SEP); p ; p = strtok(NULL,LIST_SEP)) {
1278 standard_sub_basic(desthost);
1281 dest_ip = *interpret_addr2(desthost);
1282 if (zero_ip(dest_ip)) {
1283 DEBUG(1,("Can't resolve address for %s\n",p));
1287 if (memcmp(&dest_ip,&myip,sizeof(dest_ip)) == 0) {
1288 DEBUG(1,("Password server loop - disabling password server %s\n",p));
1292 password_client = open_socket_out(SOCK_STREAM, &dest_ip, port);
1293 if (password_client >= 0) {
1294 DEBUG(3,("connected to password server %s\n",p));
1295 StrnCpy(pserver,p,sizeof(pserver)-1);
1300 if (password_client < 0) {
1301 DEBUG(1,("password server not available\n"));
1306 /* send a session request (RFC 8002) */
1308 /* put in the destination name */
1311 name_mangle(desthost,p,' ');
1316 name_mangle(remote_machine,p,' ');
1319 _smb_setlen(outbuf,len);
1320 CVAL(outbuf,0) = 0x81;
1322 send_smb(password_client,outbuf);
1323 receive_smb(password_client,inbuf,5000);
1325 if (CVAL(inbuf,0) != 0x82) {
1326 DEBUG(1,("%s rejected the session\n",pserver));
1327 close(password_client); password_client = -1;
1331 DEBUG(3,("got session\n"));
1333 bzero(outbuf,smb_size);
1335 /* setup the protocol string */
1336 set_message(outbuf,0,strlen(pass_protocol)+2,True);
1337 p = smb_buf(outbuf);
1339 strcpy(p,pass_protocol);
1341 CVAL(outbuf,smb_com) = SMBnegprot;
1342 CVAL(outbuf,smb_flg) = 0x8;
1343 SSVAL(outbuf,smb_flg2,0x1);
1345 send_smb(password_client,outbuf);
1346 ret = receive_smb(password_client,inbuf,5000);
1348 if (!ret || CVAL(inbuf,smb_rcls) || SVAL(inbuf,smb_vwv0)) {
1349 DEBUG(1,("%s rejected the protocol\n",pserver));
1350 close(password_client); password_client= -1;
1354 if (!(CVAL(inbuf,smb_vwv1) & 1)) {
1355 DEBUG(1,("%s isn't in user level security mode\n",pserver));
1356 close(password_client); password_client= -1;
1360 memcpy(buf,inbuf,smb_len(inbuf)+4);
1362 DEBUG(3,("password server OK\n"));
1367 /****************************************************************************
1368 attempted support for server level security
1369 ****************************************************************************/
1370 BOOL server_validate(char *buf)
1372 pstring inbuf,outbuf;
1375 if (password_client < 0) {
1376 DEBUG(1,("%s not connected\n",pserver));
1380 bzero(inbuf,sizeof(inbuf));
1381 memcpy(outbuf,buf,sizeof(outbuf));
1383 /* send a session setup command */
1384 CVAL(outbuf,smb_flg) = 0x8;
1385 SSVAL(outbuf,smb_flg2,0x1);
1386 CVAL(outbuf,smb_vwv0) = 0xFF;
1388 set_message(outbuf,smb_numwords(outbuf),smb_buflen(outbuf),False);
1390 SCVAL(inbuf,smb_rcls,1);
1392 send_smb(password_client,outbuf);
1393 ret = receive_smb(password_client,inbuf,5000);
1395 if (!ret || CVAL(inbuf,smb_rcls) != 0) {
1396 DEBUG(1,("password server %s rejected the password\n",pserver));
1400 /* if logged in as guest then reject */
1401 if ((SVAL(inbuf,smb_vwv2) & 1) != 0) {
1402 DEBUG(1,("password server %s gave us guest only\n",pserver));
1406 DEBUG(3,("password server %s accepted the password\n",pserver));
1408 #ifndef KEEP_PASSWORD_SERVER_OPEN
1409 close(password_client); password_client= -1;