2 Unix SMB/Netbios implementation.
4 Password and authentication handling
5 Copyright (C) Andrew Tridgell 1992-1998
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #if (defined(NETGROUP) && defined (AUTOMOUNT))
25 #include "rpcsvc/ypclnt.h"
28 extern int DEBUGLEVEL;
31 BOOL global_machine_pasword_needs_changing;
33 /* users from session setup */
34 static pstring session_users="";
36 extern pstring global_myname;
37 extern fstring global_myworkgroup;
39 /* these are kept here to keep the string_combinations function simple */
40 static char this_user[100]="";
41 static char this_salt[100]="";
42 static char this_crypted[100]="";
44 /* Data to do lanman1/2 password challenge. */
45 static unsigned char saved_challenge[8];
46 static BOOL challenge_sent=False;
48 /*******************************************************************
49 Get the next challenge value - no repeats.
50 ********************************************************************/
51 void generate_next_challenge(char *challenge)
55 * Leave this ifdef'd out while we test
56 * the new crypto random number generator.
59 unsigned char buf[16];
60 static int counter = 0;
64 /* get a sort-of random number */
66 v1 = (counter++) + getpid() + tval.tv_sec;
67 v2 = (counter++) * getpid() + tval.tv_usec;
68 SIVAL(challenge,0,v1);
69 SIVAL(challenge,4,v2);
71 /* mash it up with md4 */
72 mdfour(buf, (unsigned char *)challenge, 8);
76 generate_random_buffer(buf,8,False);
78 memcpy(saved_challenge, buf, 8);
79 memcpy(challenge,buf,8);
80 challenge_sent = True;
83 /*******************************************************************
84 set the last challenge sent, usually from a password server
85 ********************************************************************/
86 BOOL set_challenge(char *challenge)
88 memcpy(saved_challenge,challenge,8);
89 challenge_sent = True;
93 /*******************************************************************
94 get the last challenge sent
95 ********************************************************************/
96 BOOL last_challenge(unsigned char *challenge)
98 if (!challenge_sent) return(False);
99 memcpy(challenge,saved_challenge,8);
103 /* this holds info on user ids that are already validated for this VC */
104 static user_struct *validated_users = NULL;
105 static int num_validated_users = 0;
107 /****************************************************************************
108 check if a uid has been validated, and return an pointer to the user_struct
109 if it has. NULL if not. vuid is biased by an offset. This allows us to
110 tell random client vuid's (normally zero) from valid vuids.
111 ****************************************************************************/
112 user_struct *get_valid_user_struct(uint16 vuid)
114 if (vuid == UID_FIELD_INVALID)
117 if ((vuid >= (uint16)num_validated_users) ||
118 (validated_users[vuid].uid == -1) || (validated_users[vuid].gid == -1))
120 return &validated_users[vuid];
123 /****************************************************************************
125 ****************************************************************************/
126 void invalidate_vuid(uint16 vuid)
128 user_struct *vuser = get_valid_user_struct(vuid);
130 if (vuser == NULL) return;
137 /* same number of igroups as groups as attrs */
140 if (vuser->groups && (vuser->groups != (gid_t *)vuser->igroups))
143 if (vuser->igroups) free(vuser->igroups);
144 if (vuser->attrs ) free(vuser->attrs);
145 if (vuser->sids ) free(vuser->sids);
149 vuser->igroups = NULL;
150 vuser->groups = NULL;
154 /****************************************************************************
155 return a validated username
156 ****************************************************************************/
157 char *validated_username(uint16 vuid)
159 user_struct *vuser = get_valid_user_struct(vuid);
166 /****************************************************************************
167 Setup the groups a user belongs to.
168 ****************************************************************************/
169 int setup_groups(char *user, int uid, int gid, int *p_ngroups,
170 int **p_igroups, gid_t **p_groups,
173 if (-1 == initgroups(user,gid))
177 DEBUG(0,("Unable to initgroups!\n"));
178 if (gid < 0 || gid > 16000 || uid < 0 || uid > 16000)
179 DEBUG(0,("This is probably a problem with the account %s\n",user));
188 ngroups = getgroups(0,&grp);
191 igroups = (int *)malloc(sizeof(int)*ngroups);
192 attrs = (int *)malloc(sizeof(int)*ngroups);
193 for (i=0;i<ngroups;i++)
195 attrs [i] = 0x7; /* XXXX don't know what NT user attributes are yet! */
196 igroups[i] = 0x42424242;
198 ngroups = getgroups(ngroups,(gid_t *)igroups);
200 if (igroups[0] == 0x42424242)
203 *p_ngroups = ngroups;
206 /* The following bit of code is very strange. It is due to the
207 fact that some OSes use int* and some use gid_t* for
208 getgroups, and some (like SunOS) use both, one in prototypes,
209 and one in man pages and the actual code. Thus we detect it
210 dynamically using some very ugly code */
213 /* does getgroups return ints or gid_t ?? */
214 static BOOL groups_use_ints = True;
216 if (groups_use_ints &&
218 SVAL(igroups,2) == 0x4242)
219 groups_use_ints = False;
221 for (i=0;groups_use_ints && i<ngroups;i++)
222 if (igroups[i] == 0x42424242)
223 groups_use_ints = False;
227 *p_igroups = igroups;
228 *p_groups = (gid_t *)igroups;
232 gid_t *groups = (gid_t *)igroups;
233 igroups = (int *)malloc(sizeof(int)*ngroups);
234 for (i=0;i<ngroups;i++)
236 igroups[i] = groups[i];
238 *p_igroups = igroups;
239 *p_groups = (gid_t *)groups;
242 DEBUG(3,("%s is in %d groups\n",user,ngroups));
243 for (i=0;i<ngroups;i++)
244 DEBUG(3,("%d ",igroups[i]));
251 /****************************************************************************
252 register a uid/name pair as being valid and that a valid password
253 has been given. vuid is biased by an offset. This allows us to
254 tell random client vuid's (normally zero) from valid vuids.
255 ****************************************************************************/
256 uint16 register_vuid(int uid,int gid, char *unix_name, char *requested_name, BOOL guest)
259 struct passwd *pwfile; /* for getting real name from passwd file */
261 /* Ensure no vuid gets registered in share level security. */
262 if(lp_security() == SEC_SHARE)
263 return UID_FIELD_INVALID;
267 * After observing MS-Exchange services writing to a Samba share
268 * I belive this code is incorrect. Each service does its own
269 * sessionsetup_and_X for the same user, and as each service shuts
270 * down, it does a user_logoff_and_X. As we are consolidating multiple
271 * sessionsetup_and_X's onto the same vuid here, when the first service
272 * shuts down, it invalidates all the open files for the other services.
273 * Hence I am removing this code and forcing each sessionsetup_and_X
275 * Jeremy Allison. (jallison@whistle.com).
279 for(i = 0; i < num_validated_users; i++) {
280 vuser = &validated_users[i];
281 if ( vuser->uid == uid )
282 return (uint16)(i + VUID_OFFSET); /* User already validated */
286 validated_users = (user_struct *)Realloc(validated_users,
288 (num_validated_users+1));
290 if (!validated_users)
292 DEBUG(0,("Failed to realloc users struct!\n"));
293 num_validated_users = 0;
294 return UID_FIELD_INVALID;
297 vuser = &validated_users[num_validated_users];
298 num_validated_users++;
302 vuser->guest = guest;
303 fstrcpy(vuser->name,unix_name);
304 fstrcpy(vuser->requested_name,requested_name);
310 vuser->groups = NULL;
311 vuser->igroups = NULL;
314 /* Find all the groups this uid is in and store them.
315 Used by become_user() */
316 setup_groups(unix_name,uid,gid,
322 DEBUG(3,("uid %d registered to name %s\n",uid,unix_name));
324 DEBUG(3, ("Clearing default real name\n"));
325 fstrcpy(vuser->real_name, "<Full Name>\0");
326 if (lp_unix_realname()) {
327 if ((pwfile=getpwnam(vuser->name))!= NULL)
329 DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->name,pwfile->pw_gecos));
330 fstrcpy(vuser->real_name, pwfile->pw_gecos);
334 return (uint16)((num_validated_users - 1) + VUID_OFFSET);
338 /****************************************************************************
339 add a name to the session users list
340 ****************************************************************************/
341 void add_session_user(char *user)
344 StrnCpy(suser,user,sizeof(suser)-1);
346 if (!Get_Pwnam(suser,True)) return;
348 if (suser && *suser && !in_list(suser,session_users,False))
350 if (strlen(suser) + strlen(session_users) + 2 >= sizeof(pstring))
351 DEBUG(1,("Too many session users??\n"));
354 pstrcat(session_users," ");
355 pstrcat(session_users,suser);
362 /* a fake shadow password routine which just fills a fake spwd struct
363 * with the sp_pwdp field. (sreiz@aie.nl)
365 static struct spwd *getspnam(char *username) /* fake shadow password routine */
370 static struct spwd static_spwd;
372 static_spwd.sp_pwdp=0;
373 if (!(f=fopen("/etc/master.passwd", "r")))
375 while (fgets(line, 1024, f)) {
376 if (!strncmp(line, username, strlen(username)) &&
377 line[strlen(username)]==':') { /* found entry */
380 p=line+strlen(username)+1;
381 if ((q=strchr(p, ':'))) {
386 static_spwd.sp_pwdp=pw;
392 if (static_spwd.sp_pwdp)
400 /****************************************************************************
401 an enhanced crypt for OSF1
402 ****************************************************************************/
403 static char *osf1_bigcrypt(char *password,char *salt1)
405 static char result[AUTH_MAX_PASSWD_LENGTH] = "";
410 int parts = strlen(password) / AUTH_CLEARTEXT_SEG_CHARS;
411 if (strlen(password)%AUTH_CLEARTEXT_SEG_CHARS)
414 StrnCpy(salt,salt1,2);
415 StrnCpy(result,salt1,2);
417 for (i=0; i<parts;i++)
420 strncat(result,p1+2,AUTH_MAX_PASSWD_LENGTH-strlen(p1+2)-1);
421 StrnCpy(salt,&result[2+i*AUTH_CIPHERTEXT_SEG_CHARS],2);
422 p2 += AUTH_CLEARTEXT_SEG_CHARS;
429 /****************************************************************************
430 update the encrypted smbpasswd file from the plaintext username and password
431 *****************************************************************************/
432 BOOL update_smbpassword_file( char *user, fstring password)
434 struct smb_passwd *smbpw;
438 smbpw = getsmbpwnam(user);
443 DEBUG(0,("update_smbpassword_file: getsmbpwnam returned NULL\n"));
447 /* Here, the flag is one, because we want to ignore the XXXXXXX'd out password */
448 ret = change_oem_password( smbpw, password, True);
450 DEBUG(3,("update_smbpasswd_file: change_oem_password returned False\n"));
455 /****************************************************************************
456 update the enhanced security database. Only relevant for OSF1 at the moment.
457 ****************************************************************************/
458 static void update_protected_database( char *user, BOOL result)
461 struct pr_passwd *mypasswd;
464 mypasswd = getprpwnam (user);
465 starttime = time (NULL);
469 mypasswd->ufld.fd_slogin = starttime;
470 mypasswd->ufld.fd_nlogins = 0;
472 putprpwnam(user,mypasswd);
474 DEBUG(3,("Update protected database for Account %s after succesful connection\n",user));
478 mypasswd->ufld.fd_ulogin = starttime;
479 mypasswd->ufld.fd_nlogins = mypasswd->ufld.fd_nlogins + 1;
480 if ( mypasswd->ufld.fd_max_tries != 0 && mypasswd->ufld.fd_nlogins > mypasswd->ufld.fd_max_tries )
482 mypasswd->uflg.fg_lock = 0;
483 DEBUG(3,("Account is disabled -- see Account Administrator.\n"));
485 putprpwnam ( user , mypasswd );
486 DEBUG(3,("Update protected database for Account %s after refusing connection\n",user));
489 DEBUG(6,("Updated database with %s %s\n",user,BOOLSTR(result)));
495 /*******************************************************************
496 check on PAM authentication
497 ********************************************************************/
499 /* We first need some helper functions */
500 #include <security/pam_appl.h>
501 /* Static variables used to communicate between the conversation function
502 * and the server_login function
504 static char *PAM_username;
505 static char *PAM_password;
507 /* PAM conversation function
508 * Here we assume (for now, at least) that echo on means login name, and
509 * echo off means password.
511 static int PAM_conv (int num_msg,
512 const struct pam_message **msg,
513 struct pam_response **resp,
516 struct pam_response *reply = NULL;
518 #define COPY_STRING(s) (s) ? strdup(s) : NULL
520 reply = malloc(sizeof(struct pam_response) * num_msg);
521 if (!reply) return PAM_CONV_ERR;
523 for (replies = 0; replies < num_msg; replies++) {
524 switch (msg[replies]->msg_style) {
525 case PAM_PROMPT_ECHO_ON:
526 reply[replies].resp_retcode = PAM_SUCCESS;
527 reply[replies].resp = COPY_STRING(PAM_username);
530 case PAM_PROMPT_ECHO_OFF:
531 reply[replies].resp_retcode = PAM_SUCCESS;
532 reply[replies].resp = COPY_STRING(PAM_password);
539 reply[replies].resp_retcode = PAM_SUCCESS;
540 reply[replies].resp = NULL;
543 /* Must be an error of some sort... */
548 if (reply) *resp = reply;
551 static struct pam_conv PAM_conversation = {
557 static BOOL pam_auth(char *this_user,char *password)
562 /* Now use PAM to do authentication. For now, we won't worry about
563 * session logging, only authentication. Bail out if there are any
564 * errors. Since this is a limited protocol, and an even more limited
565 * function within a server speaking this protocol, we can't be as
566 * verbose as would otherwise make sense.
567 * Query: should we be using PAM_SILENT to shut PAM up?
569 #define PAM_BAIL if (pam_error != PAM_SUCCESS) { \
570 pam_end(pamh, 0); return False; \
572 PAM_password = password;
573 PAM_username = this_user;
574 pam_error = pam_start("samba", this_user, &PAM_conversation, &pamh);
576 /* Setting PAM_SILENT stops generation of error messages to syslog
577 * to enable debugging on Red Hat Linux set:
579 * auth required /lib/security/pam_pwdb.so nullok shadow audit
580 * _OR_ change PAM_SILENT to 0 to force detailed reporting (logging)
582 pam_error = pam_authenticate(pamh, PAM_SILENT);
584 /* It is not clear to me that account management is the right thing
585 * to do, but it is not clear that it isn't, either. This can be
586 * removed if no account management should be done. Alternately,
587 * put a pam_allow.so entry in /etc/pam.conf for account handling. */
588 pam_error = pam_acct_mgmt(pamh, PAM_SILENT);
590 pam_end(pamh, PAM_SUCCESS);
591 /* If this point is reached, the user has been authenticated. */
598 /*******************************************************************
599 check on AFS authentication
600 ********************************************************************/
601 static BOOL afs_auth(char *this_user,char *password)
603 long password_expires = 0;
606 /* For versions of AFS prior to 3.3, this routine has few arguments, */
607 /* but since I can't find the old documentation... :-) */
609 if (ka_UserAuthenticateGeneral(KA_USERAUTH_VERSION+KA_USERAUTH_DOSETPAG,
611 (char *) 0, /* instance */
612 (char *) 0, /* cell */
614 0, /* lifetime, default */
615 &password_expires, /*days 'til it expires */
626 sec_login_handle_t my_dce_sec_context;
627 int dcelogin_atmost_once = 0;
629 /*******************************************************************
630 check on a DCE/DFS authentication
631 ********************************************************************/
632 static BOOL dfs_auth(char *this_user,char *password)
637 boolean32 password_reset;
638 sec_passwd_rec_t my_dce_password;
639 sec_login_auth_src_t auth_src = sec_login_auth_src_network;
640 unsigned char dce_errstr[dce_c_error_string_len];
643 * We only go for a DCE login context if the given password
644 * matches that stored in the local password file..
645 * Assumes local passwd file is kept in sync w/ DCE RGY!
648 /* Fix for original (broken) code from Brett Wooldridge <brettw@austin.ibm.com> */
649 if (dcelogin_atmost_once)
651 /* This can be ifdefed as the DCE check below is stricter... */
653 if ( strcmp((char *)crypt(password,this_salt),this_crypted) )
657 if (sec_login_setup_identity(
658 (unsigned char *)this_user,
663 dce_error_inq_text(err, dce_errstr, &err2);
664 DEBUG(0,("DCE Setup Identity for %s failed: %s\n",
665 this_user,dce_errstr));
669 my_dce_password.version_number = sec_passwd_c_version_none;
670 my_dce_password.pepper = NULL;
671 my_dce_password.key.key_type = sec_passwd_plain;
672 my_dce_password.key.tagged_union.plain = (idl_char *)password;
674 if (sec_login_valid_and_cert_ident(my_dce_sec_context,
680 dce_error_inq_text(err, dce_errstr, &err2);
681 DEBUG(0,("DCE Identity Validation failed for principal %s: %s\n",
682 this_user,dce_errstr));
687 sec_login_set_context(my_dce_sec_context, &err);
688 if (err != error_status_ok )
690 dce_error_inq_text(err, dce_errstr, &err2);
691 DEBUG(0,("DCE login failed for principal %s, cant set context: %s\n",
692 this_user,dce_errstr));
693 sec_login_purge_context(my_dce_sec_context, &err);
698 DEBUG(0,("DCE login succeeded for principal %s on pid %d\n",
699 this_user, getpid()));
702 dcelogin_atmost_once = 1;
706 void dfs_unlogin(void)
710 unsigned char dce_errstr[dce_c_error_string_len];
712 sec_login_purge_context(my_dce_sec_context, &err);
713 if (err != error_status_ok )
715 dce_error_inq_text(err, dce_errstr, &err2);
716 DEBUG(0,("DCE purge login context failed for server instance %d: %s\n",
717 getpid(), dce_errstr));
724 /*******************************************************************
725 check on Kerberos authentication
726 ********************************************************************/
727 static BOOL krb5_auth(char *this_user,char *password)
729 krb5_data tgtname = {
734 krb5_context kcontext;
735 krb5_principal kprinc;
736 krb5_principal server;
739 krb5_address **addrs = (krb5_address **)0;
740 krb5_preauthtype *preauth = NULL;
741 krb5_keytab keytab = NULL;
743 krb5_ccache ccache = NULL;
747 if ( retval=krb5_init_context(&kcontext))
752 if ( retval = krb5_timeofday(kcontext, &now) )
757 if ( retval = krb5_cc_default(kcontext, &ccache) )
762 if ( retval = krb5_parse_name(kcontext, this_user, &kprinc) )
767 memset((char *)&kcreds, 0, sizeof(kcreds));
769 kcreds.client = kprinc;
771 if ((retval = krb5_build_principal_ext(kcontext, &server,
772 krb5_princ_realm(kcontext, kprinc)->length,
773 krb5_princ_realm(kcontext, kprinc)->data,
776 krb5_princ_realm(kcontext, kprinc)->length,
777 krb5_princ_realm(kcontext, kprinc)->data,
783 kcreds.server = server;
785 retval = krb5_get_in_tkt_with_password(kcontext,
802 #endif /* KRB5_AUTH */
805 /*******************************************************************
806 check on Kerberos authentication
807 ********************************************************************/
808 static BOOL krb4_auth(char *this_user,char *password)
810 char realm[REALM_SZ];
811 char tkfile[MAXPATHLEN];
813 if (krb_get_lrealm(realm, 1) != KSUCCESS)
814 (void) safe_strcpy(realm, KRB_REALM, sizeof (realm) - 1);
816 (void) slprintf(tkfile, sizeof(tkfile) - 1, "/tmp/samba_tkt_%d", getpid());
818 krb_set_tkt_string(tkfile);
819 if (krb_verify_user(this_user, "", realm,
821 "rmcd") == KSUCCESS) {
828 #endif /* KRB4_AUTH */
830 #ifdef LINUX_BIGCRYPT
831 /****************************************************************************
832 an enhanced crypt for Linux to handle password longer than 8 characters
833 ****************************************************************************/
834 static int linux_bigcrypt(char *password,char *salt1, char *crypted)
836 #define LINUX_PASSWORD_SEG_CHARS 8
840 StrnCpy(salt,salt1,2);
843 for ( i=strlen(password); i > 0; i -= LINUX_PASSWORD_SEG_CHARS) {
844 char * p = crypt(password,salt) + 2;
845 if (strncmp(p, crypted, LINUX_PASSWORD_SEG_CHARS) != 0)
847 password += LINUX_PASSWORD_SEG_CHARS;
848 crypted += strlen(p);
856 /****************************************************************************
857 apply a function to upper/lower case combinations
858 of a string and return true if one of them returns true.
859 try all combinations with N uppercase letters.
860 offset is the first char to try and change (start with 0)
861 it assumes the string starts lowercased
862 ****************************************************************************/
863 static BOOL string_combinations2(char *s,int offset,BOOL (*fn)(char *),int N)
868 #ifdef PASSWORD_LENGTH
869 len = MIN(len,PASSWORD_LENGTH);
872 if (N <= 0 || offset >= len)
875 for (i=offset;i<(len-(N-1));i++)
878 if (!islower(c)) continue;
880 if (string_combinations2(s,i+1,fn,N-1))
887 /****************************************************************************
888 apply a function to upper/lower case combinations
889 of a string and return true if one of them returns true.
890 try all combinations with up to N uppercase letters.
891 offset is the first char to try and change (start with 0)
892 it assumes the string starts lowercased
893 ****************************************************************************/
894 static BOOL string_combinations(char *s,BOOL (*fn)(char *),int N)
898 if (string_combinations2(s,0,fn,n)) return(True);
904 /****************************************************************************
905 core of password checking routine
906 ****************************************************************************/
907 BOOL password_check(char *password)
911 /* This falls through if the password check fails
912 - if NO_CRYPT is defined this causes an error msg
913 saying Warning - no crypt available
914 - if NO_CRYPT is NOT defined this is a potential security hole
915 as it may authenticate via the crypt call when PAM
916 settings say it should fail.
917 if (pam_auth(this_user,password)) return(True);
918 Hence we make a direct return to avoid a second chance!!!
920 return (pam_auth(this_user,password));
924 if (afs_auth(this_user,password)) return(True);
928 if (dfs_auth(this_user,password)) return(True);
932 if (krb5_auth(this_user,password)) return(True);
936 if (krb4_auth(this_user,password)) return(True);
940 if (pwdauth(this_user,password) == 0)
946 BOOL ret = (strcmp(osf1_bigcrypt(password,this_salt),this_crypted) == 0);
948 DEBUG(2,("password_check: OSF1_ENH_SEC failed. Trying normal crypt.\n"));
949 ret = (strcmp((char *)crypt(password,this_salt),this_crypted) == 0);
956 return (strcmp((char *)crypt16(password, this_salt ),this_crypted) == 0);
959 #ifdef LINUX_BIGCRYPT
960 return(linux_bigcrypt(password,this_salt,this_crypted));
963 #ifdef HPUX_10_TRUSTED
964 return(strcmp(bigcrypt(password,this_salt),this_crypted) == 0);
968 DEBUG(1,("Warning - no crypt available\n"));
971 return(strcmp((char *)crypt(password,this_salt),this_crypted) == 0);
975 /****************************************************************************
976 core of smb password checking routine.
977 ****************************************************************************/
978 BOOL smb_password_check(char *password, unsigned char *part_passwd, unsigned char *c8)
980 /* Finish the encryption of part_passwd. */
981 unsigned char p21[21];
982 unsigned char p24[24];
984 if (part_passwd == NULL)
985 DEBUG(10,("No password set - allowing access\n"));
986 /* No password set - always true ! */
987 if (part_passwd == NULL)
991 memcpy(p21,part_passwd,16);
996 DEBUG(100,("Part password (P16) was |"));
997 for(i = 0; i < 16; i++)
998 DEBUG(100,("%X ", (unsigned char)part_passwd[i]));
1000 DEBUG(100,("Password from client was |"));
1001 for(i = 0; i < 24; i++)
1002 DEBUG(100,("%X ", (unsigned char)password[i]));
1004 DEBUG(100,("Given challenge was |"));
1005 for(i = 0; i < 8; i++)
1006 DEBUG(100,("%X ", (unsigned char)c8[i]));
1008 DEBUG(100,("Value from encryption was |"));
1009 for(i = 0; i < 24; i++)
1010 DEBUG(100,("%X ", (unsigned char)p24[i]));
1014 return (memcmp(p24, password, 24) == 0);
1017 /****************************************************************************
1018 Do a specific test for an smb password being correct, given a smb_password and
1019 the lanman and NT responses.
1020 ****************************************************************************/
1022 BOOL smb_password_ok(struct smb_passwd *smb_pass,
1023 uchar lm_pass[24], uchar nt_pass[24])
1027 if (!lm_pass || !smb_pass) return(False);
1029 if(smb_pass->acct_ctrl & ACB_DISABLED)
1031 DEBUG(3,("smb_password_ok: account for user %s was disabled.\n", smb_pass->smb_name));
1035 if (!last_challenge(challenge))
1037 DEBUG(1,("smb_password_ok: no challenge done - password failed\n"));
1041 DEBUG(4,("smb_password_ok: Checking SMB password for user %s\n", smb_pass->smb_name));
1043 if ((Protocol >= PROTOCOL_NT1) && (smb_pass->smb_nt_passwd != NULL))
1045 /* We have the NT MD4 hash challenge available - see if we can
1046 use it (ie. does it exist in the smbpasswd file).
1048 DEBUG(4,("smb_password_ok: Checking NT MD4 password\n"));
1049 if (smb_password_check((char *)nt_pass, (uchar *)smb_pass->smb_nt_passwd, challenge))
1051 DEBUG(4,("smb_password_ok: NT MD4 password check succeeded\n"));
1054 DEBUG(4,("smb_password_ok: NT MD4 password check failed\n"));
1057 /* Try against the lanman password. smb_pass->smb_passwd == NULL means
1058 no password, allow access. */
1060 DEBUG(4,("Checking LM MD4 password\n"));
1062 if((smb_pass->smb_passwd == NULL) && (smb_pass->acct_ctrl & ACB_PWNOTREQ))
1064 DEBUG(4,("smb_password_ok: no password required for user %s\n", smb_pass->smb_name));
1068 if((smb_pass->smb_passwd != NULL) && smb_password_check((char *)lm_pass, (uchar *)smb_pass->smb_passwd, challenge))
1070 DEBUG(4,("smb_password_ok: LM MD4 password check succeeded\n"));
1074 DEBUG(4,("smb_password_ok: LM MD4 password check failed\n"));
1079 /****************************************************************************
1080 check if a username/password is OK
1081 ****************************************************************************/
1082 BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd)
1085 int level = lp_passwordlevel();
1086 struct passwd *pass;
1088 struct smb_passwd *smb_pass;
1089 BOOL update_encrypted = lp_update_encrypted();
1090 BOOL challenge_done = False;
1092 if (password) password[pwlen] = 0;
1095 challenge_done = last_challenge(challenge);
1101 DEBUG(100,("checking user=[%s] pass=[",user));
1102 for( i = 0; i < 24; i++)
1103 DEBUG(100,("%0x ", (unsigned char)password[i]));
1106 DEBUG(100,("checking user=[%s] pass=[%s]\n",user,password));
1113 if (((!*password) || (!pwlen)) && !lp_null_passwords())
1118 pass = (struct passwd *) pwd;
1119 user = pass->pw_name;
1122 pass = Get_Pwnam(user,True);
1124 DEBUG(4,("SMB Password - pwlen = %d, challenge_done = %d\n", pwlen, challenge_done));
1126 if ((pwlen == 24) && challenge_done)
1128 DEBUG(4,("Checking SMB password for user %s (l=24)\n",user));
1132 DEBUG(3,("Couldn't find user %s\n",user));
1136 smb_pass = getsmbpwnam(user);
1140 DEBUG(3,("Couldn't find user %s in smb_passwd file.\n", user));
1144 /* Quit if the account was disabled. */
1145 if(smb_pass->acct_ctrl & ACB_DISABLED)
1147 DEBUG(3,("password_ok: account for user %s was disabled.\n", user));
1151 /* Ensure the uid's match */
1152 if (smb_pass->smb_userid != pass->pw_uid)
1154 DEBUG(3,("Error : UNIX and SMB uids in password files do not match !\n"));
1158 if(smb_password_ok( smb_pass, (unsigned char *)password,(uchar *)password))
1160 update_protected_database(user,True);
1164 DEBUG(3,("Error smb_password_check failed\n"));
1167 DEBUG(4,("Checking password for user %s (l=%d)\n",user,pwlen));
1171 DEBUG(3,("Couldn't find user %s\n",user));
1179 /* many shadow systems require you to be root to get the password,
1180 in most cases this should already be the case when this
1181 function is called, except perhaps for IPC password changing
1184 spass = getspnam(pass->pw_name);
1185 if (spass && spass->sp_pwdp)
1186 pass->pw_passwd = spass->sp_pwdp;
1188 #elif defined(IA_UINFO)
1190 /* Need to get password with SVR4.2's ia_ functions instead of
1191 get{sp,pw}ent functions. Required by UnixWare 2.x, tested on
1192 version 2.1. (tangent@cyberport.com) */
1194 if (ia_openinfo(pass->pw_name, &uinfo) != -1)
1195 ia_get_logpwd(uinfo, &(pass->pw_passwd));
1201 struct pr_passwd *pr_pw = getprpwnam(pass->pw_name);
1202 if (pr_pw && pr_pw->ufld.fd_encrypt)
1203 pass->pw_passwd = pr_pw->ufld.fd_encrypt;
1207 #ifdef HPUX_10_TRUSTED
1209 struct pr_passwd *pr_pw = getprpwnam(pass->pw_name);
1210 if (pr_pw && pr_pw->ufld.fd_encrypt)
1211 pass->pw_passwd = pr_pw->ufld.fd_encrypt;
1217 struct pr_passwd *mypasswd;
1218 DEBUG(5,("Checking password for user %s in OSF1_ENH_SEC\n",user));
1219 mypasswd = getprpwnam (user);
1222 fstrcpy(pass->pw_name,mypasswd->ufld.fd_name);
1223 fstrcpy(pass->pw_passwd,mypasswd->ufld.fd_encrypt);
1227 DEBUG(5,("No entry for user %s in protected database !\n",user));
1235 AUTHORIZATION *ap = getauthuid( pass->pw_uid );
1238 fstrcpy( pass->pw_passwd, ap->a_password );
1244 /* extract relevant info */
1245 fstrcpy(this_user,pass->pw_name);
1246 fstrcpy(this_salt,pass->pw_passwd);
1248 /* The crypt on HPUX won't work with more than 2 salt characters. */
1251 fstrcpy(this_crypted,pass->pw_passwd);
1253 if (!*this_crypted) {
1254 if (!lp_null_passwords()) {
1255 DEBUG(2,("Disallowing access to %s due to null password\n",this_user));
1260 DEBUG(3,("Allowing access to %s with null password\n",this_user));
1266 /* try it as it came to us */
1267 if (password_check(password))
1269 update_protected_database(user,True);
1270 if (update_encrypted)
1271 update_smbpassword_file(user,password);
1275 /* if the password was given to us with mixed case then we don't
1276 need to proceed as we know it hasn't been case modified by the
1278 if (strhasupper(password) && strhaslower(password))
1281 /* make a copy of it */
1282 StrnCpy(pass2,password,sizeof(pstring)-1);
1284 /* try all lowercase */
1286 if (password_check(password))
1288 update_protected_database(user,True);
1289 if (update_encrypted)
1290 update_smbpassword_file(user,password);
1297 update_protected_database(user,False);
1300 fstrcpy(password,pass2);
1305 /* last chance - all combinations of up to level chars upper! */
1308 if (string_combinations(password,password_check,level))
1310 update_protected_database(user,True);
1311 if (update_encrypted)
1312 update_smbpassword_file(user,password);
1316 update_protected_database(user,False);
1319 fstrcpy(password,pass2);
1326 /****************************************************************************
1327 check if a username is valid
1328 ****************************************************************************/
1329 BOOL user_ok(char *user,int snum)
1331 pstring valid, invalid;
1334 StrnCpy(valid, lp_valid_users(snum), sizeof(pstring));
1335 StrnCpy(invalid, lp_invalid_users(snum), sizeof(pstring));
1337 string_sub(valid,"%S",lp_servicename(snum));
1338 string_sub(invalid,"%S",lp_servicename(snum));
1340 ret = !user_in_list(user,invalid);
1342 if (ret && valid && *valid)
1343 ret = user_in_list(user,valid);
1345 if (ret && lp_onlyuser(snum)) {
1346 char *user_list = lp_username(snum);
1347 string_sub(user_list,"%S",lp_servicename(snum));
1348 ret = user_in_list(user,user_list);
1357 /****************************************************************************
1358 validate a group username entry. Return the username or NULL
1359 ****************************************************************************/
1360 static char *validate_group(char *group,char *password,int pwlen,int snum)
1364 char *host, *user, *domain;
1366 while (getnetgrent(&host, &user, &domain)) {
1368 if (user_ok(user, snum) &&
1369 password_ok(user,password,pwlen,NULL)) {
1381 struct group *gptr = (struct group *)getgrnam(group);
1385 member = gptr->gr_mem;
1386 while (member && *member)
1388 static fstring name;
1389 fstrcpy(name,*member);
1390 if (user_ok(name,snum) &&
1391 password_ok(name,password,pwlen,NULL))
1395 #ifdef GROUP_CHECK_PWENT
1401 while (pwd = getpwent ()) {
1402 if (*(pwd->pw_passwd) && pwd->pw_gid == gptr->gr_gid) {
1403 /* This Entry have PASSWORD and same GID then check pwd */
1404 if (password_ok(NULL, password, pwlen, pwd)) {
1405 fstrcpy(tm, pwd->pw_name);
1413 #endif /* GROUP_CHECK_PWENT */
1422 /****************************************************************************
1423 check for authority to login to a service with a given username/password
1424 ****************************************************************************/
1425 BOOL authorise_login(int snum,char *user,char *password, int pwlen,
1426 BOOL *guest,BOOL *force,uint16 vuid)
1433 DEBUG(100,("checking authorisation on user=%s pass=%s\n",user,password));
1436 /* there are several possibilities:
1437 1) login as the given user with given password
1438 2) login as a previously registered username with the given password
1439 3) login as a session list username with the given password
1440 4) login as a previously validated user/password pair
1441 5) login as the "user =" user with given password
1442 6) login as the "user =" user with no password (guest connection)
1443 7) login as guest user with no password
1445 if the service is guest_only then steps 1 to 5 are skipped
1448 if (GUEST_ONLY(snum)) *force = True;
1450 if (!(GUEST_ONLY(snum) && GUEST_OK(snum)))
1453 user_struct *vuser = get_valid_user_struct(vuid);
1455 /* check the given username and password */
1456 if (!ok && (*user) && user_ok(user,snum)) {
1457 ok = password_ok(user,password, pwlen, NULL);
1458 if (ok) DEBUG(3,("ACCEPTED: given username password ok\n"));
1461 /* check for a previously registered guest username */
1462 if (!ok && (vuser != 0) && vuser->guest) {
1463 if (user_ok(vuser->name,snum) &&
1464 password_ok(vuser->name, password, pwlen, NULL)) {
1465 fstrcpy(user, vuser->name);
1466 vuser->guest = False;
1467 DEBUG(3,("ACCEPTED: given password with registered user %s\n", user));
1473 /* now check the list of session users */
1477 char *user_list = strdup(session_users);
1478 if (!user_list) return(False);
1480 for (auser=strtok(user_list,LIST_SEP);
1482 auser = strtok(NULL,LIST_SEP))
1485 fstrcpy(user2,auser);
1486 if (!user_ok(user2,snum)) continue;
1488 if (password_ok(user2,password, pwlen, NULL)) {
1490 fstrcpy(user,user2);
1491 DEBUG(3,("ACCEPTED: session list username and given password ok\n"));
1497 /* check for a previously validated username/password pair */
1498 if (!ok && (!lp_revalidate(snum) || lp_security() > SEC_SHARE) &&
1499 (vuser != 0) && !vuser->guest &&
1500 user_ok(vuser->name,snum)) {
1501 fstrcpy(user,vuser->name);
1503 DEBUG(3,("ACCEPTED: validated uid ok as non-guest\n"));
1507 /* check for a rhosts entry */
1508 if (!ok && user_ok(user,snum) && check_hosts_equiv(user)) {
1510 DEBUG(3,("ACCEPTED: hosts equiv or rhosts entry\n"));
1513 /* check the user= fields and the given password */
1514 if (!ok && lp_username(snum)) {
1517 StrnCpy(user_list,lp_username(snum),sizeof(pstring));
1519 string_sub(user_list,"%S",lp_servicename(snum));
1521 for (auser=strtok(user_list,LIST_SEP);
1523 auser = strtok(NULL,LIST_SEP))
1527 auser = validate_group(auser+1,password,pwlen,snum);
1531 fstrcpy(user,auser);
1532 DEBUG(3,("ACCEPTED: group username and given password ok\n"));
1538 fstrcpy(user2,auser);
1539 if (user_ok(user2,snum) &&
1540 password_ok(user2,password,pwlen,NULL))
1543 fstrcpy(user,user2);
1544 DEBUG(3,("ACCEPTED: user list username and given password ok\n"));
1549 } /* not guest only */
1551 /* check for a normal guest connection */
1552 if (!ok && GUEST_OK(snum))
1555 StrnCpy(guestname,lp_guestaccount(snum),sizeof(guestname)-1);
1556 if (Get_Pwnam(guestname,True))
1558 fstrcpy(user,guestname);
1560 DEBUG(3,("ACCEPTED: guest account and guest ok\n"));
1563 DEBUG(0,("Invalid guest account %s??\n",guestname));
1568 if (ok && !user_ok(user,snum))
1570 DEBUG(0,("rejected invalid user %s\n",user));
1578 /****************************************************************************
1579 read the a hosts.equiv or .rhosts file and check if it
1580 allows this user from this machine
1581 ****************************************************************************/
1582 static BOOL check_user_equiv(char *user, char *remote, char *equiv_file)
1585 int plus_allowed = 1;
1588 FILE *fp = fopen(equiv_file, "r");
1589 DEBUG(5, ("check_user_equiv %s %s %s\n", user, remote, equiv_file));
1590 if (! fp) return False;
1591 while(fgets(buf, sizeof(buf), fp))
1593 trim_string(buf," "," ");
1595 if (buf[0] != '#' && buf[0] != '\n')
1597 BOOL is_group = False;
1600 if (strcmp(buf, "NO_PLUS\n") == 0)
1602 DEBUG(6, ("check_user_equiv NO_PLUS\n"));
1609 if (*bp == '\n' && plus_allowed)
1611 /* a bare plus means everbody allowed */
1612 DEBUG(6, ("check_user_equiv everybody allowed\n"));
1617 else if (buf[0] == '-')
1627 file_host = strtok(bp, " \t\n");
1628 file_user = strtok(NULL, " \t\n");
1629 DEBUG(7, ("check_user_equiv %s %s\n", file_host ? file_host : "(null)",
1630 file_user ? file_user : "(null)" ));
1631 if (file_host && *file_host)
1633 BOOL host_ok = False;
1638 static char *mydomain = NULL;
1640 yp_get_default_domain(&mydomain);
1641 if (mydomain && innetgr(file_host,remote,user,mydomain))
1647 DEBUG(1,("Netgroups not configured - add -DNETGROUP and recompile\n"));
1652 /* is it this host */
1653 /* the fact that remote has come from a call of gethostbyaddr
1654 * means that it may have the fully qualified domain name
1655 * so we could look up the file version to get it into
1656 * a canonical form, but I would rather just type it
1657 * in full in the equiv file
1659 if (!host_ok && !is_group && strequal(remote, file_host))
1665 /* is it this user */
1666 if (file_user == 0 || strequal(user, file_user))
1669 DEBUG(5, ("check_user_equiv matched %s%s %s\n",
1670 (plus ? "+" : "-"), file_host,
1671 (file_user ? file_user : "")));
1672 return (plus ? True : False);
1683 /****************************************************************************
1684 check for a possible hosts equiv or rhosts entry for the user
1685 ****************************************************************************/
1686 BOOL check_hosts_equiv(char *user)
1690 struct passwd *pass = Get_Pwnam(user,True);
1695 fname = lp_hosts_equiv();
1697 /* note: don't allow hosts.equiv on root */
1698 if (fname && *fname && (pass->pw_uid != 0)) {
1700 if (check_user_equiv(user,client_name(Client),fname))
1704 if (lp_use_rhosts())
1706 char *home = get_home_dir(user);
1709 slprintf(rhostsfile, sizeof(rhostsfile)-1, "%s/.rhosts", home);
1710 if (check_user_equiv(user,client_name(Client),rhostsfile))
1719 static struct cli_state pw_cli;
1721 /****************************************************************************
1722 return the client state structure
1723 ****************************************************************************/
1724 struct cli_state *server_client(void)
1729 /****************************************************************************
1730 support for server level security
1731 ****************************************************************************/
1732 struct cli_state *server_cryptkey(void)
1735 struct in_addr dest_ip;
1736 extern fstring local_machine;
1738 BOOL connected_ok = False;
1740 if (!cli_initialise(&pw_cli))
1743 p = lp_passwordserver();
1744 while(p && next_token( &p, desthost, LIST_SEP)) {
1745 standard_sub_basic(desthost);
1748 if(!resolve_name( desthost, &dest_ip)) {
1749 DEBUG(1,("server_cryptkey: Can't resolve address for %s\n",desthost));
1753 if (ismyip(dest_ip)) {
1754 DEBUG(1,("Password server loop - disabling password server %s\n",desthost));
1758 if (cli_connect(&pw_cli, desthost, &dest_ip)) {
1759 DEBUG(3,("connected to password server %s\n",desthost));
1760 connected_ok = True;
1765 if (!connected_ok) {
1766 DEBUG(0,("password server not available\n"));
1767 cli_shutdown(&pw_cli);
1771 if (!cli_session_request(&pw_cli, desthost, 0x20, local_machine)) {
1772 DEBUG(1,("%s rejected the session\n",desthost));
1773 cli_shutdown(&pw_cli);
1777 DEBUG(3,("got session\n"));
1779 if (!cli_negprot(&pw_cli)) {
1780 DEBUG(1,("%s rejected the negprot\n",desthost));
1781 cli_shutdown(&pw_cli);
1785 if (pw_cli.protocol < PROTOCOL_LANMAN2 ||
1786 !(pw_cli.sec_mode & 1)) {
1787 DEBUG(1,("%s isn't in user level security mode\n",desthost));
1788 cli_shutdown(&pw_cli);
1792 DEBUG(3,("password server OK\n"));
1797 /****************************************************************************
1798 validate a password with the password server
1799 ****************************************************************************/
1800 BOOL server_validate(char *user, char *domain,
1801 char *pass, int passlen,
1802 char *ntpass, int ntpasslen)
1804 extern fstring local_machine;
1805 static unsigned char badpass[24];
1807 if (!pw_cli.initialised) {
1808 DEBUG(1,("password server %s is not connected\n", pw_cli.desthost));
1812 if(badpass[0] == 0) {
1813 memset(badpass, 0x1f, sizeof(badpass));
1816 if((passlen == sizeof(badpass)) && !memcmp(badpass, pass, passlen)) {
1817 /* Very unlikely, our random bad password is the same as the users
1819 memset(badpass, badpass[0]+1, sizeof(badpass));
1823 * Attempt a session setup with a totally incorrect password.
1824 * If this succeeds with the guest bit *NOT* set then the password
1825 * server is broken and is not correctly setting the guest bit. We
1826 * need to detect this as some versions of NT4.x are broken. JRA.
1829 if (cli_session_setup(&pw_cli, user, (char *)badpass, sizeof(badpass),
1830 (char *)badpass, sizeof(badpass), domain)) {
1831 if ((SVAL(pw_cli.inbuf,smb_vwv2) & 1) == 0) {
1832 DEBUG(0,("server_validate: password server %s allows users as non-guest \
1833 with a bad password.\n", pw_cli.desthost));
1834 DEBUG(0,("server_validate: This is broken (and insecure) behaviour. Please do not \
1835 use this machine as the password server.\n"));
1836 cli_ulogoff(&pw_cli);
1839 cli_ulogoff(&pw_cli);
1843 * Now we know the password server will correctly set the guest bit, or is
1844 * not guest enabled, we can try with the real password.
1847 if (!cli_session_setup(&pw_cli, user, pass, passlen, ntpass, ntpasslen, domain)) {
1848 DEBUG(1,("password server %s rejected the password\n", pw_cli.desthost));
1852 /* if logged in as guest then reject */
1853 if ((SVAL(pw_cli.inbuf,smb_vwv2) & 1) != 0) {
1854 DEBUG(1,("password server %s gave us guest only\n", pw_cli.desthost));
1855 cli_ulogoff(&pw_cli);
1860 * This patch from Rob Nielsen <ran@adc.com> makes doing
1861 * the NetWksaUserLogon a dynamic, rather than compile-time
1862 * parameter, defaulting to on. This is somewhat dangerous
1863 * as it allows people to turn off this neccessary check,
1864 * but so many people have had problems with this that I
1865 * think it is a neccessary change. JRA.
1868 if (lp_net_wksta_user_logon()) {
1869 DEBUG(3,("trying NetWkstaUserLogon with password server %s\n", pw_cli.desthost));
1871 if (!cli_send_tconX(&pw_cli, "IPC$", "IPC", "", 1)) {
1872 DEBUG(0,("password server %s refused IPC$ connect\n", pw_cli.desthost));
1873 cli_ulogoff(&pw_cli);
1877 if (!cli_NetWkstaUserLogon(&pw_cli,user,local_machine)) {
1878 DEBUG(0,("password server %s failed NetWkstaUserLogon\n", pw_cli.desthost));
1880 cli_ulogoff(&pw_cli);
1884 if (pw_cli.privilages == 0) {
1885 DEBUG(0,("password server %s gave guest privilages\n", pw_cli.desthost));
1887 cli_ulogoff(&pw_cli);
1891 if (!strequal(pw_cli.eff_name, user)) {
1892 DEBUG(0,("password server %s gave different username %s\n",
1896 cli_ulogoff(&pw_cli);
1902 DEBUG(3,("skipping NetWkstaUserLogon with password server %s\n", pw_cli.desthost));
1905 DEBUG(3,("password server %s accepted the password\n", pw_cli.desthost));
1907 cli_ulogoff(&pw_cli);
1912 /***********************************************************************
1913 Do the same as security=server, but using NT Domain calls and a session
1914 key from the machine password.
1915 ************************************************************************/
1917 BOOL domain_client_validate( char *user, char *domain,
1918 char *smb_apasswd, int smb_apasslen,
1919 char *smb_ntpasswd, int smb_ntpasslen)
1921 unsigned char local_challenge[8];
1922 unsigned char local_lm_response[24];
1923 unsigned char local_nt_reponse[24];
1924 unsigned char trust_passwd[16];
1926 fstring remote_machine;
1928 struct in_addr dest_ip;
1929 NET_ID_INFO_CTR ctr;
1930 NET_USER_INFO_3 info3;
1931 struct cli_state cli;
1933 BOOL connected_ok = False;
1936 * Check that the requested domain is not our own machine name.
1937 * If it is, we should never check the PDC here, we use our own local
1941 if(strequal( domain, global_myname)) {
1942 DEBUG(3,("domain_client_validate: Requested domain was for this machine.\n"));
1947 * Next, check that the passwords given were encrypted.
1950 if(smb_apasslen != 24 || smb_ntpasslen != 24) {
1953 * Not encrypted - do so.
1956 DEBUG(3,("domain_client_validate: User passwords not in encrypted format.\n"));
1957 generate_random_buffer( local_challenge, 8, False);
1958 SMBencrypt( (uchar *)smb_apasswd, local_challenge, local_lm_response);
1959 SMBNTencrypt((uchar *)smb_ntpasswd, local_challenge, local_nt_reponse);
1962 smb_apasswd = (char *)local_lm_response;
1963 smb_ntpasswd = (char *)local_nt_reponse;
1967 * Encrypted - get the challenge we sent for these
1971 if (!last_challenge(local_challenge)) {
1972 DEBUG(0,("domain_client_validate: no challenge done - password failed\n"));
1978 * Get the machine account password.
1980 if(!trust_password_lock( global_myworkgroup, global_myname, False)) {
1981 DEBUG(0,("domain_client_validate: unable to open the machine account password file for \
1982 machine %s in domain %s.\n", global_myname, global_myworkgroup ));
1986 if(get_trust_account_password( trust_passwd, &lct) == False) {
1987 DEBUG(0,("domain_client_validate: unable to read the machine account password for \
1988 machine %s in domain %s.\n", global_myname, global_myworkgroup ));
1989 trust_password_unlock();
1993 trust_password_unlock();
1996 * Here we should check the last change time to see if the machine
1997 * password needs changing..... TODO... JRA.
2000 if(time(NULL) > lct + lp_machine_password_timeout())
2001 global_machine_pasword_needs_changing = True;
2004 * At this point, smb_apasswd points to the lanman response to
2005 * the challenge in local_challenge, and smb_ntpasswd points to
2006 * the NT response to the challenge in local_challenge. Ship
2007 * these over the secure channel to a domain controller and
2008 * see if they were valid.
2011 memset(&cli, '\0', sizeof(struct cli_state));
2012 if(cli_initialise(&cli) == False) {
2013 DEBUG(0,("domain_client_validate: unable to initialize client connection.\n"));
2018 * Treat each name in the 'password server =' line as a potential
2019 * PDC/BDC. Contact each in turn and try and authenticate.
2022 p = lp_passwordserver();
2023 while(p && next_token( &p, remote_machine, LIST_SEP)) {
2025 standard_sub_basic(remote_machine);
2026 strupper(remote_machine);
2028 if(!resolve_name( remote_machine, &dest_ip)) {
2029 DEBUG(1,("domain_client_validate: Can't resolve address for %s\n", remote_machine));
2033 if (ismyip(dest_ip)) {
2034 DEBUG(1,("domain_client_validate: Password server loop - not using password server %s\n",remote_machine));
2038 if (!cli_connect(&cli, remote_machine, &dest_ip)) {
2039 DEBUG(0,("domain_client_validate: unable to connect to SMB server on \
2040 machine %s. Error was : %s.\n", remote_machine, cli_errstr(&cli) ));
2044 if (!cli_session_request(&cli, remote_machine, 0x20, global_myname)) {
2045 DEBUG(0,("domain_client_validate: machine %s rejected the session setup. \
2046 Error was : %s.\n", remote_machine, cli_errstr(&cli) ));
2051 cli.protocol = PROTOCOL_NT1;
2053 if (!cli_negprot(&cli)) {
2054 DEBUG(0,("domain_client_validate: machine %s rejected the negotiate protocol. \
2055 Error was : %s.\n", remote_machine, cli_errstr(&cli) ));
2060 if (cli.protocol != PROTOCOL_NT1) {
2061 DEBUG(0,("domain_client_validate: machine %s didn't negotiate NT protocol.\n",
2068 * Do an anonymous session setup.
2071 if (!cli_session_setup(&cli, "", "", 0, "", 0, "")) {
2072 DEBUG(0,("domain_client_validate: machine %s rejected the session setup. \
2073 Error was : %s.\n", remote_machine, cli_errstr(&cli) ));
2078 if (!(cli.sec_mode & 1)) {
2079 DEBUG(1,("domain_client_validate: machine %s isn't in user level security mode\n",
2085 if (!cli_send_tconX(&cli, "IPC$", "IPC", "", 1)) {
2086 DEBUG(0,("domain_client_validate: machine %s rejected the tconX on the IPC$ share. \
2087 Error was : %s.\n", remote_machine, cli_errstr(&cli) ));
2093 * We have an anonymous connection to IPC$.
2095 connected_ok = True;
2099 if (!connected_ok) {
2100 DEBUG(0,("domain_client_validate: Domain password server not available.\n"));
2106 * Ok - we have an anonymous connection to the IPC$ share.
2107 * Now start the NT Domain stuff :-).
2110 if(cli_nt_session_open(&cli, PIPE_NETLOGON, False) == False) {
2111 DEBUG(0,("domain_client_validate: unable to open the domain client session to \
2112 machine %s. Error was : %s.\n", remote_machine, cli_errstr(&cli)));
2113 cli_nt_session_close(&cli);
2119 if(cli_nt_setup_creds(&cli, trust_passwd) == False) {
2120 DEBUG(0,("domain_client_validate: unable to setup the PDC credentials to machine \
2121 %s. Error was : %s.\n", remote_machine, cli_errstr(&cli)));
2122 cli_nt_session_close(&cli);
2128 /* We really don't care what LUID we give the user. */
2129 generate_random_buffer( (unsigned char *)&smb_uid_low, 4, False);
2131 if(cli_nt_login_network(&cli, domain, user, smb_uid_low, (char *)local_challenge,
2132 smb_apasswd, smb_ntpasswd, &ctr, &info3) == False) {
2133 DEBUG(0,("domain_client_validate: unable to validate password for user %s in domain \
2134 %s to Domain controller %s. Error was %s.\n", user, domain, remote_machine, cli_errstr(&cli)));
2135 cli_nt_session_close(&cli);
2142 * Here, if we really want it, we have lots of info about the user in info3.
2147 * We don't actually need to do this - plus it fails currently with
2148 * NT_STATUS_INVALID_INFO_CLASS - we need to know *exactly* what to
2152 if(cli_nt_logoff(&cli, &ctr) == False) {
2153 DEBUG(0,("domain_client_validate: unable to log off user %s in domain \
2154 %s to Domain controller %s. Error was %s.\n", user, domain, remote_machine, cli_errstr(&cli)));
2155 cli_nt_session_close(&cli);
2162 cli_nt_session_close(&cli);