summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/smb.h4
-rw-r--r--source3/lib/genrand.c41
-rw-r--r--source3/param/loadparm.c6
-rw-r--r--source3/smbd/password.c39
-rw-r--r--source3/smbd/reply.c12
-rw-r--r--source3/smbd/server.c4
6 files changed, 93 insertions, 13 deletions
diff --git a/source3/include/smb.h b/source3/include/smb.h
index 46e282b2ba..4438024dbd 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -1061,7 +1061,11 @@ char *Strstr(char *s, char *p);
enum protocol_types {PROTOCOL_NONE,PROTOCOL_CORE,PROTOCOL_COREPLUS,PROTOCOL_LANMAN1,PROTOCOL_LANMAN2,PROTOCOL_NT1};
/* security levels */
+#ifdef DOMAIN_CLIENT
+enum security_types {SEC_SHARE,SEC_USER,SEC_SERVER,SEC_DOMAIN};
+#else /* DOMAIN_CLIENT */
enum security_types {SEC_SHARE,SEC_USER,SEC_SERVER};
+#endif /* DOMAIN_CLIENT */
/* printing types */
enum printing_types {PRINT_BSD,PRINT_SYSV,PRINT_AIX,PRINT_HPUX,
diff --git a/source3/lib/genrand.c b/source3/lib/genrand.c
index 8d7084d9f6..e20f054504 100644
--- a/source3/lib/genrand.c
+++ b/source3/lib/genrand.c
@@ -26,7 +26,6 @@
extern int DEBUGLEVEL;
static uint32 counter = 0;
-
/****************************************************************
get a 16 byte hash from the contents of a file
Note that the hash is not initialised.
@@ -102,18 +101,19 @@ static void do_dirrand(char *name, unsigned char *buf, int buf_len)
Try and get a good random number seed. Try a number of
different factors. Firstly, try /dev/random and try and
read from this. If this fails iterate through /tmp and
- XOR all the file timestamps. If this fails then just use
- a combination of pid and time of day (yes I know this
+ /dev and XOR all the file timestamps. Next add in
+ a hash of the contents of /etc/shadow and the smb passwd
+ file and a combination of pid and time of day (yes I know this
sucks :-). Finally md4 the result.
The result goes in a 16 byte buffer passed from the caller
**************************************************************/
-static void do_reseed(unsigned char *md4_outbuf)
+static uint32 do_reseed(unsigned char *md4_outbuf)
{
unsigned char md4_inbuf[40];
BOOL got_random = False;
- uint32 v1, v2;
+ uint32 v1, v2, ret;
int fd;
struct timeval tval;
pid_t mypid;
@@ -135,7 +135,7 @@ static void do_reseed(unsigned char *md4_outbuf)
if(!got_random) {
/*
- * /dev/random failed - try /tmp/ for timestamps.
+ * /dev/random failed - try /tmp and /dev for timestamps.
*/
do_dirrand("/tmp", md4_inbuf, sizeof(md4_inbuf));
do_dirrand("/dev", md4_inbuf, sizeof(md4_inbuf));
@@ -148,7 +148,7 @@ static void do_reseed(unsigned char *md4_outbuf)
/* add in the root encrypted password. On any system where security is taken
seriously this will be secret */
pw = getpwnam("root");
- if (pw) {
+ if (pw && pw->pw_passwd) {
int i;
unsigned char md4_tmp[16];
mdfour(md4_tmp, pw->pw_passwd, strlen(pw->pw_passwd));
@@ -168,6 +168,16 @@ static void do_reseed(unsigned char *md4_outbuf)
SIVAL(md4_inbuf, 36, v2 ^ IVAL(md4_inbuf, 36));
mdfour(md4_outbuf, md4_inbuf, sizeof(md4_inbuf));
+
+ /*
+ * Return a 32 bit int created from XORing the
+ * 16 bit return buffer.
+ */
+
+ ret = IVAL(md4_outbuf, 0);
+ ret ^= IVAL(md4_outbuf, 4);
+ ret ^= IVAL(md4_outbuf, 8);
+ return (ret ^ IVAL(md4_outbuf, 12));
}
/*******************************************************************
@@ -177,25 +187,38 @@ static void do_reseed(unsigned char *md4_outbuf)
void generate_random_buffer( unsigned char *out, int len, BOOL re_seed)
{
static BOOL done_reseed = False;
+ static unsigned char md4_buf[16];
unsigned char tmp_buf[16];
- unsigned char md4_buf[16];
unsigned char *p;
if(!done_reseed || re_seed) {
- do_reseed(md4_buf);
+ srandom(do_reseed(md4_buf));
done_reseed = True;
}
/*
* Generate random numbers in chunks of 64 bytes,
* then md4 them & copy to the output buffer.
+ * Added XOR with output from random, seeded
+ * by the original md4_buf. This is to stop the
+ * output from this function being the previous
+ * md4_buf md4'ed. The output from this function
+ * is often output onto the wire, and so it should
+ * not be possible to guess the next output from
+ * this function based on the previous output.
+ * XORing in the output from random(), seeded by
+ * the original md4 hash should stop this. JRA.
*/
p = out;
while(len > 0) {
+ int i;
int copy_len = len > 16 ? 16 : len;
mdfour(tmp_buf, md4_buf, sizeof(md4_buf));
memcpy(md4_buf, tmp_buf, sizeof(md4_buf));
+ /* XOR in output from random(). */
+ for(i = 0; i < 4; i++)
+ SIVAL(tmp_buf, i*4, (IVAL(tmp_buf, i*4) ^ (uint32)random()));
memcpy(p, tmp_buf, copy_len);
p += copy_len;
len -= copy_len;
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index ce9b816e81..661ca901fa 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -402,8 +402,14 @@ static struct enum_list enum_protocol[] = {{PROTOCOL_NT1, "NT1"}, {PROTOCOL_LANM
{PROTOCOL_COREPLUS, "COREPLUS"},
{PROTOCOL_COREPLUS, "CORE+"}, {-1, NULL}};
+#ifdef DOMAIN_CLIENT
+static struct enum_list enum_security[] = {{SEC_SHARE, "SHARE"}, {SEC_USER, "USER"},
+ {SEC_SERVER, "SERVER"}, {SEC_DOMAIN, "DOMAIN"},
+ {-1, NULL}};
+#else /* DOMAIN_CLIENT */
static struct enum_list enum_security[] = {{SEC_SHARE, "SHARE"}, {SEC_USER, "USER"},
{SEC_SERVER, "SERVER"}, {-1, NULL}};
+#endif /* DOMAIN_CLIENT */
static struct enum_list enum_printing[] = {{PRINT_SYSV, "sysv"}, {PRINT_AIX, "aix"},
{PRINT_HPUX, "hpux"}, {PRINT_BSD, "bsd"},
diff --git a/source3/smbd/password.c b/source3/smbd/password.c
index b69b58f54e..c347f2de0d 100644
--- a/source3/smbd/password.c
+++ b/source3/smbd/password.c
@@ -1755,12 +1755,48 @@ BOOL server_validate(char *user, char *domain,
char *ntpass, int ntpasslen)
{
extern fstring local_machine;
+ static unsigned char badpass[24];
if (!cli.initialised) {
DEBUG(1,("password server %s is not connected\n", cli.desthost));
return(False);
}
+ if(badpass[0] == 0) {
+ memset(badpass, 0x1f, sizeof(badpass));
+ }
+
+ if((passlen == sizeof(badpass)) && !memcmp(badpass, pass, passlen)) {
+ /* Very unlikely, our random bad password is the same as the users
+ password. */
+ memset(badpass, badpass[0]+1, sizeof(badpass));
+ }
+
+ /*
+ * Attempt a session setup with a totally incorrect password.
+ * If this succeeds with the guest bit *NOT* set then the password
+ * server is broken and is not correctly setting the guest bit. We
+ * need to detect this as some versions of NT4.x are broken. JRA.
+ */
+
+ if (cli_session_setup(&cli, user, badpass, sizeof(badpass), badpass, sizeof(badpass),
+ domain)) {
+ if ((SVAL(cli.inbuf,smb_vwv2) & 1) == 0) {
+ DEBUG(0,("server_validate: password server %s allows users as non-guest \
+with a bad password.\n", cli.desthost));
+ DEBUG(0,("server_validate: This is broken (and insecure) behaviour. Please do not \
+use this machine as the password server.\n"));
+ cli_ulogoff(&cli);
+ return False;
+ }
+ cli_ulogoff(&cli);
+ }
+
+ /*
+ * Now we know the password server will correctly set the guest bit, or is
+ * not guest enabled, we can try with the real password.
+ */
+
if (!cli_session_setup(&cli, user, pass, passlen, ntpass, ntpasslen, domain)) {
DEBUG(1,("password server %s rejected the password\n", cli.desthost));
return False;
@@ -1773,7 +1809,6 @@ BOOL server_validate(char *user, char *domain,
return(False);
}
-
if (!cli_send_tconX(&cli, "IPC$", "IPC", "", 1)) {
DEBUG(1,("password server %s refused IPC$ connect\n", cli.desthost));
cli_ulogoff(&cli);
@@ -1825,5 +1860,3 @@ BOOL server_validate(char *user, char *domain,
return(True);
}
-
-
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index 2c4800b1c2..2f3b3660fc 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -515,7 +515,11 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
passlen1 = MIN(passlen1, MAX_PASS_LEN);
passlen2 = MIN(passlen2, MAX_PASS_LEN);
- if(doencrypt || (lp_security() == SEC_SERVER)) {
+#ifdef DOMAIN_CLIENT
+ if(doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) {
+#else /* DOMAIN_CLIENT */
+ if(doencrypt || lp_security() == SEC_SERVER) {
+#endif /* DOMAIN_CLIENT */
/* Save the lanman2 password and the NT md4 password. */
smb_apasslen = passlen1;
memcpy(smb_apasswd,p,smb_apasslen);
@@ -603,6 +607,12 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
server_validate(user, domain,
smb_apasswd, smb_apasslen,
smb_ntpasswd, smb_ntpasslen)) &&
+#ifdef DOMAIN_CLIENT
+ !(lp_security() == SEC_DOMAIN &&
+ domain_client_validate(user, domain,
+ smb_apasswd, smb_apasslen,
+ smb_ntpasswd, smb_ntpasslen)) &&
+#endif /* DOMAIN_CLIENT */
!check_hosts_equiv(user))
{
diff --git a/source3/smbd/server.c b/source3/smbd/server.c
index 4a3edeb871..81fe5c9306 100644
--- a/source3/smbd/server.c
+++ b/source3/smbd/server.c
@@ -4133,7 +4133,11 @@ static int reply_negprot(char *inbuf,char *outbuf, int dum_size, int dum_buffsiz
/* a special case to stop password server loops */
if (Index == 1 && strequal(remote_machine,myhostname) &&
+#ifdef DOMAIN_CLIENT
+ (lp_security()==SEC_SERVER || lp_security()==SEC_DOMAIN))
+#else /* DOMAIN_CLIENT */
lp_security()==SEC_SERVER)
+#endif /* DOMAIN_CLIENT */
exit_server("Password server loop!");
/* Check for protocols, most desirable first */