diff options
Diffstat (limited to 'source/smbd/password.c')
-rw-r--r-- | source/smbd/password.c | 745 |
1 files changed, 473 insertions, 272 deletions
diff --git a/source/smbd/password.c b/source/smbd/password.c index 87c1fef94c5..24ee52ed692 100644 --- a/source/smbd/password.c +++ b/source/smbd/password.c @@ -2,7 +2,7 @@ Unix SMB/Netbios implementation. Version 1.9. Password and authentication handling - Copyright (C) Andrew Tridgell 1992-1995 + Copyright (C) Andrew Tridgell 1992-1997 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,7 +20,10 @@ */ #include "includes.h" -#include "loadparm.h" + +#if (defined(NETGROUP) && defined (AUTOMOUNT)) +#include "rpcsvc/ypclnt.h" +#endif extern int DEBUGLEVEL; extern int Protocol; @@ -33,7 +36,6 @@ static char this_user[100]=""; static char this_salt[100]=""; static char this_crypted[100]=""; -#ifdef SMB_PASSWD /* Data to do lanman1/2 password challenge. */ static unsigned char saved_challenge[8]; static BOOL challenge_sent=False; @@ -43,18 +45,24 @@ Get the next challenge value - no repeats. ********************************************************************/ void generate_next_challenge(char *challenge) { - extern void E1(char *,char *,char *); - static int counter = 0; - struct timeval tval; - int v1,v2; - GetTimeOfDay(&tval); - v1 = (counter++) + getpid() + tval.tv_sec; - v2 = (counter++) * getpid() + tval.tv_usec; - SIVAL(challenge,0,v1); - SIVAL(challenge,4,v2); - E1(challenge,"SAMBA",saved_challenge); - memcpy(challenge,saved_challenge,8); - challenge_sent = True; + unsigned char buf[16]; + static int counter = 0; + struct timeval tval; + int v1,v2; + + /* get a sort-of random number */ + GetTimeOfDay(&tval); + v1 = (counter++) + getpid() + tval.tv_sec; + v2 = (counter++) * getpid() + tval.tv_usec; + SIVAL(challenge,0,v1); + SIVAL(challenge,4,v2); + + /* mash it up with md4 */ + mdfour(buf, (unsigned char *)challenge, 8); + + memcpy(saved_challenge, buf, 8); + memcpy(challenge,buf,8); + challenge_sent = True; } /******************************************************************* @@ -76,38 +84,23 @@ BOOL last_challenge(char *challenge) memcpy(challenge,saved_challenge,8); return(True); } -#endif /* this holds info on user ids that are already validated for this VC */ static user_struct *validated_users = NULL; static int num_validated_users = 0; /**************************************************************************** -check if a uid has been validated, and return an index if it has. -1 if not -****************************************************************************/ -int valid_uid(int uid) -{ - int i; - if (uid == -1) return(-1); - - for (i=0;i<num_validated_users;i++) - if (validated_users[i].uid == uid) - { - DEBUG(3,("valid uid %d mapped to vuid %d (user=%s)\n", - uid,i,validated_users[i].name)); - return(i); - } - return(-1); -} - -/**************************************************************************** check if a uid has been validated, and return an pointer to the user_struct -if it has. NULL if not +if it has. NULL if not. vuid is biased by an offset. This allows us to +tell random client vuid's (normally zero) from valid vuids. ****************************************************************************/ -user_struct *get_valid_user_struct(int uid) +user_struct *get_valid_user_struct(uint16 vuid) { - int vuid = valid_uid(uid); - if(vuid == -1 || validated_users[vuid].guest) + if (vuid == UID_FIELD_INVALID) + return NULL; + vuid -= VUID_OFFSET; + if ((vuid >= (uint16)num_validated_users) || + (validated_users[vuid].uid == -1) || (validated_users[vuid].gid == -1)) return NULL; return &validated_users[vuid]; } @@ -115,75 +108,124 @@ user_struct *get_valid_user_struct(int uid) /**************************************************************************** invalidate a uid ****************************************************************************/ -void invalidate_uid(int uid) +void invalidate_vuid(uint16 vuid) { - int i; - for (i=0;i<num_validated_users;i++) - if (validated_users[i].uid == uid) - { - user_struct *vuser = &validated_users[i]; - vuser->uid = -1; - vuser->gid = -1; - vuser->user_ngroups = 0; - if(vuser->user_groups && - (vuser->user_groups != (gid_t *)vuser->user_igroups)) - free(vuser->user_groups); - vuser->user_groups = NULL; - if(vuser->user_igroups) - free(vuser->user_igroups); - vuser->user_igroups = NULL; - } + user_struct *vuser = get_valid_user_struct(vuid); + + if (vuser == NULL) return; + + vuser->uid = -1; + vuser->gid = -1; + + vuser->n_sids = 0; + + /* same number of igroups as groups as attrs */ + vuser->n_groups = 0; + + if (vuser->groups && (vuser->groups != (gid_t *)vuser->igroups)) + free(vuser->groups); + + if (vuser->igroups) free(vuser->igroups); + if (vuser->attrs ) free(vuser->attrs); + if (vuser->sids ) free(vuser->sids); + + vuser->attrs = NULL; + vuser->sids = NULL; + vuser->igroups = NULL; + vuser->groups = NULL; } /**************************************************************************** return a validated username ****************************************************************************/ -char *validated_username(int vuid) +char *validated_username(uint16 vuid) { - return(validated_users[vuid].name); + user_struct *vuser = get_valid_user_struct(vuid); + if (vuser == NULL) + return 0; + return(vuser->name); } /**************************************************************************** register a uid/name pair as being valid and that a valid password -has been given. +has been given. vuid is biased by an offset. This allows us to +tell random client vuid's (normally zero) from valid vuids. ****************************************************************************/ -void register_uid(int uid,int gid, char *name,BOOL guest) +uint16 register_vuid(int uid,int gid, char *name,BOOL guest) { user_struct *vuser; + struct passwd *pwfile; /* for getting real name from passwd file */ - if (valid_uid(uid) >= 0) - return; - validated_users = (user_struct *)Realloc(validated_users, - sizeof(user_struct)* - (num_validated_users+1)); +#if 0 + /* + * After observing MS-Exchange services writing to a Samba share + * I belive this code is incorrect. Each service does its own + * sessionsetup_and_X for the same user, and as each service shuts + * down, it does a user_logoff_and_X. As we are consolidating multiple + * sessionsetup_and_X's onto the same vuid here, when the first service + * shuts down, it invalidates all the open files for the other services. + * Hence I am removing this code and forcing each sessionsetup_and_X + * to get a new vuid. + * Jeremy Allison. (jallison@whistle.com). + */ + + int i; + for(i = 0; i < num_validated_users; i++) { + vuser = &validated_users[i]; + if ( vuser->uid == uid ) + return (uint16)(i + VUID_OFFSET); /* User already validated */ + } +#endif + validated_users = (user_struct *)Realloc(validated_users, + sizeof(user_struct)* + (num_validated_users+1)); + if (!validated_users) { DEBUG(0,("Failed to realloc users struct!\n")); - return; + num_validated_users = 0; + return UID_FIELD_INVALID; } vuser = &validated_users[num_validated_users]; + num_validated_users++; + vuser->uid = uid; vuser->gid = gid; vuser->guest = guest; strcpy(vuser->name,name); - vuser->user_ngroups = 0; - vuser->user_groups = NULL; - vuser->user_igroups = NULL; + vuser->n_sids = 0; + vuser->sids = NULL; + + vuser->n_groups = 0; + vuser->groups = NULL; + vuser->igroups = NULL; + vuser->attrs = NULL; /* Find all the groups this uid is in and store them. Used by become_user() */ setup_groups(name,uid,gid, - &vuser->user_ngroups, - &vuser->user_igroups, - &vuser->user_groups); + &vuser->n_groups, + &vuser->igroups, + &vuser->groups, + &vuser->attrs); DEBUG(3,("uid %d registered to name %s\n",uid,name)); - - num_validated_users++; + + DEBUG(3, ("Clearing default real name\n")); + fstrcpy(vuser->real_name, "<Full Name>\0"); + if (lp_unix_realname()) { + if ((pwfile=getpwnam(vuser->name))!= NULL) + { + DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->name,pwfile->pw_gecos)); + fstrcpy(vuser->real_name, pwfile->pw_gecos); + } + } + + return (uint16)((num_validated_users - 1) + VUID_OFFSET); } @@ -287,15 +329,13 @@ static void update_protected_database( char *user, BOOL result) #ifdef OSF1_ENH_SEC struct pr_passwd *mypasswd; time_t starttime; - long tz; mypasswd = getprpwnam (user); starttime = time (NULL); - tz = mktime ( localtime ( &starttime ) ); if (result) { - mypasswd->ufld.fd_slogin = tz; + mypasswd->ufld.fd_slogin = starttime; mypasswd->ufld.fd_nlogins = 0; putprpwnam(user,mypasswd); @@ -304,7 +344,7 @@ static void update_protected_database( char *user, BOOL result) } else { - mypasswd->ufld.fd_ulogin = tz; + mypasswd->ufld.fd_ulogin = starttime; mypasswd->ufld.fd_nlogins = mypasswd->ufld.fd_nlogins + 1; if ( mypasswd->ufld.fd_max_tries != 0 && mypasswd->ufld.fd_nlogins > mypasswd->ufld.fd_max_tries ) { @@ -320,6 +360,103 @@ static void update_protected_database( char *user, BOOL result) } +#ifdef USE_PAM +/******************************************************************* +check on PAM authentication +********************************************************************/ + +/* We first need some helper functions */ +#include <security/pam_appl.h> +/* Static variables used to communicate between the conversation function + * and the server_login function + */ +static char *PAM_username; +static char *PAM_password; + +/* PAM conversation function + * Here we assume (for now, at least) that echo on means login name, and + * echo off means password. + */ +static int PAM_conv (int num_msg, + struct pam_message **msg, + struct pam_response **resp, + void *appdata_ptr) { + int replies = 0; + struct pam_response *reply = NULL; + + #define COPY_STRING(s) (s) ? strdup(s) : NULL + + reply = malloc(sizeof(struct pam_response) * num_msg); + if (!reply) return PAM_CONV_ERR; + + for (replies = 0; replies < num_msg; replies++) { + switch (msg[replies]->msg_style) { + case PAM_PROMPT_ECHO_ON: + reply[replies].resp_retcode = PAM_SUCCESS; + reply[replies].resp = COPY_STRING(PAM_username); + /* PAM frees resp */ + break; + case PAM_PROMPT_ECHO_OFF: + reply[replies].resp_retcode = PAM_SUCCESS; + reply[replies].resp = COPY_STRING(PAM_password); + /* PAM frees resp */ + break; + case PAM_TEXT_INFO: + /* fall through */ + case PAM_ERROR_MSG: + /* ignore it... */ + reply[replies].resp_retcode = PAM_SUCCESS; + reply[replies].resp = NULL; + break; + default: + /* Must be an error of some sort... */ + free (reply); + return PAM_CONV_ERR; + } + } + if (reply) *resp = reply; + return PAM_SUCCESS; +} +static struct pam_conv PAM_conversation = { + &PAM_conv, + NULL +}; + + +static BOOL pam_auth(char *this_user,char *password) +{ + pam_handle_t *pamh; + int pam_error; + + /* Now use PAM to do authentication. For now, we won't worry about + * session logging, only authentication. Bail out if there are any + * errors. Since this is a limited protocol, and an even more limited + * function within a server speaking this protocol, we can't be as + * verbose as would otherwise make sense. + * Query: should we be using PAM_SILENT to shut PAM up? + */ + #define PAM_BAIL if (pam_error != PAM_SUCCESS) { \ + pam_end(pamh, 0); return False; \ + } + PAM_password = password; + PAM_username = this_user; + pam_error = pam_start("samba", this_user, &PAM_conversation, &pamh); + PAM_BAIL; + pam_error = pam_authenticate(pamh, 0); + PAM_BAIL; + /* It is not clear to me that account management is the right thing + * to do, but it is not clear that it isn't, either. This can be + * removed if no account management should be done. Alternately, + * put a pam_allow.so entry in /etc/pam.conf for account handling. */ + pam_error = pam_acct_mgmt(pamh, 0); + PAM_BAIL; + pam_end(pamh, PAM_SUCCESS); + /* If this point is reached, the user has been authenticated. */ + return(True); +} +#endif + + #ifdef AFS_AUTH /******************************************************************* check on AFS authentication @@ -441,6 +578,86 @@ void dfs_unlogin(void) #endif +#ifdef KRB5_AUTH +/******************************************************************* +check on Kerberos authentication +********************************************************************/ +static BOOL krb5_auth(char *this_user,char *password) +{ + krb5_data tgtname = { + 0, + KRB5_TGS_NAME_SIZE, + KRB5_TGS_NAME + }; + krb5_context kcontext; + krb5_principal kprinc; + krb5_principal server; + krb5_creds kcreds; + int options = 0; + krb5_address **addrs = (krb5_address **)0; + krb5_preauthtype *preauth = NULL; + krb5_keytab keytab = NULL; + krb5_timestamp now; + krb5_ccache ccache = NULL; + int retval; + char *name; + + if ( retval=krb5_init_context(&kcontext)) + { + return(False); + } + + if ( retval = krb5_timeofday(kcontext, &now) ) + { + return(False); + } + + if ( retval = krb5_cc_default(kcontext, &ccache) ) + { + return(False); + } + + if ( retval = krb5_parse_name(kcontext, this_user, &kprinc) ) + { + return(False); + } + + memset((char *)&kcreds, 0, sizeof(kcreds)); + + kcreds.client = kprinc; + + if ((retval = krb5_build_principal_ext(kcontext, &server, + krb5_princ_realm(kcontext, kprinc)->length, + krb5_princ_realm(kcontext, kprinc)->data, + tgtname.length, + tgtname.data, + krb5_princ_realm(kcontext, kprinc)->length, + krb5_princ_realm(kcontext, kprinc)->data, + 0))) + { + return(False); + } + + kcreds.server = server; + + retval = krb5_get_in_tkt_with_password(kcontext, + options, + addrs, + NULL, + preauth, + password, + 0, + &kcreds, + 0); + + if ( retval ) + { + return(False); + } + + return(True); +} +#endif /* KRB5_AUTH */ #ifdef LINUX_BIGCRYPT /**************************************************************************** @@ -457,7 +674,7 @@ static int linux_bigcrypt(char *password,char *salt1, char *crypted) for ( i=strlen(password); i > 0; i -= LINUX_PASSWORD_SEG_CHARS) { char * p = crypt(password,salt) + 2; - if(strncmp(p, crypted, LINUX_PASSWORD_SEG_CHARS) != 0) + if (strncmp(p, crypted, LINUX_PASSWORD_SEG_CHARS) != 0) return(0); password += LINUX_PASSWORD_SEG_CHARS; crypted += strlen(p); @@ -521,6 +738,20 @@ core of password checking routine ****************************************************************************/ BOOL password_check(char *password) { + +#ifdef USE_PAM +/* This falls through if the password check fails + - if NO_CRYPT is defined this causes an error msg + saying Warning - no crypt available + - if NO_CRYPT is NOT defined this is a potential security hole + as it may authenticate via the crypt call when PAM + settings say it should fail. + if (pam_auth(this_user,password)) return(True); +Hence we make a direct return to avoid a second chance!!! +*/ + return (pam_auth(this_user,password)); +#endif + #ifdef AFS_AUTH if (afs_auth(this_user,password)) return(True); #endif @@ -529,6 +760,10 @@ BOOL password_check(char *password) if (dfs_auth(this_user,password)) return(True); #endif +#ifdef KRB5_AUTH + if (krb5_auth(this_user,password)) return(True); +#endif + #ifdef PWDAUTH if (pwdauth(this_user,password) == 0) return(True); @@ -554,7 +789,6 @@ BOOL password_check(char *password) #endif } -#ifdef SMB_PASSWD /**************************************************************************** core of smb password checking routine. ****************************************************************************/ @@ -564,10 +798,10 @@ BOOL smb_password_check(char *password, unsigned char *part_passwd, unsigned cha unsigned char p21[21]; unsigned char p24[24]; - if(part_passwd == NULL) + if (part_passwd == NULL) DEBUG(10,("No password set - allowing access\n")); /* No password set - always true ! */ - if(part_passwd == NULL) + if (part_passwd == NULL) return 1; memset(p21,'\0',21); @@ -596,31 +830,25 @@ BOOL smb_password_check(char *password, unsigned char *part_passwd, unsigned cha #endif return (memcmp(p24, password, 24) == 0); } -#endif /**************************************************************************** check if a username/password is OK ****************************************************************************/ -BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd, BOOL is_nt_password) +BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) { pstring pass2; int level = lp_passwordlevel(); struct passwd *pass; -#ifdef SMB_PASSWD char challenge[8]; struct smb_passwd *smb_pass; BOOL challenge_done = False; -#endif if (password) password[pwlen] = 0; -#ifdef SMB_PASSWD if (pwlen == 24) challenge_done = last_challenge(challenge); -#endif #if DEBUG_PASSWORD -#ifdef SMB_PASSWD if (challenge_done) { int i; @@ -628,10 +856,9 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd, BOOL for( i = 0; i < 24; i++) DEBUG(100,("%0x ", (unsigned char)password[i])); DEBUG(100,("]\n")); + } else { + DEBUG(100,("checking user=[%s] pass=[%s]\n",user,password)); } - else -#endif - DEBUG(100,("checking user=[%s] pass=[%s]\n",user,password)); #endif if (!password) @@ -648,11 +875,9 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd, BOOL else pass = Get_Pwnam(user,True); -#ifdef SMB_PASSWD - DEBUG(4,("SMB Password - pwlen = %d, challenge_done = %d\n", pwlen, challenge_done)); - if((pwlen == 24) && challenge_done) + if ((pwlen == 24) && challenge_done) { DEBUG(4,("Checking SMB password for user %s (l=24)\n",user)); @@ -663,48 +888,49 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd, BOOL } smb_pass = get_smbpwnam(user); - if(!smb_pass) + if (!smb_pass) { DEBUG(3,("Couldn't find user %s in smb_passwd file.\n", user)); return(False); } /* Ensure the uid's match */ - if(smb_pass->smb_userid != pass->pw_uid) + if (smb_pass->smb_userid != pass->pw_uid) { DEBUG(3,("Error : UNIX and SMB uids in password files do not match !\n")); return(False); } - if(Protocol >= PROTOCOL_NT1 && is_nt_password) + if (Protocol >= PROTOCOL_NT1) { /* We have the NT MD4 hash challenge available - see if we can use it (ie. does it exist in the smbpasswd file). */ - if(smb_pass->smb_nt_passwd != NULL) + if (smb_pass->smb_nt_passwd != NULL) { DEBUG(4,("Checking NT MD4 password\n")); - if(smb_password_check(password, smb_pass->smb_nt_passwd, challenge)) + if (smb_password_check(password, + smb_pass->smb_nt_passwd, + (unsigned char *)challenge)) { update_protected_database(user,True); return(True); } DEBUG(4,("NT MD4 password check failed\n")); - return (False); } } /* Try against the lanman password */ - if(smb_password_check(password, smb_pass->smb_passwd, challenge)) - { - update_protected_database(user,True); - return(True); - } + if (smb_password_check(password, + smb_pass->smb_passwd, + (unsigned char *)challenge)) { + update_protected_database(user,True); + return(True); + } DEBUG(3,("Error smb_password_check failed\n")); } -#endif DEBUG(4,("Checking password for user %s (l=%d)\n",user,pwlen)); @@ -727,6 +953,15 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd, BOOL if (spass && spass->sp_pwdp) pass->pw_passwd = spass->sp_pwdp; } +#elif defined(IA_UINFO) + { + /* Need to get password with SVR4.2's ia_ functions instead of + get{sp,pw}ent functions. Required by UnixWare 2.x, tested on + version 2.1. (tangent@cyberport.com) */ + uinfo_t uinfo; + if (ia_openinfo(pass->pw_name, &uinfo) != -1) + ia_get_logpwd(uinfo, &(pass->pw_passwd)); + } #endif #ifdef SecureWare @@ -777,6 +1012,7 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd, BOOL /* extract relevant info */ strcpy(this_user,pass->pw_name); strcpy(this_salt,pass->pw_passwd); + this_salt[2] = 0; strcpy(this_crypted,pass->pw_passwd); if (!*this_crypted) { @@ -817,7 +1053,7 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd, BOOL } /* give up? */ - if(level < 1) + if (level < 1) { update_protected_database(user,False); @@ -889,7 +1125,7 @@ static char *validate_group(char *group,char *password,int pwlen,int snum) while (getnetgrent(&host, &user, &domain)) { if (user) { if (user_ok(user, snum) && - password_ok(user,password,pwlen,NULL,False)) { + password_ok(user,password,pwlen,NULL)) { endnetgrent(); return(user); } @@ -911,7 +1147,7 @@ static char *validate_group(char *group,char *password,int pwlen,int snum) static fstring name; strcpy(name,*member); if (user_ok(name,snum) && - password_ok(name,password,pwlen,NULL,False)) + password_ok(name,password,pwlen,NULL)) return(&name[0]); member++; } @@ -924,7 +1160,7 @@ static char *validate_group(char *group,char *password,int pwlen,int snum) while (pwd = getpwent ()) { if (*(pwd->pw_passwd) && pwd->pw_gid == gptr->gr_gid) { /* This Entry have PASSWORD and same GID then check pwd */ - if (password_ok(NULL, password, pwlen, pwd,False)) { + if (password_ok(NULL, password, pwlen, pwd)) { strcpy(tm, pwd->pw_name); endpwent (); return tm; @@ -946,7 +1182,7 @@ static char *validate_group(char *group,char *password,int pwlen,int snum) check for authority to login to a service with a given username/password ****************************************************************************/ BOOL authorise_login(int snum,char *user,char *password, int pwlen, - BOOL *guest,BOOL *force,int vuid) + BOOL *guest,BOOL *force,uint16 vuid) { BOOL ok = False; @@ -956,7 +1192,7 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, DEBUG(100,("checking authorisation on user=%s pass=%s\n",user,password)); #endif - /* there are several possabilities: + /* there are several possibilities: 1) login as the given user with given password 2) login as a previously registered username with the given password 3) login as a session list username with the given password @@ -973,18 +1209,20 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, if (!(GUEST_ONLY(snum) && GUEST_OK(snum))) { + user_struct *vuser = get_valid_user_struct(vuid); + /* check the given username and password */ if (!ok && (*user) && user_ok(user,snum)) { - ok = password_ok(user,password, pwlen, NULL, False); + ok = password_ok(user,password, pwlen, NULL); if (ok) DEBUG(3,("ACCEPTED: given username password ok\n")); } /* check for a previously registered guest username */ - if (!ok && (vuid >= 0) && validated_users[vuid].guest) { - if (user_ok(validated_users[vuid].name,snum) && - password_ok(validated_users[vuid].name, password, pwlen, NULL, False)) { - strcpy(user, validated_users[vuid].name); - validated_users[vuid].guest = False; + if (!ok && (vuser != 0) && vuser->guest) { + if (user_ok(vuser->name,snum) && + password_ok(vuser->name, password, pwlen, NULL)) { + strcpy(user, vuser->name); + vuser->guest = False; DEBUG(3,("ACCEPTED: given password with registered user %s\n", user)); ok = True; } @@ -1006,7 +1244,7 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, strcpy(user2,auser); if (!user_ok(user2,snum)) continue; - if (password_ok(user2,password, pwlen, NULL, False)) { + if (password_ok(user2,password, pwlen, NULL)) { ok = True; strcpy(user,user2); DEBUG(3,("ACCEPTED: session list username and given password ok\n")); @@ -1017,9 +1255,9 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, /* check for a previously validated username/password pair */ if (!ok && !lp_revalidate(snum) && - (vuid >= 0) && !validated_users[vuid].guest && - user_ok(validated_users[vuid].name,snum)) { - strcpy(user,validated_users[vuid].name); + (vuser != 0) && !vuser->guest && + user_ok(vuser->name,snum)) { + strcpy(user,vuser->name); *guest = False; DEBUG(3,("ACCEPTED: validated uid ok as non-guest\n")); ok = True; @@ -1058,7 +1296,7 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, fstring user2; strcpy(user2,auser); if (user_ok(user2,snum) && - password_ok(user2,password,pwlen,NULL, False)) + password_ok(user2,password,pwlen,NULL)) { ok = True; strcpy(user,user2); @@ -1147,19 +1385,19 @@ static BOOL check_user_equiv(char *user, char *remote, char *equiv_file) } file_host = strtok(bp, " \t\n"); file_user = strtok(NULL, " \t\n"); - DEBUG(7, ("check_user_equiv %s %s\n", file_host, file_user)); + DEBUG(7, ("check_user_equiv %s %s\n", file_host ? file_host : "(null)", + file_user ? file_user : "(null)" )); if (file_host && *file_host) { BOOL host_ok = False; #ifdef NETGROUP - /* THIS IS UNTESTED!! */ if (is_group) { static char *mydomain = NULL; if (!mydomain) yp_get_default_domain(&mydomain); - if (mydomain && innetgr(remote,file_host,user,mydomain)) + if (mydomain && innetgr(file_host,remote,user,mydomain)) host_ok = True; } #else @@ -1210,20 +1448,15 @@ BOOL check_hosts_equiv(char *user) pstring rhostsfile; struct passwd *pass = Get_Pwnam(user,True); - extern struct from_host Client_info; - extern int Client; - if (!pass) return(False); - fromhost(Client,&Client_info); - fname = lp_hosts_equiv(); /* note: don't allow hosts.equiv on root */ if (fname && *fname && (pass->pw_uid != 0)) { - if (check_user_equiv(user,Client_info.name,fname)) + if (check_user_equiv(user,client_name(),fname)) return(True); } @@ -1233,7 +1466,7 @@ BOOL check_hosts_equiv(char *user) if (home) { sprintf(rhostsfile, "%s/.rhosts", home); - if (check_user_equiv(user,Client_info.name,rhostsfile)) + if (check_user_equiv(user,client_name(),rhostsfile)) return(True); } } @@ -1242,175 +1475,143 @@ BOOL check_hosts_equiv(char *user) } -static int password_client = -1; -static fstring pserver; +static struct cli_state cli; /**************************************************************************** -attempted support for server level security +return the client state structure ****************************************************************************/ -BOOL server_cryptkey(char *buf) +struct cli_state *server_client(void) { - pstring inbuf,outbuf; - fstring pass_protocol; - extern fstring remote_machine; - char *p; - int len; - fstring desthost; - struct in_addr dest_ip; - extern struct in_addr myip; - int port = 139; - BOOL ret; - - if (password_client >= 0) - close(password_client); - password_client = -1; - - if (Protocol < PROTOCOL_NT1) { - strcpy(pass_protocol,"LM1.2X002"); - } else { - strcpy(pass_protocol,"NT LM 0.12"); - } - - bzero(inbuf,sizeof(inbuf)); - bzero(outbuf,sizeof(outbuf)); - - for (p=strtok(lp_passwordserver(),LIST_SEP); p ; p = strtok(NULL,LIST_SEP)) { - strcpy(desthost,p); - standard_sub_basic(desthost); - strupper(desthost); - - dest_ip = *interpret_addr2(desthost); - if (zero_ip(dest_ip)) { - DEBUG(1,("Can't resolve address for %s\n",p)); - continue; - } - - if (memcmp(&dest_ip,&myip,sizeof(dest_ip)) == 0) { - DEBUG(1,("Password server loop - disabling password server %s\n",p)); - continue; - } - - password_client = open_socket_out(SOCK_STREAM, &dest_ip, port); - if (password_client >= 0) { - DEBUG(3,("connected to password server %s\n",p)); - StrnCpy(pserver,p,sizeof(pserver)-1); - break; - } - } - - if (password_client < 0) { - DEBUG(1,("password server not available\n")); - return(False); - } - - - /* send a session request (RFC 8002) */ - - /* put in the destination name */ - len = 4; - p = outbuf+len; - name_mangle(desthost,p,' '); - len += name_len(p); - - /* and my name */ - p = outbuf+len; - name_mangle(remote_machine,p,' '); - len += name_len(p); - - _smb_setlen(outbuf,len); - CVAL(outbuf,0) = 0x81; - - send_smb(password_client,outbuf); - receive_smb(password_client,inbuf,5000); - - if (CVAL(inbuf,0) != 0x82) { - DEBUG(1,("%s rejected the session\n",pserver)); - close(password_client); password_client = -1; - return(False); - } + return &cli; +} - DEBUG(3,("got session\n")); +/**************************************************************************** +support for server level security +****************************************************************************/ +struct cli_state *server_cryptkey(void) +{ + fstring desthost; + struct in_addr dest_ip; + extern fstring local_machine; + char *p; + + if (!cli_initialise(&cli)) + return NULL; + + for (p=strtok(lp_passwordserver(),LIST_SEP); p ; p = strtok(NULL,LIST_SEP)) { + fstrcpy(desthost,p); + standard_sub_basic(desthost); + strupper(desthost); + + dest_ip = *interpret_addr2(desthost); + if (zero_ip(dest_ip)) { + DEBUG(1,("Can't resolve address for %s\n",p)); + continue; + } - bzero(outbuf,smb_size); + if (ismyip(dest_ip)) { + DEBUG(1,("Password server loop - disabling password server %s\n",p)); + continue; + } - /* setup the protocol string */ - set_message(outbuf,0,strlen(pass_protocol)+2,True); - p = smb_buf(outbuf); - *p++ = 2; - strcpy(p,pass_protocol); + if (cli_connect(&cli, desthost, &dest_ip)) { + DEBUG(3,("connected to password server %s\n",p)); + break; + } + } - CVAL(outbuf,smb_com) = SMBnegprot; - CVAL(outbuf,smb_flg) = 0x8; - SSVAL(outbuf,smb_flg2,0x1); + if (!p) { + DEBUG(1,("password server not available\n")); + cli_shutdown(&cli); + return NULL; + } - send_smb(password_client,outbuf); - ret = receive_smb(password_client,inbuf,5000); + if (!cli_session_request(&cli, desthost, 0x20, local_machine)) { + DEBUG(1,("%s rejected the session\n",desthost)); + cli_shutdown(&cli); + return NULL; + } - if (!ret || CVAL(inbuf,smb_rcls) || SVAL(inbuf,smb_vwv0)) { - DEBUG(1,("%s rejected the protocol\n",pserver)); - close(password_client); password_client= -1; - return(False); - } + DEBUG(3,("got session\n")); - if (!(CVAL(inbuf,smb_vwv1) & 1)) { - DEBUG(1,("%s isn't in user level security mode\n",pserver)); - close(password_client); password_client= -1; - return(False); - } + if (!cli_negprot(&cli)) { + DEBUG(1,("%s rejected the negprot\n",desthost)); + cli_shutdown(&cli); + return NULL; + } - memcpy(buf,inbuf,smb_len(inbuf)+4); + if (cli.protocol < PROTOCOL_LANMAN2 || + !(cli.sec_mode & 1)) { + DEBUG(1,("%s isn't in user level security mode\n",desthost)); + cli_shutdown(&cli); + return NULL; + } - DEBUG(3,("password server OK\n")); + DEBUG(3,("password server OK\n")); - return(True); + return &cli; } /**************************************************************************** -attempted support for server level security +validate a password with the password server ****************************************************************************/ -BOOL server_validate(char *buf) +BOOL server_validate(char *user, char *domain, + char *pass, int passlen, + char *ntpass, int ntpasslen) { - pstring inbuf,outbuf; - BOOL ret; + extern fstring local_machine; + fstring share; - if (password_client < 0) { - DEBUG(1,("%s not connected\n",pserver)); - return(False); - } + if (!cli.initialised) { + DEBUG(1,("password server %s is not connected\n", cli.desthost)); + return(False); + } - bzero(inbuf,sizeof(inbuf)); - memcpy(outbuf,buf,sizeof(outbuf)); + if (!cli_session_setup(&cli, user, pass, passlen, ntpass, ntpasslen, domain)) { + DEBUG(1,("password server %s rejected the password\n", cli.desthost)); + return False; + } - /* send a session setup command */ - CVAL(outbuf,smb_flg) = 0x8; - SSVAL(outbuf,smb_flg2,0x1); - CVAL(outbuf,smb_vwv0) = 0xFF; + /* if logged in as guest then reject */ + if ((SVAL(cli.inbuf,smb_vwv2) & 1) != 0) { + DEBUG(1,("password server %s gave us guest only\n", cli.desthost)); + return(False); + } - set_message(outbuf,smb_numwords(outbuf),smb_buflen(outbuf),False); - SCVAL(inbuf,smb_rcls,1); + sprintf(share,"\\\\%s\\IPC$", cli.desthost); - send_smb(password_client,outbuf); - ret = receive_smb(password_client,inbuf,5000); + if (!cli_send_tconX(&cli, share, "IPC", "", 1)) { + DEBUG(1,("password server %s refused IPC$ connect\n", cli.desthost)); + return False; + } - if (!ret || CVAL(inbuf,smb_rcls) != 0) { - DEBUG(1,("password server %s rejected the password\n",pserver)); - return(False); - } - /* if logged in as guest then reject */ - if ((SVAL(inbuf,smb_vwv2) & 1) != 0) { - DEBUG(1,("password server %s gave us guest only\n",pserver)); - return(False); - } + if (!cli_NetWkstaUserLogon(&cli,user,local_machine)) { + DEBUG(1,("password server %s failed NetWkstaUserLogon\n", cli.desthost)); + cli_tdis(&cli); + return False; + } - DEBUG(3,("password server %s accepted the password\n",pserver)); + if (cli.privilages == 0) { + DEBUG(1,("password server %s gave guest privilages\n", cli.desthost)); + cli_tdis(&cli); + return False; + } -#ifndef KEEP_PASSWORD_SERVER_OPEN - close(password_client); password_client= -1; -#endif + if (!strequal(cli.eff_name, user)) { + DEBUG(1,("password server %s gave different username %s\n", + cli.desthost, + cli.eff_name)); + cli_tdis(&cli); + return False; + } - return(True); + DEBUG(3,("password server %s accepted the password\n", cli.desthost)); + + cli_tdis(&cli); + + return(True); } |