summaryrefslogtreecommitdiff
path: root/source/smbd/password.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/smbd/password.c')
-rw-r--r--source/smbd/password.c745
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);
}