- added interface.c and removed all the references to myip, bcast_ip
[samba.git] / source3 / 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 #include "loadparm.h"
24
25 extern int DEBUGLEVEL;
26 extern int Protocol;
27
28 /* users from session setup */
29 static pstring session_users="";
30
31 /* these are kept here to keep the string_combinations function simple */
32 static char this_user[100]="";
33 static char this_salt[100]="";
34 static char this_crypted[100]="";
35
36 #ifdef SMB_PASSWD
37 /* Data to do lanman1/2 password challenge. */
38 static unsigned char saved_challenge[8];
39 static BOOL challenge_sent=False;
40
41 /*******************************************************************
42 Get the next challenge value - no repeats.
43 ********************************************************************/
44 void generate_next_challenge(char *challenge)
45 {
46   static int counter = 0;
47   struct timeval tval;
48   int v1,v2;
49   GetTimeOfDay(&tval);
50   v1 = (counter++) + getpid() + tval.tv_sec;
51   v2 = (counter++) * getpid() + tval.tv_usec;
52   SIVAL(challenge,0,v1);
53   SIVAL(challenge,4,v2);
54   E1(challenge,"SAMBA",(char *)saved_challenge);
55   memcpy(challenge,saved_challenge,8);
56   challenge_sent = True;
57 }
58
59 /*******************************************************************
60 set the last challenge sent, usually from a password server
61 ********************************************************************/
62 BOOL set_challenge(char *challenge)
63 {
64   memcpy(saved_challenge,challenge,8);
65   challenge_sent = True;
66   return(True);
67 }
68
69 /*******************************************************************
70 get the last challenge sent
71 ********************************************************************/
72 BOOL last_challenge(char *challenge)
73 {
74   if (!challenge_sent) return(False);
75   memcpy(challenge,saved_challenge,8);
76   return(True);
77 }
78 #endif
79
80 /* this holds info on user ids that are already validated for this VC */
81 static user_struct *validated_users = NULL;
82 static int num_validated_users = 0;
83
84 /****************************************************************************
85 check if a uid has been validated, and return an index if it has. -1 if not
86 ****************************************************************************/
87 int valid_uid(int uid)
88 {
89   int i;
90   if (uid == -1) return(-1);
91
92   for (i=0;i<num_validated_users;i++)
93     if (validated_users[i].uid == uid)
94       {
95         DEBUG(3,("valid uid %d mapped to vuid %d (user=%s)\n",
96                  uid,i,validated_users[i].name));
97         return(i);
98       }
99   return(-1);
100 }
101
102 /****************************************************************************
103 check if a uid has been validated, and return an pointer to the user_struct
104 if it has. NULL if not
105 ****************************************************************************/
106 user_struct *get_valid_user_struct(int uid)
107 {
108   int vuid = valid_uid(uid);
109   if(vuid == -1 || validated_users[vuid].guest)
110     return NULL;
111   return &validated_users[vuid];
112 }
113
114 /****************************************************************************
115 invalidate a uid
116 ****************************************************************************/
117 void invalidate_uid(int uid)
118 {
119   int i;
120   for (i=0;i<num_validated_users;i++)
121     if (validated_users[i].uid == uid)
122       {
123         user_struct *vuser = &validated_users[i];
124         vuser->uid = -1;
125         vuser->gid = -1;
126         vuser->user_ngroups = 0;
127         if(vuser->user_groups && 
128            (vuser->user_groups != (gid_t *)vuser->user_igroups))
129           free(vuser->user_groups);
130         vuser->user_groups = NULL;
131         if(vuser->user_igroups)
132           free(vuser->user_igroups);
133         vuser->user_igroups = NULL;
134       }
135 }
136
137
138 /****************************************************************************
139 return a validated username
140 ****************************************************************************/
141 char *validated_username(int vuid)
142 {
143   return(validated_users[vuid].name);
144 }
145
146 /****************************************************************************
147 register a uid/name pair as being valid and that a valid password
148 has been given.
149 ****************************************************************************/
150 void register_uid(int uid,int gid, char *name,BOOL guest)
151 {
152   user_struct *vuser;
153
154   if (valid_uid(uid) >= 0)
155     return;
156   validated_users = (user_struct *)Realloc(validated_users,
157                                            sizeof(user_struct)*
158                                            (num_validated_users+1));
159
160   if (!validated_users)
161     {
162       DEBUG(0,("Failed to realloc users struct!\n"));
163       return;
164     }
165
166   vuser = &validated_users[num_validated_users];
167   vuser->uid = uid;
168   vuser->gid = gid;
169   vuser->guest = guest;
170   strcpy(vuser->name,name);
171
172   vuser->user_ngroups = 0;
173   vuser->user_groups = NULL;
174   vuser->user_igroups = NULL;
175
176   /* Find all the groups this uid is in and store them. 
177      Used by become_user() */
178   setup_groups(name,uid,gid,
179                &vuser->user_ngroups,
180                &vuser->user_igroups,
181                &vuser->user_groups);
182
183   DEBUG(3,("uid %d registered to name %s\n",uid,name));
184   
185   num_validated_users++;
186 }
187
188
189 /****************************************************************************
190 add a name to the session users list
191 ****************************************************************************/
192 void add_session_user(char *user)
193 {
194   fstring suser;
195   StrnCpy(suser,user,sizeof(suser)-1);
196
197   if (!Get_Pwnam(suser,True)) return;
198
199   if (suser && *suser && !in_list(suser,session_users,False))
200     {
201       if (strlen(suser) + strlen(session_users) + 2 >= sizeof(pstring))
202         DEBUG(1,("Too many session users??\n"));
203       else
204         {
205           strcat(session_users," ");
206           strcat(session_users,suser);
207         }
208     }
209 }
210
211
212 #ifdef NO_GETSPNAM
213 /* a fake shadow password routine which just fills a fake spwd struct
214  * with the sp_pwdp field. (sreiz@aie.nl)
215  */
216 static struct spwd *getspnam(char *username) /* fake shadow password routine */
217 {
218        FILE *f;
219        char line[1024];
220        static char pw[20];
221        static struct spwd static_spwd;
222
223        static_spwd.sp_pwdp=0;
224        if (!(f=fopen("/etc/master.passwd", "r")))
225                return 0;
226        while (fgets(line, 1024, f)) {
227                if (!strncmp(line, username, strlen(username)) &&
228                 line[strlen(username)]==':') { /* found entry */
229                        char *p, *q;
230
231                        p=line+strlen(username)+1;
232                        if ((q=strchr(p, ':'))) {
233                                *q=0;
234                                if (q-p+1>20)
235                                        break;
236                                strcpy(pw, p);
237                                static_spwd.sp_pwdp=pw;
238                        }
239                        break;
240                }
241        }
242        fclose(f);
243        if (static_spwd.sp_pwdp)
244                return &static_spwd;
245        return 0;
246 }
247 #endif
248
249
250 #ifdef OSF1_ENH_SEC
251 /****************************************************************************
252 an enhanced crypt for OSF1
253 ****************************************************************************/
254 static char *osf1_bigcrypt(char *password,char *salt1)
255 {
256   static char result[AUTH_MAX_PASSWD_LENGTH] = "";
257   char *p1;
258   char *p2=password;
259   char salt[3];
260   int i;
261   int parts = strlen(password) / AUTH_CLEARTEXT_SEG_CHARS;
262   if (strlen(password)%AUTH_CLEARTEXT_SEG_CHARS)
263     parts++;
264
265   StrnCpy(salt,salt1,2);
266   StrnCpy(result,salt1,2);
267
268   for (i=0; i<parts;i++)
269     {
270       p1 = crypt(p2,salt);
271       strcat(result,p1+2);
272       StrnCpy(salt,&result[2+i*AUTH_CIPHERTEXT_SEG_CHARS],2);
273       p2 += AUTH_CLEARTEXT_SEG_CHARS;
274     }
275
276   return(result);
277 }
278 #endif
279
280
281 /****************************************************************************
282 update the enhanced security database. Only relevant for OSF1 at the moment.
283 ****************************************************************************/
284 static void update_protected_database( char *user, BOOL result)
285 {
286 #ifdef OSF1_ENH_SEC
287   struct pr_passwd *mypasswd;
288   time_t starttime;
289
290   mypasswd = getprpwnam (user);
291   starttime = time (NULL);
292
293   if (result)
294     {
295       mypasswd->ufld.fd_slogin = starttime;
296       mypasswd->ufld.fd_nlogins = 0;
297       
298       putprpwnam(user,mypasswd);
299       
300       DEBUG(3,("Update protected database for Account %s after succesful connection\n",user));
301     }
302   else
303     {
304       mypasswd->ufld.fd_ulogin = starttime;
305       mypasswd->ufld.fd_nlogins = mypasswd->ufld.fd_nlogins + 1;
306       if ( mypasswd->ufld.fd_max_tries != 0 && mypasswd->ufld.fd_nlogins > mypasswd->ufld.fd_max_tries )
307         {
308           mypasswd->uflg.fg_lock = 0;
309           DEBUG(3,("Account is disabled -- see Account Administrator.\n"));
310         }
311       putprpwnam ( user , mypasswd );
312       DEBUG(3,("Update protected database for Account %s after refusing connection\n",user));
313     }
314 #else
315   DEBUG(6,("Updated database with %s %s\n",user,BOOLSTR(result)));
316 #endif
317 }
318
319
320 #ifdef AFS_AUTH
321 /*******************************************************************
322 check on AFS authentication
323 ********************************************************************/
324 static BOOL afs_auth(char *this_user,char *password)
325 {
326   long password_expires = 0;
327   char *reason;
328     
329   /* For versions of AFS prior to 3.3, this routine has few arguments, */
330   /* but since I can't find the old documentation... :-)               */
331   setpag();
332   if (ka_UserAuthenticateGeneral(KA_USERAUTH_VERSION+KA_USERAUTH_DOSETPAG,
333                                  this_user,
334                                  (char *) 0, /* instance */
335                                  (char *) 0, /* cell */
336                                  password,
337                                  0,          /* lifetime, default */
338                                  &password_expires, /*days 'til it expires */
339                                  0,          /* spare 2 */
340                                  &reason) == 0)
341     return(True);
342   return(False);
343 }
344 #endif
345
346
347 #ifdef DFS_AUTH
348
349 sec_login_handle_t my_dce_sec_context;
350 int dcelogin_atmost_once = 0;
351
352 /*******************************************************************
353 check on a DCE/DFS authentication
354 ********************************************************************/
355 static BOOL dfs_auth(char *this_user,char *password)
356 {
357   error_status_t err;
358   int err2;
359   int prterr;
360   boolean32 password_reset;
361   sec_passwd_rec_t my_dce_password;
362   sec_login_auth_src_t auth_src = sec_login_auth_src_network;
363   unsigned char dce_errstr[dce_c_error_string_len];
364
365   /*
366    * We only go for a DCE login context if the given password
367    * matches that stored in the local password file.. 
368    * Assumes local passwd file is kept in sync w/ DCE RGY!
369    */
370
371   if (!strcmp((char *)crypt(password,this_salt),this_crypted) ||
372       dcelogin_atmost_once)
373     return(False);
374
375   if (sec_login_setup_identity(
376                                (unsigned char *)this_user,
377                                sec_login_no_flags,
378                                &my_dce_sec_context,
379                                &err) == 0)
380     {
381       dce_error_inq_text(err, dce_errstr, &err2);
382       DEBUG(0,("DCE Setup Identity for %s failed: %s\n",
383                this_user,dce_errstr));
384       return(False);
385     }
386
387   my_dce_password.version_number = sec_passwd_c_version_none;
388   my_dce_password.pepper = NULL; 
389   my_dce_password.key.key_type = sec_passwd_plain;
390   my_dce_password.key.tagged_union.plain  = (idl_char *)password;
391   
392   if (sec_login_valid_and_cert_ident(my_dce_sec_context,
393                                      &my_dce_password,
394                                      &password_reset,
395                                      &auth_src,
396                                      &err) == 0 )
397     { 
398       dce_error_inq_text(err, dce_errstr, &err2);
399       DEBUG(0,("DCE Identity Validation failed for principal %s: %s\n",
400                this_user,dce_errstr));
401           
402       return(False);
403     }
404
405   sec_login_set_context(my_dce_sec_context, &err);
406   if (err != error_status_ok )
407     {  
408       dce_error_inq_text(err, dce_errstr, &err2);
409       DEBUG(0,("DCE login failed for principal %s, cant set context: %s\n",
410                this_user,dce_errstr));
411       sec_login_purge_context(my_dce_sec_context, &err);
412       return(False);
413     }
414   else
415     {
416       DEBUG(0,("DCE login succeeded for principal %s on pid %d\n",
417                this_user, getpid()));
418     }
419
420   dcelogin_atmost_once = 1;
421   return (True);
422 }
423
424 void dfs_unlogin(void)
425 {
426   error_status_t err;
427   int err2;
428   unsigned char dce_errstr[dce_c_error_string_len];
429
430   sec_login_purge_context(my_dce_sec_context, &err);
431   if (err != error_status_ok )
432     {  
433       dce_error_inq_text(err, dce_errstr, &err2);
434       DEBUG(0,("DCE purge login context failed for server instance %d: %s\n",
435                getpid(), dce_errstr));
436     }
437 }
438
439 #endif
440
441
442 #ifdef LINUX_BIGCRYPT
443 /****************************************************************************
444 an enhanced crypt for Linux to handle password longer than 8 characters
445 ****************************************************************************/
446 static int linux_bigcrypt(char *password,char *salt1, char *crypted)
447 {
448 #define LINUX_PASSWORD_SEG_CHARS 8
449   char salt[3];
450   int i;
451   
452   StrnCpy(salt,salt1,2);
453   crypted +=2;
454   
455   for ( i=strlen(password); i > 0; i -= LINUX_PASSWORD_SEG_CHARS) {
456     char * p = crypt(password,salt) + 2;
457     if(strncmp(p, crypted, LINUX_PASSWORD_SEG_CHARS) != 0)
458       return(0);
459     password += LINUX_PASSWORD_SEG_CHARS;
460     crypted  += strlen(p);
461   }
462   
463   return(1);
464 }
465 #endif
466
467
468 /****************************************************************************
469 apply a function to upper/lower case combinations
470 of a string and return true if one of them returns true.
471 try all combinations with N uppercase letters.
472 offset is the first char to try and change (start with 0)
473 it assumes the string starts lowercased
474 ****************************************************************************/
475 static BOOL string_combinations2(char *s,int offset,BOOL (*fn)(),int N)
476 {
477   int len = strlen(s);
478   int i;
479
480 #ifdef PASSWORD_LENGTH
481   len = MIN(len,PASSWORD_LENGTH);
482 #endif
483
484   if (N <= 0 || offset >= len)
485     return(fn(s));
486
487   for (i=offset;i<(len-(N-1));i++)
488     {      
489       char c = s[i];
490       if (!islower(c)) continue;
491       s[i] = toupper(c);
492       if (string_combinations2(s,i+1,fn,N-1))
493         return(True);
494       s[i] = c;
495     }
496   return(False);
497 }
498
499 /****************************************************************************
500 apply a function to upper/lower case combinations
501 of a string and return true if one of them returns true.
502 try all combinations with up to N uppercase letters.
503 offset is the first char to try and change (start with 0)
504 it assumes the string starts lowercased
505 ****************************************************************************/
506 static BOOL string_combinations(char *s,BOOL (*fn)(),int N)
507 {
508   int n;
509   for (n=1;n<=N;n++)
510     if (string_combinations2(s,0,fn,n)) return(True);
511   return(False);
512 }
513
514
515
516 /****************************************************************************
517 core of password checking routine
518 ****************************************************************************/
519 BOOL password_check(char *password)
520 {
521 #ifdef AFS_AUTH
522   if (afs_auth(this_user,password)) return(True);
523 #endif
524
525 #ifdef DFS_AUTH
526   if (dfs_auth(this_user,password)) return(True);
527 #endif 
528
529 #ifdef PWDAUTH
530   if (pwdauth(this_user,password) == 0)
531     return(True);
532 #endif
533
534 #ifdef OSF1_ENH_SEC
535   return(strcmp(osf1_bigcrypt(password,this_salt),this_crypted) == 0);
536 #endif
537
538 #ifdef ULTRIX_AUTH
539   return (strcmp((char *)crypt16(password, this_salt ),this_crypted) == 0);
540 #endif
541
542 #ifdef LINUX_BIGCRYPT
543   return(linux_bigcrypt(password,this_salt,this_crypted));
544 #endif
545
546 #ifdef NO_CRYPT
547   DEBUG(1,("Warning - no crypt available\n"));
548   return(False);
549 #else
550   return(strcmp((char *)crypt(password,this_salt),this_crypted) == 0);
551 #endif
552 }
553
554 #ifdef SMB_PASSWD
555 /****************************************************************************
556 core of smb password checking routine.
557 ****************************************************************************/
558 BOOL smb_password_check(char *password, unsigned char *part_passwd, unsigned char *c8)
559 {
560   /* Finish the encryption of part_passwd. */
561   unsigned char p21[21];
562   unsigned char p24[24];
563
564   if(part_passwd == NULL)
565     DEBUG(10,("No password set - allowing access\n"));
566   /* No password set - always true ! */
567   if(part_passwd == NULL)
568     return 1;
569
570   memset(p21,'\0',21);
571   memcpy(p21,part_passwd,16);
572   E_P24(p21, c8, p24);
573 #if DEBUG_PASSWORD
574   {
575     int i;
576     DEBUG(100,("Part password (P16) was |"));
577     for(i = 0; i < 16; i++)
578       DEBUG(100,("%X ", (unsigned char)part_passwd[i]));
579     DEBUG(100,("|\n"));
580     DEBUG(100,("Password from client was |"));
581     for(i = 0; i < 24; i++)
582       DEBUG(100,("%X ", (unsigned char)password[i]));
583     DEBUG(100,("|\n"));
584     DEBUG(100,("Given challenge was |"));
585     for(i = 0; i < 8; i++)
586       DEBUG(100,("%X ", (unsigned char)c8[i]));
587     DEBUG(100,("|\n"));
588     DEBUG(100,("Value from encryption was |"));
589     for(i = 0; i < 24; i++)
590       DEBUG(100,("%X ", (unsigned char)p24[i]));
591     DEBUG(100,("|\n"));
592   }
593 #endif
594   return (memcmp(p24, password, 24) == 0);
595 }
596 #endif
597
598 /****************************************************************************
599 check if a username/password is OK
600 ****************************************************************************/
601 BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd, BOOL is_nt_password)
602 {
603   pstring pass2;
604   int level = lp_passwordlevel();
605   struct passwd *pass;
606 #ifdef SMB_PASSWD
607   char challenge[8];
608   struct smb_passwd *smb_pass;
609   BOOL challenge_done = False;
610 #endif
611
612   if (password) password[pwlen] = 0;
613
614 #ifdef SMB_PASSWD
615   if (pwlen == 24)
616     challenge_done = last_challenge(challenge);
617 #endif
618
619 #if DEBUG_PASSWORD
620 #ifdef SMB_PASSWD
621   if (challenge_done)
622     {
623       int i;      
624       DEBUG(100,("checking user=[%s] pass=[",user));
625       for( i = 0; i < 24; i++)
626         DEBUG(100,("%0x ", (unsigned char)password[i]));
627       DEBUG(100,("]\n"));
628     }
629   else
630 #endif
631     DEBUG(100,("checking user=[%s] pass=[%s]\n",user,password));
632 #endif
633
634   if (!password)
635     return(False);
636
637   if (((!*password) || (!pwlen)) && !lp_null_passwords())
638     return(False);
639
640   if (pwd && !user) 
641     {
642       pass = (struct passwd *) pwd;
643       user = pass->pw_name;
644     } 
645   else 
646     pass = Get_Pwnam(user,True);
647
648 #ifdef SMB_PASSWD
649
650   DEBUG(4,("SMB Password - pwlen = %d, challenge_done = %d\n", pwlen, challenge_done));
651
652   if((pwlen == 24) && challenge_done)
653     {
654       DEBUG(4,("Checking SMB password for user %s (l=24)\n",user));
655
656       if (!pass) 
657         {
658           DEBUG(3,("Couldn't find user %s\n",user));
659           return(False);
660         }
661
662       smb_pass = get_smbpwnam(user);
663       if(!smb_pass)
664         {
665           DEBUG(3,("Couldn't find user %s in smb_passwd file.\n", user));
666           return(False);
667         }
668
669       /* Ensure the uid's match */
670       if(smb_pass->smb_userid != pass->pw_uid)
671         {
672           DEBUG(3,("Error : UNIX and SMB uids in password files do not match !\n"));
673           return(False);
674         }
675
676         if(Protocol >= PROTOCOL_NT1 && is_nt_password)
677         {
678                 /* We have the NT MD4 hash challenge available - see if we can
679                    use it (ie. does it exist in the smbpasswd file).
680                 */
681                 if(smb_pass->smb_nt_passwd != NULL)
682                 {
683                   DEBUG(4,("Checking NT MD4 password\n"));
684                   if(smb_password_check(password, 
685                                         smb_pass->smb_nt_passwd, 
686                                         (char *)challenge))
687                   {
688                 update_protected_database(user,True);
689                 return(True);
690           }
691                   DEBUG(4,("NT MD4 password check failed\n"));
692                   return (False);
693                 }
694         }
695
696         /* Try against the lanman password */
697
698       if (smb_password_check(password, 
699                              smb_pass->smb_passwd,
700                              (char *)challenge)) {
701         update_protected_database(user,True);
702         return(True);
703       }
704
705         DEBUG(3,("Error smb_password_check failed\n"));
706     }
707 #endif 
708
709   DEBUG(4,("Checking password for user %s (l=%d)\n",user,pwlen));
710
711   if (!pass) 
712     {
713       DEBUG(3,("Couldn't find user %s\n",user));
714       return(False);
715     }
716
717 #ifdef SHADOW_PWD
718   {
719     struct spwd *spass;
720
721     /* many shadow systems require you to be root to get the password,
722        in most cases this should already be the case when this
723        function is called, except perhaps for IPC password changing
724        requests */
725
726     spass = getspnam(pass->pw_name);
727     if (spass && spass->sp_pwdp)
728       pass->pw_passwd = spass->sp_pwdp;
729   }
730 #endif
731
732 #ifdef SecureWare
733   {
734     struct pr_passwd *pr_pw = getprpwnam(pass->pw_name);
735     if (pr_pw && pr_pw->ufld.fd_encrypt)
736       pass->pw_passwd = pr_pw->ufld.fd_encrypt;
737   }
738 #endif
739
740 #ifdef HPUX_10_TRUSTED
741   {
742     struct pr_passwd *pr_pw = getprpwnam(pass->pw_name);
743     if (pr_pw && pr_pw->ufld.fd_encrypt)
744       pass->pw_passwd = pr_pw->ufld.fd_encrypt;
745   }
746 #endif
747
748 #ifdef OSF1_ENH_SEC
749   {
750     struct pr_passwd *mypasswd;
751     DEBUG(5,("Checking password for user %s in OSF1_ENH_SEC\n",user));
752     mypasswd = getprpwnam (user);
753     if ( mypasswd )
754       { 
755         strcpy(pass->pw_name,mypasswd->ufld.fd_name);
756         strcpy(pass->pw_passwd,mypasswd->ufld.fd_encrypt);
757       }
758     else
759       {
760         DEBUG(5,("No entry for user %s in protected database !\n",user));
761         return(False);
762       }
763   }
764 #endif
765
766 #ifdef ULTRIX_AUTH
767   {
768     AUTHORIZATION *ap = getauthuid( pass->pw_uid );
769     if (ap)
770       {
771         strcpy( pass->pw_passwd, ap->a_password );
772         endauthent();
773       }
774   }
775 #endif
776
777   /* extract relevant info */
778   strcpy(this_user,pass->pw_name);  
779   strcpy(this_salt,pass->pw_passwd);
780   strcpy(this_crypted,pass->pw_passwd);
781  
782   if (!*this_crypted) {
783     if (!lp_null_passwords()) {
784       DEBUG(2,("Disallowing access to %s due to null password\n",this_user));
785       return(False);
786     }
787 #ifndef PWDAUTH
788     if (!*password) {
789       DEBUG(3,("Allowing access to %s with null password\n",this_user));
790       return(True);
791     }
792 #endif    
793   }
794
795   /* try it as it came to us */
796   if (password_check(password))
797     {
798       update_protected_database(user,True);
799       return(True);
800     }
801
802   /* if the password was given to us with mixed case then we don't
803      need to proceed as we know it hasn't been case modified by the
804      client */
805   if (strhasupper(password) && strhaslower(password))
806     return(False);
807
808   /* make a copy of it */
809   StrnCpy(pass2,password,sizeof(pstring)-1);
810   
811   /* try all lowercase */
812   strlower(password);
813   if (password_check(password))
814     {
815       update_protected_database(user,True);
816       return(True);
817     }
818
819   /* give up? */
820   if(level < 1)
821     {
822       update_protected_database(user,False);
823
824       /* restore it */
825       strcpy(password,pass2);
826
827       return(False);
828     }
829
830   /* last chance - all combinations of up to level chars upper! */
831   strlower(password);
832
833   if (string_combinations(password,password_check,level))
834     {
835       update_protected_database(user,True);
836       return(True);
837     }
838
839   update_protected_database(user,False);
840   
841   /* restore it */
842   strcpy(password,pass2);
843   
844   return(False);
845 }
846
847
848
849 /****************************************************************************
850 check if a username is valid
851 ****************************************************************************/
852 BOOL user_ok(char *user,int snum)
853 {
854   pstring valid, invalid;
855   BOOL ret;
856
857   StrnCpy(valid, lp_valid_users(snum), sizeof(pstring));
858   StrnCpy(invalid, lp_invalid_users(snum), sizeof(pstring));
859
860   string_sub(valid,"%S",lp_servicename(snum));
861   string_sub(invalid,"%S",lp_servicename(snum));
862
863   ret = !user_in_list(user,invalid);
864
865   if (ret && valid && *valid)
866     ret = user_in_list(user,valid);
867
868   if (ret && lp_onlyuser(snum)) {
869     char *user_list = lp_username(snum);
870     string_sub(user_list,"%S",lp_servicename(snum));
871     ret = user_in_list(user,user_list);
872   }
873
874   return(ret);
875 }
876
877
878
879
880 /****************************************************************************
881 validate a group username entry. Return the username or NULL
882 ****************************************************************************/
883 static char *validate_group(char *group,char *password,int pwlen,int snum)
884 {
885 #ifdef NETGROUP
886   {
887     char *host, *user, *domain;
888     setnetgrent(group);
889     while (getnetgrent(&host, &user, &domain)) {
890       if (user) {
891         if (user_ok(user, snum) && 
892             password_ok(user,password,pwlen,NULL,False)) {
893           endnetgrent();
894           return(user);
895         }
896       }
897     }
898     endnetgrent();
899   }
900 #endif
901   
902 #if HAVE_GETGRNAM 
903   {
904     struct group *gptr = (struct group *)getgrnam(group);
905     char **member;
906     if (gptr)
907       {
908         member = gptr->gr_mem;
909         while (member && *member)
910           {
911             static fstring name;
912             strcpy(name,*member);
913             if (user_ok(name,snum) &&
914                 password_ok(name,password,pwlen,NULL,False))
915               return(&name[0]);
916             member++;
917           }
918 #ifdef GROUP_CHECK_PWENT
919         {
920           struct passwd *pwd;
921           static fstring tm;
922           
923           setpwent ();
924           while (pwd = getpwent ()) {
925             if (*(pwd->pw_passwd) && pwd->pw_gid == gptr->gr_gid) {
926               /* This Entry have PASSWORD and same GID then check pwd */
927               if (password_ok(NULL, password, pwlen, pwd,False)) {
928                 strcpy(tm, pwd->pw_name);
929                 endpwent ();
930                 return tm;
931               }
932             }
933           }
934           endpwent ();
935         }
936 #endif /* GROUP_CHECK_PWENT */
937       }
938   }      
939 #endif
940   return(NULL);
941 }
942
943
944
945 /****************************************************************************
946 check for authority to login to a service with a given username/password
947 ****************************************************************************/
948 BOOL authorise_login(int snum,char *user,char *password, int pwlen, 
949                      BOOL *guest,BOOL *force,int vuid)
950 {
951   BOOL ok = False;
952   
953   *guest = False;
954   
955 #if DEBUG_PASSWORD
956   DEBUG(100,("checking authorisation on user=%s pass=%s\n",user,password));
957 #endif
958
959   /* there are several possabilities:
960      1) login as the given user with given password
961      2) login as a previously registered username with the given password
962      3) login as a session list username with the given password
963      4) login as a previously validated user/password pair
964      5) login as the "user =" user with given password
965      6) login as the "user =" user with no password (guest connection)
966      7) login as guest user with no password
967
968      if the service is guest_only then steps 1 to 5 are skipped
969   */
970
971   if (GUEST_ONLY(snum)) *force = True;
972
973   if (!(GUEST_ONLY(snum) && GUEST_OK(snum)))
974     {
975
976       /* check the given username and password */
977       if (!ok && (*user) && user_ok(user,snum)) {
978         ok = password_ok(user,password, pwlen, NULL, False);
979         if (ok) DEBUG(3,("ACCEPTED: given username password ok\n"));
980       }
981
982       /* check for a previously registered guest username */
983       if (!ok && (vuid >= 0) && validated_users[vuid].guest) {    
984         if (user_ok(validated_users[vuid].name,snum) &&
985             password_ok(validated_users[vuid].name, password, pwlen, NULL, False)) {
986           strcpy(user, validated_users[vuid].name);
987           validated_users[vuid].guest = False;
988           DEBUG(3,("ACCEPTED: given password with registered user %s\n", user));
989           ok = True;
990         }
991       }
992
993
994       /* now check the list of session users */
995       if (!ok)
996         {
997           char *auser;
998           char *user_list = strdup(session_users);
999           if (!user_list) return(False);
1000
1001           for (auser=strtok(user_list,LIST_SEP); 
1002                !ok && auser; 
1003                auser = strtok(NULL,LIST_SEP))
1004             {
1005               fstring user2;
1006               strcpy(user2,auser);
1007               if (!user_ok(user2,snum)) continue;
1008                   
1009               if (password_ok(user2,password, pwlen, NULL, False)) {
1010                 ok = True;
1011                 strcpy(user,user2);
1012                 DEBUG(3,("ACCEPTED: session list username and given password ok\n"));
1013               }
1014             }
1015           free(user_list);
1016         }
1017
1018       /* check for a previously validated username/password pair */
1019       if (!ok && !lp_revalidate(snum) &&
1020           (vuid >= 0) && !validated_users[vuid].guest &&
1021           user_ok(validated_users[vuid].name,snum)) {
1022         strcpy(user,validated_users[vuid].name);
1023         *guest = False;
1024         DEBUG(3,("ACCEPTED: validated uid ok as non-guest\n"));
1025         ok = True;
1026       }
1027
1028       /* check for a rhosts entry */
1029       if (!ok && user_ok(user,snum) && check_hosts_equiv(user)) {
1030         ok = True;
1031         DEBUG(3,("ACCEPTED: hosts equiv or rhosts entry\n"));
1032       }
1033
1034       /* check the user= fields and the given password */
1035       if (!ok && lp_username(snum)) {
1036         char *auser;
1037         pstring user_list;
1038         StrnCpy(user_list,lp_username(snum),sizeof(pstring));
1039
1040         string_sub(user_list,"%S",lp_servicename(snum));
1041           
1042         for (auser=strtok(user_list,LIST_SEP);
1043              auser && !ok;
1044              auser = strtok(NULL,LIST_SEP))
1045           {
1046             if (*auser == '@')
1047               {
1048                 auser = validate_group(auser+1,password,pwlen,snum);
1049                 if (auser)
1050                   {
1051                     ok = True;
1052                     strcpy(user,auser);
1053                     DEBUG(3,("ACCEPTED: group username and given password ok\n"));
1054                   }
1055               }
1056             else
1057               {
1058                 fstring user2;
1059                 strcpy(user2,auser);
1060                 if (user_ok(user2,snum) && 
1061                     password_ok(user2,password,pwlen,NULL, False))
1062                   {
1063                     ok = True;
1064                     strcpy(user,user2);
1065                     DEBUG(3,("ACCEPTED: user list username and given password ok\n"));
1066                   }
1067               }
1068           }
1069       }      
1070     } /* not guest only */
1071
1072   /* check for a normal guest connection */
1073   if (!ok && GUEST_OK(snum))
1074     {
1075       fstring guestname;
1076       StrnCpy(guestname,lp_guestaccount(snum),sizeof(guestname)-1);
1077       if (Get_Pwnam(guestname,True))
1078         {
1079           strcpy(user,guestname);
1080           ok = True;
1081           DEBUG(3,("ACCEPTED: guest account and guest ok\n"));
1082         }
1083       else
1084         DEBUG(0,("Invalid guest account %s??\n",guestname));
1085       *guest = True;
1086       *force = True;
1087     }
1088
1089   if (ok && !user_ok(user,snum))
1090     {
1091       DEBUG(0,("rejected invalid user %s\n",user));
1092       ok = False;
1093     }
1094
1095   return(ok);
1096 }
1097
1098
1099 /****************************************************************************
1100 read the a hosts.equiv or .rhosts file and check if it
1101 allows this user from this machine
1102 ****************************************************************************/
1103 static BOOL check_user_equiv(char *user, char *remote, char *equiv_file)
1104 {
1105   pstring buf;
1106   int plus_allowed = 1;
1107   char *file_host;
1108   char *file_user;
1109   FILE *fp = fopen(equiv_file, "r");
1110   DEBUG(5, ("check_user_equiv %s %s %s\n", user, remote, equiv_file));
1111   if (! fp) return False;
1112   while(fgets(buf, sizeof(buf), fp)) 
1113   {
1114     trim_string(buf," "," ");
1115
1116     if (buf[0] != '#' && buf[0] != '\n') 
1117     {
1118       BOOL is_group = False;
1119       int plus = 1;
1120       char *bp = buf;
1121       if (strcmp(buf, "NO_PLUS\n") == 0)
1122       {
1123         DEBUG(6, ("check_user_equiv NO_PLUS\n"));
1124         plus_allowed = 0;
1125       }
1126       else {
1127         if (buf[0] == '+') 
1128         {
1129           bp++;
1130           if (*bp == '\n' && plus_allowed) 
1131           {
1132             /* a bare plus means everbody allowed */
1133             DEBUG(6, ("check_user_equiv everybody allowed\n"));
1134             fclose(fp);
1135             return True;
1136           }
1137         }
1138         else if (buf[0] == '-')
1139         {
1140           bp++;
1141           plus = 0;
1142         }
1143         if (*bp == '@') 
1144         {
1145           is_group = True;
1146           bp++;
1147         }
1148         file_host = strtok(bp, " \t\n");
1149         file_user = strtok(NULL, " \t\n");
1150         DEBUG(7, ("check_user_equiv %s %s\n", file_host, file_user));
1151         if (file_host && *file_host) 
1152         {
1153           BOOL host_ok = False;
1154
1155 #ifdef NETGROUP   
1156           if (is_group)
1157             {
1158               static char *mydomain = NULL;
1159               if (!mydomain)
1160                 yp_get_default_domain(&mydomain);
1161               if (mydomain && innetgr(file_host,remote,user,mydomain))
1162                 host_ok = True;
1163             }
1164 #else
1165           if (is_group)
1166             {
1167               DEBUG(1,("Netgroups not configured - add -DNETGROUP and recompile\n"));
1168               continue;
1169             }
1170 #endif
1171
1172           /* is it this host */
1173           /* the fact that remote has come from a call of gethostbyaddr
1174            * means that it may have the fully qualified domain name
1175            * so we could look up the file version to get it into
1176            * a canonical form, but I would rather just type it
1177            * in full in the equiv file
1178            */
1179           if (!host_ok && !is_group && strequal(remote, file_host))
1180             host_ok = True;
1181
1182           if (!host_ok)
1183             continue;
1184
1185           /* is it this user */
1186           if (file_user == 0 || strequal(user, file_user)) 
1187             {
1188               fclose(fp);
1189               DEBUG(5, ("check_user_equiv matched %s%s %s\n",
1190                         (plus ? "+" : "-"), file_host,
1191                         (file_user ? file_user : "")));
1192               return (plus ? True : False);
1193             }
1194         }
1195       }
1196     }
1197   }
1198   fclose(fp);
1199   return False;
1200 }
1201
1202
1203 /****************************************************************************
1204 check for a possible hosts equiv or rhosts entry for the user
1205 ****************************************************************************/
1206 BOOL check_hosts_equiv(char *user)
1207 {
1208   char *fname = NULL;
1209   pstring rhostsfile;
1210   struct passwd *pass = Get_Pwnam(user,True);
1211
1212   extern struct from_host Client_info;
1213   extern int Client;
1214
1215   if (!pass) 
1216     return(False);
1217
1218   fromhost(Client,&Client_info);
1219
1220   fname = lp_hosts_equiv();
1221
1222   /* note: don't allow hosts.equiv on root */
1223   if (fname && *fname && (pass->pw_uid != 0))
1224     {
1225       if (check_user_equiv(user,Client_info.name,fname))
1226         return(True);
1227     }
1228   
1229   if (lp_use_rhosts())
1230     {
1231       char *home = get_home_dir(user);
1232       if (home)
1233         {
1234           sprintf(rhostsfile, "%s/.rhosts", home);
1235           if (check_user_equiv(user,Client_info.name,rhostsfile))
1236             return(True);
1237         }
1238     }
1239
1240   return(False);
1241 }
1242
1243
1244 int password_client = -1;
1245 static fstring pserver;
1246
1247 /****************************************************************************
1248 attempted support for server level security 
1249 ****************************************************************************/
1250 BOOL server_cryptkey(char *buf)
1251 {
1252   pstring inbuf,outbuf;
1253   fstring pass_protocol;
1254   extern fstring remote_machine;
1255   char *p;
1256   int len;
1257   fstring desthost;
1258   struct in_addr dest_ip;
1259   int port = SMB_PORT;
1260   BOOL ret;
1261
1262   if (password_client >= 0)
1263     close(password_client);
1264   password_client = -1;
1265
1266   if (Protocol < PROTOCOL_NT1) {
1267     strcpy(pass_protocol,"LM1.2X002");
1268   } else {
1269     strcpy(pass_protocol,"NT LM 0.12");
1270   }
1271
1272   bzero(inbuf,sizeof(inbuf));
1273   bzero(outbuf,sizeof(outbuf));
1274
1275   for (p=strtok(lp_passwordserver(),LIST_SEP); p ; p = strtok(NULL,LIST_SEP)) {
1276     strcpy(desthost,p);
1277     standard_sub_basic(desthost);
1278     strupper(desthost);
1279
1280     dest_ip = *interpret_addr2(desthost);
1281     if (zero_ip(dest_ip)) {
1282       DEBUG(1,("Can't resolve address for %s\n",p));
1283       continue;
1284     }
1285
1286     if (ismyip(dest_ip)) {
1287       DEBUG(1,("Password server loop - disabling password server %s\n",p));
1288       continue;
1289     }
1290
1291     password_client = open_socket_out(SOCK_STREAM, &dest_ip, port);
1292     if (password_client >= 0) {
1293       DEBUG(3,("connected to password server %s\n",p));
1294       StrnCpy(pserver,p,sizeof(pserver)-1);
1295       break;
1296     }
1297   }
1298
1299   if (password_client < 0) {
1300     DEBUG(1,("password server not available\n"));
1301     return(False);
1302   }
1303
1304
1305   /* send a session request (RFC 8002) */
1306
1307   /* put in the destination name */
1308   len = 4;
1309   p = outbuf+len;
1310   name_mangle(desthost,p,' ');
1311   len += name_len(p);
1312
1313   /* and my name */
1314   p = outbuf+len;
1315   name_mangle(remote_machine,p,' ');
1316   len += name_len(p);
1317
1318   _smb_setlen(outbuf,len);
1319   CVAL(outbuf,0) = 0x81;
1320
1321   send_smb(password_client,outbuf);
1322   receive_smb(password_client,inbuf,5000);
1323  
1324   if (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