- add timeouts to connect() for password server connections. This
[samba.git] / source / smbd / password.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Password and authentication handling
5    Copyright (C) Andrew Tridgell 1992-1995
6    
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.
11    
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.
16    
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.
20 */
21
22 #include "includes.h"
23
24 extern int DEBUGLEVEL;
25 extern int Protocol;
26
27 /* users from session setup */
28 static pstring session_users="";
29
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]="";
34
35 #ifdef SMB_PASSWD
36 /* Data to do lanman1/2 password challenge. */
37 static unsigned char saved_challenge[8];
38 static BOOL challenge_sent=False;
39
40 /*******************************************************************
41 Get the next challenge value - no repeats.
42 ********************************************************************/
43 void generate_next_challenge(char *challenge)
44 {
45   static int counter = 0;
46   struct timeval tval;
47   int v1,v2;
48   GetTimeOfDay(&tval);
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;
56 }
57
58 /*******************************************************************
59 set the last challenge sent, usually from a password server
60 ********************************************************************/
61 BOOL set_challenge(char *challenge)
62 {
63   memcpy(saved_challenge,challenge,8);
64   challenge_sent = True;
65   return(True);
66 }
67
68 /*******************************************************************
69 get the last challenge sent
70 ********************************************************************/
71 BOOL last_challenge(char *challenge)
72 {
73   if (!challenge_sent) return(False);
74   memcpy(challenge,saved_challenge,8);
75   return(True);
76 }
77 #endif
78
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;
82
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)
87 {
88   int i;
89   if (uid == -1) return(-1);
90
91   for (i=0;i<num_validated_users;i++)
92     if (validated_users[i].uid == uid)
93       {
94         DEBUG(3,("valid uid %d mapped to vuid %d (user=%s)\n",
95                  uid,i,validated_users[i].name));
96         return(i);
97       }
98   return(-1);
99 }
100
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)
106 {
107   int vuid = valid_uid(uid);
108   if(vuid == -1 || validated_users[vuid].guest)
109     return NULL;
110   return &validated_users[vuid];
111 }
112
113 /****************************************************************************
114 invalidate a uid
115 ****************************************************************************/
116 void invalidate_uid(int uid)
117 {
118   int i;
119   for (i=0;i<num_validated_users;i++)
120     if (validated_users[i].uid == uid)
121       {
122         user_struct *vuser = &validated_users[i];
123         vuser->uid = -1;
124         vuser->gid = -1;
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;
133       }
134 }
135
136
137 /****************************************************************************
138 return a validated username
139 ****************************************************************************/
140 char *validated_username(int vuid)
141 {
142   return(validated_users[vuid].name);
143 }
144
145 /****************************************************************************
146 register a uid/name pair as being valid and that a valid password
147 has been given.
148 ****************************************************************************/
149 void register_uid(int uid,int gid, char *name,BOOL guest)
150 {
151   user_struct *vuser;
152
153   if (valid_uid(uid) >= 0)
154     return;
155   validated_users = (user_struct *)Realloc(validated_users,
156                                            sizeof(user_struct)*
157                                            (num_validated_users+1));
158
159   if (!validated_users)
160     {
161       DEBUG(0,("Failed to realloc users struct!\n"));
162       return;
163     }
164
165   vuser = &validated_users[num_validated_users];
166   vuser->uid = uid;
167   vuser->gid = gid;
168   vuser->guest = guest;
169   strcpy(vuser->name,name);
170
171   vuser->user_ngroups = 0;
172   vuser->user_groups = NULL;
173   vuser->user_igroups = NULL;
174
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);
181
182   DEBUG(3,("uid %d registered to name %s\n",uid,name));
183   
184   num_validated_users++;
185 }
186
187
188 /****************************************************************************
189 add a name to the session users list
190 ****************************************************************************/
191 void add_session_user(char *user)
192 {
193   fstring suser;
194   StrnCpy(suser,user,sizeof(suser)-1);
195
196   if (!Get_Pwnam(suser,True)) return;
197
198   if (suser && *suser && !in_list(suser,session_users,False))
199     {
200       if (strlen(suser) + strlen(session_users) + 2 >= sizeof(pstring))
201         DEBUG(1,("Too many session users??\n"));
202       else
203         {
204           strcat(session_users," ");
205           strcat(session_users,suser);
206         }
207     }
208 }
209
210
211 #ifdef NO_GETSPNAM
212 /* a fake shadow password routine which just fills a fake spwd struct
213  * with the sp_pwdp field. (sreiz@aie.nl)
214  */
215 static struct spwd *getspnam(char *username) /* fake shadow password routine */
216 {
217        FILE *f;
218        char line[1024];
219        static char pw[20];
220        static struct spwd static_spwd;
221
222        static_spwd.sp_pwdp=0;
223        if (!(f=fopen("/etc/master.passwd", "r")))
224                return 0;
225        while (fgets(line, 1024, f)) {
226                if (!strncmp(line, username, strlen(username)) &&
227                 line[strlen(username)]==':') { /* found entry */
228                        char *p, *q;
229
230                        p=line+strlen(username)+1;
231                        if ((q=strchr(p, ':'))) {
232                                *q=0;
233                                if (q-p+1>20)
234                                        break;
235                                strcpy(pw, p);
236                                static_spwd.sp_pwdp=pw;
237                        }
238                        break;
239                }
240        }
241        fclose(f);
242        if (static_spwd.sp_pwdp)
243                return &static_spwd;
244        return 0;
245 }
246 #endif
247
248
249 #ifdef OSF1_ENH_SEC
250 /****************************************************************************
251 an enhanced crypt for OSF1
252 ****************************************************************************/
253 static char *osf1_bigcrypt(char *password,char *salt1)
254 {
255   static char result[AUTH_MAX_PASSWD_LENGTH] = "";
256   char *p1;
257   char *p2=password;
258   char salt[3];
259   int i;
260   int parts = strlen(password) / AUTH_CLEARTEXT_SEG_CHARS;
261   if (strlen(password)%AUTH_CLEARTEXT_SEG_CHARS)
262     parts++;
263
264   StrnCpy(salt,salt1,2);
265   StrnCpy(result,salt1,2);
266
267   for (i=0; i<parts;i++)
268     {
269       p1 = crypt(p2,salt);
270       strcat(result,p1+2);
271       StrnCpy(salt,&result[2+i*AUTH_CIPHERTEXT_SEG_CHARS],2);
272       p2 += AUTH_CLEARTEXT_SEG_CHARS;
273     }
274
275   return(result);
276 }
277 #endif
278
279
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)
284 {
285 #ifdef OSF1_ENH_SEC
286   struct pr_passwd *mypasswd;
287   time_t starttime;
288
289   mypasswd = getprpwnam (user);
290   starttime = time (NULL);
291
292   if (result)
293     {
294       mypasswd->ufld.fd_slogin = starttime;
295       mypasswd->ufld.fd_nlogins = 0;
296       
297       putprpwnam(user,mypasswd);
298       
299       DEBUG(3,("Update protected database for Account %s after succesful connection\n",user));
300     }
301   else
302     {
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 )
306         {
307           mypasswd->uflg.fg_lock = 0;
308           DEBUG(3,("Account is disabled -- see Account Administrator.\n"));
309         }
310       putprpwnam ( user , mypasswd );
311       DEBUG(3,("Update protected database for Account %s after refusing connection\n",user));
312     }
313 #else
314   DEBUG(6,("Updated database with %s %s\n",user,BOOLSTR(result)));
315 #endif
316 }
317
318
319 #ifdef AFS_AUTH
320 /*******************************************************************
321 check on AFS authentication
322 ********************************************************************/
323 static BOOL afs_auth(char *this_user,char *password)
324 {
325   long password_expires = 0;
326   char *reason;
327     
328   /* For versions of AFS prior to 3.3, this routine has few arguments, */
329   /* but since I can't find the old documentation... :-)               */
330   setpag();
331   if (ka_UserAuthenticateGeneral(KA_USERAUTH_VERSION+KA_USERAUTH_DOSETPAG,
332                                  this_user,
333                                  (char *) 0, /* instance */
334                                  (char *) 0, /* cell */
335                                  password,
336                                  0,          /* lifetime, default */
337                                  &password_expires, /*days 'til it expires */
338                                  0,          /* spare 2 */
339                                  &reason) == 0)
340     return(True);
341   return(False);
342 }
343 #endif
344
345
346 #ifdef DFS_AUTH
347
348 sec_login_handle_t my_dce_sec_context;
349 int dcelogin_atmost_once = 0;
350
351 /*******************************************************************
352 check on a DCE/DFS authentication
353 ********************************************************************/
354 static BOOL dfs_auth(char *this_user,char *password)
355 {
356   error_status_t err;
357   int err2;
358   int prterr;
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];
363
364   /*
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!
368    */
369
370   if (!strcmp((char *)crypt(password,this_salt),this_crypted) ||
371       dcelogin_atmost_once)
372     return(False);
373
374   if (sec_login_setup_identity(
375                                (unsigned char *)this_user,
376                                sec_login_no_flags,
377                                &my_dce_sec_context,
378                                &err) == 0)
379     {
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));
383       return(False);
384     }
385
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;
390   
391   if (sec_login_valid_and_cert_ident(my_dce_sec_context,
392                                      &my_dce_password,
393                                      &password_reset,
394                                      &auth_src,
395                                      &err) == 0 )
396     { 
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));
400           
401       return(False);
402     }
403
404   sec_login_set_context(my_dce_sec_context, &err);
405   if (err != error_status_ok )
406     {  
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);
411       return(False);
412     }
413   else
414     {
415       DEBUG(0,("DCE login succeeded for principal %s on pid %d\n",
416                this_user, getpid()));
417     }
418
419   dcelogin_atmost_once = 1;
420   return (True);
421 }
422
423 void dfs_unlogin(void)
424 {
425   error_status_t err;
426   int err2;
427   unsigned char dce_errstr[dce_c_error_string_len];
428
429   sec_login_purge_context(my_dce_sec_context, &err);
430   if (err != error_status_ok )
431     {  
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));
435     }
436 }
437
438 #endif
439
440
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)
446 {
447 #define LINUX_PASSWORD_SEG_CHARS 8
448   char salt[3];
449   int i;
450   
451   StrnCpy(salt,salt1,2);
452   crypted +=2;
453   
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)
457       return(0);
458     password += LINUX_PASSWORD_SEG_CHARS;
459     crypted  += strlen(p);
460   }
461   
462   return(1);
463 }
464 #endif
465
466
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)
475 {
476   int len = strlen(s);
477   int i;
478
479 #ifdef PASSWORD_LENGTH
480   len = MIN(len,PASSWORD_LENGTH);
481 #endif
482
483   if (N <= 0 || offset >= len)
484     return(fn(s));
485
486   for (i=offset;i<(len-(N-1));i++)
487     {      
488       char c = s[i];
489       if (!islower(c)) continue;
490       s[i] = toupper(c);
491       if (string_combinations2(s,i+1,fn,N-1))
492         return(True);
493       s[i] = c;
494     }
495   return(False);
496 }
497
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)
506 {
507   int n;
508   for (n=1;n<=N;n++)
509     if (string_combinations2(s,0,fn,n)) return(True);
510   return(False);
511 }
512
513
514
515 /****************************************************************************
516 core of password checking routine
517 ****************************************************************************/
518 BOOL password_check(char *password)
519 {
520 #ifdef AFS_AUTH
521   if (afs_auth(this_user,password)) return(True);
522 #endif
523
524 #ifdef DFS_AUTH
525   if (dfs_auth(this_user,password)) return(True);
526 #endif 
527
528 #ifdef PWDAUTH
529   if (pwdauth(this_user,password) == 0)
530     return(True);
531 #endif
532
533 #ifdef OSF1_ENH_SEC
534   return(strcmp(osf1_bigcrypt(password,this_salt),this_crypted) == 0);
535 #endif
536
537 #ifdef ULTRIX_AUTH
538   return (strcmp((char *)crypt16(password, this_salt ),this_crypted) == 0);
539 #endif
540
541 #ifdef LINUX_BIGCRYPT
542   return(linux_bigcrypt(password,this_salt,this_crypted));
543 #endif
544
545 #ifdef NO_CRYPT
546   DEBUG(1,("Warning - no crypt available\n"));
547   return(False);
548 #else
549   return(strcmp((char *)crypt(password,this_salt),this_crypted) == 0);
550 #endif
551 }
552
553 #ifdef SMB_PASSWD
554 /****************************************************************************
555 core of smb password checking routine.
556 ****************************************************************************/
557 BOOL smb_password_check(char *password, unsigned char *part_passwd, unsigned char *c8)
558 {
559   /* Finish the encryption of part_passwd. */
560   unsigned char p21[21];
561   unsigned char p24[24];
562
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)
567     return 1;
568
569   memset(p21,'\0',21);
570   memcpy(p21,part_passwd,16);
571   E_P24(p21, c8, p24);
572 #if DEBUG_PASSWORD
573   {
574     int i;
575     DEBUG(100,("Part password (P16) was |"));
576     for(i = 0; i < 16; i++)
577       DEBUG(100,("%X ", (unsigned char)part_passwd[i]));
578     DEBUG(100,("|\n"));
579     DEBUG(100,("Password from client was |"));
580     for(i = 0; i < 24; i++)
581       DEBUG(100,("%X ", (unsigned char)password[i]));
582     DEBUG(100,("|\n"));
583     DEBUG(100,("Given challenge was |"));
584     for(i = 0; i < 8; i++)
585       DEBUG(100,("%X ", (unsigned char)c8[i]));
586     DEBUG(100,("|\n"));
587     DEBUG(100,("Value from encryption was |"));
588     for(i = 0; i < 24; i++)
589       DEBUG(100,("%X ", (unsigned char)p24[i]));
590     DEBUG(100,("|\n"));
591   }
592 #endif
593   return (memcmp(p24, password, 24) == 0);
594 }
595 #endif
596
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)
601 {
602   pstring pass2;
603   int level = lp_passwordlevel();
604   struct passwd *pass;
605 #ifdef SMB_PASSWD
606   char challenge[8];
607   struct smb_passwd *smb_pass;
608   BOOL challenge_done = False;
609 #endif
610
611   if (password) password[pwlen] = 0;
612
613 #ifdef SMB_PASSWD
614   if (pwlen == 24)
615     challenge_done = last_challenge(challenge);
616 #endif
617
618 #if DEBUG_PASSWORD
619 #ifdef SMB_PASSWD
620   if (challenge_done)
621     {
622       int i;      
623       DEBUG(100,("checking user=[%s] pass=[",user));
624       for( i = 0; i < 24; i++)
625         DEBUG(100,("%0x ", (unsigned char)password[i]));
626       DEBUG(100,("]\n"));
627     }
628   else
629 #endif
630     DEBUG(100,("checking user=[%s] pass=[%s]\n",user,password));
631 #endif
632
633   if (!password)
634     return(False);
635
636   if (((!*password) || (!pwlen)) && !lp_null_passwords())
637     return(False);
638
639   if (pwd && !user) 
640     {
641       pass = (struct passwd *) pwd;
642       user = pass->pw_name;
643     } 
644   else 
645     pass = Get_Pwnam(user,True);
646
647 #ifdef SMB_PASSWD
648
649   DEBUG(4,("SMB Password - pwlen = %d, challenge_done = %d\n", pwlen, challenge_done));
650
651   if((pwlen == 24) && challenge_done)
652     {
653       DEBUG(4,("Checking SMB password for user %s (l=24)\n",user));
654
655       if (!pass) 
656         {
657           DEBUG(3,("Couldn't find user %s\n",user));
658           return(False);
659         }
660
661       smb_pass = get_smbpwnam(user);
662       if(!smb_pass)
663         {
664           DEBUG(3,("Couldn't find user %s in smb_passwd file.\n", user));
665           return(False);
666         }
667
668       /* Ensure the uid's match */
669       if(smb_pass->smb_userid != pass->pw_uid)
670         {
671           DEBUG(3,("Error : UNIX and SMB uids in password files do not match !\n"));
672           return(False);
673         }
674
675         if(Protocol >= PROTOCOL_NT1 && is_nt_password)
676         {
677                 /* We have the NT MD4 hash challenge available - see if we can
678                    use it (ie. does it exist in the smbpasswd file).
679                 */
680                 if(smb_pass->smb_nt_passwd != NULL)
681                 {
682                   DEBUG(4,("Checking NT MD4 password\n"));
683                   if(smb_password_check(password, 
684                                         smb_pass->smb_nt_passwd, 
685                                         (char *)challenge))
686                   {
687                 update_protected_database(user,True);
688                 return(True);
689           }
690                   DEBUG(4,("NT MD4 password check failed\n"));
691                   return (False);
692                 }
693         }
694
695         /* Try against the lanman password */
696
697       if (smb_password_check(password, 
698                              smb_pass->smb_passwd,
699                              (char *)challenge)) {
700         update_protected_database(user,True);
701         return(True);
702       }
703
704         DEBUG(3,("Error smb_password_check failed\n"));
705     }
706 #endif 
707
708   DEBUG(4,("Checking password for user %s (l=%d)\n",user,pwlen));
709
710   if (!pass) 
711     {
712       DEBUG(3,("Couldn't find user %s\n",user));
713       return(False);
714     }
715
716 #ifdef SHADOW_PWD
717   {
718     struct spwd *spass;
719
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
723        requests */
724
725     spass = getspnam(pass->pw_name);
726     if (spass && spass->sp_pwdp)
727       pass->pw_passwd = spass->sp_pwdp;
728   }
729 #endif
730
731 #ifdef SecureWare
732   {
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;
736   }
737 #endif
738
739 #ifdef HPUX_10_TRUSTED
740   {
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;
744   }
745 #endif
746
747 #ifdef OSF1_ENH_SEC
748   {
749     struct pr_passwd *mypasswd;
750     DEBUG(5,("Checking password for user %s in OSF1_ENH_SEC\n",user));
751     mypasswd = getprpwnam (user);
752     if ( mypasswd )
753       { 
754         strcpy(pass->pw_name,mypasswd->ufld.fd_name);
755         strcpy(pass->pw_passwd,mypasswd->ufld.fd_encrypt);
756       }
757     else
758       {
759         DEBUG(5,("No entry for user %s in protected database !\n",user));
760         return(False);
761       }
762   }
763 #endif
764
765 #ifdef ULTRIX_AUTH
766   {
767     AUTHORIZATION *ap = getauthuid( pass->pw_uid );
768     if (ap)
769       {
770         strcpy( pass->pw_passwd, ap->a_password );
771         endauthent();
772       }
773   }
774 #endif
775
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);
780  
781   if (!*this_crypted) {
782     if (!lp_null_passwords()) {
783       DEBUG(2,("Disallowing access to %s due to null password\n",this_user));
784       return(False);
785     }
786 #ifndef PWDAUTH
787     if (!*password) {
788       DEBUG(3,("Allowing access to %s with null password\n",this_user));
789       return(True);
790     }
791 #endif    
792   }
793
794   /* try it as it came to us */
795   if (password_check(password))
796     {
797       update_protected_database(user,True);
798       return(True);
799     }
800
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
803      client */
804   if (strhasupper(password) && strhaslower(password))
805     return(False);
806
807   /* make a copy of it */
808   StrnCpy(pass2,password,sizeof(pstring)-1);
809   
810   /* try all lowercase */
811   strlower(password);
812   if (password_check(password))
813     {
814       update_protected_database(user,True);
815       return(True);
816     }
817
818   /* give up? */
819   if(level < 1)
820     {
821       update_protected_database(user,False);
822
823       /* restore it */
824       strcpy(password,pass2);
825
826       return(False);
827     }
828
829   /* last chance - all combinations of up to level chars upper! */
830   strlower(password);
831
832   if (string_combinations(password,password_check,level))
833     {
834       update_protected_database(user,True);
835       return(True);
836     }
837
838   update_protected_database(user,False);
839   
840   /* restore it */
841   strcpy(password,pass2);
842   
843   return(False);
844 }
845
846
847
848 /****************************************************************************
849 check if a username is valid
850 ****************************************************************************/
851 BOOL user_ok(char *user,int snum)
852 {
853   pstring valid, invalid;
854   BOOL ret;
855
856   StrnCpy(valid, lp_valid_users(snum), sizeof(pstring));
857   StrnCpy(invalid, lp_invalid_users(snum), sizeof(pstring));
858
859   string_sub(valid,"%S",lp_servicename(snum));
860   string_sub(invalid,"%S",lp_servicename(snum));
861
862   ret = !user_in_list(user,invalid);
863
864   if (ret && valid && *valid)
865     ret = user_in_list(user,valid);
866
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);
871   }
872
873   return(ret);
874 }
875
876
877
878
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)
883 {
884 #ifdef NETGROUP
885   {
886     char *host, *user, *domain;
887     setnetgrent(group);
888     while (getnetgrent(&host, &user, &domain)) {
889       if (user) {
890         if (user_ok(user, snum) && 
891             password_ok(user,password,pwlen,NULL,False)) {
892           endnetgrent();
893           return(user);
894         }
895       }
896     }
897     endnetgrent();
898   }
899 #endif
900   
901 #if HAVE_GETGRNAM 
902   {
903     struct group *gptr = (struct group *)getgrnam(group);
904     char **member;
905     if (gptr)
906       {
907         member = gptr->gr_mem;
908         while (member && *member)
909           {
910             static fstring name;
911             strcpy(name,*member);
912             if (user_ok(name,snum) &&
913                 password_ok(name,password,pwlen,NULL,False))
914               return(&name[0]);
915             member++;
916           }
917 #ifdef GROUP_CHECK_PWENT
918         {
919           struct passwd *pwd;
920           static fstring tm;
921           
922           setpwent ();
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);
928                 endpwent ();
929                 return tm;
930               }
931             }
932           }
933           endpwent ();
934         }
935 #endif /* GROUP_CHECK_PWENT */
936       }
937   }      
938 #endif
939   return(NULL);
940 }
941
942
943
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)
949 {
950   BOOL ok = False;
951   
952   *guest = False;
953   
954 #if DEBUG_PASSWORD
955   DEBUG(100,("checking authorisation on user=%s pass=%s\n",user,password));
956 #endif
957
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
966
967      if the service is guest_only then steps 1 to 5 are skipped
968   */
969
970   if (GUEST_ONLY(snum)) *force = True;
971
972   if (!(GUEST_ONLY(snum) && GUEST_OK(snum)))
973     {
974
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"));
979       }
980
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));
988           ok = True;
989         }
990       }
991
992
993       /* now check the list of session users */
994       if (!ok)
995         {
996           char *auser;
997           char *user_list = strdup(session_users);
998           if (!user_list) return(False);
999
1000           for (auser=strtok(user_list,LIST_SEP); 
1001                !ok && auser; 
1002                auser = strtok(NULL,LIST_SEP))
1003             {
1004               fstring user2;
1005               strcpy(user2,auser);
1006               if (!user_ok(user2,snum)) continue;
1007                   
1008               if (password_ok(user2,password, pwlen, NULL, False)) {
1009                 ok = True;
1010                 strcpy(user,user2);
1011                 DEBUG(3,("ACCEPTED: session list username and given password ok\n"));
1012               }
1013             }
1014           free(user_list);
1015         }
1016
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);
1022         *guest = False;
1023         DEBUG(3,("ACCEPTED: validated uid ok as non-guest\n"));
1024         ok = True;
1025       }
1026
1027       /* check for a rhosts entry */
1028       if (!ok && user_ok(user,snum) && check_hosts_equiv(user)) {
1029         ok = True;
1030         DEBUG(3,("ACCEPTED: hosts equiv or rhosts entry\n"));
1031       }
1032
1033       /* check the user= fields and the given password */
1034       if (!ok && lp_username(snum)) {
1035         char *auser;
1036         pstring user_list;
1037         StrnCpy(user_list,lp_username(snum),sizeof(pstring));
1038
1039         string_sub(user_list,"%S",lp_servicename(snum));
1040           
1041         for (auser=strtok(user_list,LIST_SEP);
1042              auser && !ok;
1043              auser = strtok(NULL,LIST_SEP))
1044           {
1045             if (*auser == '@')
1046               {
1047                 auser = validate_group(auser+1,password,pwlen,snum);
1048                 if (auser)
1049                   {
1050                     ok = True;
1051                     strcpy(user,auser);
1052                     DEBUG(3,("ACCEPTED: group username and given password ok\n"));
1053                   }
1054               }
1055             else
1056               {
1057                 fstring user2;
1058                 strcpy(user2,auser);
1059                 if (user_ok(user2,snum) && 
1060                     password_ok(user2,password,pwlen,NULL, False))
1061                   {
1062                     ok = True;
1063                     strcpy(user,user2);
1064                     DEBUG(3,("ACCEPTED: user list username and given password ok\n"));
1065                   }
1066               }
1067           }
1068       }      
1069     } /* not guest only */
1070
1071   /* check for a normal guest connection */
1072   if (!ok && GUEST_OK(snum))
1073     {
1074       fstring guestname;
1075       StrnCpy(guestname,lp_guestaccount(snum),sizeof(guestname)-1);
1076       if (Get_Pwnam(guestname,True))
1077         {
1078           strcpy(user,guestname);
1079           ok = True;
1080           DEBUG(3,("ACCEPTED: guest account and guest ok\n"));
1081         }
1082       else
1083         DEBUG(0,("Invalid guest account %s??\n",guestname));
1084       *guest = True;
1085       *force = True;
1086     }
1087
1088   if (ok && !user_ok(user,snum))
1089     {
1090       DEBUG(0,("rejected invalid user %s\n",user));
1091       ok = False;
1092     }
1093
1094   return(ok);
1095 }
1096
1097
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)
1103 {
1104   pstring buf;
1105   int plus_allowed = 1;
1106   char *file_host;
1107   char *file_user;
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)) 
1112   {
1113     trim_string(buf," "," ");
1114
1115     if (buf[0] != '#' && buf[0] != '\n') 
1116     {
1117       BOOL is_group = False;
1118       int plus = 1;
1119       char *bp = buf;
1120       if (strcmp(buf, "NO_PLUS\n") == 0)
1121       {
1122         DEBUG(6, ("check_user_equiv NO_PLUS\n"));
1123         plus_allowed = 0;
1124       }
1125       else {
1126         if (buf[0] == '+') 
1127         {
1128           bp++;
1129           if (*bp == '\n' && plus_allowed) 
1130           {
1131             /* a bare plus means everbody allowed */
1132             DEBUG(6, ("check_user_equiv everybody allowed\n"));
1133             fclose(fp);
1134             return True;
1135           }
1136         }
1137         else if (buf[0] == '-')
1138         {
1139           bp++;
1140           plus = 0;
1141         }
1142         if (*bp == '@') 
1143         {
1144           is_group = True;
1145           bp++;
1146         }
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) 
1151         {
1152           BOOL host_ok = False;
1153
1154 #ifdef NETGROUP   
1155           if (is_group)
1156             {
1157               static char *mydomain = NULL;
1158               if (!mydomain)
1159                 yp_get_default_domain(&mydomain);
1160               if (mydomain && innetgr(file_host,remote,user,mydomain))
1161                 host_ok = True;
1162             }
1163 #else
1164           if (is_group)
1165             {
1166               DEBUG(1,("Netgroups not configured - add -DNETGROUP and recompile\n"));
1167               continue;
1168             }
1169 #endif
1170
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
1177            */
1178           if (!host_ok && !is_group && strequal(remote, file_host))
1179             host_ok = True;
1180
1181           if (!host_ok)
1182             continue;
1183
1184           /* is it this user */
1185           if (file_user == 0 || strequal(user, file_user)) 
1186             {
1187               fclose(fp);
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);
1192             }
1193         }
1194       }
1195     }
1196   }
1197   fclose(fp);
1198   return False;
1199 }
1200
1201
1202 /****************************************************************************
1203 check for a possible hosts equiv or rhosts entry for the user
1204 ****************************************************************************/
1205 BOOL check_hosts_equiv(char *user)
1206 {
1207   char *fname = NULL;
1208   pstring rhostsfile;
1209   struct passwd *pass = Get_Pwnam(user,True);
1210
1211   extern struct from_host Client_info;
1212   extern int Client;
1213
1214   if (!pass) 
1215     return(False);
1216
1217   fromhost(Client,&Client_info);
1218
1219   fname = lp_hosts_equiv();
1220
1221   /* note: don't allow hosts.equiv on root */
1222   if (fname && *fname && (pass->pw_uid != 0))
1223     {
1224       if (check_user_equiv(user,Client_info.name,fname))
1225         return(True);
1226     }
1227   
1228   if (lp_use_rhosts())
1229     {
1230       char *home = get_home_dir(user);
1231       if (home)
1232         {
1233           sprintf(rhostsfile, "%s/.rhosts", home);
1234           if (check_user_equiv(user,Client_info.name,rhostsfile))
1235             return(True);
1236         }
1237     }
1238
1239   return(False);
1240 }
1241
1242
1243 int password_client = -1;
1244 static fstring pserver;
1245
1246 /****************************************************************************
1247 attempted support for server level security 
1248 ****************************************************************************/
1249 BOOL server_cryptkey(char *buf)
1250 {
1251   pstring inbuf,outbuf;
1252   fstring pass_protocol;
1253   extern fstring remote_machine;
1254   char *p;
1255   int len;
1256   fstring desthost;
1257   struct in_addr dest_ip;
1258   int port = SMB_PORT;
1259   BOOL ret;
1260
1261   if (password_client >= 0)
1262     close(password_client);
1263   password_client = -1;
1264
1265   if (Protocol < PROTOCOL_NT1) {
1266     strcpy(pass_protocol,"LM1.2X002");
1267   } else {
1268     strcpy(pass_protocol,"NT LM 0.12");
1269   }
1270
1271   bzero(inbuf,sizeof(inbuf));
1272   bzero(outbuf,sizeof(outbuf));
1273
1274   for (p=strtok(lp_passwordserver(),LIST_SEP); p ; p = strtok(NULL,LIST_SEP)) {
1275     strcpy(desthost,p);
1276     standard_sub_basic(desthost);
1277     strupper(desthost);
1278
1279     dest_ip = *interpret_addr2(desthost);
1280     if (zero_ip(dest_ip)) {
1281       DEBUG(1,("Can't resolve address for %s\n",p));
1282       continue;
1283     }
1284
1285     if (ismyip(dest_ip)) {
1286       DEBUG(1,("Password server loop - disabling password server %s\n",p));
1287       continue;
1288     }
1289
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);
1294       break;
1295     }
1296   }
1297
1298   if (password_client < 0) {
1299     DEBUG(1,("password server not available\n"));
1300     return(False);
1301   }
1302
1303
1304   /* send a session request (RFC 8002) */
1305
1306   /* put in the destination name */
1307   len = 4;
1308   p = outbuf+len;
1309   name_mangle(desthost,p,' ');
1310   len += name_len(p);
1311
1312   /* and my name */
1313   p = outbuf+len;
1314   name_mangle(remote_machine,p,' ');
1315   len += name_len(p);
1316
1317   _smb_setlen(outbuf,len);
1318   CVAL(outbuf,0) = 0x81;
1319
1320   send_smb(password_client,outbuf);
1321   
1322  
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;
1327     return(False);
1328   }
1329
1330   DEBUG(3,("got session\n"));
1331
1332   bzero(outbuf,smb_size);
1333
1334   /* setup the protocol string */
1335   set_message(outbuf,0,strlen(pass_protocol)+2,True);
1336   p = smb_buf(outbuf);
1337   *p++ = 2;
1338   strcpy(p,pass_protocol);
1339
1340   CVAL(outbuf,smb_com) = SMBnegprot;
1341   CVAL(outbuf,smb_flg) = 0x8;
1342   SSVAL(outbuf,smb_flg2,0x1);
1343
1344   send_smb(password_client,outbuf);
1345   ret = receive_smb(password_client,inbuf,5000);
1346
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;
1350     return(False);
1351   }
1352
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;
1356     return(False);
1357   }
1358
1359   memcpy(buf,inbuf,smb_len(inbuf)+4);
1360
1361   DEBUG(3,("password server OK\n"));
1362
1363   return(True);
1364 }
1365
1366 /****************************************************************************
1367 attempted support for server level security 
1368 ****************************************************************************/
1369 BOOL server_validate(char *buf)
1370 {
1371   pstring inbuf,outbuf;  
1372   BOOL ret;
1373
1374   if (password_client < 0) {
1375     DEBUG(1,("%s not connected\n",pserver));
1376     return(False);
1377   }  
1378
1379   bzero(inbuf,sizeof(inbuf));
1380   memcpy(outbuf,buf,sizeof(outbuf));
1381
1382   /* send a session setup command */
1383   CVAL(outbuf,smb_flg) = 0x8;
1384   SSVAL(outbuf,smb_flg2,0x1);
1385   CVAL(outbuf,smb_vwv0) = 0xFF;
1386
1387   set_message(outbuf,smb_numwords(outbuf),smb_buflen(outbuf),False);
1388
1389   SCVAL(inbuf,smb_rcls,1);
1390
1391   send_smb(password_client,outbuf);
1392   ret = receive_smb(password_client,inbuf,5000);
1393
1394   if (!ret || CVAL(inbuf,smb_rcls) != 0) {
1395     DEBUG(1,("password server %s rejected the password\n",pserver));
1396     return(False);
1397   }
1398
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));
1402     return(False);
1403   }
1404
1405   DEBUG(3,("password server %s accepted the password\n",pserver));
1406
1407 #if !KEEP_PASSWORD_SERVER_OPEN
1408   close(password_client); password_client= -1;
1409 #endif
1410
1411   return(True);
1412 }
1413
1414