summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--source/client/client.c2
-rw-r--r--source/client/ntclient.c127
-rw-r--r--source/include/proto.h41
-rw-r--r--source/include/smb.h50
-rw-r--r--source/libsmb/clientgen.c146
-rw-r--r--source/libsmb/nterr.c30
-rw-r--r--source/libsmb/smbencrypt.c22
-rw-r--r--source/libsmb/smberr.c26
-rw-r--r--source/nmbsync.c3
-rw-r--r--source/passdb/smbpass.c2
-rw-r--r--source/pwd_validate.c276
-rw-r--r--source/smbd/password.c140
-rw-r--r--source/smbd/reply.c89
-rw-r--r--source/smbd/server.c93
-rw-r--r--source/utils/torture.c6
15 files changed, 731 insertions, 322 deletions
diff --git a/source/client/client.c b/source/client/client.c
index 52f4b837a6e..082118e0bac 100644
--- a/source/client/client.c
+++ b/source/client/client.c
@@ -3900,7 +3900,7 @@ static void usage(char *pname)
{
if (!cli_send_login(NULL,NULL,True,True)) return(1);
- do_nt_login(desthost, myhostname, Client, cnum);
+ do_nt_login(dest_ip, desthost, myhostname, Client, cnum);
cli_send_logout();
close_sockets();
diff --git a/source/client/ntclient.c b/source/client/ntclient.c
index 7e360981c02..a32f6e690d6 100644
--- a/source/client/ntclient.c
+++ b/source/client/ntclient.c
@@ -25,6 +25,7 @@
#endif
#include "includes.h"
+#include "nterr.h"
extern int DEBUGLEVEL;
extern pstring username;
@@ -35,11 +36,110 @@ extern pstring workgroup;
#ifdef NTDOMAIN
+/************************************************************************
+ check workstation trust account status
+ ************************************************************************/
+BOOL wksta_trust_account_check(struct in_addr dest_ip, char *dest_host,
+ char *myhostname, char *domain)
+{
+ pstring tmp;
+ struct cli_state wksta_trust;
+ fstring mach_acct;
+ fstring mach_pwd;
+ fstring new_mach_pwd;
+ uchar lm_owf_mach_pwd[16];
+ uchar nt_owf_mach_pwd[16];
+ uchar lm_sess_pwd[24];
+ uchar nt_sess_pwd[24];
+ BOOL right_error_code = False;
+
+ char *start_mach_pwd;
+ char *change_mach_pwd;
+
+ fstrcpy(mach_acct, myhostname);
+ strlower(mach_pwd);
+
+ fstrcpy(mach_pwd , myhostname);
+ strcat(mach_acct, "$");
+ strupper(mach_acct);
+
+ sprintf(tmp, "Enter Workstation Trust Account password for [%s].\nDefault is [%s]. Password: ",
+ mach_acct, mach_pwd);
+
+ start_mach_pwd = (char*)getpass(tmp);
+
+ if (start_mach_pwd[0] != 0)
+ {
+ fstrcpy(mach_pwd, start_mach_pwd);
+ }
+
+ sprintf(tmp, "Enter new Workstation Trust Account password for [%s]\nPress Return to leave at old value. Password: ",
+ mach_acct);
+
+ change_mach_pwd = (char*)getpass(tmp);
+
+ fstrcpy(new_mach_pwd, change_mach_pwd);
+
+ if (!cli_initialise(&wksta_trust))
+ {
+ DEBUG(1,("cli_initialise failed for wksta_trust\n"));
+ return False;
+ }
+
+ if (!server_connect_init(&wksta_trust, myhostname, dest_ip, dest_host))
+ {
+ int err_cls;
+ int err_num;
+ cli_error(&wksta_trust, &err_cls, &err_num);
+ DEBUG(1,("server_connect_init failed (%s)\n", cli_errstr(&wksta_trust)));
+
+ cli_shutdown(&wksta_trust);
+ return False;
+ }
+
+ nt_lm_owf_gen(mach_pwd, nt_owf_mach_pwd, lm_owf_mach_pwd);
+
+ DEBUG(5,("generating nt owf from initial machine pwd: %s\n", mach_pwd));
+ SMBOWFencrypt(nt_owf_mach_pwd, wksta_trust.cryptkey, nt_sess_pwd);
+ SMBOWFencrypt(lm_owf_mach_pwd, wksta_trust.cryptkey, lm_sess_pwd);
+
+ right_error_code = False;
+
+ if (!server_validate2(&wksta_trust, mach_acct, domain,
+ lm_sess_pwd, sizeof(lm_sess_pwd),
+ nt_sess_pwd, sizeof(nt_sess_pwd)))
+ {
+ int err_cls;
+ int err_num;
+ cli_error(&wksta_trust, &err_cls, &err_num);
+
+ if (err_cls == 0xC000 && err_num == NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)
+ {
+ DEBUG(1,("server_validate: valid workstation trust account exists\n"));
+ right_error_code = True;
+ }
+
+ if (err_cls == 0xC000 && err_num == NT_STATUS_NO_SUCH_USER)
+ {
+ DEBUG(1,("server_validate: workstation trust account does not exist\n"));
+ right_error_code = False;
+ }
+ }
+
+ if (!right_error_code)
+ {
+ DEBUG(1,("server_validate failed (%s)\n", cli_errstr(&wksta_trust)));
+ }
+
+ cli_shutdown(&wksta_trust);
+ return right_error_code;
+}
/****************************************************************************
experimental nt login.
****************************************************************************/
-BOOL do_nt_login(char *desthost, char *myhostname,
+BOOL do_nt_login(struct in_addr dest_ip, char *dest_host,
+ char *myhostname,
int Client, int cnum)
{
DOM_CHAL clnt_chal;
@@ -66,9 +166,12 @@ BOOL do_nt_login(char *desthost, char *myhostname,
uchar sess_key[8];
char nt_owf_mach_pwd[16];
+
+ fstring server_name;
fstring mach_acct;
+
fstring mach_pwd;
- fstring server_name;
+ fstring new_mach_pwd;
RPC_IFACE abstract;
RPC_IFACE transfer;
@@ -88,6 +191,8 @@ BOOL do_nt_login(char *desthost, char *myhostname,
uint32 call_id = 0;
char *inbuf,*outbuf;
+ /******************** initialise ********************************/
+
zerotime.time = 0;
inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
@@ -99,6 +204,10 @@ BOOL do_nt_login(char *desthost, char *myhostname,
return False;
}
+ /************ check workstation trust account *******************/
+
+ wksta_trust_account_check(dest_ip, dest_host, myhostname, workgroup);
+
/******************* open the \PIPE\lsarpc file *****************/
if ((fnum = rpc_pipe_open(inbuf, outbuf, PIPE_LSARPC, Client, cnum)) == 0xffff)
@@ -216,17 +325,11 @@ BOOL do_nt_login(char *desthost, char *myhostname,
/******************* Request Challenge ********************/
- fstrcpy(mach_acct, myhostname);
- strlower(mach_pwd);
-
- fstrcpy(mach_pwd , myhostname);
- strcat(mach_acct, "$");
-
SIVAL(clnt_chal.data, 0, 0x11111111);
SIVAL(clnt_chal.data, 4, 0x22222222);
/* send a client challenge; receive a server challenge */
- if (!do_lsa_req_chal(fnum, ++call_id, desthost, myhostname, &clnt_chal, &srv_chal))
+ if (!do_lsa_req_chal(fnum, ++call_id, dest_host, myhostname, &clnt_chal, &srv_chal))
{
cli_smb_close(inbuf, outbuf, Client, cnum, fnum);
free(inbuf); free(outbuf);
@@ -268,7 +371,7 @@ BOOL do_nt_login(char *desthost, char *myhostname,
cred_create(sess_key, &clnt_chal, zerotime, &(clnt_cred.challenge));
/* send client auth-2 challenge; receive an auth-2 challenge */
- if (!do_lsa_auth2(fnum, ++call_id, desthost, mach_acct, 2, myhostname,
+ if (!do_lsa_auth2(fnum, ++call_id, dest_host, mach_acct, 2, myhostname,
&(clnt_cred.challenge), 0x000001ff, &auth2_srv_chal))
{
cli_smb_close(inbuf, outbuf, Client, cnum, fnum);
@@ -311,7 +414,7 @@ BOOL do_nt_login(char *desthost, char *myhostname,
/* send client sam-logon challenge; receive a sam-logon challenge */
if (!do_lsa_sam_logon(fnum, ++call_id, sess_key, &clnt_cred,
- desthost, mach_acct,
+ dest_host, mach_acct,
&sam_logon_clnt_cred, &sam_logon_rtn_cred,
1, 1, &id1, &user_info1,
&sam_logon_srv_cred))
@@ -332,7 +435,7 @@ BOOL do_nt_login(char *desthost, char *myhostname,
/* send client sam-logoff challenge; receive a sam-logoff challenge */
if (!do_lsa_sam_logoff(fnum, ++call_id, sess_key, &clnt_cred,
- desthost, mach_acct,
+ dest_host, mach_acct,
&sam_logoff_clnt_cred, &sam_logoff_rtn_cred,
1, 1, &id1,
&sam_logoff_srv_cred))
diff --git a/source/include/proto.h b/source/include/proto.h
index 98c671ea868..cffa2974135 100644
--- a/source/include/proto.h
+++ b/source/include/proto.h
@@ -61,13 +61,14 @@ BOOL cli_unlock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int
int cli_read(struct cli_state *cli, int fnum, char *buf, uint32 offset, uint16 size);
int cli_write(struct cli_state *cli, int fnum, char *buf, uint32 offset, uint16 size);
BOOL cli_negprot(struct cli_state *cli);
-BOOL cli_session_request(struct cli_state *cli, char *host, int name_type,
- char *myname);
+BOOL cli_session_request(struct cli_state *cli,
+ char *called_host_name , int called_name_type,
+ char calling_netbios_name[16], int calling_name_type);
BOOL cli_connect(struct cli_state *cli, char *host, struct in_addr *ip);
BOOL cli_initialise(struct cli_state *cli);
void cli_shutdown(struct cli_state *cli);
char *cli_errstr(struct cli_state *cli);
-void cli_error(struct cli_state *cli, int *eclass, int *num);
+BOOL cli_error(struct cli_state *cli, uint8 *eclass, uint32 *num);
void cli_sockopt(struct cli_state *cli, char *options);
int cli_setpid(struct cli_state *cli, int pid);
@@ -627,9 +628,16 @@ void sync_browse_lists(struct subnet_record *d, struct work_record *work,
/*The following definitions come from ntclient.c */
-BOOL do_nt_login(char *desthost, char *myhostname,
+BOOL wksta_trust_account_check(struct in_addr dest_ip, char *dest_host,
+ char *myhostname, char *domain);
+BOOL do_nt_login(struct in_addr dest_ip, char *dest_host,
+ char *myhostname,
int Client, int cnum);
+/*The following definitions come from nterr.c */
+
+char *get_nt_error_msg(uint16 nt_code);
+
/*The following definitions come from params.c */
BOOL pm_process( char *FileName,
@@ -654,11 +662,6 @@ BOOL user_ok(char *user,int snum);
BOOL authorise_login(int snum,char *user,char *password, int pwlen,
BOOL *guest,BOOL *force,uint16 vuid);
BOOL check_hosts_equiv(char *user);
-struct cli_state *server_client(void);
-struct cli_state *server_cryptkey(void);
-BOOL server_validate(char *user, char *domain,
- char *pass, int passlen,
- char *ntpass, int ntpasslen);
/*The following definitions come from pcap.c */
@@ -692,6 +695,18 @@ void status_printjob(int cnum,int snum,int jobid,int status);
int printjob_encode(int snum, int job);
void printjob_decode(int jobid, int *snum, int *job);
+/*The following definitions come from pwd_validate.c */
+
+BOOL server_connect_init(struct cli_state *clnt, char my_netbios_name[16],
+ struct in_addr dest_ip, char *desthost);
+BOOL server_cryptkey(struct cli_state *clnt, char my_netbios_name[16]);
+BOOL server_validate2(struct cli_state *clnt, char *user, char *domain,
+ char *pass, int passlen,
+ char *ntpass, int ntpasslen);
+BOOL server_validate(struct cli_state *clnt, char *user, char *domain,
+ char *pass, int passlen,
+ char *ntpass, int ntpasslen);
+
/*The following definitions come from quotas.c */
BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize);
@@ -1029,6 +1044,7 @@ char* wks_io_r_unknown_0(BOOL io, WKS_R_UNKNOWN_0 *r_u, char *q, char *base, int
/*The following definitions come from server.c */
+struct cli_state *pwd_server_connection(void);
void *dflt_sig(void);
void killkids(void);
mode_t unix_mode(int cnum,int dosmode);
@@ -1096,10 +1112,11 @@ void cred_hash2(unsigned char *out,unsigned char *in,unsigned char *key);
/*The following definitions come from smbencrypt.c */
-void SMBencrypt(uchar *passwd, uchar *c8, uchar *p24);
+void SMBencrypt(uchar *passwd, uchar *c8, uchar p24[24]);
void E_md4hash(uchar *passwd, uchar *p16);
-void SMBNTencrypt(uchar *passwd, uchar *c8, uchar *p24);
-void nt_lm_owf_gen(char *pwd, char *nt_p16, char *p16);
+void SMBOWFencrypt(char passwd[16], uchar *c8, uchar p24[24]);
+void SMBNTencrypt(uchar *passwd, uchar *c8, uchar p24[24]);
+void nt_lm_owf_gen(char *pwd, char nt_p16[16], char p16[16]);
/*The following definitions come from smberr.c */
diff --git a/source/include/smb.h b/source/include/smb.h
index afa9e3d9b90..687f14b9caa 100644
--- a/source/include/smb.h
+++ b/source/include/smb.h
@@ -1363,9 +1363,13 @@ struct cli_state {
int protocol;
int sec_mode;
int error;
- int privilages;
+ int privileges;
fstring eff_name;
- fstring desthost;
+
+ fstring full_dest_host_name;
+ char called_netbios_name[16];
+ char calling_netbios_name[16];
+
char cryptkey[8];
uint32 sesskey;
int serverzone;
@@ -2020,6 +2024,15 @@ char *Strstr(char *s, char *p);
#define BROWSER_CONSTANT 0xaa55
+/* NT Flags2 bits - cifs6.txt section 3.1.2 */
+
+#define FLAGS2_LONG_PATH_COMPONENTS 0x0001
+#define FLAGS2_EXTENDED_ATTRIBUTES 0x0002
+#define FLAGS2_DFS_PATHNAMES 0x1000
+#define FLAGS2_READ_PERMIT_NO_EXECUTE 0x2000
+#define FLAGS2_32_BIT_ERROR_CODES 0x4000
+#define FLAGS2_UNICODE_STRINGS 0x8000
+
/* Capabilities. see ftp.microsoft.com/developr/drg/cifs/cifs/cifs4.txt */
#define CAP_RAW_MODE 0x0001
@@ -2037,14 +2050,39 @@ char *Strstr(char *s, char *p);
/* protocol types. It assumes that higher protocols include lower protocols
as subsets */
-enum protocol_types {PROTOCOL_NONE,PROTOCOL_CORE,PROTOCOL_COREPLUS,PROTOCOL_LANMAN1,PROTOCOL_LANMAN2,PROTOCOL_NT1};
+enum protocol_types
+{
+ PROTOCOL_NONE,
+ PROTOCOL_CORE,
+ PROTOCOL_COREPLUS,
+ PROTOCOL_LANMAN1,
+ PROTOCOL_LANMAN2,
+ PROTOCOL_NT1
+};
/* security levels */
-enum security_types {SEC_SHARE,SEC_USER,SEC_SERVER};
+enum security_types
+{
+ SEC_SHARE,
+ SEC_USER,
+ SEC_SERVER
+};
+
+/* bit-masks for security mode. see cifs6.txt Negprot 4.1.1 server response */
+#define USE_USER_LEVEL_SECURITY 1
+#define USE_CHALLENGE_RESPONSE 2
/* printing types */
-enum printing_types {PRINT_BSD,PRINT_SYSV,PRINT_AIX,PRINT_HPUX,
- PRINT_QNX,PRINT_PLP,PRINT_LPRNG};
+enum printing_types
+{
+ PRINT_BSD,
+ PRINT_SYSV,
+ PRINT_AIX,
+ PRINT_HPUX,
+ PRINT_QNX,
+ PRINT_PLP,
+ PRINT_LPRNG
+};
/* Remote architectures we know about. */
enum remote_arch_types {RA_UNKNOWN, RA_WFWG, RA_OS2, RA_WIN95, RA_WINNT, RA_SAMBA};
diff --git a/source/libsmb/clientgen.c b/source/libsmb/clientgen.c
index b98f2fca69a..78bbf8115fb 100644
--- a/source/libsmb/clientgen.c
+++ b/source/libsmb/clientgen.c
@@ -104,7 +104,7 @@ static BOOL cli_send_trans(struct cli_state *cli,
if (this_ldata < ldata || this_lparam < lparam) {
/* receive interim response */
if (!receive_smb(cli->fd,cli->inbuf,cli->timeout) ||
- CVAL(cli->inbuf,smb_rcls) != 0) {
+ cli_error(cli,NULL, NULL)) {
return(False);
}
@@ -176,8 +176,7 @@ static BOOL cli_receive_trans(struct cli_state *cli,
CVAL(cli->inbuf,smb_com)));
return(False);
}
- if (CVAL(cli->inbuf,smb_rcls) != 0)
- return(False);
+ if (cli_error(cli,NULL, NULL)) return(False);
/* parse out the lengths */
total_data = SVAL(cli->inbuf,smb_tdrcnt);
@@ -227,8 +226,7 @@ static BOOL cli_receive_trans(struct cli_state *cli,
CVAL(cli->inbuf,smb_com)));
return(False);
}
- if (CVAL(cli->inbuf,smb_rcls) != 0)
- return(False);
+ if (cli_error(cli,NULL, NULL)) return(False);
}
return(True);
@@ -300,7 +298,7 @@ BOOL cli_NetWkstaUserLogon(struct cli_state *cli,char *user, char *workstation)
if (cli->error == 0) {
DEBUG(4,("NetWkstaUserLogon success\n"));
- cli->privilages = SVAL(p, 24);
+ cli->privileges = SVAL(p, 24);
fstrcpy(cli->eff_name,p+2);
} else {
DEBUG(1,("NetwkstaUserLogon gave error %d\n", cli->error));
@@ -424,15 +422,22 @@ BOOL cli_session_setup(struct cli_state *cli,
return False;
}
- if ((cli->sec_mode & 2) && *pass && passlen != 24) {
+ if ((cli->sec_mode & USE_CHALLENGE_RESPONSE) && *pass && passlen != 24)
+ {
passlen = 24;
SMBencrypt((uchar *)pass,(uchar *)cli->cryptkey,(uchar *)pword);
- } else {
+ }
+ else
+ {
memcpy(pword, pass, passlen);
}
/* if in share level security then don't send a password now */
- if (!(cli->sec_mode & 1)) {fstrcpy(pword, "");passlen=1;}
+ if (!(cli->sec_mode & USE_USER_LEVEL_SECURITY))
+ {
+ fstrcpy(pword, "");
+ passlen=1;
+ }
/* send a session setup command */
bzero(cli->outbuf,smb_size);
@@ -487,9 +492,7 @@ BOOL cli_session_setup(struct cli_state *cli,
show_msg(cli->inbuf);
- if (CVAL(cli->inbuf,smb_rcls) != 0) {
- return False;
- }
+ if (cli_error(cli,NULL, NULL)) return(False);
/* use the returned uid from now on */
cli->uid = SVAL(cli->inbuf,smb_uid);
@@ -509,19 +512,19 @@ BOOL cli_send_tconX(struct cli_state *cli,
bzero(cli->outbuf,smb_size);
bzero(cli->inbuf,smb_size);
- if (cli->sec_mode & 1) {
+ if (cli->sec_mode & USE_USER_LEVEL_SECURITY) {
passlen = 1;
pass = "";
}
- if ((cli->sec_mode & 2) && *pass && passlen != 24) {
+ if ((cli->sec_mode & USE_CHALLENGE_RESPONSE) && *pass && passlen != 24) {
passlen = 24;
SMBencrypt((uchar *)pass,(uchar *)cli->cryptkey,(uchar *)pword);
} else {
memcpy(pword, pass, passlen);
}
- sprintf(fullshare, "\\\\%s\\%s", cli->desthost, share);
+ sprintf(fullshare, "\\\\%s\\%s", cli->called_netbios_name, share);
set_message(cli->outbuf,4,
2 + strlen(fullshare) + passlen + strlen(dev),True);
@@ -544,9 +547,7 @@ BOOL cli_send_tconX(struct cli_state *cli,
if (!receive_smb(cli->fd,cli->inbuf,cli->timeout))
return False;
- if (CVAL(cli->inbuf,smb_rcls) != 0) {
- return False;
- }
+ if (cli_error(cli,NULL, NULL)) return(False);
cli->cnum = SVAL(cli->inbuf,smb_tid);
return True;
@@ -568,7 +569,7 @@ BOOL cli_tdis(struct cli_state *cli)
if (!receive_smb(cli->fd,cli->inbuf,cli->timeout))
return False;
- return CVAL(cli->inbuf,smb_rcls) == 0;
+ return !cli_error(cli,NULL, NULL);
}
/****************************************************************************
@@ -599,9 +600,7 @@ BOOL cli_unlink(struct cli_state *cli, char *fname)
return False;
}
- if (CVAL(cli->inbuf,smb_rcls) != 0) {
- return False;
- }
+ if (cli_error(cli,NULL, NULL)) return False;
return True;
}
@@ -659,9 +658,7 @@ int cli_open(struct cli_state *cli, char *fname, int flags, int share_mode)
return -1;
}
- if (CVAL(cli->inbuf,smb_rcls) != 0) {
- return -1;
- }
+ if (cli_error(cli,NULL, NULL)) return -1;
return SVAL(cli->inbuf,smb_vwv2);
}
@@ -692,9 +689,7 @@ BOOL cli_close(struct cli_state *cli, int fnum)
return False;
}
- if (CVAL(cli->inbuf,smb_rcls) != 0) {
- return False;
- }
+ if (cli_error(cli,NULL, NULL)) return False;
return True;
}
@@ -733,9 +728,7 @@ BOOL cli_lock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int ti
return False;
}
- if (CVAL(cli->inbuf,smb_rcls) != 0) {
- return False;
- }
+ if (cli_error(cli,NULL, NULL)) return False;
return True;
}
@@ -773,9 +766,7 @@ BOOL cli_unlock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int
return False;
}
- if (CVAL(cli->inbuf,smb_rcls) != 0) {
- return False;
- }
+ if (cli_error(cli,NULL, NULL)) return False;
return True;
}
@@ -808,9 +799,7 @@ int cli_read(struct cli_state *cli, int fnum, char *buf, uint32 offset, uint16 s
return -1;
}
- if (CVAL(cli->inbuf,smb_rcls) != 0) {
- return -1;
- }
+ if (cli_error(cli,NULL, NULL)) return -1;
size = SVAL(cli->inbuf, smb_vwv5);
p = smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_vwv6);
@@ -852,9 +841,7 @@ int cli_write(struct cli_state *cli, int fnum, char *buf, uint32 offset, uint16
return -1;
}
- if (CVAL(cli->inbuf,smb_rcls) != 0) {
- return -1;
- }
+ if (cli_error(cli,NULL, NULL)) return -1;
return SVAL(cli->inbuf, smb_vwv2);
}
@@ -899,10 +886,8 @@ BOOL cli_negprot(struct cli_state *cli)
show_msg(cli->inbuf);
- if (CVAL(cli->inbuf,smb_rcls) != 0 ||
- ((int)SVAL(cli->inbuf,smb_vwv0) >= numprots)) {
- return(False);
- }
+ if (cli_error(cli,NULL, NULL)) return False;
+ if ((int)SVAL(cli->inbuf,smb_vwv0) >= numprots) return(False);
cli->protocol = prots[SVAL(cli->inbuf,smb_vwv0)].prot;
@@ -936,33 +921,43 @@ BOOL cli_negprot(struct cli_state *cli)
return True;
}
+#define TRUNCATE_NETBIOS_NAME 1
/****************************************************************************
- send a session request
+ send a session request. see rfc1002.txt 4.3 and 4.3.2
****************************************************************************/
-BOOL cli_session_request(struct cli_state *cli, char *host, int name_type,
- char *myname)
+BOOL cli_session_request(struct cli_state *cli,
+ char *called_host_name , int called_name_type,
+ char calling_netbios_name[16], int calling_name_type)
{
- fstring dest;
char *p;
int len = 4;
/* send a session request (RFC 1002) */
- fstrcpy(dest,host);
+ strncpy(cli->called_netbios_name , called_host_name , sizeof(cli->called_netbios_name ));
+ strncpy(cli->calling_netbios_name, calling_netbios_name, sizeof(cli->calling_netbios_name));
- p = strchr(dest,'.');
+ /* sorry, don't trust strncpy to null-terminate the string... */
+ cli->called_netbios_name [sizeof(cli->called_netbios_name )-1] = 0;
+ cli->calling_netbios_name[sizeof(cli->calling_netbios_name)-1] = 0;
+
+#ifdef TRUNCATE_NETBIOS_NAME
+ /* ok. this is because of a stupid microsoft-ism. if the called host
+ name contains a '.', microsoft clients expect you to truncate the
+ netbios name up to and including the '.'
+ */
+ p = strchr(cli->called_netbios_name, '.');
if (p) *p = 0;
-
- fstrcpy(cli->desthost, dest);
+#endif /* TRUNCATE_NETBIOS_NAME */
/* put in the destination name */
p = cli->outbuf+len;
- name_mangle(dest,p,name_type);
+ name_mangle(cli->called_netbios_name, p, called_name_type);
len += name_len(p);
/* and my name */
p = cli->outbuf+len;
- name_mangle(myname,p,0);
+ name_mangle(cli->calling_netbios_name, p, calling_name_type);
len += name_len(p);
/* setup the packet length */
@@ -990,26 +985,27 @@ BOOL cli_connect(struct cli_state *cli, char *host, struct in_addr *ip)
{
struct in_addr dest_ip;
- fstrcpy(cli->desthost, host);
+ fstrcpy(cli->full_dest_host_name, host);
- if (!ip) {
+ if (!ip)
+ {
+ /* no ip specified - look up the name */
struct hostent *hp;
- if ((hp = Get_Hostbyname(cli->desthost)) == 0) {
+ if ((hp = Get_Hostbyname(host)) == 0) {
return False;
}
putip((char *)&dest_ip,(char *)hp->h_addr);
} else {
+ /* use the given ip address */
dest_ip = *ip;
}
-
+ /* open the socket */
cli->fd = open_socket_out(SOCK_STREAM, &dest_ip, 139, cli->timeout);
- if (cli->fd == -1)
- return False;
- return True;
+ return (cli->fd != -1);
}
@@ -1059,10 +1055,32 @@ char *cli_errstr(struct cli_state *cli)
/****************************************************************************
return error codes for the last packet
****************************************************************************/
-void cli_error(struct cli_state *cli, int *eclass, int *num)
+BOOL cli_error(struct cli_state *cli, uint8 *eclass, uint32 *num)
{
- *eclass = CVAL(cli->inbuf,smb_rcls);
- *num = SVAL(cli->inbuf,smb_err);
+ int flgs2 = SVAL(cli->inbuf,smb_flg2);
+
+ if (eclass) *eclass = 0;
+ if (num ) *num = 0;
+
+ if (flgs2 & FLAGS2_32_BIT_ERROR_CODES)
+ {
+ /* 32 bit error codes detected */
+ uint32 nt_err = IVAL(cli->inbuf,smb_rcls);
+ if (num) *num = nt_err;
+ return (nt_err != 0);
+ }
+ else
+ {
+ /* dos 16 bit error codes detected */
+ char rcls = CVAL(cli->inbuf,smb_rcls);
+ if (rcls != 0)
+ {
+ if (eclass) *eclass = rcls;
+ if (num ) *num = SVAL(cli->inbuf,smb_err);
+ return True;
+ }
+ }
+ return False;
}
/****************************************************************************
diff --git a/source/libsmb/nterr.c b/source/libsmb/nterr.c
index bda0f882a64..7dd2234e1d7 100644
--- a/source/libsmb/nterr.c
+++ b/source/libsmb/nterr.c
@@ -1,12 +1,16 @@
+/* NT error codes. please read nterr.h */
+#include "includes.h"
#include "nterr.h"
-static struct
+typedef struct
{
char *nt_errstr;
uint16 nt_errcode;
-} nt_errs[] =
+} nt_err_code_struct;
+
+nt_err_code_struct nt_errs[] =
{
{ "NT_STATUS_UNSUCCESSFUL", NT_STATUS_UNSUCCESSFUL },
{ "NT_STATUS_NOT_IMPLEMENTED", NT_STATUS_NOT_IMPLEMENTED },
@@ -512,3 +516,25 @@ static struct
{ NULL, 0 }
};
+/*****************************************************************************
+ returns an NT error message. not amazingly helpful, but better than a number.
+ *****************************************************************************/
+char *get_nt_error_msg(uint16 nt_code)
+{
+ static pstring msg;
+ int idx = 0;
+
+ strcpy(msg, "Unknown NT error");
+
+ while (nt_errs[idx].nt_errstr != NULL)
+ {
+ if (nt_errs[idx].nt_errcode == nt_code)
+ {
+ strcpy(msg, nt_errs[idx].nt_errstr);
+ return msg;
+ }
+ idx++;
+ }
+ return NULL;
+}
+
diff --git a/source/libsmb/smbencrypt.c b/source/libsmb/smbencrypt.c
index 38d414cf23d..1bf0bcc8e68 100644
--- a/source/libsmb/smbencrypt.c
+++ b/source/libsmb/smbencrypt.c
@@ -29,8 +29,9 @@ extern int DEBUGLEVEL;
/*
This implements the X/Open SMB password encryption
It takes a password, a 8 byte "crypt key" and puts 24 bytes of
- encrypted password into p24 */
-void SMBencrypt(uchar *passwd, uchar *c8, uchar *p24)
+ encrypted password into p24
+ */
+void SMBencrypt(uchar *passwd, uchar *c8, uchar p24[24])
{
uchar p14[15], p21[21];
@@ -97,9 +98,19 @@ void E_md4hash(uchar *passwd, uchar *p16)
mdfour(p16, (unsigned char *)wpwd, len);
}
-/* Does the NT MD4 hash then des encryption. */
+/* Does the des encryption from the NT or LM MD4 hash. */
+void SMBOWFencrypt(char passwd[16], uchar *c8, uchar p24[24])
+{
+ uchar p21[21];
+
+ memset(p21,'\0',21);
-void SMBNTencrypt(uchar *passwd, uchar *c8, uchar *p24)
+ memcpy(p21, passwd, sizeof(passwd));
+ E_P24(p21, c8, p24);
+}
+
+/* Does the NT MD4 hash then des encryption. */
+void SMBNTencrypt(uchar *passwd, uchar *c8, uchar p24[24])
{
uchar p21[21];
@@ -110,8 +121,7 @@ void SMBNTencrypt(uchar *passwd, uchar *c8, uchar *p24)
}
/* Does both the NT and LM owfs of a user's password */
-
-void nt_lm_owf_gen(char *pwd, char *nt_p16, char *p16)
+void nt_lm_owf_gen(char *pwd, char nt_p16[16], char p16[16])
{
char passwd[130];
StrnCpy(passwd, pwd, sizeof(passwd)-1);
diff --git a/source/libsmb/smberr.c b/source/libsmb/smberr.c
index 5149568c045..35cd0bf88f0 100644
--- a/source/libsmb/smberr.c
+++ b/source/libsmb/smberr.c
@@ -151,9 +151,28 @@ return a SMB error string from a SMB buffer
char *smb_errstr(char *inbuf)
{
static pstring ret;
+ int i,j;
+ BOOL nt_errors = (SVAL(inbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES) == FLAGS2_32_BIT_ERROR_CODES;
+
+ if (nt_errors)
+ {
+ char *nt_errstr = NULL;
+ uint32 nt_err = IVAL(inbuf, smb_rcls);
+ uint16 nt_num = nt_err & 0x0000ffff;
+ uint16 class = (nt_err & 0xffff0000) >> 16;
+
+ /* maybe lookup the error message in the nt error codes... */
+ if ((nt_errstr = get_nt_error_msg(nt_num)) != NULL)
+ {
+ sprintf(ret,"NT Error: (%4x, %s)", class, nt_errstr);
+ return ret;
+ }
+ sprintf(ret,"NT Error: Unknown error (%4x %4x)", class, nt_num);
+ }
+ else
+ {
int class = CVAL(inbuf,smb_rcls);
int num = SVAL(inbuf,smb_err);
- int i,j;
for (i=0;err_classes[i].class;i++)
if (err_classes[i].code == class)
@@ -176,7 +195,8 @@ char *smb_errstr(char *inbuf)
sprintf(ret,"%s - %d",err_classes[i].class,num);
return ret;
}
-
- sprintf(ret,"Error: Unknown error (%d,%d)",class,num);
+ sprintf(ret,"Error: Unknown error (%4x,%d)", class, num);
+ }
+
return(ret);
}
diff --git a/source/nmbsync.c b/source/nmbsync.c
index c1db37ff5cc..7fc422d2547 100644
--- a/source/nmbsync.c
+++ b/source/nmbsync.c
@@ -77,7 +77,8 @@ void sync_browse_lists(struct subnet_record *d, struct work_record *work,
DEBUG(1,("Failed to start browse sync with %s\n", name));
}
- if (!cli_session_request(&cli, name, nm_type, local_machine)) {
+ if (!cli_session_request(&cli, name, nm_type, local_machine, 0x0))
+ {
DEBUG(1,("%s rejected the browse sync session\n",name));
cli_shutdown(&cli);
return;
diff --git a/source/passdb/smbpass.c b/source/passdb/smbpass.c
index cc0e1fd26de..e74a8f7610b 100644
--- a/source/passdb/smbpass.c
+++ b/source/passdb/smbpass.c
@@ -508,7 +508,7 @@ Error was %s\n",
}
sprintf(new_entry, "%s:%u:", pwd->smb_name, (unsigned)pwd->smb_userid);
- p = &new_entry[strlen(new_entry)];
+ p = (unsigned char*)(&new_entry[strlen(new_entry)]);
for( i = 0; i < 16; i++)
{
diff --git a/source/pwd_validate.c b/source/pwd_validate.c
new file mode 100644
index 00000000000..2eefa1e5f07
--- /dev/null
+++ b/source/pwd_validate.c
@@ -0,0 +1,276 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ Password and authentication handling
+ 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+
+extern int DEBUGLEVEL;
+extern int Protocol;
+
+
+/****************************************************************************
+initiates a connection to a user-level server.
+****************************************************************************/
+BOOL server_connect_init(struct cli_state *clnt, char my_netbios_name[16],
+ struct in_addr dest_ip, char *desthost)
+{
+ DEBUG(5,("password server connection requested: %s [%s]\n",
+ desthost, inet_ntoa(dest_ip)));
+
+ if (clnt == NULL || !clnt->initialised)
+ {
+ DEBUG(1,("password server client state not initialised\n", desthost));
+ return(False);
+ }
+
+ if (!cli_connect(clnt, desthost, &dest_ip))
+ {
+ DEBUG(3,("connected to password server %s\n", desthost));
+ return False;
+ }
+
+ if (!cli_session_request(clnt, desthost, 0x20, my_netbios_name, 0x0))
+ {
+ DEBUG(1,("%s rejected the session\n", desthost));
+ return False;
+ }
+
+ DEBUG(3,("got session\n"));
+
+ if (!cli_negprot(clnt))
+ {
+ DEBUG(1,("%s rejected the negprot\n", desthost));
+ return False;
+ }
+
+ if (clnt->protocol < PROTOCOL_LANMAN2 || !(clnt->sec_mode & 1))
+ {
+ DEBUG(1,("%s isn't in user level security mode\n", desthost));
+ return False;
+ }
+
+ DEBUG(3,("password server OK\n"));
+
+ return True;
+}
+
+/****************************************************************************
+support for server level security
+****************************************************************************/
+BOOL server_cryptkey(struct cli_state *clnt, char my_netbios_name[16])
+{
+ fstring desthost;
+ struct in_addr dest_ip;
+ char *p;
+ BOOL connection_found = False;
+
+ if (clnt == NULL || !cli_initialise(clnt))
+ {
+ DEBUG(1,("server_cryptkey: failed to initialise client state\n"));
+ return False;
+ }
+
+ for (p = strtok(lp_passwordserver(),LIST_SEP); p && !connection_found; 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;
+ }
+
+ if (ismyip(dest_ip))
+ {
+ DEBUG(1,("Password server loop - disabling password server %s\n", p));
+ continue;
+ }
+
+ connection_found = server_connect_init(clnt, my_netbios_name, dest_ip, desthost);
+ }
+
+ if (!p && !connection_found)
+ {
+ DEBUG(1,("password server not available\n"));
+ cli_shutdown(clnt);
+ return False;
+ }
+
+ DEBUG(3,("password server OK\n"));
+
+ return True;
+}
+
+/****************************************************************************
+validate a password
+****************************************************************************/
+BOOL server_validate2(struct cli_state *clnt, char *user, char *domain,
+ char *pass, int passlen,
+ char *ntpass, int ntpasslen)
+{
+ BOOL pwd_ok = False;
+
+ DEBUG(4,("server_validate2: user:[%s] domain:[%s]\n", user, domain));
+
+ if (clnt == NULL)
+ {
+ DEBUG(1,("server_validate2: NULL client_state. cannot validate\n"));
+ return(False);
+ }
+
+ if (pass == NULL && ntpass == NULL)
+ {
+ DEBUG(1,("server_validate2: both lm and nt passwords are NULL. cannot validate\n"));
+ return(False);
+ }
+
+ if (!clnt->initialised)
+ {
+ DEBUG(1,("server %s is not connected\n", clnt->full_dest_host_name));
+ return(False);
+ }
+
+ if (!cli_session_setup(clnt, user, pass, passlen, ntpass, ntpasslen, domain)) {
+ DEBUG(1,("server %s rejected the password\n", clnt->full_dest_host_name));
+ return False;
+ }
+
+ /* if logged in as guest then reject */
+ if ((SVAL(clnt->inbuf,smb_vwv2) & 1) != 0) {
+ DEBUG(1,("server %s gave us guest only\n", clnt->full_dest_host_name));
+ return(False);
+ }
+
+ pwd_ok = False;
+
+ if (!pwd_ok)
+ {
+ pwd_ok = pass != NULL && !cli_send_tconX(clnt, "IPC$", "IPC", pass, passlen);
+ }
+
+ if (!pwd_ok)
+ {
+ DEBUG(1,("server %s refused IPC$ connect with LM password\n", clnt->full_dest_host_name));
+ }
+
+ if (!pwd_ok)
+ {
+ pwd_ok = ntpass != NULL && !cli_send_tconX(clnt, "IPC$", "IPC", ntpass, ntpasslen);
+ }
+
+ if (!pwd_ok)
+ {
+ DEBUG(1,("server %s refused IPC$ connect with NT password\n", clnt->full_dest_host_name));
+ return False;
+ }
+
+ if (!pwd_ok)
+ {
+ DEBUG(3,("server %s rejected the password\n", clnt->full_dest_host_name));
+ }
+ else
+ {
+ DEBUG(3,("server %s accepted the password\n", clnt->full_dest_host_name));
+ }
+
+ cli_tdis(clnt);
+
+ return(True);
+}
+
+
+/****************************************************************************
+validate a password with the password server. here's some good code to go
+into an SMB pam, by the way...
+****************************************************************************/
+BOOL server_validate(struct cli_state *clnt, char *user, char *domain,
+ char *pass, int passlen,
+ char *ntpass, int ntpasslen)
+{
+ if (clnt == NULL)
+ {
+ DEBUG(1,("server_validate: NULL client_state. cannot validate\n"));
+ return(False);
+ }
+
+ if (!clnt->initialised) {
+ DEBUG(1,("password server %s is not connected\n", clnt->full_dest_host_name));
+ return(False);
+ }
+
+ if (!cli_session_setup(clnt, user, pass, passlen, ntpass, ntpasslen, domain)) {
+ DEBUG(1,("password server %s rejected the password\n", clnt->full_dest_host_name));
+ return False;
+ }
+
+ /* if logged in as guest then reject */
+ if ((SVAL(clnt->inbuf,smb_vwv2) & 1) != 0) {
+ DEBUG(1,("password server %s gave us guest only\n", clnt->full_dest_host_name));
+ return(False);
+ }
+
+
+ if (!cli_send_tconX(clnt, "IPC$", "IPC", "", 1))
+ {
+ DEBUG(1,("password server %s refused IPC$ connect\n", clnt->full_dest_host_name));
+ return False;
+ }
+
+
+ if (!cli_send_tconX(clnt, "IPC$", "IPC", "", 1)) {
+ DEBUG(1,("password server %s refused IPC$ connect\n", clnt->full_dest_host_name));
+ return False;
+ }
+
+
+ if (!cli_NetWkstaUserLogon(clnt, user, clnt->called_netbios_name))
+ {
+ DEBUG(1,("password server %s failed NetWkstaUserLogon\n", clnt->full_dest_host_name));
+ cli_tdis(clnt);
+ return False;
+ }
+
+ if (clnt->privileges == 0)
+ {
+ DEBUG(1,("password server %s gave guest privilages\n", clnt->full_dest_host_name));
+ cli_tdis(clnt);
+ return False;
+ }
+
+ if (!strequal(clnt->eff_name, user)) {
+ DEBUG(1,("password server %s gave different username %s\n",
+ clnt->full_dest_host_name,
+ clnt->eff_name));
+ cli_tdis(clnt);
+ return False;
+ }
+
+ DEBUG(3,("password server %s accepted the password\n", clnt->full_dest_host_name));
+
+ cli_tdis(clnt);
+
+ return(True);
+}
+
+
diff --git a/source/smbd/password.c b/source/smbd/password.c
index 185fc68f5a3..7dd2133406d 100644
--- a/source/smbd/password.c
+++ b/source/smbd/password.c
@@ -21,7 +21,7 @@
#include "includes.h"
-#if (defined(NETGROUP) && defined (AUTOMOUNT))
+#ifdef NETGROUP
#include "rpcsvc/ypclnt.h"
#endif
@@ -1475,141 +1475,3 @@ BOOL check_hosts_equiv(char *user)
return(False);
}
-
-static struct cli_state cli;
-
-/****************************************************************************
-return the client state structure
-****************************************************************************/
-struct cli_state *server_client(void)
-{
- return &cli;
-}
-
-/****************************************************************************
-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;
- }
-
- if (ismyip(dest_ip)) {
- DEBUG(1,("Password server loop - disabling password server %s\n",p));
- continue;
- }
-
- if (cli_connect(&cli, desthost, &dest_ip)) {
- DEBUG(3,("connected to password server %s\n",p));
- break;
- }
- }
-
- if (!p) {
- DEBUG(1,("password server not available\n"));
- cli_shutdown(&cli);
- return NULL;
- }
-
- if (!cli_session_request(&cli, desthost, 0x20, local_machine)) {
- DEBUG(1,("%s rejected the session\n",desthost));
- cli_shutdown(&cli);
- return NULL;
- }
-
- DEBUG(3,("got session\n"));
-
- if (!cli_negprot(&cli)) {
- DEBUG(1,("%s rejected the negprot\n",desthost));
- cli_shutdown(&cli);
- return NULL;
- }
-
- 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"));
-
- return &cli;
-}
-
-/****************************************************************************
-validate a password with the password server
-****************************************************************************/
-BOOL server_validate(char *user, char *domain,
- char *pass, int passlen,
- char *ntpass, int ntpasslen)
-{
- extern fstring local_machine;
-
- if (!cli.initialised) {
- DEBUG(1,("password server %s is not connected\n", cli.desthost));
- return(False);
- }
-
- if (!cli_session_setup(&cli, user, pass, passlen, ntpass, ntpasslen, domain)) {
- DEBUG(1,("password server %s rejected the password\n", cli.desthost));
- return False;
- }
-
- /* 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);
- }
-
-
- if (!cli_send_tconX(&cli, "IPC$", "IPC", "", 1)) {
- DEBUG(1,("password server %s refused IPC$ connect\n", cli.desthost));
- return False;
- }
-
-
- if (!cli_NetWkstaUserLogon(&cli,user,local_machine)) {
- DEBUG(1,("password server %s failed NetWkstaUserLogon\n", cli.desthost));
- cli_tdis(&cli);
- return False;
- }
-
- if (cli.privilages == 0) {
- DEBUG(1,("password server %s gave guest privilages\n", cli.desthost));
- cli_tdis(&cli);
- return False;
- }
-
- 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;
- }
-
- DEBUG(3,("password server %s accepted the password\n", cli.desthost));
-
- cli_tdis(&cli);
-
- return(True);
-}
-
-
diff --git a/source/smbd/reply.c b/source/smbd/reply.c
index 78dad6f02f5..532fc583c2e 100644
--- a/source/smbd/reply.c
+++ b/source/smbd/reply.c
@@ -395,6 +395,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
static BOOL done_sesssetup = False;
BOOL doencrypt = SMBENCRYPT();
char *domain = "";
+ struct cli_state *pwd_srv = NULL;
*smb_apasswd = 0;
*smb_ntpasswd = 0;
@@ -518,19 +519,17 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
if (!smb_pass)
{
/* lkclXXXX: if workstation entry doesn't exist, indicate logon failure */
- DEBUG(4,("Workstation trust account %s doesn't exist.",user));
- SSVAL(outbuf, smb_flg2, 0xc003); /* PAXX: Someone please unhack this */
- CVAL(outbuf, smb_reh) = 1; /* PAXX: Someone please unhack this */
- return(ERROR(NT_STATUS_LOGON_FAILURE, 0xc000)); /* decimal 109 NT error, 0xc000 */
+ DEBUG(4,("Workstation trust account %s doesn't exist\n",user));
+ SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); /* PAXX: Someone please unhack this */
+ return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE)); /* decimal 109; critical NT error */
}
else
{
/* PAXX: This is the NO LOGON workstation trust account stuff */
/* lkclXXXX: if the workstation *does* exist, indicate failure differently! */
- DEBUG(4,("No Workstation trust account %s",user));
- SSVAL(outbuf, smb_flg2, 0xc003); /* PAXX: Someone please unhack this */
- CVAL(outbuf, smb_reh) = 1; /* PAXX: Someone please unhack this */
- return(ERROR(NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT, 0xc000)); /* decimal 409 NT error, 0xc000 */
+ DEBUG(4,("No Workstation trust account %s\n",user));
+ SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); /* PAXX: Someone please unhack this */
+ return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)); /* decimal 409; critical NT error */
}
computer_id = True;
@@ -563,43 +562,59 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
*/
if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
+ {
guest = True;
+ }
- if (!guest && !(lp_security() == SEC_SERVER &&
- server_validate(user, domain,
- smb_apasswd, smb_apasslen,
- smb_ntpasswd, smb_ntpasslen)) &&
- !check_hosts_equiv(user))
- {
-
- /* now check if it's a valid username/password */
- /* If an NT password was supplied try and validate with that
- first. This is superior as the passwords are mixed case
- 128 length unicode */
- if(smb_ntpasslen)
- {
- if(!password_ok(user,smb_ntpasswd,smb_ntpasslen,NULL))
- DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
- else
- valid_nt_password = True;
- }
- if (!valid_nt_password && !password_ok(user,smb_apasswd,smb_apasslen,NULL))
+ if (!guest && !(lp_security() == SEC_SERVER &&
+ ((pwd_srv = pwd_server_connection()) != NULL) &&
+ server_validate(pwd_srv, user, domain,
+ smb_apasswd, smb_apasslen,
+ smb_ntpasswd, smb_ntpasslen)) &&
+ !check_hosts_equiv(user))
{
- if (!computer_id && lp_security() >= SEC_USER) {
+
+ /* now check if it's a valid username/password */
+ /* If an NT password was supplied try and validate with that
+ first. This is superior as the passwords are mixed case
+ 128 length unicode */
+
+ if (smb_ntpasslen)
+ {
+ /* check the NT password, if there is one. */
+ if(!password_ok(user,smb_ntpasswd,smb_ntpasslen,NULL))
+ {
+ DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
+ }
+ else
+ {
+ valid_nt_password = True;
+ }
+ }
+
+ /* check the LM password instead */
+ if (!valid_nt_password && !password_ok(user,smb_apasswd,smb_apasslen,NULL))
+ {
+ if (!computer_id && lp_security() >= SEC_USER)
+ {
#if (GUEST_SESSSETUP == 0)
- return(ERROR(ERRSRV,ERRbadpw));
+ return(ERROR(ERRSRV,ERRbadpw));
#endif
#if (GUEST_SESSSETUP == 1)
- if (Get_Pwnam(user,True))
- return(ERROR(ERRSRV,ERRbadpw));
+ if (Get_Pwnam(user,True))
+ return(ERROR(ERRSRV,ERRbadpw));
#endif
- }
- if (*smb_apasswd || !Get_Pwnam(user,True))
- strcpy(user,lp_guestaccount(-1));
- DEBUG(3,("Registered username %s for guest access\n",user));
- guest = True;
+ }
+
+ /* no lm or nt password specified: username doesn't exist. allow guest access */
+ if (*smb_apasswd || !Get_Pwnam(user,True))
+ {
+ strcpy(user, lp_guestaccount(-1));
+ DEBUG(3,("Registered username %s for guest access\n",user));
+ guest = True;
+ }
+ }
}
- }
if (!Get_Pwnam(user,True)) {
DEBUG(3,("No such user %s - using guest account\n",user));
diff --git a/source/smbd/server.c b/source/smbd/server.c
index 908cf984b8e..a42b4deea24 100644
--- a/source/smbd/server.c
+++ b/source/smbd/server.c
@@ -25,6 +25,7 @@
pstring servicesf = CONFIGFILE;
extern pstring debugf;
extern pstring sesssetup_user;
+extern pstring local_machine;
extern fstring myworkgroup;
char *InBuffer = NULL;
@@ -114,6 +115,21 @@ static int find_free_connection(int hash);
#define IS_DOS_SYSTEM(test_mode) (((test_mode) & aSYSTEM) != 0)
#define IS_DOS_HIDDEN(test_mode) (((test_mode) & aHIDDEN) != 0)
+/* use this to validate user against a password server. "security = server" */
+static struct cli_state pwd_srv;
+
+/****************************************************************************
+ for use in reply.c, to access the password server connection.
+****************************************************************************/
+struct cli_state *pwd_server_connection(void)
+{
+ if (pwd_srv.initialised)
+ {
+ return &pwd_srv;
+ }
+ return NULL;
+}
+
/****************************************************************************
when exiting, take the whole family
****************************************************************************/
@@ -2257,21 +2273,30 @@ int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int
{
int outsize = set_message(outbuf,0,0,True);
int cmd;
- cmd = CVAL(inbuf,smb_com);
-
- CVAL(outbuf,smb_rcls) = error_class;
- SSVAL(outbuf,smb_err,error_code);
+ int flgs2;
+ cmd = CVAL(inbuf,smb_com);
+ flgs2 = SVAL(outbuf,smb_flg2);
- DEBUG(3,("%s error packet at line %d cmd=%d (%s) eclass=%d ecode=%d\n",
- timestring(),
- line,
- (int)CVAL(inbuf,smb_com),
- smb_fn_name(CVAL(inbuf,smb_com)),
- error_class,
- error_code));
+ if ((flgs2 & FLAGS2_32_BIT_ERROR_CODES) == FLAGS2_32_BIT_ERROR_CODES)
+ {
+ SIVAL(outbuf,smb_rcls,error_code);
+
+ DEBUG(3,("%s 32 bit error packet at line %d cmd=%d (%s) eclass=%08x [%s]\n",
+ timestring(), line, cmd, smb_fn_name(cmd), error_code, smb_errstr(outbuf)));
+ }
+ else
+ {
+ CVAL(outbuf,smb_rcls) = error_class;
+ SSVAL(outbuf,smb_err,error_code);
+ DEBUG(3,("%s error packet at line %d cmd=%d (%s) eclass=%d ecode=%d\n",
+ timestring(), line, cmd, smb_fn_name(cmd), error_class, error_code));
+ }
+
if (errno != 0)
- DEBUG(3,("error string = %s\n",strerror(errno)));
+ {
+ DEBUG(3,("error string = %s\n", strerror(errno)));
+ }
return(outsize);
}
@@ -2328,12 +2353,13 @@ static int sig_cld()
**************************************************************************/
static int sig_pipe()
{
- struct cli_state *cli;
BlockSignals(True,SIGPIPE);
- if ((cli = server_client()) && cli->initialised) {
+ if (pwd_srv.initialised)
+ {
DEBUG(3,("lost connection to password server\n"));
- cli_shutdown(cli);
+ cli_shutdown(&pwd_srv);
+
#ifndef DONT_REINSTALL_SIG
signal(SIGPIPE, SIGNAL_CAST sig_pipe);
#endif
@@ -3684,29 +3710,27 @@ int reply_lanman2(char *outbuf)
int secword=0;
BOOL doencrypt = SMBENCRYPT();
time_t t = time(NULL);
- struct cli_state *cli = NULL;
char cryptkey[8];
char crypt_len = 0;
- if (lp_security() == SEC_SERVER) {
- cli = server_cryptkey();
- }
-
- if (cli) {
+ if (lp_security() == SEC_SERVER && server_cryptkey(&pwd_srv, local_machine))
+ {
DEBUG(3,("using password server validation\n"));
- doencrypt = ((cli->sec_mode & 2) != 0);
+ doencrypt = ((pwd_srv.sec_mode & 2) != 0);
}
if (lp_security()>=SEC_USER) secword |= 1;
if (doencrypt) secword |= 2;
- if (doencrypt) {
+ if (doencrypt)
+ {
crypt_len = 8;
- if (!cli) {
+ if (pwd_srv.initialised)
+ {
generate_next_challenge(cryptkey);
} else {
- memcpy(cryptkey, cli->cryptkey, 8);
- set_challenge(cli->cryptkey);
+ memcpy(cryptkey, pwd_srv.cryptkey, 8);
+ set_challenge(pwd_srv.cryptkey);
}
}
@@ -3751,16 +3775,14 @@ int reply_nt1(char *outbuf)
char cryptkey[8];
char crypt_len = 0;
- if (lp_security() == SEC_SERVER) {
- cli = server_cryptkey();
- }
-
- if (cli) {
+ if (lp_security() == SEC_SERVER && server_cryptkey(&pwd_srv, local_machine))
+ {
DEBUG(3,("using password server validation\n"));
- doencrypt = ((cli->sec_mode & 2) != 0);
+ doencrypt = ((pwd_srv.sec_mode & 2) != 0);
}
- if (doencrypt) {
+ if (doencrypt)
+ {
crypt_len = 8;
if (!cli) {
generate_next_challenge(cryptkey);
@@ -4862,15 +4884,14 @@ static void process(void)
if (keepalive && (counter-last_keepalive)>keepalive)
{
- struct cli_state *cli = server_client();
if (!send_keepalive(Client)) {
DEBUG(2,("%s Keepalive failed - exiting\n",timestring()));
return;
}
/* also send a keepalive to the password server if its still
connected */
- if (cli && cli->initialised)
- send_keepalive(cli->fd);
+ if (pwd_srv.initialised)
+ send_keepalive(pwd_srv.fd);
last_keepalive = counter;
}
diff --git a/source/utils/torture.c b/source/utils/torture.c
index 506f31481c3..a0e32ff3954 100644
--- a/source/utils/torture.c
+++ b/source/utils/torture.c
@@ -46,12 +46,14 @@ static double end_timer()
static BOOL open_connection(struct cli_state *c)
{
- if (!cli_initialise(c) || !cli_connect(c, host, NULL)) {
+ if (!cli_initialise(c) || !cli_connect(c, host, NULL))
+ {
printf("Failed to connect with %s\n", host);
return False;
}
- if (!cli_session_request(c, host, 0x20, myname)) {
+ if (!cli_session_request(c, host, 0x20, myname, 0x0))
+ {
printf("%s rejected the session\n",host);
cli_shutdown(c);
return False;