charset.c: Fixed signed/unsigned issues.
[Samba.git] / source / smbd / password.c
blobeb837c258431bb3020399f80fb976c5b549f3f15
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 Password and authentication handling
5 Copyright (C) Andrew Tridgell 1992-1997
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.
22 #include "includes.h"
24 #if (defined(NETGROUP) && defined (AUTOMOUNT))
25 #include "rpcsvc/ypclnt.h"
26 #endif
28 extern int DEBUGLEVEL;
29 extern int Protocol;
31 /* users from session setup */
32 static pstring session_users="";
34 /* these are kept here to keep the string_combinations function simple */
35 static char this_user[100]="";
36 static char this_salt[100]="";
37 static char this_crypted[100]="";
39 #ifdef SMB_PASSWD
40 /* Data to do lanman1/2 password challenge. */
41 static unsigned char saved_challenge[8];
42 static BOOL challenge_sent=False;
44 /*******************************************************************
45 Get the next challenge value - no repeats.
46 ********************************************************************/
47 void generate_next_challenge(char *challenge)
49 static int counter = 0;
50 struct timeval tval;
51 int v1,v2;
52 GetTimeOfDay(&tval);
53 v1 = (counter++) + getpid() + tval.tv_sec;
54 v2 = (counter++) * getpid() + tval.tv_usec;
55 SIVAL(challenge,0,v1);
56 SIVAL(challenge,4,v2);
57 E1(challenge,"SAMBA",(char *)saved_challenge);
58 memcpy(challenge,saved_challenge,8);
59 challenge_sent = True;
62 /*******************************************************************
63 set the last challenge sent, usually from a password server
64 ********************************************************************/
65 BOOL set_challenge(char *challenge)
67 memcpy(saved_challenge,challenge,8);
68 challenge_sent = True;
69 return(True);
72 /*******************************************************************
73 get the last challenge sent
74 ********************************************************************/
75 BOOL last_challenge(char *challenge)
77 if (!challenge_sent) return(False);
78 memcpy(challenge,saved_challenge,8);
79 return(True);
81 #endif
83 /* this holds info on user ids that are already validated for this VC */
84 static user_struct *validated_users = NULL;
85 static int num_validated_users = 0;
87 /****************************************************************************
88 check if a uid has been validated, and return an pointer to the user_struct
89 if it has. NULL if not. vuid is biased by an offset. This allows us to
90 tell random client vuid's (normally zero) from valid vuids.
91 ****************************************************************************/
92 user_struct *get_valid_user_struct(uint16 vuid)
94 if(vuid == UID_FIELD_INVALID)
95 return NULL;
96 vuid -= VUID_OFFSET;
97 if((vuid >= (uint16)num_validated_users) ||
98 (validated_users[vuid].uid == -1) || (validated_users[vuid].gid == -1))
99 return NULL;
100 return &validated_users[vuid];
103 /****************************************************************************
104 invalidate a uid
105 ****************************************************************************/
106 void invalidate_vuid(uint16 vuid)
108 user_struct *vuser = get_valid_user_struct(vuid);
109 if(vuser == 0)
110 return;
112 vuser->uid = -1;
113 vuser->gid = -1;
114 vuser->user_ngroups = 0;
115 if(vuser->user_groups &&
116 (vuser->user_groups != (gid_t *)vuser->user_igroups))
117 free(vuser->user_groups);
118 vuser->user_groups = NULL;
119 if(vuser->user_igroups)
120 free(vuser->user_igroups);
121 vuser->user_igroups = NULL;
125 /****************************************************************************
126 return a validated username
127 ****************************************************************************/
128 char *validated_username(uint16 vuid)
130 user_struct *vuser = get_valid_user_struct(vuid);
131 if(vuser == 0)
132 return 0;
133 return(vuser->name);
136 /****************************************************************************
137 register a uid/name pair as being valid and that a valid password
138 has been given. vuid is biased by an offset. This allows us to
139 tell random client vuid's (normally zero) from valid vuids.
140 ****************************************************************************/
141 uint16 register_vuid(int uid,int gid, char *name,BOOL guest)
143 user_struct *vuser;
145 #if (defined(NETGROUP) && defined (AUTOMOUNT))
146 int nis_error; /* returned by yp all functions */
147 char *nis_result; /* yp_match inits this */
148 int nis_result_len; /* and set this */
149 char *nis_domain; /* yp_get_default_domain inits this */
150 char *nis_map = (char *)lp_nis_home_map_name();
151 int home_server_len;
152 #endif
153 struct passwd *pwfile; /* for getting real name from passwd file */
154 int real_name_len;
156 #if 0
158 * After observing MS-Exchange services writing to a Samba share
159 * I belive this code is incorrect. Each service does it's own
160 * sessionsetup_and_X for the same user, and as each service shuts
161 * down, it does a user_logoff_and_X. As we are consolidating multiple
162 * sessionsetup_and_X's onto the same vuid here, when the first service
163 * shuts down, it invalidates all the open files for the other services.
164 * Hence I am removing this code and forcing each sessionsetup_and_X
165 * to get a new vuid.
166 * Jeremy Allison. (jallison@whistle.com).
169 int i;
170 for(i = 0; i < num_validated_users; i++) {
171 vuser = &validated_users[i];
172 if( vuser->uid == uid )
173 return (uint16)(i + VUID_OFFSET); /* User already validated */
175 #endif
177 validated_users = (user_struct *)Realloc(validated_users,
178 sizeof(user_struct)*
179 (num_validated_users+1));
181 if (!validated_users)
183 DEBUG(0,("Failed to realloc users struct!\n"));
184 num_validated_users = 0;
185 return UID_FIELD_INVALID;
188 vuser = &validated_users[num_validated_users];
189 num_validated_users++;
191 vuser->uid = uid;
192 vuser->gid = gid;
193 vuser->guest = guest;
194 strcpy(vuser->name,name);
196 vuser->user_ngroups = 0;
197 vuser->user_groups = NULL;
198 vuser->user_igroups = NULL;
200 /* Find all the groups this uid is in and store them.
201 Used by become_user() */
202 setup_groups(name,uid,gid,
203 &vuser->user_ngroups,
204 &vuser->user_igroups,
205 &vuser->user_groups);
207 DEBUG(3,("uid %d registered to name %s\n",uid,name));
209 #if (defined(NETGROUP) && defined (AUTOMOUNT))
210 vuser->home_share = NULL;
211 DEBUG(3, ("Setting default HOMESHR to: \\\\logon server\\HOMES\n"));
212 vuser->home_share = Realloc(vuser->home_share, 32);
213 strcpy(vuser->home_share,"\\\\%L\\HOMES");
215 if (nis_error = yp_get_default_domain(&nis_domain))
216 DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error)));
217 DEBUG(3, ("NIS Domain: %s\n", nis_domain));
219 if (nis_error = yp_match(nis_domain, nis_map, vuser->name, strlen(vuser->name),
220 &nis_result, &nis_result_len))
221 DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error)));
222 if (!nis_error && lp_nis_home_map()) {
223 home_server_len = strcspn(nis_result,":");
224 DEBUG(3, ("NIS lookup succeeded\n\tHome server length: %d\n",home_server_len));
225 vuser->home_share = (char *)Realloc(vuser->home_share, home_server_len+12);
226 DEBUG(3, ("\tAllocated %d bytes for HOMESHR\n",home_server_len+12 ));
227 strcpy(vuser->home_share,"\\\\");
228 strncat(vuser->home_share, nis_result, home_server_len);
229 strcat(vuser->home_share,"\\homes");
230 DEBUG(2,("\tUser = %s\n\tUID = %d\n\tNIS result = %s\n\tHOMESHR = %s\n",
231 vuser->name, vuser->uid, nis_result, vuser->home_share));
233 #endif
235 vuser->real_name = NULL;
236 DEBUG(3, ("Clearing default real name\n"));
237 vuser->real_name = Realloc(vuser->real_name, 15);
238 strcpy(vuser->real_name, "<Full Name>\0");
239 if (lp_unix_realname()) {
240 pwfile=getpwnam(vuser->name);
241 DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->name,pwfile->pw_gecos));
242 real_name_len = strcspn(pwfile->pw_gecos, ",");
243 DEBUG(3, ("Real name length: %d\n", real_name_len));
244 vuser->real_name = (char *)Realloc(vuser->real_name, real_name_len+1);
245 strncpy(vuser->real_name, pwfile->pw_gecos, real_name_len);
246 vuser->real_name[real_name_len]='\0';
249 return (uint16)((num_validated_users - 1) + VUID_OFFSET);
253 /****************************************************************************
254 add a name to the session users list
255 ****************************************************************************/
256 void add_session_user(char *user)
258 fstring suser;
259 StrnCpy(suser,user,sizeof(suser)-1);
261 if (!Get_Pwnam(suser,True)) return;
263 if (suser && *suser && !in_list(suser,session_users,False))
265 if (strlen(suser) + strlen(session_users) + 2 >= sizeof(pstring))
266 DEBUG(1,("Too many session users??\n"));
267 else
269 strcat(session_users," ");
270 strcat(session_users,suser);
276 #ifdef NO_GETSPNAM
277 /* a fake shadow password routine which just fills a fake spwd struct
278 * with the sp_pwdp field. (sreiz@aie.nl)
280 static struct spwd *getspnam(char *username) /* fake shadow password routine */
282 FILE *f;
283 char line[1024];
284 static char pw[20];
285 static struct spwd static_spwd;
287 static_spwd.sp_pwdp=0;
288 if (!(f=fopen("/etc/master.passwd", "r")))
289 return 0;
290 while (fgets(line, 1024, f)) {
291 if (!strncmp(line, username, strlen(username)) &&
292 line[strlen(username)]==':') { /* found entry */
293 char *p, *q;
295 p=line+strlen(username)+1;
296 if ((q=strchr(p, ':'))) {
297 *q=0;
298 if (q-p+1>20)
299 break;
300 strcpy(pw, p);
301 static_spwd.sp_pwdp=pw;
303 break;
306 fclose(f);
307 if (static_spwd.sp_pwdp)
308 return &static_spwd;
309 return 0;
311 #endif
314 #ifdef OSF1_ENH_SEC
315 /****************************************************************************
316 an enhanced crypt for OSF1
317 ****************************************************************************/
318 static char *osf1_bigcrypt(char *password,char *salt1)
320 static char result[AUTH_MAX_PASSWD_LENGTH] = "";
321 char *p1;
322 char *p2=password;
323 char salt[3];
324 int i;
325 int parts = strlen(password) / AUTH_CLEARTEXT_SEG_CHARS;
326 if (strlen(password)%AUTH_CLEARTEXT_SEG_CHARS)
327 parts++;
329 StrnCpy(salt,salt1,2);
330 StrnCpy(result,salt1,2);
332 for (i=0; i<parts;i++)
334 p1 = crypt(p2,salt);
335 strcat(result,p1+2);
336 StrnCpy(salt,&result[2+i*AUTH_CIPHERTEXT_SEG_CHARS],2);
337 p2 += AUTH_CLEARTEXT_SEG_CHARS;
340 return(result);
342 #endif
345 /****************************************************************************
346 update the enhanced security database. Only relevant for OSF1 at the moment.
347 ****************************************************************************/
348 static void update_protected_database( char *user, BOOL result)
350 #ifdef OSF1_ENH_SEC
351 struct pr_passwd *mypasswd;
352 time_t starttime;
354 mypasswd = getprpwnam (user);
355 starttime = time (NULL);
357 if (result)
359 mypasswd->ufld.fd_slogin = starttime;
360 mypasswd->ufld.fd_nlogins = 0;
362 putprpwnam(user,mypasswd);
364 DEBUG(3,("Update protected database for Account %s after succesful connection\n",user));
366 else
368 mypasswd->ufld.fd_ulogin = starttime;
369 mypasswd->ufld.fd_nlogins = mypasswd->ufld.fd_nlogins + 1;
370 if ( mypasswd->ufld.fd_max_tries != 0 && mypasswd->ufld.fd_nlogins > mypasswd->ufld.fd_max_tries )
372 mypasswd->uflg.fg_lock = 0;
373 DEBUG(3,("Account is disabled -- see Account Administrator.\n"));
375 putprpwnam ( user , mypasswd );
376 DEBUG(3,("Update protected database for Account %s after refusing connection\n",user));
378 #else
379 DEBUG(6,("Updated database with %s %s\n",user,BOOLSTR(result)));
380 #endif
384 #ifdef USE_PAM
385 /*******************************************************************
386 check on PAM authentication
387 ********************************************************************/
389 /* We first need some helper functions */
390 #include <security/pam_appl.h>
391 /* Static variables used to communicate between the conversation function
392 * and the server_login function
394 static char *PAM_username;
395 static char *PAM_password;
397 /* PAM conversation function
398 * Here we assume (for now, at least) that echo on means login name, and
399 * echo off means password.
401 static int PAM_conv (int num_msg,
402 const struct pam_message **msg,
403 struct pam_response **resp,
404 void *appdata_ptr) {
405 int count = 0, replies = 0;
406 struct pam_response *reply = NULL;
407 int size = sizeof(struct pam_response);
409 #define GET_MEM if (reply) realloc(reply, size); else reply = malloc(size); \
410 if (!reply) return PAM_CONV_ERR; \
411 size += sizeof(struct pam_response)
412 #define COPY_STRING(s) (s) ? strdup(s) : NULL
414 for (count = 0; count < num_msg; count++) {
415 switch (msg[count]->msg_style) {
416 case PAM_PROMPT_ECHO_ON:
417 GET_MEM;
418 reply[replies].resp_retcode = PAM_SUCCESS;
419 reply[replies++].resp = COPY_STRING(PAM_username);
420 /* PAM frees resp */
421 break;
422 case PAM_PROMPT_ECHO_OFF:
423 GET_MEM;
424 reply[replies].resp_retcode = PAM_SUCCESS;
425 reply[replies++].resp = COPY_STRING(PAM_password);
426 /* PAM frees resp */
427 break;
428 case PAM_TEXT_INFO:
429 /* ignore it... */
430 break;
431 case PAM_ERROR_MSG:
432 default:
433 /* Must be an error of some sort... */
434 free (reply);
435 return PAM_CONV_ERR;
438 if (reply) *resp = reply;
439 return PAM_SUCCESS;
441 static struct pam_conv PAM_conversation = {
442 &PAM_conv,
443 NULL
447 static BOOL pam_auth(char *this_user,char *password)
449 pam_handle_t *pamh;
450 int pam_error;
452 /* Now use PAM to do authentication. For now, we won't worry about
453 * session logging, only authentication. Bail out if there are any
454 * errors. Since this is a limited protocol, and an even more limited
455 * function within a server speaking this protocol, we can't be as
456 * verbose as would otherwise make sense.
457 * Query: should we be using PAM_SILENT to shut PAM up?
459 #define PAM_BAIL if (pam_error != PAM_SUCCESS) { \
460 pam_end(pamh, 0); return False; \
462 PAM_password = password;
463 PAM_username = this_user;
464 pam_error = pam_start("samba", this_user, &PAM_conversation, &pamh);
465 PAM_BAIL;
466 pam_error = pam_authenticate(pamh, 0);
467 PAM_BAIL;
468 /* It is not clear to me that account management is the right thing
469 * to do, but it is not clear that it isn't, either. This can be
470 * removed if no account management should be done. Alternately,
471 * put a pam_allow.so entry in /etc/pam.conf for account handling. */
472 pam_error = pam_acct_mgmt(pamh, 0);
473 PAM_BAIL;
474 pam_end(pamh, PAM_SUCCESS);
475 /* If this point is reached, the user has been authenticated. */
476 return(True);
478 #endif
481 #ifdef AFS_AUTH
482 /*******************************************************************
483 check on AFS authentication
484 ********************************************************************/
485 static BOOL afs_auth(char *this_user,char *password)
487 long password_expires = 0;
488 char *reason;
490 /* For versions of AFS prior to 3.3, this routine has few arguments, */
491 /* but since I can't find the old documentation... :-) */
492 setpag();
493 if (ka_UserAuthenticateGeneral(KA_USERAUTH_VERSION+KA_USERAUTH_DOSETPAG,
494 this_user,
495 (char *) 0, /* instance */
496 (char *) 0, /* cell */
497 password,
498 0, /* lifetime, default */
499 &password_expires, /*days 'til it expires */
500 0, /* spare 2 */
501 &reason) == 0)
502 return(True);
503 return(False);
505 #endif
508 #ifdef DFS_AUTH
510 sec_login_handle_t my_dce_sec_context;
511 int dcelogin_atmost_once = 0;
513 /*******************************************************************
514 check on a DCE/DFS authentication
515 ********************************************************************/
516 static BOOL dfs_auth(char *this_user,char *password)
518 error_status_t err;
519 int err2;
520 int prterr;
521 boolean32 password_reset;
522 sec_passwd_rec_t my_dce_password;
523 sec_login_auth_src_t auth_src = sec_login_auth_src_network;
524 unsigned char dce_errstr[dce_c_error_string_len];
527 * We only go for a DCE login context if the given password
528 * matches that stored in the local password file..
529 * Assumes local passwd file is kept in sync w/ DCE RGY!
532 if (!strcmp((char *)crypt(password,this_salt),this_crypted) ||
533 dcelogin_atmost_once)
534 return(False);
536 if (sec_login_setup_identity(
537 (unsigned char *)this_user,
538 sec_login_no_flags,
539 &my_dce_sec_context,
540 &err) == 0)
542 dce_error_inq_text(err, dce_errstr, &err2);
543 DEBUG(0,("DCE Setup Identity for %s failed: %s\n",
544 this_user,dce_errstr));
545 return(False);
548 my_dce_password.version_number = sec_passwd_c_version_none;
549 my_dce_password.pepper = NULL;
550 my_dce_password.key.key_type = sec_passwd_plain;
551 my_dce_password.key.tagged_union.plain = (idl_char *)password;
553 if (sec_login_valid_and_cert_ident(my_dce_sec_context,
554 &my_dce_password,
555 &password_reset,
556 &auth_src,
557 &err) == 0 )
559 dce_error_inq_text(err, dce_errstr, &err2);
560 DEBUG(0,("DCE Identity Validation failed for principal %s: %s\n",
561 this_user,dce_errstr));
563 return(False);
566 sec_login_set_context(my_dce_sec_context, &err);
567 if (err != error_status_ok )
569 dce_error_inq_text(err, dce_errstr, &err2);
570 DEBUG(0,("DCE login failed for principal %s, cant set context: %s\n",
571 this_user,dce_errstr));
572 sec_login_purge_context(my_dce_sec_context, &err);
573 return(False);
575 else
577 DEBUG(0,("DCE login succeeded for principal %s on pid %d\n",
578 this_user, getpid()));
581 dcelogin_atmost_once = 1;
582 return (True);
585 void dfs_unlogin(void)
587 error_status_t err;
588 int err2;
589 unsigned char dce_errstr[dce_c_error_string_len];
591 sec_login_purge_context(my_dce_sec_context, &err);
592 if (err != error_status_ok )
594 dce_error_inq_text(err, dce_errstr, &err2);
595 DEBUG(0,("DCE purge login context failed for server instance %d: %s\n",
596 getpid(), dce_errstr));
600 #endif
602 #ifdef KRB5_AUTH
603 /*******************************************************************
604 check on Kerberos authentication
605 ********************************************************************/
606 static BOOL krb5_auth(char *this_user,char *password)
608 krb5_data tgtname = {
610 KRB5_TGS_NAME_SIZE,
611 KRB5_TGS_NAME
613 krb5_context kcontext;
614 krb5_principal kprinc;
615 krb5_principal server;
616 krb5_creds kcreds;
617 int options = 0;
618 krb5_address **addrs = (krb5_address **)0;
619 krb5_preauthtype *preauth = NULL;
620 krb5_keytab keytab = NULL;
621 krb5_timestamp now;
622 krb5_ccache ccache = NULL;
623 int retval;
624 char *name;
626 if ( retval=krb5_init_context(&kcontext))
628 return(False);
631 if ( retval = krb5_timeofday(kcontext, &now) )
633 return(False);
636 if ( retval = krb5_cc_default(kcontext, &ccache) )
638 return(False);
641 if ( retval = krb5_parse_name(kcontext, this_user, &kprinc) )
643 return(False);
646 memset((char *)&kcreds, 0, sizeof(kcreds));
648 kcreds.client = kprinc;
650 if ((retval = krb5_build_principal_ext(kcontext, &server,
651 krb5_princ_realm(kcontext, kprinc)->length,
652 krb5_princ_realm(kcontext, kprinc)->data,
653 tgtname.length,
654 tgtname.data,
655 krb5_princ_realm(kcontext, kprinc)->length,
656 krb5_princ_realm(kcontext, kprinc)->data,
657 0)))
659 return(False);
662 kcreds.server = server;
664 retval = krb5_get_in_tkt_with_password(kcontext,
665 options,
666 addrs,
667 NULL,
668 preauth,
669 password,
671 &kcreds,
674 if ( retval )
676 return(False);
679 return(True);
681 #endif /* KRB5_AUTH */
683 #ifdef LINUX_BIGCRYPT
684 /****************************************************************************
685 an enhanced crypt for Linux to handle password longer than 8 characters
686 ****************************************************************************/
687 static int linux_bigcrypt(char *password,char *salt1, char *crypted)
689 #define LINUX_PASSWORD_SEG_CHARS 8
690 char salt[3];
691 int i;
693 StrnCpy(salt,salt1,2);
694 crypted +=2;
696 for ( i=strlen(password); i > 0; i -= LINUX_PASSWORD_SEG_CHARS) {
697 char * p = crypt(password,salt) + 2;
698 if(strncmp(p, crypted, LINUX_PASSWORD_SEG_CHARS) != 0)
699 return(0);
700 password += LINUX_PASSWORD_SEG_CHARS;
701 crypted += strlen(p);
704 return(1);
706 #endif
709 /****************************************************************************
710 apply a function to upper/lower case combinations
711 of a string and return true if one of them returns true.
712 try all combinations with N uppercase letters.
713 offset is the first char to try and change (start with 0)
714 it assumes the string starts lowercased
715 ****************************************************************************/
716 static BOOL string_combinations2(char *s,int offset,BOOL (*fn)(),int N)
718 int len = strlen(s);
719 int i;
721 #ifdef PASSWORD_LENGTH
722 len = MIN(len,PASSWORD_LENGTH);
723 #endif
725 if (N <= 0 || offset >= len)
726 return(fn(s));
728 for (i=offset;i<(len-(N-1));i++)
730 char c = s[i];
731 if (!islower(c)) continue;
732 s[i] = toupper(c);
733 if (string_combinations2(s,i+1,fn,N-1))
734 return(True);
735 s[i] = c;
737 return(False);
740 /****************************************************************************
741 apply a function to upper/lower case combinations
742 of a string and return true if one of them returns true.
743 try all combinations with up to N uppercase letters.
744 offset is the first char to try and change (start with 0)
745 it assumes the string starts lowercased
746 ****************************************************************************/
747 static BOOL string_combinations(char *s,BOOL (*fn)(),int N)
749 int n;
750 for (n=1;n<=N;n++)
751 if (string_combinations2(s,0,fn,n)) return(True);
752 return(False);
757 /****************************************************************************
758 core of password checking routine
759 ****************************************************************************/
760 BOOL password_check(char *password)
763 #ifdef USE_PAM
764 /* This falls through if the password check fails
765 - if NO_CRYPT is defined this causes an error msg
766 saying Warning - no crypt available
767 - if NO_CRYPT is NOT defined this is a potential security hole
768 as it may authenticate via the crypt call when PAM
769 settings say it should fail.
770 if (pam_auth(this_user,password)) return(True);
771 Hence we make a direct return to avoid a second chance!!!
773 return (pam_auth(this_user,password));
774 #endif
776 #ifdef AFS_AUTH
777 if (afs_auth(this_user,password)) return(True);
778 #endif
780 #ifdef DFS_AUTH
781 if (dfs_auth(this_user,password)) return(True);
782 #endif
784 #ifdef KRB5_AUTH
785 if (krb5_auth(this_user,password)) return(True);
786 #endif
788 #ifdef PWDAUTH
789 if (pwdauth(this_user,password) == 0)
790 return(True);
791 #endif
793 #ifdef OSF1_ENH_SEC
794 return(strcmp(osf1_bigcrypt(password,this_salt),this_crypted) == 0);
795 #endif
797 #ifdef ULTRIX_AUTH
798 return (strcmp((char *)crypt16(password, this_salt ),this_crypted) == 0);
799 #endif
801 #ifdef LINUX_BIGCRYPT
802 return(linux_bigcrypt(password,this_salt,this_crypted));
803 #endif
805 #ifdef NO_CRYPT
806 DEBUG(1,("Warning - no crypt available\n"));
807 return(False);
808 #else
809 return(strcmp((char *)crypt(password,this_salt),this_crypted) == 0);
810 #endif
813 #ifdef SMB_PASSWD
814 /****************************************************************************
815 core of smb password checking routine.
816 ****************************************************************************/
817 BOOL smb_password_check(char *password, unsigned char *part_passwd, unsigned char *c8)
819 /* Finish the encryption of part_passwd. */
820 unsigned char p21[21];
821 unsigned char p24[24];
823 if(part_passwd == NULL)
824 DEBUG(10,("No password set - allowing access\n"));
825 /* No password set - always true ! */
826 if(part_passwd == NULL)
827 return 1;
829 memset(p21,'\0',21);
830 memcpy(p21,part_passwd,16);
831 E_P24(p21, c8, p24);
832 #if DEBUG_PASSWORD
834 int i;
835 DEBUG(100,("Part password (P16) was |"));
836 for(i = 0; i < 16; i++)
837 DEBUG(100,("%X ", (unsigned char)part_passwd[i]));
838 DEBUG(100,("|\n"));
839 DEBUG(100,("Password from client was |"));
840 for(i = 0; i < 24; i++)
841 DEBUG(100,("%X ", (unsigned char)password[i]));
842 DEBUG(100,("|\n"));
843 DEBUG(100,("Given challenge was |"));
844 for(i = 0; i < 8; i++)
845 DEBUG(100,("%X ", (unsigned char)c8[i]));
846 DEBUG(100,("|\n"));
847 DEBUG(100,("Value from encryption was |"));
848 for(i = 0; i < 24; i++)
849 DEBUG(100,("%X ", (unsigned char)p24[i]));
850 DEBUG(100,("|\n"));
852 #endif
853 return (memcmp(p24, password, 24) == 0);
855 #endif
857 /****************************************************************************
858 check if a username/password is OK
859 ****************************************************************************/
860 BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd)
862 pstring pass2;
863 int level = lp_passwordlevel();
864 struct passwd *pass;
865 #ifdef SMB_PASSWD
866 char challenge[8];
867 struct smb_passwd *smb_pass;
868 BOOL challenge_done = False;
869 #endif
871 if (password) password[pwlen] = 0;
873 #ifdef SMB_PASSWD
874 if (pwlen == 24)
875 challenge_done = last_challenge(challenge);
876 #endif
878 #if DEBUG_PASSWORD
879 #ifdef SMB_PASSWD
880 if (challenge_done)
882 int i;
883 DEBUG(100,("checking user=[%s] pass=[",user));
884 for( i = 0; i < 24; i++)
885 DEBUG(100,("%0x ", (unsigned char)password[i]));
886 DEBUG(100,("]\n"));
888 else
889 #endif
890 DEBUG(100,("checking user=[%s] pass=[%s]\n",user,password));
891 #endif
893 if (!password)
894 return(False);
896 if (((!*password) || (!pwlen)) && !lp_null_passwords())
897 return(False);
899 if (pwd && !user)
901 pass = (struct passwd *) pwd;
902 user = pass->pw_name;
904 else
905 pass = Get_Pwnam(user,True);
907 #ifdef SMB_PASSWD
909 DEBUG(4,("SMB Password - pwlen = %d, challenge_done = %d\n", pwlen, challenge_done));
911 if((pwlen == 24) && challenge_done)
913 DEBUG(4,("Checking SMB password for user %s (l=24)\n",user));
915 if (!pass)
917 DEBUG(3,("Couldn't find user %s\n",user));
918 return(False);
921 smb_pass = get_smbpwnam(user);
922 if(!smb_pass)
924 DEBUG(3,("Couldn't find user %s in smb_passwd file.\n", user));
925 return(False);
928 /* Ensure the uid's match */
929 if(smb_pass->smb_userid != pass->pw_uid)
931 DEBUG(3,("Error : UNIX and SMB uids in password files do not match !\n"));
932 return(False);
935 if(Protocol >= PROTOCOL_NT1)
937 /* We have the NT MD4 hash challenge available - see if we can
938 use it (ie. does it exist in the smbpasswd file).
940 if(smb_pass->smb_nt_passwd != NULL)
942 DEBUG(4,("Checking NT MD4 password\n"));
943 if(smb_password_check(password,
944 smb_pass->smb_nt_passwd,
945 (char *)challenge))
947 update_protected_database(user,True);
948 return(True);
950 DEBUG(4,("NT MD4 password check failed\n"));
954 /* Try against the lanman password */
956 if (smb_password_check(password,
957 smb_pass->smb_passwd,
958 (char *)challenge)) {
959 update_protected_database(user,True);
960 return(True);
963 DEBUG(3,("Error smb_password_check failed\n"));
965 #endif
967 DEBUG(4,("Checking password for user %s (l=%d)\n",user,pwlen));
969 if (!pass)
971 DEBUG(3,("Couldn't find user %s\n",user));
972 return(False);
975 #ifdef SHADOW_PWD
977 struct spwd *spass;
979 /* many shadow systems require you to be root to get the password,
980 in most cases this should already be the case when this
981 function is called, except perhaps for IPC password changing
982 requests */
984 spass = getspnam(pass->pw_name);
985 if (spass && spass->sp_pwdp)
986 pass->pw_passwd = spass->sp_pwdp;
988 #elif defined(IA_UINFO)
990 /* Need to get password with SVR4.2's ia_ functions instead of
991 get{sp,pw}ent functions. Required by UnixWare 2.x, tested on
992 version 2.1. (tangent@cyberport.com) */
993 uinfo_t uinfo;
994 if (ia_openinfo(pass->pw_name, &uinfo) != -1)
995 ia_get_logpwd(uinfo, &(pass->pw_passwd));
997 #endif
999 #ifdef SecureWare
1001 struct pr_passwd *pr_pw = getprpwnam(pass->pw_name);
1002 if (pr_pw && pr_pw->ufld.fd_encrypt)
1003 pass->pw_passwd = pr_pw->ufld.fd_encrypt;
1005 #endif
1007 #ifdef HPUX_10_TRUSTED
1009 struct pr_passwd *pr_pw = getprpwnam(pass->pw_name);
1010 if (pr_pw && pr_pw->ufld.fd_encrypt)
1011 pass->pw_passwd = pr_pw->ufld.fd_encrypt;
1013 #endif
1015 #ifdef OSF1_ENH_SEC
1017 struct pr_passwd *mypasswd;
1018 DEBUG(5,("Checking password for user %s in OSF1_ENH_SEC\n",user));
1019 mypasswd = getprpwnam (user);
1020 if ( mypasswd )
1022 strcpy(pass->pw_name,mypasswd->ufld.fd_name);
1023 strcpy(pass->pw_passwd,mypasswd->ufld.fd_encrypt);
1025 else
1027 DEBUG(5,("No entry for user %s in protected database !\n",user));
1028 return(False);
1031 #endif
1033 #ifdef ULTRIX_AUTH
1035 AUTHORIZATION *ap = getauthuid( pass->pw_uid );
1036 if (ap)
1038 strcpy( pass->pw_passwd, ap->a_password );
1039 endauthent();
1042 #endif
1044 /* extract relevant info */
1045 strcpy(this_user,pass->pw_name);
1046 strcpy(this_salt,pass->pw_passwd);
1047 strcpy(this_crypted,pass->pw_passwd);
1049 if (!*this_crypted) {
1050 if (!lp_null_passwords()) {
1051 DEBUG(2,("Disallowing access to %s due to null password\n",this_user));
1052 return(False);
1054 #ifndef PWDAUTH
1055 if (!*password) {
1056 DEBUG(3,("Allowing access to %s with null password\n",this_user));
1057 return(True);
1059 #endif
1062 /* try it as it came to us */
1063 if (password_check(password))
1065 update_protected_database(user,True);
1066 return(True);
1069 /* if the password was given to us with mixed case then we don't
1070 need to proceed as we know it hasn't been case modified by the
1071 client */
1072 if (strhasupper(password) && strhaslower(password))
1073 return(False);
1075 /* make a copy of it */
1076 StrnCpy(pass2,password,sizeof(pstring)-1);
1078 /* try all lowercase */
1079 strlower(password);
1080 if (password_check(password))
1082 update_protected_database(user,True);
1083 return(True);
1086 /* give up? */
1087 if(level < 1)
1089 update_protected_database(user,False);
1091 /* restore it */
1092 strcpy(password,pass2);
1094 return(False);
1097 /* last chance - all combinations of up to level chars upper! */
1098 strlower(password);
1100 if (string_combinations(password,password_check,level))
1102 update_protected_database(user,True);
1103 return(True);
1106 update_protected_database(user,False);
1108 /* restore it */
1109 strcpy(password,pass2);
1111 return(False);
1116 /****************************************************************************
1117 check if a username is valid
1118 ****************************************************************************/
1119 BOOL user_ok(char *user,int snum)
1121 pstring valid, invalid;
1122 BOOL ret;
1124 StrnCpy(valid, lp_valid_users(snum), sizeof(pstring));
1125 StrnCpy(invalid, lp_invalid_users(snum), sizeof(pstring));
1127 string_sub(valid,"%S",lp_servicename(snum));
1128 string_sub(invalid,"%S",lp_servicename(snum));
1130 ret = !user_in_list(user,invalid);
1132 if (ret && valid && *valid)
1133 ret = user_in_list(user,valid);
1135 if (ret && lp_onlyuser(snum)) {
1136 char *user_list = lp_username(snum);
1137 string_sub(user_list,"%S",lp_servicename(snum));
1138 ret = user_in_list(user,user_list);
1141 return(ret);
1147 /****************************************************************************
1148 validate a group username entry. Return the username or NULL
1149 ****************************************************************************/
1150 static char *validate_group(char *group,char *password,int pwlen,int snum)
1152 #ifdef NETGROUP
1154 char *host, *user, *domain;
1155 setnetgrent(group);
1156 while (getnetgrent(&host, &user, &domain)) {
1157 if (user) {
1158 if (user_ok(user, snum) &&
1159 password_ok(user,password,pwlen,NULL)) {
1160 endnetgrent();
1161 return(user);
1165 endnetgrent();
1167 #endif
1169 #if HAVE_GETGRNAM
1171 struct group *gptr = (struct group *)getgrnam(group);
1172 char **member;
1173 if (gptr)
1175 member = gptr->gr_mem;
1176 while (member && *member)
1178 static fstring name;
1179 strcpy(name,*member);
1180 if (user_ok(name,snum) &&
1181 password_ok(name,password,pwlen,NULL))
1182 return(&name[0]);
1183 member++;
1185 #ifdef GROUP_CHECK_PWENT
1187 struct passwd *pwd;
1188 static fstring tm;
1190 setpwent ();
1191 while (pwd = getpwent ()) {
1192 if (*(pwd->pw_passwd) && pwd->pw_gid == gptr->gr_gid) {
1193 /* This Entry have PASSWORD and same GID then check pwd */
1194 if (password_ok(NULL, password, pwlen, pwd)) {
1195 strcpy(tm, pwd->pw_name);
1196 endpwent ();
1197 return tm;
1201 endpwent ();
1203 #endif /* GROUP_CHECK_PWENT */
1206 #endif
1207 return(NULL);
1212 /****************************************************************************
1213 check for authority to login to a service with a given username/password
1214 ****************************************************************************/
1215 BOOL authorise_login(int snum,char *user,char *password, int pwlen,
1216 BOOL *guest,BOOL *force,uint16 vuid)
1218 BOOL ok = False;
1220 *guest = False;
1222 #if DEBUG_PASSWORD
1223 DEBUG(100,("checking authorisation on user=%s pass=%s\n",user,password));
1224 #endif
1226 /* there are several possabilities:
1227 1) login as the given user with given password
1228 2) login as a previously registered username with the given password
1229 3) login as a session list username with the given password
1230 4) login as a previously validated user/password pair
1231 5) login as the "user =" user with given password
1232 6) login as the "user =" user with no password (guest connection)
1233 7) login as guest user with no password
1235 if the service is guest_only then steps 1 to 5 are skipped
1238 if (GUEST_ONLY(snum)) *force = True;
1240 if (!(GUEST_ONLY(snum) && GUEST_OK(snum)))
1243 user_struct *vuser = get_valid_user_struct(vuid);
1245 /* check the given username and password */
1246 if (!ok && (*user) && user_ok(user,snum)) {
1247 ok = password_ok(user,password, pwlen, NULL);
1248 if (ok) DEBUG(3,("ACCEPTED: given username password ok\n"));
1251 /* check for a previously registered guest username */
1252 if (!ok && (vuser != 0) && vuser->guest) {
1253 if (user_ok(vuser->name,snum) &&
1254 password_ok(vuser->name, password, pwlen, NULL)) {
1255 strcpy(user, vuser->name);
1256 vuser->guest = False;
1257 DEBUG(3,("ACCEPTED: given password with registered user %s\n", user));
1258 ok = True;
1263 /* now check the list of session users */
1264 if (!ok)
1266 char *auser;
1267 char *user_list = strdup(session_users);
1268 if (!user_list) return(False);
1270 for (auser=strtok(user_list,LIST_SEP);
1271 !ok && auser;
1272 auser = strtok(NULL,LIST_SEP))
1274 fstring user2;
1275 strcpy(user2,auser);
1276 if (!user_ok(user2,snum)) continue;
1278 if (password_ok(user2,password, pwlen, NULL)) {
1279 ok = True;
1280 strcpy(user,user2);
1281 DEBUG(3,("ACCEPTED: session list username and given password ok\n"));
1284 free(user_list);
1287 /* check for a previously validated username/password pair */
1288 if (!ok && !lp_revalidate(snum) &&
1289 (vuser != 0) && !vuser->guest &&
1290 user_ok(vuser->name,snum)) {
1291 strcpy(user,vuser->name);
1292 *guest = False;
1293 DEBUG(3,("ACCEPTED: validated uid ok as non-guest\n"));
1294 ok = True;
1297 /* check for a rhosts entry */
1298 if (!ok && user_ok(user,snum) && check_hosts_equiv(user)) {
1299 ok = True;
1300 DEBUG(3,("ACCEPTED: hosts equiv or rhosts entry\n"));
1303 /* check the user= fields and the given password */
1304 if (!ok && lp_username(snum)) {
1305 char *auser;
1306 pstring user_list;
1307 StrnCpy(user_list,lp_username(snum),sizeof(pstring));
1309 string_sub(user_list,"%S",lp_servicename(snum));
1311 for (auser=strtok(user_list,LIST_SEP);
1312 auser && !ok;
1313 auser = strtok(NULL,LIST_SEP))
1315 if (*auser == '@')
1317 auser = validate_group(auser+1,password,pwlen,snum);
1318 if (auser)
1320 ok = True;
1321 strcpy(user,auser);
1322 DEBUG(3,("ACCEPTED: group username and given password ok\n"));
1325 else
1327 fstring user2;
1328 strcpy(user2,auser);
1329 if (user_ok(user2,snum) &&
1330 password_ok(user2,password,pwlen,NULL))
1332 ok = True;
1333 strcpy(user,user2);
1334 DEBUG(3,("ACCEPTED: user list username and given password ok\n"));
1339 } /* not guest only */
1341 /* check for a normal guest connection */
1342 if (!ok && GUEST_OK(snum))
1344 fstring guestname;
1345 StrnCpy(guestname,lp_guestaccount(snum),sizeof(guestname)-1);
1346 if (Get_Pwnam(guestname,True))
1348 strcpy(user,guestname);
1349 ok = True;
1350 DEBUG(3,("ACCEPTED: guest account and guest ok\n"));
1352 else
1353 DEBUG(0,("Invalid guest account %s??\n",guestname));
1354 *guest = True;
1355 *force = True;
1358 if (ok && !user_ok(user,snum))
1360 DEBUG(0,("rejected invalid user %s\n",user));
1361 ok = False;
1364 return(ok);
1368 /****************************************************************************
1369 read the a hosts.equiv or .rhosts file and check if it
1370 allows this user from this machine
1371 ****************************************************************************/
1372 static BOOL check_user_equiv(char *user, char *remote, char *equiv_file)
1374 pstring buf;
1375 int plus_allowed = 1;
1376 char *file_host;
1377 char *file_user;
1378 FILE *fp = fopen(equiv_file, "r");
1379 DEBUG(5, ("check_user_equiv %s %s %s\n", user, remote, equiv_file));
1380 if (! fp) return False;
1381 while(fgets(buf, sizeof(buf), fp))
1383 trim_string(buf," "," ");
1385 if (buf[0] != '#' && buf[0] != '\n')
1387 BOOL is_group = False;
1388 int plus = 1;
1389 char *bp = buf;
1390 if (strcmp(buf, "NO_PLUS\n") == 0)
1392 DEBUG(6, ("check_user_equiv NO_PLUS\n"));
1393 plus_allowed = 0;
1395 else {
1396 if (buf[0] == '+')
1398 bp++;
1399 if (*bp == '\n' && plus_allowed)
1401 /* a bare plus means everbody allowed */
1402 DEBUG(6, ("check_user_equiv everybody allowed\n"));
1403 fclose(fp);
1404 return True;
1407 else if (buf[0] == '-')
1409 bp++;
1410 plus = 0;
1412 if (*bp == '@')
1414 is_group = True;
1415 bp++;
1417 file_host = strtok(bp, " \t\n");
1418 file_user = strtok(NULL, " \t\n");
1419 DEBUG(7, ("check_user_equiv %s %s\n", file_host ? file_host : "(null)",
1420 file_user ? file_user : "(null)" ));
1421 if (file_host && *file_host)
1423 BOOL host_ok = False;
1425 #ifdef NETGROUP
1426 if (is_group)
1428 static char *mydomain = NULL;
1429 if (!mydomain)
1430 yp_get_default_domain(&mydomain);
1431 if (mydomain && innetgr(file_host,remote,user,mydomain))
1432 host_ok = True;
1434 #else
1435 if (is_group)
1437 DEBUG(1,("Netgroups not configured - add -DNETGROUP and recompile\n"));
1438 continue;
1440 #endif
1442 /* is it this host */
1443 /* the fact that remote has come from a call of gethostbyaddr
1444 * means that it may have the fully qualified domain name
1445 * so we could look up the file version to get it into
1446 * a canonical form, but I would rather just type it
1447 * in full in the equiv file
1449 if (!host_ok && !is_group && strequal(remote, file_host))
1450 host_ok = True;
1452 if (!host_ok)
1453 continue;
1455 /* is it this user */
1456 if (file_user == 0 || strequal(user, file_user))
1458 fclose(fp);
1459 DEBUG(5, ("check_user_equiv matched %s%s %s\n",
1460 (plus ? "+" : "-"), file_host,
1461 (file_user ? file_user : "")));
1462 return (plus ? True : False);
1468 fclose(fp);
1469 return False;
1473 /****************************************************************************
1474 check for a possible hosts equiv or rhosts entry for the user
1475 ****************************************************************************/
1476 BOOL check_hosts_equiv(char *user)
1478 char *fname = NULL;
1479 pstring rhostsfile;
1480 struct passwd *pass = Get_Pwnam(user,True);
1482 if (!pass)
1483 return(False);
1485 fname = lp_hosts_equiv();
1487 /* note: don't allow hosts.equiv on root */
1488 if (fname && *fname && (pass->pw_uid != 0))
1490 if (check_user_equiv(user,client_name(),fname))
1491 return(True);
1494 if (lp_use_rhosts())
1496 char *home = get_home_dir(user);
1497 if (home)
1499 sprintf(rhostsfile, "%s/.rhosts", home);
1500 if (check_user_equiv(user,client_name(),rhostsfile))
1501 return(True);
1505 return(False);
1509 int password_client = -1;
1510 static fstring pserver;
1512 /****************************************************************************
1513 attempted support for server level security
1514 ****************************************************************************/
1515 BOOL server_cryptkey(char *buf)
1517 pstring inbuf,outbuf;
1518 fstring pass_protocol;
1519 extern fstring remote_machine;
1520 char *p;
1521 int len;
1522 fstring desthost;
1523 struct in_addr dest_ip;
1524 int port = SMB_PORT;
1525 BOOL ret;
1527 if (password_client >= 0)
1528 close(password_client);
1529 password_client = -1;
1531 if (Protocol < PROTOCOL_NT1) {
1532 strcpy(pass_protocol,"LM1.2X002");
1533 } else {
1534 strcpy(pass_protocol,"NT LM 0.12");
1537 bzero(inbuf,sizeof(inbuf));
1538 bzero(outbuf,sizeof(outbuf));
1540 for (p=strtok(lp_passwordserver(),LIST_SEP); p ; p = strtok(NULL,LIST_SEP)) {
1541 strcpy(desthost,p);
1542 standard_sub_basic(desthost);
1543 strupper(desthost);
1545 dest_ip = *interpret_addr2(desthost);
1546 if (zero_ip(dest_ip)) {
1547 DEBUG(1,("Can't resolve address for %s\n",p));
1548 continue;
1551 if (ismyip(dest_ip)) {
1552 DEBUG(1,("Password server loop - disabling password server %s\n",p));
1553 continue;
1556 password_client = open_socket_out(SOCK_STREAM, &dest_ip, port, SHORT_CONNECT_TIMEOUT);
1557 if (password_client >= 0) {
1558 DEBUG(3,("connected to password server %s\n",p));
1559 StrnCpy(pserver,p,sizeof(pserver)-1);
1560 break;
1564 if (password_client < 0) {
1565 DEBUG(1,("password server not available\n"));
1566 return(False);
1570 /* send a session request (RFC 8002) */
1572 /* put in the destination name */
1573 len = 4;
1574 p = outbuf+len;
1575 name_mangle(desthost,p,' ');
1576 len += name_len(p);
1578 /* and my name */
1579 p = outbuf+len;
1580 name_mangle(remote_machine,p,' ');
1581 len += name_len(p);
1583 _smb_setlen(outbuf,len);
1584 CVAL(outbuf,0) = 0x81;
1586 send_smb(password_client,outbuf);
1589 if (!receive_smb(password_client,inbuf,5000) ||
1590 CVAL(inbuf,0) != 0x82) {
1591 DEBUG(1,("%s rejected the session\n",pserver));
1592 close(password_client); password_client = -1;
1593 return(False);
1596 DEBUG(3,("got session\n"));
1598 bzero(outbuf,smb_size);
1600 /* setup the protocol string */
1601 set_message(outbuf,0,strlen(pass_protocol)+2,True);
1602 p = smb_buf(outbuf);
1603 *p++ = 2;
1604 strcpy(p,pass_protocol);
1606 CVAL(outbuf,smb_com) = SMBnegprot;
1607 CVAL(outbuf,smb_flg) = 0x8;
1608 SSVAL(outbuf,smb_flg2,0x1);
1610 send_smb(password_client,outbuf);
1611 ret = receive_smb(password_client,inbuf,5000);
1613 if (!ret || CVAL(inbuf,smb_rcls) || SVAL(inbuf,smb_vwv0)) {
1614 DEBUG(1,("%s rejected the protocol\n",pserver));
1615 close(password_client); password_client= -1;
1616 return(False);
1619 if (!(CVAL(inbuf,smb_vwv1) & 1)) {
1620 DEBUG(1,("%s isn't in user level security mode\n",pserver));
1621 close(password_client); password_client= -1;
1622 return(False);
1625 memcpy(buf,inbuf,smb_len(inbuf)+4);
1627 DEBUG(3,("password server OK\n"));
1629 return(True);
1632 /****************************************************************************
1633 attempted support for server level security
1634 ****************************************************************************/
1635 BOOL server_validate(char *buf)
1637 pstring inbuf,outbuf;
1638 BOOL ret;
1640 if (password_client < 0) {
1641 DEBUG(1,("%s not connected\n",pserver));
1642 return(False);
1645 bzero(inbuf,sizeof(inbuf));
1646 memcpy(outbuf,buf,sizeof(outbuf));
1648 /* send a session setup command */
1649 CVAL(outbuf,smb_flg) = 0x8;
1650 SSVAL(outbuf,smb_flg2,0x1);
1651 CVAL(outbuf,smb_vwv0) = 0xFF;
1653 set_message(outbuf,smb_numwords(outbuf),smb_buflen(outbuf),False);
1655 SCVAL(inbuf,smb_rcls,1);
1657 send_smb(password_client,outbuf);
1658 ret = receive_smb(password_client,inbuf,5000);
1660 if (!ret || CVAL(inbuf,smb_rcls) != 0) {
1661 DEBUG(1,("password server %s rejected the password\n",pserver));
1662 return(False);
1665 /* if logged in as guest then reject */
1666 if ((SVAL(inbuf,smb_vwv2) & 1) != 0) {
1667 DEBUG(1,("password server %s gave us guest only\n",pserver));
1668 return(False);
1671 DEBUG(3,("password server %s accepted the password\n",pserver));
1673 #if !KEEP_PASSWORD_SERVER_OPEN
1674 close(password_client); password_client= -1;
1675 #endif
1677 return(True);