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 index if it has. -1 if not
85 ****************************************************************************/
86 int valid_uid(int uid)
89 if (uid == -1) return(-1);
91 for (i=0;i<num_validated_users;i++)
92 if (validated_users[i].uid == uid)
94 DEBUG(3,("valid uid %d mapped to vuid %d (user=%s)\n",
95 uid,i,validated_users[i].name));
101 /****************************************************************************
102 check if a uid has been validated, and return an pointer to the user_struct
103 if it has. NULL if not
104 ****************************************************************************/
105 user_struct *get_valid_user_struct(int uid)
107 int vuid = valid_uid(uid);
108 if(vuid == -1 || validated_users[vuid].guest)
110 return &validated_users[vuid];
113 /****************************************************************************
115 ****************************************************************************/
116 void invalidate_uid(int uid)
119 for (i=0;i<num_validated_users;i++)
120 if (validated_users[i].uid == uid)
122 user_struct *vuser = &validated_users[i];
125 vuser->user_ngroups = 0;
126 if(vuser->user_groups &&
127 (vuser->user_groups != (gid_t *)vuser->user_igroups))
128 free(vuser->user_groups);
129 vuser->user_groups = NULL;
130 if(vuser->user_igroups)
131 free(vuser->user_igroups);
132 vuser->user_igroups = NULL;
137 /****************************************************************************
138 return a validated username
139 ****************************************************************************/
140 char *validated_username(int vuid)
142 return(validated_users[vuid].name);
145 /****************************************************************************
146 register a uid/name pair as being valid and that a valid password
148 ****************************************************************************/
149 void register_uid(int uid,int gid, char *name,BOOL guest)
153 if (valid_uid(uid) >= 0)
155 validated_users = (user_struct *)Realloc(validated_users,
157 (num_validated_users+1));
159 if (!validated_users)
161 DEBUG(0,("Failed to realloc users struct!\n"));
165 vuser = &validated_users[num_validated_users];
168 vuser->guest = guest;
169 strcpy(vuser->name,name);
171 vuser->user_ngroups = 0;
172 vuser->user_groups = NULL;
173 vuser->user_igroups = NULL;
175 /* Find all the groups this uid is in and store them.
176 Used by become_user() */
177 setup_groups(name,uid,gid,
178 &vuser->user_ngroups,
179 &vuser->user_igroups,
180 &vuser->user_groups);
182 DEBUG(3,("uid %d registered to name %s\n",uid,name));
184 num_validated_users++;
188 /****************************************************************************
189 add a name to the session users list
190 ****************************************************************************/
191 void add_session_user(char *user)
194 StrnCpy(suser,user,sizeof(suser)-1);
196 if (!Get_Pwnam(suser,True)) return;
198 if (suser && *suser && !in_list(suser,session_users,False))
200 if (strlen(suser) + strlen(session_users) + 2 >= sizeof(pstring))
201 DEBUG(1,("Too many session users??\n"));
204 strcat(session_users," ");
205 strcat(session_users,suser);
212 /* a fake shadow password routine which just fills a fake spwd struct
213 * with the sp_pwdp field. (sreiz@aie.nl)
215 static struct spwd *getspnam(char *username) /* fake shadow password routine */
220 static struct spwd static_spwd;
222 static_spwd.sp_pwdp=0;
223 if (!(f=fopen("/etc/master.passwd", "r")))
225 while (fgets(line, 1024, f)) {
226 if (!strncmp(line, username, strlen(username)) &&
227 line[strlen(username)]==':') { /* found entry */
230 p=line+strlen(username)+1;
231 if ((q=strchr(p, ':'))) {
236 static_spwd.sp_pwdp=pw;
242 if (static_spwd.sp_pwdp)
250 /****************************************************************************
251 an enhanced crypt for OSF1
252 ****************************************************************************/
253 static char *osf1_bigcrypt(char *password,char *salt1)
255 static char result[AUTH_MAX_PASSWD_LENGTH] = "";
260 int parts = strlen(password) / AUTH_CLEARTEXT_SEG_CHARS;
261 if (strlen(password)%AUTH_CLEARTEXT_SEG_CHARS)
264 StrnCpy(salt,salt1,2);
265 StrnCpy(result,salt1,2);
267 for (i=0; i<parts;i++)
271 StrnCpy(salt,&result[2+i*AUTH_CIPHERTEXT_SEG_CHARS],2);
272 p2 += AUTH_CLEARTEXT_SEG_CHARS;
280 /****************************************************************************
281 update the enhanced security database. Only relevant for OSF1 at the moment.
282 ****************************************************************************/
283 static void update_protected_database( char *user, BOOL result)
286 struct pr_passwd *mypasswd;
289 mypasswd = getprpwnam (user);
290 starttime = time (NULL);
294 mypasswd->ufld.fd_slogin = starttime;
295 mypasswd->ufld.fd_nlogins = 0;
297 putprpwnam(user,mypasswd);
299 DEBUG(3,("Update protected database for Account %s after succesful connection\n",user));
303 mypasswd->ufld.fd_ulogin = starttime;
304 mypasswd->ufld.fd_nlogins = mypasswd->ufld.fd_nlogins + 1;
305 if ( mypasswd->ufld.fd_max_tries != 0 && mypasswd->ufld.fd_nlogins > mypasswd->ufld.fd_max_tries )
307 mypasswd->uflg.fg_lock = 0;
308 DEBUG(3,("Account is disabled -- see Account Administrator.\n"));
310 putprpwnam ( user , mypasswd );
311 DEBUG(3,("Update protected database for Account %s after refusing connection\n",user));
314 DEBUG(6,("Updated database with %s %s\n",user,BOOLSTR(result)));
320 /*******************************************************************
321 check on AFS authentication
322 ********************************************************************/
323 static BOOL afs_auth(char *this_user,char *password)
325 long password_expires = 0;
328 /* For versions of AFS prior to 3.3, this routine has few arguments, */
329 /* but since I can't find the old documentation... :-) */
331 if (ka_UserAuthenticateGeneral(KA_USERAUTH_VERSION+KA_USERAUTH_DOSETPAG,
333 (char *) 0, /* instance */
334 (char *) 0, /* cell */
336 0, /* lifetime, default */
337 &password_expires, /*days 'til it expires */
348 sec_login_handle_t my_dce_sec_context;
349 int dcelogin_atmost_once = 0;
351 /*******************************************************************
352 check on a DCE/DFS authentication
353 ********************************************************************/
354 static BOOL dfs_auth(char *this_user,char *password)
359 boolean32 password_reset;
360 sec_passwd_rec_t my_dce_password;
361 sec_login_auth_src_t auth_src = sec_login_auth_src_network;
362 unsigned char dce_errstr[dce_c_error_string_len];
365 * We only go for a DCE login context if the given password
366 * matches that stored in the local password file..
367 * Assumes local passwd file is kept in sync w/ DCE RGY!
370 if (!strcmp((char *)crypt(password,this_salt),this_crypted) ||
371 dcelogin_atmost_once)
374 if (sec_login_setup_identity(
375 (unsigned char *)this_user,
380 dce_error_inq_text(err, dce_errstr, &err2);
381 DEBUG(0,("DCE Setup Identity for %s failed: %s\n",
382 this_user,dce_errstr));
386 my_dce_password.version_number = sec_passwd_c_version_none;
387 my_dce_password.pepper = NULL;
388 my_dce_password.key.key_type = sec_passwd_plain;
389 my_dce_password.key.tagged_union.plain = (idl_char *)password;
391 if (sec_login_valid_and_cert_ident(my_dce_sec_context,
397 dce_error_inq_text(err, dce_errstr, &err2);
398 DEBUG(0,("DCE Identity Validation failed for principal %s: %s\n",
399 this_user,dce_errstr));
404 sec_login_set_context(my_dce_sec_context, &err);
405 if (err != error_status_ok )
407 dce_error_inq_text(err, dce_errstr, &err2);
408 DEBUG(0,("DCE login failed for principal %s, cant set context: %s\n",
409 this_user,dce_errstr));
410 sec_login_purge_context(my_dce_sec_context, &err);
415 DEBUG(0,("DCE login succeeded for principal %s on pid %d\n",
416 this_user, getpid()));
419 dcelogin_atmost_once = 1;
423 void dfs_unlogin(void)
427 unsigned char dce_errstr[dce_c_error_string_len];
429 sec_login_purge_context(my_dce_sec_context, &err);
430 if (err != error_status_ok )
432 dce_error_inq_text(err, dce_errstr, &err2);
433 DEBUG(0,("DCE purge login context failed for server instance %d: %s\n",
434 getpid(), dce_errstr));
441 #ifdef LINUX_BIGCRYPT
442 /****************************************************************************
443 an enhanced crypt for Linux to handle password longer than 8 characters
444 ****************************************************************************/
445 static int linux_bigcrypt(char *password,char *salt1, char *crypted)
447 #define LINUX_PASSWORD_SEG_CHARS 8
451 StrnCpy(salt,salt1,2);
454 for ( i=strlen(password); i > 0; i -= LINUX_PASSWORD_SEG_CHARS) {
455 char * p = crypt(password,salt) + 2;
456 if(strncmp(p, crypted, LINUX_PASSWORD_SEG_CHARS) != 0)
458 password += LINUX_PASSWORD_SEG_CHARS;
459 crypted += strlen(p);
467 /****************************************************************************
468 apply a function to upper/lower case combinations
469 of a string and return true if one of them returns true.
470 try all combinations with N uppercase letters.
471 offset is the first char to try and change (start with 0)
472 it assumes the string starts lowercased
473 ****************************************************************************/
474 static BOOL string_combinations2(char *s,int offset,BOOL (*fn)(),int N)
479 #ifdef PASSWORD_LENGTH
480 len = MIN(len,PASSWORD_LENGTH);
483 if (N <= 0 || offset >= len)
486 for (i=offset;i<(len-(N-1));i++)
489 if (!islower(c)) continue;
491 if (string_combinations2(s,i+1,fn,N-1))
498 /****************************************************************************
499 apply a function to upper/lower case combinations
500 of a string and return true if one of them returns true.
501 try all combinations with up to N uppercase letters.
502 offset is the first char to try and change (start with 0)
503 it assumes the string starts lowercased
504 ****************************************************************************/
505 static BOOL string_combinations(char *s,BOOL (*fn)(),int N)
509 if (string_combinations2(s,0,fn,n)) return(True);
515 /****************************************************************************
516 core of password checking routine
517 ****************************************************************************/
518 BOOL password_check(char *password)
521 if (afs_auth(this_user,password)) return(True);
525 if (dfs_auth(this_user,password)) return(True);
529 if (pwdauth(this_user,password) == 0)
534 return(strcmp(osf1_bigcrypt(password,this_salt),this_crypted) == 0);
538 return (strcmp((char *)crypt16(password, this_salt ),this_crypted) == 0);
541 #ifdef LINUX_BIGCRYPT
542 return(linux_bigcrypt(password,this_salt,this_crypted));
546 DEBUG(1,("Warning - no crypt available\n"));
549 return(strcmp((char *)crypt(password,this_salt),this_crypted) == 0);
554 /****************************************************************************
555 core of smb password checking routine.
556 ****************************************************************************/
557 BOOL smb_password_check(char *password, unsigned char *part_passwd, unsigned char *c8)
559 /* Finish the encryption of part_passwd. */
560 unsigned char p21[21];
561 unsigned char p24[24];
563 if(part_passwd == NULL)
564 DEBUG(10,("No password set - allowing access\n"));
565 /* No password set - always true ! */
566 if(part_passwd == NULL)
570 memcpy(p21,part_passwd,16);
575 DEBUG(100,("Part password (P16) was |"));
576 for(i = 0; i < 16; i++)
577 DEBUG(100,("%X ", (unsigned char)part_passwd[i]));
579 DEBUG(100,("Password from client was |"));
580 for(i = 0; i < 24; i++)
581 DEBUG(100,("%X ", (unsigned char)password[i]));
583 DEBUG(100,("Given challenge was |"));
584 for(i = 0; i < 8; i++)
585 DEBUG(100,("%X ", (unsigned char)c8[i]));
587 DEBUG(100,("Value from encryption was |"));
588 for(i = 0; i < 24; i++)
589 DEBUG(100,("%X ", (unsigned char)p24[i]));
593 return (memcmp(p24, password, 24) == 0);
597 /****************************************************************************
598 check if a username/password is OK
599 ****************************************************************************/
600 BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd, BOOL is_nt_password)
603 int level = lp_passwordlevel();
607 struct smb_passwd *smb_pass;
608 BOOL challenge_done = False;
611 if (password) password[pwlen] = 0;
615 challenge_done = last_challenge(challenge);
623 DEBUG(100,("checking user=[%s] pass=[",user));
624 for( i = 0; i < 24; i++)
625 DEBUG(100,("%0x ", (unsigned char)password[i]));
630 DEBUG(100,("checking user=[%s] pass=[%s]\n",user,password));
636 if (((!*password) || (!pwlen)) && !lp_null_passwords())
641 pass = (struct passwd *) pwd;
642 user = pass->pw_name;
645 pass = Get_Pwnam(user,True);
649 DEBUG(4,("SMB Password - pwlen = %d, challenge_done = %d\n", pwlen, challenge_done));
651 if((pwlen == 24) && challenge_done)
653 DEBUG(4,("Checking SMB password for user %s (l=24)\n",user));
657 DEBUG(3,("Couldn't find user %s\n",user));
661 smb_pass = get_smbpwnam(user);
664 DEBUG(3,("Couldn't find user %s in smb_passwd file.\n", user));
668 /* Ensure the uid's match */
669 if(smb_pass->smb_userid != pass->pw_uid)
671 DEBUG(3,("Error : UNIX and SMB uids in password files do not match !\n"));
675 if(Protocol >= PROTOCOL_NT1 && is_nt_password)
677 /* We have the NT MD4 hash challenge available - see if we can
678 use it (ie. does it exist in the smbpasswd file).
680 if(smb_pass->smb_nt_passwd != NULL)
682 DEBUG(4,("Checking NT MD4 password\n"));
683 if(smb_password_check(password,
684 smb_pass->smb_nt_passwd,
687 update_protected_database(user,True);
690 DEBUG(4,("NT MD4 password check failed\n"));
695 /* Try against the lanman password */
697 if (smb_password_check(password,
698 smb_pass->smb_passwd,
699 (char *)challenge)) {
700 update_protected_database(user,True);
704 DEBUG(3,("Error smb_password_check failed\n"));
708 DEBUG(4,("Checking password for user %s (l=%d)\n",user,pwlen));
712 DEBUG(3,("Couldn't find user %s\n",user));
720 /* many shadow systems require you to be root to get the password,
721 in most cases this should already be the case when this
722 function is called, except perhaps for IPC password changing
725 spass = getspnam(pass->pw_name);
726 if (spass && spass->sp_pwdp)
727 pass->pw_passwd = spass->sp_pwdp;
733 struct pr_passwd *pr_pw = getprpwnam(pass->pw_name);
734 if (pr_pw && pr_pw->ufld.fd_encrypt)
735 pass->pw_passwd = pr_pw->ufld.fd_encrypt;
739 #ifdef HPUX_10_TRUSTED
741 struct pr_passwd *pr_pw = getprpwnam(pass->pw_name);
742 if (pr_pw && pr_pw->ufld.fd_encrypt)
743 pass->pw_passwd = pr_pw->ufld.fd_encrypt;
749 struct pr_passwd *mypasswd;
750 DEBUG(5,("Checking password for user %s in OSF1_ENH_SEC\n",user));
751 mypasswd = getprpwnam (user);
754 strcpy(pass->pw_name,mypasswd->ufld.fd_name);
755 strcpy(pass->pw_passwd,mypasswd->ufld.fd_encrypt);
759 DEBUG(5,("No entry for user %s in protected database !\n",user));
767 AUTHORIZATION *ap = getauthuid( pass->pw_uid );
770 strcpy( pass->pw_passwd, ap->a_password );
776 /* extract relevant info */
777 strcpy(this_user,pass->pw_name);
778 strcpy(this_salt,pass->pw_passwd);
779 strcpy(this_crypted,pass->pw_passwd);
781 if (!*this_crypted) {
782 if (!lp_null_passwords()) {
783 DEBUG(2,("Disallowing access to %s due to null password\n",this_user));
788 DEBUG(3,("Allowing access to %s with null password\n",this_user));
794 /* try it as it came to us */
795 if (password_check(password))
797 update_protected_database(user,True);
801 /* if the password was given to us with mixed case then we don't
802 need to proceed as we know it hasn't been case modified by the
804 if (strhasupper(password) && strhaslower(password))
807 /* make a copy of it */
808 StrnCpy(pass2,password,sizeof(pstring)-1);
810 /* try all lowercase */
812 if (password_check(password))
814 update_protected_database(user,True);
821 update_protected_database(user,False);
824 strcpy(password,pass2);
829 /* last chance - all combinations of up to level chars upper! */
832 if (string_combinations(password,password_check,level))
834 update_protected_database(user,True);
838 update_protected_database(user,False);
841 strcpy(password,pass2);
848 /****************************************************************************
849 check if a username is valid
850 ****************************************************************************/
851 BOOL user_ok(char *user,int snum)
853 pstring valid, invalid;
856 StrnCpy(valid, lp_valid_users(snum), sizeof(pstring));
857 StrnCpy(invalid, lp_invalid_users(snum), sizeof(pstring));
859 string_sub(valid,"%S",lp_servicename(snum));
860 string_sub(invalid,"%S",lp_servicename(snum));
862 ret = !user_in_list(user,invalid);
864 if (ret && valid && *valid)
865 ret = user_in_list(user,valid);
867 if (ret && lp_onlyuser(snum)) {
868 char *user_list = lp_username(snum);
869 string_sub(user_list,"%S",lp_servicename(snum));
870 ret = user_in_list(user,user_list);
879 /****************************************************************************
880 validate a group username entry. Return the username or NULL
881 ****************************************************************************/
882 static char *validate_group(char *group,char *password,int pwlen,int snum)
886 char *host, *user, *domain;
888 while (getnetgrent(&host, &user, &domain)) {
890 if (user_ok(user, snum) &&
891 password_ok(user,password,pwlen,NULL,False)) {
903 struct group *gptr = (struct group *)getgrnam(group);
907 member = gptr->gr_mem;
908 while (member && *member)
911 strcpy(name,*member);
912 if (user_ok(name,snum) &&
913 password_ok(name,password,pwlen,NULL,False))
917 #ifdef GROUP_CHECK_PWENT
923 while (pwd = getpwent ()) {
924 if (*(pwd->pw_passwd) && pwd->pw_gid == gptr->gr_gid) {
925 /* This Entry have PASSWORD and same GID then check pwd */
926 if (password_ok(NULL, password, pwlen, pwd,False)) {
927 strcpy(tm, pwd->pw_name);
935 #endif /* GROUP_CHECK_PWENT */
944 /****************************************************************************
945 check for authority to login to a service with a given username/password
946 ****************************************************************************/
947 BOOL authorise_login(int snum,char *user,char *password, int pwlen,
948 BOOL *guest,BOOL *force,int vuid)
955 DEBUG(100,("checking authorisation on user=%s pass=%s\n",user,password));
958 /* there are several possabilities:
959 1) login as the given user with given password
960 2) login as a previously registered username with the given password
961 3) login as a session list username with the given password
962 4) login as a previously validated user/password pair
963 5) login as the "user =" user with given password
964 6) login as the "user =" user with no password (guest connection)
965 7) login as guest user with no password
967 if the service is guest_only then steps 1 to 5 are skipped
970 if (GUEST_ONLY(snum)) *force = True;
972 if (!(GUEST_ONLY(snum) && GUEST_OK(snum)))
975 /* check the given username and password */
976 if (!ok && (*user) && user_ok(user,snum)) {
977 ok = password_ok(user,password, pwlen, NULL, False);
978 if (ok) DEBUG(3,("ACCEPTED: given username password ok\n"));
981 /* check for a previously registered guest username */
982 if (!ok && (vuid >= 0) && validated_users[vuid].guest) {
983 if (user_ok(validated_users[vuid].name,snum) &&
984 password_ok(validated_users[vuid].name, password, pwlen, NULL, False)) {
985 strcpy(user, validated_users[vuid].name);
986 validated_users[vuid].guest = False;
987 DEBUG(3,("ACCEPTED: given password with registered user %s\n", user));
993 /* now check the list of session users */
997 char *user_list = strdup(session_users);
998 if (!user_list) return(False);
1000 for (auser=strtok(user_list,LIST_SEP);
1002 auser = strtok(NULL,LIST_SEP))
1005 strcpy(user2,auser);
1006 if (!user_ok(user2,snum)) continue;
1008 if (password_ok(user2,password, pwlen, NULL, False)) {
1011 DEBUG(3,("ACCEPTED: session list username and given password ok\n"));
1017 /* check for a previously validated username/password pair */
1018 if (!ok && !lp_revalidate(snum) &&
1019 (vuid >= 0) && !validated_users[vuid].guest &&
1020 user_ok(validated_users[vuid].name,snum)) {
1021 strcpy(user,validated_users[vuid].name);
1023 DEBUG(3,("ACCEPTED: validated uid ok as non-guest\n"));
1027 /* check for a rhosts entry */
1028 if (!ok && user_ok(user,snum) && check_hosts_equiv(user)) {
1030 DEBUG(3,("ACCEPTED: hosts equiv or rhosts entry\n"));
1033 /* check the user= fields and the given password */
1034 if (!ok && lp_username(snum)) {
1037 StrnCpy(user_list,lp_username(snum),sizeof(pstring));
1039 string_sub(user_list,"%S",lp_servicename(snum));
1041 for (auser=strtok(user_list,LIST_SEP);
1043 auser = strtok(NULL,LIST_SEP))
1047 auser = validate_group(auser+1,password,pwlen,snum);
1052 DEBUG(3,("ACCEPTED: group username and given password ok\n"));
1058 strcpy(user2,auser);
1059 if (user_ok(user2,snum) &&
1060 password_ok(user2,password,pwlen,NULL, False))
1064 DEBUG(3,("ACCEPTED: user list username and given password ok\n"));
1069 } /* not guest only */
1071 /* check for a normal guest connection */
1072 if (!ok && GUEST_OK(snum))
1075 StrnCpy(guestname,lp_guestaccount(snum),sizeof(guestname)-1);
1076 if (Get_Pwnam(guestname,True))
1078 strcpy(user,guestname);
1080 DEBUG(3,("ACCEPTED: guest account and guest ok\n"));
1083 DEBUG(0,("Invalid guest account %s??\n",guestname));
1088 if (ok && !user_ok(user,snum))
1090 DEBUG(0,("rejected invalid user %s\n",user));
1098 /****************************************************************************
1099 read the a hosts.equiv or .rhosts file and check if it
1100 allows this user from this machine
1101 ****************************************************************************/
1102 static BOOL check_user_equiv(char *user, char *remote, char *equiv_file)
1105 int plus_allowed = 1;
1108 FILE *fp = fopen(equiv_file, "r");
1109 DEBUG(5, ("check_user_equiv %s %s %s\n", user, remote, equiv_file));
1110 if (! fp) return False;
1111 while(fgets(buf, sizeof(buf), fp))
1113 trim_string(buf," "," ");
1115 if (buf[0] != '#' && buf[0] != '\n')
1117 BOOL is_group = False;
1120 if (strcmp(buf, "NO_PLUS\n") == 0)
1122 DEBUG(6, ("check_user_equiv NO_PLUS\n"));
1129 if (*bp == '\n' && plus_allowed)
1131 /* a bare plus means everbody allowed */
1132 DEBUG(6, ("check_user_equiv everybody allowed\n"));
1137 else if (buf[0] == '-')
1147 file_host = strtok(bp, " \t\n");
1148 file_user = strtok(NULL, " \t\n");
1149 DEBUG(7, ("check_user_equiv %s %s\n", file_host, file_user));
1150 if (file_host && *file_host)
1152 BOOL host_ok = False;
1157 static char *mydomain = NULL;
1159 yp_get_default_domain(&mydomain);
1160 if (mydomain && innetgr(file_host,remote,user,mydomain))
1166 DEBUG(1,("Netgroups not configured - add -DNETGROUP and recompile\n"));
1171 /* is it this host */
1172 /* the fact that remote has come from a call of gethostbyaddr
1173 * means that it may have the fully qualified domain name
1174 * so we could look up the file version to get it into
1175 * a canonical form, but I would rather just type it
1176 * in full in the equiv file
1178 if (!host_ok && !is_group && strequal(remote, file_host))
1184 /* is it this user */
1185 if (file_user == 0 || strequal(user, file_user))
1188 DEBUG(5, ("check_user_equiv matched %s%s %s\n",
1189 (plus ? "+" : "-"), file_host,
1190 (file_user ? file_user : "")));
1191 return (plus ? True : False);
1202 /****************************************************************************
1203 check for a possible hosts equiv or rhosts entry for the user
1204 ****************************************************************************/
1205 BOOL check_hosts_equiv(char *user)
1209 struct passwd *pass = Get_Pwnam(user,True);
1211 extern struct from_host Client_info;
1217 fromhost(Client,&Client_info);
1219 fname = lp_hosts_equiv();
1221 /* note: don't allow hosts.equiv on root */
1222 if (fname && *fname && (pass->pw_uid != 0))
1224 if (check_user_equiv(user,Client_info.name,fname))
1228 if (lp_use_rhosts())
1230 char *home = get_home_dir(user);
1233 sprintf(rhostsfile, "%s/.rhosts", home);
1234 if (check_user_equiv(user,Client_info.name,rhostsfile))
1243 int password_client = -1;
1244 static fstring pserver;
1246 /****************************************************************************
1247 attempted support for server level security
1248 ****************************************************************************/
1249 BOOL server_cryptkey(char *buf)
1251 pstring inbuf,outbuf;
1252 fstring pass_protocol;
1253 extern fstring remote_machine;
1257 struct in_addr dest_ip;
1258 int port = SMB_PORT;
1261 if (password_client >= 0)
1262 close(password_client);
1263 password_client = -1;
1265 if (Protocol < PROTOCOL_NT1) {
1266 strcpy(pass_protocol,"LM1.2X002");
1268 strcpy(pass_protocol,"NT LM 0.12");
1271 bzero(inbuf,sizeof(inbuf));
1272 bzero(outbuf,sizeof(outbuf));
1274 for (p=strtok(lp_passwordserver(),LIST_SEP); p ; p = strtok(NULL,LIST_SEP)) {
1276 standard_sub_basic(desthost);
1279 dest_ip = *interpret_addr2(desthost);
1280 if (zero_ip(dest_ip)) {
1281 DEBUG(1,("Can't resolve address for %s\n",p));
1285 if (ismyip(dest_ip)) {
1286 DEBUG(1,("Password server loop - disabling password server %s\n",p));
1290 password_client = open_socket_out(SOCK_STREAM, &dest_ip, port, SHORT_CONNECT_TIMEOUT);
1291 if (password_client >= 0) {
1292 DEBUG(3,("connected to password server %s\n",p));
1293 StrnCpy(pserver,p,sizeof(pserver)-1);
1298 if (password_client < 0) {
1299 DEBUG(1,("password server not available\n"));
1304 /* send a session request (RFC 8002) */
1306 /* put in the destination name */
1309 name_mangle(desthost,p,' ');
1314 name_mangle(remote_machine,p,' ');
1317 _smb_setlen(outbuf,len);
1318 CVAL(outbuf,0) = 0x81;
1320 send_smb(password_client,outbuf);
1323 if (!receive_smb(password_client,inbuf,5000) ||
1324 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;