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 static int counter = 0;
50 v1 = (counter++) + getpid() + tval.tv_sec;
51 v2 = (counter++) * getpid() + tval.tv_usec;
52 SIVAL(challenge,0,v1);
53 SIVAL(challenge,4,v2);
54 E1(challenge,"SAMBA",(char *)saved_challenge);
55 memcpy(challenge,saved_challenge,8);
56 challenge_sent = True;
59 /*******************************************************************
60 set the last challenge sent, usually from a password server
61 ********************************************************************/
62 BOOL set_challenge(char *challenge)
64 memcpy(saved_challenge,challenge,8);
65 challenge_sent = True;
69 /*******************************************************************
70 get the last challenge sent
71 ********************************************************************/
72 BOOL last_challenge(char *challenge)
74 if (!challenge_sent) return(False);
75 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 = NULL;
82 static int num_validated_users = 0;
84 /****************************************************************************
85 check if a uid has been validated, and return an index if it has. -1 if not
86 ****************************************************************************/
87 int valid_uid(int uid)
90 if (uid == -1) return(-1);
92 for (i=0;i<num_validated_users;i++)
93 if (validated_users[i].uid == uid)
95 DEBUG(3,("valid uid %d mapped to vuid %d (user=%s)\n",
96 uid,i,validated_users[i].name));
102 /****************************************************************************
103 check if a uid has been validated, and return an pointer to the user_struct
104 if it has. NULL if not
105 ****************************************************************************/
106 user_struct *get_valid_user_struct(int uid)
108 int vuid = valid_uid(uid);
109 if(vuid == -1 || validated_users[vuid].guest)
111 return &validated_users[vuid];
114 /****************************************************************************
116 ****************************************************************************/
117 void invalidate_uid(int uid)
120 for (i=0;i<num_validated_users;i++)
121 if (validated_users[i].uid == uid)
123 user_struct *vuser = &validated_users[i];
126 vuser->user_ngroups = 0;
127 if(vuser->user_groups &&
128 (vuser->user_groups != (gid_t *)vuser->user_igroups))
129 free(vuser->user_groups);
130 vuser->user_groups = NULL;
131 if(vuser->user_igroups)
132 free(vuser->user_igroups);
133 vuser->user_igroups = NULL;
138 /****************************************************************************
139 return a validated username
140 ****************************************************************************/
141 char *validated_username(int vuid)
143 return(validated_users[vuid].name);
146 /****************************************************************************
147 register a uid/name pair as being valid and that a valid password
149 ****************************************************************************/
150 void register_uid(int uid,int gid, char *name,BOOL guest)
154 if (valid_uid(uid) >= 0)
156 validated_users = (user_struct *)Realloc(validated_users,
158 (num_validated_users+1));
160 if (!validated_users)
162 DEBUG(0,("Failed to realloc users struct!\n"));
166 vuser = &validated_users[num_validated_users];
169 vuser->guest = guest;
170 strcpy(vuser->name,name);
172 vuser->user_ngroups = 0;
173 vuser->user_groups = NULL;
174 vuser->user_igroups = NULL;
176 /* Find all the groups this uid is in and store them.
177 Used by become_user() */
178 setup_groups(name,uid,gid,
179 &vuser->user_ngroups,
180 &vuser->user_igroups,
181 &vuser->user_groups);
183 DEBUG(3,("uid %d registered to name %s\n",uid,name));
185 num_validated_users++;
189 /****************************************************************************
190 add a name to the session users list
191 ****************************************************************************/
192 void add_session_user(char *user)
195 StrnCpy(suser,user,sizeof(suser)-1);
197 if (!Get_Pwnam(suser,True)) return;
199 if (suser && *suser && !in_list(suser,session_users,False))
201 if (strlen(suser) + strlen(session_users) + 2 >= sizeof(pstring))
202 DEBUG(1,("Too many session users??\n"));
205 strcat(session_users," ");
206 strcat(session_users,suser);
213 /* a fake shadow password routine which just fills a fake spwd struct
214 * with the sp_pwdp field. (sreiz@aie.nl)
216 static struct spwd *getspnam(char *username) /* fake shadow password routine */
221 static struct spwd static_spwd;
223 static_spwd.sp_pwdp=0;
224 if (!(f=fopen("/etc/master.passwd", "r")))
226 while (fgets(line, 1024, f)) {
227 if (!strncmp(line, username, strlen(username)) &&
228 line[strlen(username)]==':') { /* found entry */
231 p=line+strlen(username)+1;
232 if ((q=strchr(p, ':'))) {
237 static_spwd.sp_pwdp=pw;
243 if (static_spwd.sp_pwdp)
251 /****************************************************************************
252 an enhanced crypt for OSF1
253 ****************************************************************************/
254 static char *osf1_bigcrypt(char *password,char *salt1)
256 static char result[AUTH_MAX_PASSWD_LENGTH] = "";
261 int parts = strlen(password) / AUTH_CLEARTEXT_SEG_CHARS;
262 if (strlen(password)%AUTH_CLEARTEXT_SEG_CHARS)
265 StrnCpy(salt,salt1,2);
266 StrnCpy(result,salt1,2);
268 for (i=0; i<parts;i++)
272 StrnCpy(salt,&result[2+i*AUTH_CIPHERTEXT_SEG_CHARS],2);
273 p2 += AUTH_CLEARTEXT_SEG_CHARS;
281 /****************************************************************************
282 update the enhanced security database. Only relevant for OSF1 at the moment.
283 ****************************************************************************/
284 static void update_protected_database( char *user, BOOL result)
287 struct pr_passwd *mypasswd;
290 mypasswd = getprpwnam (user);
291 starttime = time (NULL);
295 mypasswd->ufld.fd_slogin = starttime;
296 mypasswd->ufld.fd_nlogins = 0;
298 putprpwnam(user,mypasswd);
300 DEBUG(3,("Update protected database for Account %s after succesful connection\n",user));
304 mypasswd->ufld.fd_ulogin = starttime;
305 mypasswd->ufld.fd_nlogins = mypasswd->ufld.fd_nlogins + 1;
306 if ( mypasswd->ufld.fd_max_tries != 0 && mypasswd->ufld.fd_nlogins > mypasswd->ufld.fd_max_tries )
308 mypasswd->uflg.fg_lock = 0;
309 DEBUG(3,("Account is disabled -- see Account Administrator.\n"));
311 putprpwnam ( user , mypasswd );
312 DEBUG(3,("Update protected database for Account %s after refusing connection\n",user));
315 DEBUG(6,("Updated database with %s %s\n",user,BOOLSTR(result)));
321 /*******************************************************************
322 check on AFS authentication
323 ********************************************************************/
324 static BOOL afs_auth(char *this_user,char *password)
326 long password_expires = 0;
329 /* For versions of AFS prior to 3.3, this routine has few arguments, */
330 /* but since I can't find the old documentation... :-) */
332 if (ka_UserAuthenticateGeneral(KA_USERAUTH_VERSION+KA_USERAUTH_DOSETPAG,
334 (char *) 0, /* instance */
335 (char *) 0, /* cell */
337 0, /* lifetime, default */
338 &password_expires, /*days 'til it expires */
349 sec_login_handle_t my_dce_sec_context;
350 int dcelogin_atmost_once = 0;
352 /*******************************************************************
353 check on a DCE/DFS authentication
354 ********************************************************************/
355 static BOOL dfs_auth(char *this_user,char *password)
360 boolean32 password_reset;
361 sec_passwd_rec_t my_dce_password;
362 sec_login_auth_src_t auth_src = sec_login_auth_src_network;
363 unsigned char dce_errstr[dce_c_error_string_len];
366 * We only go for a DCE login context if the given password
367 * matches that stored in the local password file..
368 * Assumes local passwd file is kept in sync w/ DCE RGY!
371 if (!strcmp((char *)crypt(password,this_salt),this_crypted) ||
372 dcelogin_atmost_once)
375 if (sec_login_setup_identity(
376 (unsigned char *)this_user,
381 dce_error_inq_text(err, dce_errstr, &err2);
382 DEBUG(0,("DCE Setup Identity for %s failed: %s\n",
383 this_user,dce_errstr));
387 my_dce_password.version_number = sec_passwd_c_version_none;
388 my_dce_password.pepper = NULL;
389 my_dce_password.key.key_type = sec_passwd_plain;
390 my_dce_password.key.tagged_union.plain = (idl_char *)password;
392 if (sec_login_valid_and_cert_ident(my_dce_sec_context,
398 dce_error_inq_text(err, dce_errstr, &err2);
399 DEBUG(0,("DCE Identity Validation failed for principal %s: %s\n",
400 this_user,dce_errstr));
405 sec_login_set_context(my_dce_sec_context, &err);
406 if (err != error_status_ok )
408 dce_error_inq_text(err, dce_errstr, &err2);
409 DEBUG(0,("DCE login failed for principal %s, cant set context: %s\n",
410 this_user,dce_errstr));
411 sec_login_purge_context(my_dce_sec_context, &err);
416 DEBUG(0,("DCE login succeeded for principal %s on pid %d\n",
417 this_user, getpid()));
420 dcelogin_atmost_once = 1;
424 void dfs_unlogin(void)
428 unsigned char dce_errstr[dce_c_error_string_len];
430 sec_login_purge_context(my_dce_sec_context, &err);
431 if (err != error_status_ok )
433 dce_error_inq_text(err, dce_errstr, &err2);
434 DEBUG(0,("DCE purge login context failed for server instance %d: %s\n",
435 getpid(), dce_errstr));
442 #ifdef LINUX_BIGCRYPT
443 /****************************************************************************
444 an enhanced crypt for Linux to handle password longer than 8 characters
445 ****************************************************************************/
446 static int linux_bigcrypt(char *password,char *salt1, char *crypted)
448 #define LINUX_PASSWORD_SEG_CHARS 8
452 StrnCpy(salt,salt1,2);
455 for ( i=strlen(password); i > 0; i -= LINUX_PASSWORD_SEG_CHARS) {
456 char * p = crypt(password,salt) + 2;
457 if(strncmp(p, crypted, LINUX_PASSWORD_SEG_CHARS) != 0)
459 password += LINUX_PASSWORD_SEG_CHARS;
460 crypted += strlen(p);
468 /****************************************************************************
469 apply a function to upper/lower case combinations
470 of a string and return true if one of them returns true.
471 try all combinations with N uppercase letters.
472 offset is the first char to try and change (start with 0)
473 it assumes the string starts lowercased
474 ****************************************************************************/
475 static BOOL string_combinations2(char *s,int offset,BOOL (*fn)(),int N)
480 #ifdef PASSWORD_LENGTH
481 len = MIN(len,PASSWORD_LENGTH);
484 if (N <= 0 || offset >= len)
487 for (i=offset;i<(len-(N-1));i++)
490 if (!islower(c)) continue;
492 if (string_combinations2(s,i+1,fn,N-1))
499 /****************************************************************************
500 apply a function to upper/lower case combinations
501 of a string and return true if one of them returns true.
502 try all combinations with up to N uppercase letters.
503 offset is the first char to try and change (start with 0)
504 it assumes the string starts lowercased
505 ****************************************************************************/
506 static BOOL string_combinations(char *s,BOOL (*fn)(),int N)
510 if (string_combinations2(s,0,fn,n)) return(True);
516 /****************************************************************************
517 core of password checking routine
518 ****************************************************************************/
519 BOOL password_check(char *password)
522 if (afs_auth(this_user,password)) return(True);
526 if (dfs_auth(this_user,password)) return(True);
530 if (pwdauth(this_user,password) == 0)
535 return(strcmp(osf1_bigcrypt(password,this_salt),this_crypted) == 0);
539 return (strcmp((char *)crypt16(password, this_salt ),this_crypted) == 0);
542 #ifdef LINUX_BIGCRYPT
543 return(linux_bigcrypt(password,this_salt,this_crypted));
547 DEBUG(1,("Warning - no crypt available\n"));
550 return(strcmp((char *)crypt(password,this_salt),this_crypted) == 0);
555 /****************************************************************************
556 core of smb password checking routine.
557 ****************************************************************************/
558 BOOL smb_password_check(char *password, unsigned char *part_passwd, unsigned char *c8)
560 /* Finish the encryption of part_passwd. */
561 unsigned char p21[21];
562 unsigned char p24[24];
564 if(part_passwd == NULL)
565 DEBUG(10,("No password set - allowing access\n"));
566 /* No password set - always true ! */
567 if(part_passwd == NULL)
571 memcpy(p21,part_passwd,16);
576 DEBUG(100,("Part password (P16) was |"));
577 for(i = 0; i < 16; i++)
578 DEBUG(100,("%X ", (unsigned char)part_passwd[i]));
580 DEBUG(100,("Password from client was |"));
581 for(i = 0; i < 24; i++)
582 DEBUG(100,("%X ", (unsigned char)password[i]));
584 DEBUG(100,("Given challenge was |"));
585 for(i = 0; i < 8; i++)
586 DEBUG(100,("%X ", (unsigned char)c8[i]));
588 DEBUG(100,("Value from encryption was |"));
589 for(i = 0; i < 24; i++)
590 DEBUG(100,("%X ", (unsigned char)p24[i]));
594 return (memcmp(p24, password, 24) == 0);
598 /****************************************************************************
599 check if a username/password is OK
600 ****************************************************************************/
601 BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd, BOOL is_nt_password)
604 int level = lp_passwordlevel();
608 struct smb_passwd *smb_pass;
609 BOOL challenge_done = False;
612 if (password) password[pwlen] = 0;
616 challenge_done = last_challenge(challenge);
624 DEBUG(100,("checking user=[%s] pass=[",user));
625 for( i = 0; i < 24; i++)
626 DEBUG(100,("%0x ", (unsigned char)password[i]));
631 DEBUG(100,("checking user=[%s] pass=[%s]\n",user,password));
637 if (((!*password) || (!pwlen)) && !lp_null_passwords())
642 pass = (struct passwd *) pwd;
643 user = pass->pw_name;
646 pass = Get_Pwnam(user,True);
650 DEBUG(4,("SMB Password - pwlen = %d, challenge_done = %d\n", pwlen, challenge_done));
652 if((pwlen == 24) && challenge_done)
654 DEBUG(4,("Checking SMB password for user %s (l=24)\n",user));
658 DEBUG(3,("Couldn't find user %s\n",user));
662 smb_pass = get_smbpwnam(user);
665 DEBUG(3,("Couldn't find user %s in smb_passwd file.\n", user));
669 /* Ensure the uid's match */
670 if(smb_pass->smb_userid != pass->pw_uid)
672 DEBUG(3,("Error : UNIX and SMB uids in password files do not match !\n"));
676 if(Protocol >= PROTOCOL_NT1 && is_nt_password)
678 /* We have the NT MD4 hash challenge available - see if we can
679 use it (ie. does it exist in the smbpasswd file).
681 if(smb_pass->smb_nt_passwd != NULL)
683 DEBUG(4,("Checking NT MD4 password\n"));
684 if(smb_password_check(password,
685 smb_pass->smb_nt_passwd,
688 update_protected_database(user,True);
691 DEBUG(4,("NT MD4 password check failed\n"));
696 /* Try against the lanman password */
698 if (smb_password_check(password,
699 smb_pass->smb_passwd,
700 (char *)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 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 int port = SMB_PORT;
1262 if (password_client >= 0)
1263 close(password_client);
1264 password_client = -1;
1266 if (Protocol < PROTOCOL_NT1) {
1267 strcpy(pass_protocol,"LM1.2X002");
1269 strcpy(pass_protocol,"NT LM 0.12");
1272 bzero(inbuf,sizeof(inbuf));
1273 bzero(outbuf,sizeof(outbuf));
1275 for (p=strtok(lp_passwordserver(),LIST_SEP); p ; p = strtok(NULL,LIST_SEP)) {
1277 standard_sub_basic(desthost);
1280 dest_ip = *interpret_addr2(desthost);
1281 if (zero_ip(dest_ip)) {
1282 DEBUG(1,("Can't resolve address for %s\n",p));
1286 if (ismyip(dest_ip)) {
1287 DEBUG(1,("Password server loop - disabling password server %s\n",p));
1291 password_client = open_socket_out(SOCK_STREAM, &dest_ip, port);
1292 if (password_client >= 0) {
1293 DEBUG(3,("connected to password server %s\n",p));
1294 StrnCpy(pserver,p,sizeof(pserver)-1);
1299 if (password_client < 0) {
1300 DEBUG(1,("password server not available\n"));
1305 /* send a session request (RFC 8002) */
1307 /* put in the destination name */
1310 name_mangle(desthost,p,' ');
1315 name_mangle(remote_machine,p,' ');
1318 _smb_setlen(outbuf,len);
1319 CVAL(outbuf,0) = 0x81;
1321 send_smb(password_client,outbuf);
1322 receive_smb(password_client,inbuf,5000);
1324 if (CVAL(inbuf,0) != 0x82) {
1325 DEBUG(1,("%s rejected the session\n",pserver));
1326 close(password_client); password_client = -1;
1330 DEBUG(3,("got session\n"));
1332 bzero(outbuf,smb_size);
1334 /* setup the protocol string */
1335 set_message(outbuf,0,strlen(pass_protocol)+2,True);
1336 p = smb_buf(outbuf);
1338 strcpy(p,pass_protocol);
1340 CVAL(outbuf,smb_com) = SMBnegprot;
1341 CVAL(outbuf,smb_flg) = 0x8;
1342 SSVAL(outbuf,smb_flg2,0x1);
1344 send_smb(password_client,outbuf);
1345 ret = receive_smb(password_client,inbuf,5000);
1347 if (!ret || CVAL(inbuf,smb_rcls) || SVAL(inbuf,smb_vwv0)) {
1348 DEBUG(1,("%s rejected the protocol\n",pserver));
1349 close(password_client); password_client= -1;
1353 if (!(CVAL(inbuf,smb_vwv1) & 1)) {
1354 DEBUG(1,("%s isn't in user level security mode\n",pserver));
1355 close(password_client); password_client= -1;
1359 memcpy(buf,inbuf,smb_len(inbuf)+4);
1361 DEBUG(3,("password server OK\n"));
1366 /****************************************************************************
1367 attempted support for server level security
1368 ****************************************************************************/
1369 BOOL server_validate(char *buf)
1371 pstring inbuf,outbuf;
1374 if (password_client < 0) {
1375 DEBUG(1,("%s not connected\n",pserver));
1379 bzero(inbuf,sizeof(inbuf));
1380 memcpy(outbuf,buf,sizeof(outbuf));
1382 /* send a session setup command */
1383 CVAL(outbuf,smb_flg) = 0x8;
1384 SSVAL(outbuf,smb_flg2,0x1);
1385 CVAL(outbuf,smb_vwv0) = 0xFF;
1387 set_message(outbuf,smb_numwords(outbuf),smb_buflen(outbuf),False);
1389 SCVAL(inbuf,smb_rcls,1);
1391 send_smb(password_client,outbuf);
1392 ret = receive_smb(password_client,inbuf,5000);
1394 if (!ret || CVAL(inbuf,smb_rcls) != 0) {
1395 DEBUG(1,("password server %s rejected the password\n",pserver));
1399 /* if logged in as guest then reject */
1400 if ((SVAL(inbuf,smb_vwv2) & 1) != 0) {
1401 DEBUG(1,("password server %s gave us guest only\n",pserver));
1405 DEBUG(3,("password server %s accepted the password\n",pserver));
1407 #if !KEEP_PASSWORD_SERVER_OPEN
1408 close(password_client); password_client= -1;