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.
24 extern int DEBUGLEVEL;
27 /* users from session setup */
28 static pstring session_users="";
30 /* these are kept here to keep the string_combinations function simple */
31 static char this_user[100]="";
32 static char this_salt[100]="";
33 static char this_crypted[100]="";
36 /* Data to do lanman1/2 password challenge. */
37 static unsigned char saved_challenge[8];
38 static BOOL challenge_sent=False;
40 /*******************************************************************
41 Get the next challenge value - no repeats.
42 ********************************************************************/
43 void generate_next_challenge(char *challenge)
45 static int counter = 0;
49 v1 = (counter++) + getpid() + tval.tv_sec;
50 v2 = (counter++) * getpid() + tval.tv_usec;
51 SIVAL(challenge,0,v1);
52 SIVAL(challenge,4,v2);
53 E1(challenge,"SAMBA",(char *)saved_challenge);
54 memcpy(challenge,saved_challenge,8);
55 challenge_sent = True;
58 /*******************************************************************
59 set the last challenge sent, usually from a password server
60 ********************************************************************/
61 BOOL set_challenge(char *challenge)
63 memcpy(saved_challenge,challenge,8);
64 challenge_sent = True;
68 /*******************************************************************
69 get the last challenge sent
70 ********************************************************************/
71 BOOL last_challenge(char *challenge)
73 if (!challenge_sent) return(False);
74 memcpy(challenge,saved_challenge,8);
79 /* this holds info on user ids that are already validated for this VC */
80 static user_struct *validated_users = NULL;
81 static int num_validated_users = 0;
83 /****************************************************************************
84 check if a uid has been validated, and return an pointer to the user_struct
85 if it has. NULL if not. vuid is biased by an offset. This allows us to
86 tell random client vuid's (normally zero) from valid vuids.
87 ****************************************************************************/
88 user_struct *get_valid_user_struct(uint16 vuid)
90 if(vuid == UID_FIELD_INVALID)
93 if((vuid >= (uint16)num_validated_users) ||
94 (validated_users[vuid].uid == -1) || (validated_users[vuid].gid == -1))
96 return &validated_users[vuid];
99 /****************************************************************************
101 ****************************************************************************/
102 void invalidate_vuid(uint16 vuid)
104 user_struct *vuser = get_valid_user_struct(vuid);
110 vuser->user_ngroups = 0;
111 if(vuser->user_groups &&
112 (vuser->user_groups != (gid_t *)vuser->user_igroups))
113 free(vuser->user_groups);
114 vuser->user_groups = NULL;
115 if(vuser->user_igroups)
116 free(vuser->user_igroups);
117 vuser->user_igroups = NULL;
121 /****************************************************************************
122 return a validated username
123 ****************************************************************************/
124 char *validated_username(uint16 vuid)
126 user_struct *vuser = get_valid_user_struct(vuid);
132 /****************************************************************************
133 register a uid/name pair as being valid and that a valid password
134 has been given. vuid is biased by an offset. This allows us to
135 tell random client vuid's (normally zero) from valid vuids.
136 ****************************************************************************/
137 uint16 register_vuid(int uid,int gid, char *name,BOOL guest)
142 for(i = 0; i < num_validated_users; i++) {
143 vuser = &validated_users[i];
144 if( vuser->uid == uid )
145 return i; /* User already validated */
148 validated_users = (user_struct *)Realloc(validated_users,
150 (num_validated_users+1));
152 if (!validated_users)
154 DEBUG(0,("Failed to realloc users struct!\n"));
155 num_validated_users = 0;
156 return UID_FIELD_INVALID;
159 vuser = &validated_users[num_validated_users];
160 num_validated_users++;
164 vuser->guest = guest;
165 strcpy(vuser->name,name);
167 vuser->user_ngroups = 0;
168 vuser->user_groups = NULL;
169 vuser->user_igroups = NULL;
171 /* Find all the groups this uid is in and store them.
172 Used by become_user() */
173 setup_groups(name,uid,gid,
174 &vuser->user_ngroups,
175 &vuser->user_igroups,
176 &vuser->user_groups);
178 DEBUG(3,("uid %d registered to name %s\n",uid,name));
180 return (uint16)((num_validated_users - 1) + VUID_OFFSET);
184 /****************************************************************************
185 add a name to the session users list
186 ****************************************************************************/
187 void add_session_user(char *user)
190 StrnCpy(suser,user,sizeof(suser)-1);
192 if (!Get_Pwnam(suser,True)) return;
194 if (suser && *suser && !in_list(suser,session_users,False))
196 if (strlen(suser) + strlen(session_users) + 2 >= sizeof(pstring))
197 DEBUG(1,("Too many session users??\n"));
200 strcat(session_users," ");
201 strcat(session_users,suser);
208 /* a fake shadow password routine which just fills a fake spwd struct
209 * with the sp_pwdp field. (sreiz@aie.nl)
211 static struct spwd *getspnam(char *username) /* fake shadow password routine */
216 static struct spwd static_spwd;
218 static_spwd.sp_pwdp=0;
219 if (!(f=fopen("/etc/master.passwd", "r")))
221 while (fgets(line, 1024, f)) {
222 if (!strncmp(line, username, strlen(username)) &&
223 line[strlen(username)]==':') { /* found entry */
226 p=line+strlen(username)+1;
227 if ((q=strchr(p, ':'))) {
232 static_spwd.sp_pwdp=pw;
238 if (static_spwd.sp_pwdp)
246 /****************************************************************************
247 an enhanced crypt for OSF1
248 ****************************************************************************/
249 static char *osf1_bigcrypt(char *password,char *salt1)
251 static char result[AUTH_MAX_PASSWD_LENGTH] = "";
256 int parts = strlen(password) / AUTH_CLEARTEXT_SEG_CHARS;
257 if (strlen(password)%AUTH_CLEARTEXT_SEG_CHARS)
260 StrnCpy(salt,salt1,2);
261 StrnCpy(result,salt1,2);
263 for (i=0; i<parts;i++)
267 StrnCpy(salt,&result[2+i*AUTH_CIPHERTEXT_SEG_CHARS],2);
268 p2 += AUTH_CLEARTEXT_SEG_CHARS;
276 /****************************************************************************
277 update the enhanced security database. Only relevant for OSF1 at the moment.
278 ****************************************************************************/
279 static void update_protected_database( char *user, BOOL result)
282 struct pr_passwd *mypasswd;
285 mypasswd = getprpwnam (user);
286 starttime = time (NULL);
290 mypasswd->ufld.fd_slogin = starttime;
291 mypasswd->ufld.fd_nlogins = 0;
293 putprpwnam(user,mypasswd);
295 DEBUG(3,("Update protected database for Account %s after succesful connection\n",user));
299 mypasswd->ufld.fd_ulogin = starttime;
300 mypasswd->ufld.fd_nlogins = mypasswd->ufld.fd_nlogins + 1;
301 if ( mypasswd->ufld.fd_max_tries != 0 && mypasswd->ufld.fd_nlogins > mypasswd->ufld.fd_max_tries )
303 mypasswd->uflg.fg_lock = 0;
304 DEBUG(3,("Account is disabled -- see Account Administrator.\n"));
306 putprpwnam ( user , mypasswd );
307 DEBUG(3,("Update protected database for Account %s after refusing connection\n",user));
310 DEBUG(6,("Updated database with %s %s\n",user,BOOLSTR(result)));
316 /*******************************************************************
317 check on AFS authentication
318 ********************************************************************/
319 static BOOL afs_auth(char *this_user,char *password)
321 long password_expires = 0;
324 /* For versions of AFS prior to 3.3, this routine has few arguments, */
325 /* but since I can't find the old documentation... :-) */
327 if (ka_UserAuthenticateGeneral(KA_USERAUTH_VERSION+KA_USERAUTH_DOSETPAG,
329 (char *) 0, /* instance */
330 (char *) 0, /* cell */
332 0, /* lifetime, default */
333 &password_expires, /*days 'til it expires */
344 sec_login_handle_t my_dce_sec_context;
345 int dcelogin_atmost_once = 0;
347 /*******************************************************************
348 check on a DCE/DFS authentication
349 ********************************************************************/
350 static BOOL dfs_auth(char *this_user,char *password)
355 boolean32 password_reset;
356 sec_passwd_rec_t my_dce_password;
357 sec_login_auth_src_t auth_src = sec_login_auth_src_network;
358 unsigned char dce_errstr[dce_c_error_string_len];
361 * We only go for a DCE login context if the given password
362 * matches that stored in the local password file..
363 * Assumes local passwd file is kept in sync w/ DCE RGY!
366 if (!strcmp((char *)crypt(password,this_salt),this_crypted) ||
367 dcelogin_atmost_once)
370 if (sec_login_setup_identity(
371 (unsigned char *)this_user,
376 dce_error_inq_text(err, dce_errstr, &err2);
377 DEBUG(0,("DCE Setup Identity for %s failed: %s\n",
378 this_user,dce_errstr));
382 my_dce_password.version_number = sec_passwd_c_version_none;
383 my_dce_password.pepper = NULL;
384 my_dce_password.key.key_type = sec_passwd_plain;
385 my_dce_password.key.tagged_union.plain = (idl_char *)password;
387 if (sec_login_valid_and_cert_ident(my_dce_sec_context,
393 dce_error_inq_text(err, dce_errstr, &err2);
394 DEBUG(0,("DCE Identity Validation failed for principal %s: %s\n",
395 this_user,dce_errstr));
400 sec_login_set_context(my_dce_sec_context, &err);
401 if (err != error_status_ok )
403 dce_error_inq_text(err, dce_errstr, &err2);
404 DEBUG(0,("DCE login failed for principal %s, cant set context: %s\n",
405 this_user,dce_errstr));
406 sec_login_purge_context(my_dce_sec_context, &err);
411 DEBUG(0,("DCE login succeeded for principal %s on pid %d\n",
412 this_user, getpid()));
415 dcelogin_atmost_once = 1;
419 void dfs_unlogin(void)
423 unsigned char dce_errstr[dce_c_error_string_len];
425 sec_login_purge_context(my_dce_sec_context, &err);
426 if (err != error_status_ok )
428 dce_error_inq_text(err, dce_errstr, &err2);
429 DEBUG(0,("DCE purge login context failed for server instance %d: %s\n",
430 getpid(), dce_errstr));
437 #ifdef LINUX_BIGCRYPT
438 /****************************************************************************
439 an enhanced crypt for Linux to handle password longer than 8 characters
440 ****************************************************************************/
441 static int linux_bigcrypt(char *password,char *salt1, char *crypted)
443 #define LINUX_PASSWORD_SEG_CHARS 8
447 StrnCpy(salt,salt1,2);
450 for ( i=strlen(password); i > 0; i -= LINUX_PASSWORD_SEG_CHARS) {
451 char * p = crypt(password,salt) + 2;
452 if(strncmp(p, crypted, LINUX_PASSWORD_SEG_CHARS) != 0)
454 password += LINUX_PASSWORD_SEG_CHARS;
455 crypted += strlen(p);
463 /****************************************************************************
464 apply a function to upper/lower case combinations
465 of a string and return true if one of them returns true.
466 try all combinations with N uppercase letters.
467 offset is the first char to try and change (start with 0)
468 it assumes the string starts lowercased
469 ****************************************************************************/
470 static BOOL string_combinations2(char *s,int offset,BOOL (*fn)(),int N)
475 #ifdef PASSWORD_LENGTH
476 len = MIN(len,PASSWORD_LENGTH);
479 if (N <= 0 || offset >= len)
482 for (i=offset;i<(len-(N-1));i++)
485 if (!islower(c)) continue;
487 if (string_combinations2(s,i+1,fn,N-1))
494 /****************************************************************************
495 apply a function to upper/lower case combinations
496 of a string and return true if one of them returns true.
497 try all combinations with up to N uppercase letters.
498 offset is the first char to try and change (start with 0)
499 it assumes the string starts lowercased
500 ****************************************************************************/
501 static BOOL string_combinations(char *s,BOOL (*fn)(),int N)
505 if (string_combinations2(s,0,fn,n)) return(True);
511 /****************************************************************************
512 core of password checking routine
513 ****************************************************************************/
514 BOOL password_check(char *password)
517 if (afs_auth(this_user,password)) return(True);
521 if (dfs_auth(this_user,password)) return(True);
525 if (pwdauth(this_user,password) == 0)
530 return(strcmp(osf1_bigcrypt(password,this_salt),this_crypted) == 0);
534 return (strcmp((char *)crypt16(password, this_salt ),this_crypted) == 0);
537 #ifdef LINUX_BIGCRYPT
538 return(linux_bigcrypt(password,this_salt,this_crypted));
542 DEBUG(1,("Warning - no crypt available\n"));
545 return(strcmp((char *)crypt(password,this_salt),this_crypted) == 0);
550 /****************************************************************************
551 core of smb password checking routine.
552 ****************************************************************************/
553 BOOL smb_password_check(char *password, unsigned char *part_passwd, unsigned char *c8)
555 /* Finish the encryption of part_passwd. */
556 unsigned char p21[21];
557 unsigned char p24[24];
559 if(part_passwd == NULL)
560 DEBUG(10,("No password set - allowing access\n"));
561 /* No password set - always true ! */
562 if(part_passwd == NULL)
566 memcpy(p21,part_passwd,16);
571 DEBUG(100,("Part password (P16) was |"));
572 for(i = 0; i < 16; i++)
573 DEBUG(100,("%X ", (unsigned char)part_passwd[i]));
575 DEBUG(100,("Password from client was |"));
576 for(i = 0; i < 24; i++)
577 DEBUG(100,("%X ", (unsigned char)password[i]));
579 DEBUG(100,("Given challenge was |"));
580 for(i = 0; i < 8; i++)
581 DEBUG(100,("%X ", (unsigned char)c8[i]));
583 DEBUG(100,("Value from encryption was |"));
584 for(i = 0; i < 24; i++)
585 DEBUG(100,("%X ", (unsigned char)p24[i]));
589 return (memcmp(p24, password, 24) == 0);
593 /****************************************************************************
594 check if a username/password is OK
595 ****************************************************************************/
596 BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd)
599 int level = lp_passwordlevel();
603 struct smb_passwd *smb_pass;
604 BOOL challenge_done = False;
607 if (password) password[pwlen] = 0;
611 challenge_done = last_challenge(challenge);
619 DEBUG(100,("checking user=[%s] pass=[",user));
620 for( i = 0; i < 24; i++)
621 DEBUG(100,("%0x ", (unsigned char)password[i]));
626 DEBUG(100,("checking user=[%s] pass=[%s]\n",user,password));
632 if (((!*password) || (!pwlen)) && !lp_null_passwords())
637 pass = (struct passwd *) pwd;
638 user = pass->pw_name;
641 pass = Get_Pwnam(user,True);
645 DEBUG(4,("SMB Password - pwlen = %d, challenge_done = %d\n", pwlen, challenge_done));
647 if((pwlen == 24) && challenge_done)
649 DEBUG(4,("Checking SMB password for user %s (l=24)\n",user));
653 DEBUG(3,("Couldn't find user %s\n",user));
657 smb_pass = get_smbpwnam(user);
660 DEBUG(3,("Couldn't find user %s in smb_passwd file.\n", user));
664 /* Ensure the uid's match */
665 if(smb_pass->smb_userid != pass->pw_uid)
667 DEBUG(3,("Error : UNIX and SMB uids in password files do not match !\n"));
671 if(Protocol >= PROTOCOL_NT1)
673 /* We have the NT MD4 hash challenge available - see if we can
674 use it (ie. does it exist in the smbpasswd file).
676 if(smb_pass->smb_nt_passwd != NULL)
678 DEBUG(4,("Checking NT MD4 password\n"));
679 if(smb_password_check(password,
680 smb_pass->smb_nt_passwd,
683 update_protected_database(user,True);
686 DEBUG(4,("NT MD4 password check failed\n"));
690 /* Try against the lanman password */
692 if (smb_password_check(password,
693 smb_pass->smb_passwd,
694 (char *)challenge)) {
695 update_protected_database(user,True);
699 DEBUG(3,("Error smb_password_check failed\n"));
703 DEBUG(4,("Checking password for user %s (l=%d)\n",user,pwlen));
707 DEBUG(3,("Couldn't find user %s\n",user));
715 /* many shadow systems require you to be root to get the password,
716 in most cases this should already be the case when this
717 function is called, except perhaps for IPC password changing
720 spass = getspnam(pass->pw_name);
721 if (spass && spass->sp_pwdp)
722 pass->pw_passwd = spass->sp_pwdp;
728 struct pr_passwd *pr_pw = getprpwnam(pass->pw_name);
729 if (pr_pw && pr_pw->ufld.fd_encrypt)
730 pass->pw_passwd = pr_pw->ufld.fd_encrypt;
734 #ifdef HPUX_10_TRUSTED
736 struct pr_passwd *pr_pw = getprpwnam(pass->pw_name);
737 if (pr_pw && pr_pw->ufld.fd_encrypt)
738 pass->pw_passwd = pr_pw->ufld.fd_encrypt;
744 struct pr_passwd *mypasswd;
745 DEBUG(5,("Checking password for user %s in OSF1_ENH_SEC\n",user));
746 mypasswd = getprpwnam (user);
749 strcpy(pass->pw_name,mypasswd->ufld.fd_name);
750 strcpy(pass->pw_passwd,mypasswd->ufld.fd_encrypt);
754 DEBUG(5,("No entry for user %s in protected database !\n",user));
762 AUTHORIZATION *ap = getauthuid( pass->pw_uid );
765 strcpy( pass->pw_passwd, ap->a_password );
771 /* extract relevant info */
772 strcpy(this_user,pass->pw_name);
773 strcpy(this_salt,pass->pw_passwd);
774 strcpy(this_crypted,pass->pw_passwd);
776 if (!*this_crypted) {
777 if (!lp_null_passwords()) {
778 DEBUG(2,("Disallowing access to %s due to null password\n",this_user));
783 DEBUG(3,("Allowing access to %s with null password\n",this_user));
789 /* try it as it came to us */
790 if (password_check(password))
792 update_protected_database(user,True);
796 /* if the password was given to us with mixed case then we don't
797 need to proceed as we know it hasn't been case modified by the
799 if (strhasupper(password) && strhaslower(password))
802 /* make a copy of it */
803 StrnCpy(pass2,password,sizeof(pstring)-1);
805 /* try all lowercase */
807 if (password_check(password))
809 update_protected_database(user,True);
816 update_protected_database(user,False);
819 strcpy(password,pass2);
824 /* last chance - all combinations of up to level chars upper! */
827 if (string_combinations(password,password_check,level))
829 update_protected_database(user,True);
833 update_protected_database(user,False);
836 strcpy(password,pass2);
843 /****************************************************************************
844 check if a username is valid
845 ****************************************************************************/
846 BOOL user_ok(char *user,int snum)
848 pstring valid, invalid;
851 StrnCpy(valid, lp_valid_users(snum), sizeof(pstring));
852 StrnCpy(invalid, lp_invalid_users(snum), sizeof(pstring));
854 string_sub(valid,"%S",lp_servicename(snum));
855 string_sub(invalid,"%S",lp_servicename(snum));
857 ret = !user_in_list(user,invalid);
859 if (ret && valid && *valid)
860 ret = user_in_list(user,valid);
862 if (ret && lp_onlyuser(snum)) {
863 char *user_list = lp_username(snum);
864 string_sub(user_list,"%S",lp_servicename(snum));
865 ret = user_in_list(user,user_list);
874 /****************************************************************************
875 validate a group username entry. Return the username or NULL
876 ****************************************************************************/
877 static char *validate_group(char *group,char *password,int pwlen,int snum)
881 char *host, *user, *domain;
883 while (getnetgrent(&host, &user, &domain)) {
885 if (user_ok(user, snum) &&
886 password_ok(user,password,pwlen,NULL)) {
898 struct group *gptr = (struct group *)getgrnam(group);
902 member = gptr->gr_mem;
903 while (member && *member)
906 strcpy(name,*member);
907 if (user_ok(name,snum) &&
908 password_ok(name,password,pwlen,NULL))
912 #ifdef GROUP_CHECK_PWENT
918 while (pwd = getpwent ()) {
919 if (*(pwd->pw_passwd) && pwd->pw_gid == gptr->gr_gid) {
920 /* This Entry have PASSWORD and same GID then check pwd */
921 if (password_ok(NULL, password, pwlen, pwd)) {
922 strcpy(tm, pwd->pw_name);
930 #endif /* GROUP_CHECK_PWENT */
939 /****************************************************************************
940 check for authority to login to a service with a given username/password
941 ****************************************************************************/
942 BOOL authorise_login(int snum,char *user,char *password, int pwlen,
943 BOOL *guest,BOOL *force,uint16 vuid)
950 DEBUG(100,("checking authorisation on user=%s pass=%s\n",user,password));
953 /* there are several possabilities:
954 1) login as the given user with given password
955 2) login as a previously registered username with the given password
956 3) login as a session list username with the given password
957 4) login as a previously validated user/password pair
958 5) login as the "user =" user with given password
959 6) login as the "user =" user with no password (guest connection)
960 7) login as guest user with no password
962 if the service is guest_only then steps 1 to 5 are skipped
965 if (GUEST_ONLY(snum)) *force = True;
967 if (!(GUEST_ONLY(snum) && GUEST_OK(snum)))
970 user_struct *vuser = get_valid_user_struct(vuid);
972 /* check the given username and password */
973 if (!ok && (*user) && user_ok(user,snum)) {
974 ok = password_ok(user,password, pwlen, NULL);
975 if (ok) DEBUG(3,("ACCEPTED: given username password ok\n"));
978 /* check for a previously registered guest username */
979 if (!ok && (vuser != 0) && vuser->guest) {
980 if (user_ok(vuser->name,snum) &&
981 password_ok(vuser->name, password, pwlen, NULL)) {
982 strcpy(user, vuser->name);
983 vuser->guest = False;
984 DEBUG(3,("ACCEPTED: given password with registered user %s\n", user));
990 /* now check the list of session users */
994 char *user_list = strdup(session_users);
995 if (!user_list) return(False);
997 for (auser=strtok(user_list,LIST_SEP);
999 auser = strtok(NULL,LIST_SEP))
1002 strcpy(user2,auser);
1003 if (!user_ok(user2,snum)) continue;
1005 if (password_ok(user2,password, pwlen, NULL)) {
1008 DEBUG(3,("ACCEPTED: session list username and given password ok\n"));
1014 /* check for a previously validated username/password pair */
1015 if (!ok && !lp_revalidate(snum) &&
1016 (vuser != 0) && !vuser->guest &&
1017 user_ok(vuser->name,snum)) {
1018 strcpy(user,vuser->name);
1020 DEBUG(3,("ACCEPTED: validated uid ok as non-guest\n"));
1024 /* check for a rhosts entry */
1025 if (!ok && user_ok(user,snum) && check_hosts_equiv(user)) {
1027 DEBUG(3,("ACCEPTED: hosts equiv or rhosts entry\n"));
1030 /* check the user= fields and the given password */
1031 if (!ok && lp_username(snum)) {
1034 StrnCpy(user_list,lp_username(snum),sizeof(pstring));
1036 string_sub(user_list,"%S",lp_servicename(snum));
1038 for (auser=strtok(user_list,LIST_SEP);
1040 auser = strtok(NULL,LIST_SEP))
1044 auser = validate_group(auser+1,password,pwlen,snum);
1049 DEBUG(3,("ACCEPTED: group username and given password ok\n"));
1055 strcpy(user2,auser);
1056 if (user_ok(user2,snum) &&
1057 password_ok(user2,password,pwlen,NULL))
1061 DEBUG(3,("ACCEPTED: user list username and given password ok\n"));
1066 } /* not guest only */
1068 /* check for a normal guest connection */
1069 if (!ok && GUEST_OK(snum))
1072 StrnCpy(guestname,lp_guestaccount(snum),sizeof(guestname)-1);
1073 if (Get_Pwnam(guestname,True))
1075 strcpy(user,guestname);
1077 DEBUG(3,("ACCEPTED: guest account and guest ok\n"));
1080 DEBUG(0,("Invalid guest account %s??\n",guestname));
1085 if (ok && !user_ok(user,snum))
1087 DEBUG(0,("rejected invalid user %s\n",user));
1095 /****************************************************************************
1096 read the a hosts.equiv or .rhosts file and check if it
1097 allows this user from this machine
1098 ****************************************************************************/
1099 static BOOL check_user_equiv(char *user, char *remote, char *equiv_file)
1102 int plus_allowed = 1;
1105 FILE *fp = fopen(equiv_file, "r");
1106 DEBUG(5, ("check_user_equiv %s %s %s\n", user, remote, equiv_file));
1107 if (! fp) return False;
1108 while(fgets(buf, sizeof(buf), fp))
1110 trim_string(buf," "," ");
1112 if (buf[0] != '#' && buf[0] != '\n')
1114 BOOL is_group = False;
1117 if (strcmp(buf, "NO_PLUS\n") == 0)
1119 DEBUG(6, ("check_user_equiv NO_PLUS\n"));
1126 if (*bp == '\n' && plus_allowed)
1128 /* a bare plus means everbody allowed */
1129 DEBUG(6, ("check_user_equiv everybody allowed\n"));
1134 else if (buf[0] == '-')
1144 file_host = strtok(bp, " \t\n");
1145 file_user = strtok(NULL, " \t\n");
1146 DEBUG(7, ("check_user_equiv %s %s\n", file_host, file_user));
1147 if (file_host && *file_host)
1149 BOOL host_ok = False;
1154 static char *mydomain = NULL;
1156 yp_get_default_domain(&mydomain);
1157 if (mydomain && innetgr(file_host,remote,user,mydomain))
1163 DEBUG(1,("Netgroups not configured - add -DNETGROUP and recompile\n"));
1168 /* is it this host */
1169 /* the fact that remote has come from a call of gethostbyaddr
1170 * means that it may have the fully qualified domain name
1171 * so we could look up the file version to get it into
1172 * a canonical form, but I would rather just type it
1173 * in full in the equiv file
1175 if (!host_ok && !is_group && strequal(remote, file_host))
1181 /* is it this user */
1182 if (file_user == 0 || strequal(user, file_user))
1185 DEBUG(5, ("check_user_equiv matched %s%s %s\n",
1186 (plus ? "+" : "-"), file_host,
1187 (file_user ? file_user : "")));
1188 return (plus ? True : False);
1199 /****************************************************************************
1200 check for a possible hosts equiv or rhosts entry for the user
1201 ****************************************************************************/
1202 BOOL check_hosts_equiv(char *user)
1206 struct passwd *pass = Get_Pwnam(user,True);
1211 fname = lp_hosts_equiv();
1213 /* note: don't allow hosts.equiv on root */
1214 if (fname && *fname && (pass->pw_uid != 0))
1216 if (check_user_equiv(user,client_name(),fname))
1220 if (lp_use_rhosts())
1222 char *home = get_home_dir(user);
1225 sprintf(rhostsfile, "%s/.rhosts", home);
1226 if (check_user_equiv(user,client_name(),rhostsfile))
1235 int password_client = -1;
1236 static fstring pserver;
1238 /****************************************************************************
1239 attempted support for server level security
1240 ****************************************************************************/
1241 BOOL server_cryptkey(char *buf)
1243 pstring inbuf,outbuf;
1244 fstring pass_protocol;
1245 extern fstring remote_machine;
1249 struct in_addr dest_ip;
1250 int port = SMB_PORT;
1253 if (password_client >= 0)
1254 close(password_client);
1255 password_client = -1;
1257 if (Protocol < PROTOCOL_NT1) {
1258 strcpy(pass_protocol,"LM1.2X002");
1260 strcpy(pass_protocol,"NT LM 0.12");
1263 bzero(inbuf,sizeof(inbuf));
1264 bzero(outbuf,sizeof(outbuf));
1266 for (p=strtok(lp_passwordserver(),LIST_SEP); p ; p = strtok(NULL,LIST_SEP)) {
1268 standard_sub_basic(desthost);
1271 dest_ip = *interpret_addr2(desthost);
1272 if (zero_ip(dest_ip)) {
1273 DEBUG(1,("Can't resolve address for %s\n",p));
1277 if (ismyip(dest_ip)) {
1278 DEBUG(1,("Password server loop - disabling password server %s\n",p));
1282 password_client = open_socket_out(SOCK_STREAM, &dest_ip, port, SHORT_CONNECT_TIMEOUT);
1283 if (password_client >= 0) {
1284 DEBUG(3,("connected to password server %s\n",p));
1285 StrnCpy(pserver,p,sizeof(pserver)-1);
1290 if (password_client < 0) {
1291 DEBUG(1,("password server not available\n"));
1296 /* send a session request (RFC 8002) */
1298 /* put in the destination name */
1301 name_mangle(desthost,p,' ');
1306 name_mangle(remote_machine,p,' ');
1309 _smb_setlen(outbuf,len);
1310 CVAL(outbuf,0) = 0x81;
1312 send_smb(password_client,outbuf);
1315 if (!receive_smb(password_client,inbuf,5000) ||
1316 CVAL(inbuf,0) != 0x82) {
1317 DEBUG(1,("%s rejected the session\n",pserver));
1318 close(password_client); password_client = -1;
1322 DEBUG(3,("got session\n"));
1324 bzero(outbuf,smb_size);
1326 /* setup the protocol string */
1327 set_message(outbuf,0,strlen(pass_protocol)+2,True);
1328 p = smb_buf(outbuf);
1330 strcpy(p,pass_protocol);
1332 CVAL(outbuf,smb_com) = SMBnegprot;
1333 CVAL(outbuf,smb_flg) = 0x8;
1334 SSVAL(outbuf,smb_flg2,0x1);
1336 send_smb(password_client,outbuf);
1337 ret = receive_smb(password_client,inbuf,5000);
1339 if (!ret || CVAL(inbuf,smb_rcls) || SVAL(inbuf,smb_vwv0)) {
1340 DEBUG(1,("%s rejected the protocol\n",pserver));
1341 close(password_client); password_client= -1;
1345 if (!(CVAL(inbuf,smb_vwv1) & 1)) {
1346 DEBUG(1,("%s isn't in user level security mode\n",pserver));
1347 close(password_client); password_client= -1;
1351 memcpy(buf,inbuf,smb_len(inbuf)+4);
1353 DEBUG(3,("password server OK\n"));
1358 /****************************************************************************
1359 attempted support for server level security
1360 ****************************************************************************/
1361 BOOL server_validate(char *buf)
1363 pstring inbuf,outbuf;
1366 if (password_client < 0) {
1367 DEBUG(1,("%s not connected\n",pserver));
1371 bzero(inbuf,sizeof(inbuf));
1372 memcpy(outbuf,buf,sizeof(outbuf));
1374 /* send a session setup command */
1375 CVAL(outbuf,smb_flg) = 0x8;
1376 SSVAL(outbuf,smb_flg2,0x1);
1377 CVAL(outbuf,smb_vwv0) = 0xFF;
1379 set_message(outbuf,smb_numwords(outbuf),smb_buflen(outbuf),False);
1381 SCVAL(inbuf,smb_rcls,1);
1383 send_smb(password_client,outbuf);
1384 ret = receive_smb(password_client,inbuf,5000);
1386 if (!ret || CVAL(inbuf,smb_rcls) != 0) {
1387 DEBUG(1,("password server %s rejected the password\n",pserver));
1391 /* if logged in as guest then reject */
1392 if ((SVAL(inbuf,smb_vwv2) & 1) != 0) {
1393 DEBUG(1,("password server %s gave us guest only\n",pserver));
1397 DEBUG(3,("password server %s accepted the password\n",pserver));
1399 #if !KEEP_PASSWORD_SERVER_OPEN
1400 close(password_client); password_client= -1;