Skip to content

Commit

Permalink
[CIFS] Support for setting up SMB sessions to legacy lanman servers
Browse files Browse the repository at this point in the history
  • Loading branch information
Steve French committed May 31, 2006
1 parent 26a21b9 commit 3979877
Show file tree
Hide file tree
Showing 20 changed files with 837 additions and 76 deletions.
40 changes: 38 additions & 2 deletions fs/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -1663,7 +1663,7 @@ config CIFS_STATS
mounted by the cifs client to be displayed in /proc/fs/cifs/Stats

config CIFS_STATS2
bool "CIFS extended statistics"
bool "Extended statistics"
depends on CIFS_STATS
help
Enabling this option will allow more detailed statistics on SMB
Expand All @@ -1676,6 +1676,32 @@ config CIFS_STATS2
Unless you are a developer or are doing network performance analysis
or tuning, say N.

config CIFS_WEAK_PW_HASH
bool "Support legacy servers which use weaker LANMAN security"
depends on CIFS
help
Modern CIFS servers including Samba and most Windows versions
(since 1997) support stronger NTLM (and even NTLMv2 and Kerberos)
security mechanisms. These hash the password more securely
than the mechanisms used in the older LANMAN version of the
SMB protocol needed to establish sessions with old SMB servers.

Enabling this option allows the cifs module to mount to older
LANMAN based servers such as OS/2 and Windows 95, but such
mounts may be less secure than mounts using NTLM or more recent
security mechanisms if you are on a public network. Unless you
have a need to access old SMB servers (and are on a private
network) you probably want to say N. Even if this support
is enabled in the kernel build, they will not be used
automatically. At runtime LANMAN mounts are disabled but
can be set to required (or optional) either in
/proc/fs/cifs (see fs/cifs/README for more detail) or via an
option on the mount command. This support is disabled by
default in order to reduce the possibility of a downgrade
attack.

If unsure, say N.

config CIFS_XATTR
bool "CIFS extended attributes"
depends on CIFS
Expand Down Expand Up @@ -1704,6 +1730,16 @@ config CIFS_POSIX
(such as Samba 3.10 and later) which can negotiate
CIFS POSIX ACL support. If unsure, say N.

config CIFS_DEBUG2
bool "Enable additional CIFS debugging routines
help
Enabling this option adds a few more debugging routines
to the cifs code which slightly increases the size of
the cifs module and can cause additional logging of debug
messages in some error paths, slowing performance. This
option can be turned off unless you are debugging
cifs problems. If unsure, say N.

config CIFS_EXPERIMENTAL
bool "CIFS Experimental Features (EXPERIMENTAL)"
depends on CIFS && EXPERIMENTAL
Expand All @@ -1719,7 +1755,7 @@ config CIFS_EXPERIMENTAL
If unsure, say N.

config CIFS_UPCALL
bool "CIFS Kerberos/SPNEGO advanced session setup (EXPERIMENTAL)"
bool "Kerberos/SPNEGO advanced session setup (EXPERIMENTAL)"
depends on CIFS_EXPERIMENTAL
select CONNECTOR
help
Expand Down
5 changes: 5 additions & 0 deletions fs/cifs/CHANGES
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
Version 1.44
------------
Rewritten sessionsetup support, including support for legacy SMB
session setup needed for OS/2 and older servers such as Windows 95 and 98.

Version 1.43
------------
POSIX locking to servers which support CIFS POSIX Extensions
Expand Down
2 changes: 1 addition & 1 deletion fs/cifs/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
#
obj-$(CONFIG_CIFS) += cifs.o

cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o readdir.o ioctl.o ntlmssp.o
cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o readdir.o ioctl.o sess.o
84 changes: 71 additions & 13 deletions fs/cifs/cifs_debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ cifs_dump_mem(char *label, void *data, int length)
char *charptr = data;
char buf[10], line[80];

printk(KERN_DEBUG "%s: dump of %d bytes of data at 0x%p\n\n",
printk(KERN_DEBUG "%s: dump of %d bytes of data at 0x%p\n",
label, length, data);
for (i = 0; i < length; i += 16) {
line[0] = 0;
Expand All @@ -57,6 +57,57 @@ cifs_dump_mem(char *label, void *data, int length)
}
}

#ifdef CONFIG_CIFS_DEBUG2
void cifs_dump_detail(struct smb_hdr * smb)
{
cERROR(1,("Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d",
smb->Command, smb->Status.CifsError,
smb->Flags, smb->Flags2, smb->Mid, smb->Pid));
cERROR(1,("smb buf %p len %d", smb, smbCalcSize_LE(smb)));
}


void cifs_dump_mids(struct TCP_Server_Info * server)
{
struct list_head *tmp;
struct mid_q_entry * mid_entry;

if(server == NULL)
return;

cERROR(1,("Dump pending requests:"));
spin_lock(&GlobalMid_Lock);
list_for_each(tmp, &server->pending_mid_q) {
mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
if(mid_entry) {
cERROR(1,("State: %d Cmd: %d Pid: %d Tsk: %p Mid %d",
mid_entry->midState,
(int)mid_entry->command,
mid_entry->pid,
mid_entry->tsk,
mid_entry->mid));
#ifdef CONFIG_CIFS_STATS2
cERROR(1,("IsLarge: %d buf: %p time rcv: %ld now: %ld",
mid_entry->largeBuf,
mid_entry->resp_buf,
mid_entry->when_received,
jiffies));
#endif /* STATS2 */
cERROR(1,("IsMult: %d IsEnd: %d", mid_entry->multiRsp,
mid_entry->multiEnd));
if(mid_entry->resp_buf) {
cifs_dump_detail(mid_entry->resp_buf);
cifs_dump_mem("existing buf: ",
mid_entry->resp_buf,
62 /* fixme */);
}

}
}
spin_unlock(&GlobalMid_Lock);
}
#endif /* CONFIG_CIFS_DEBUG2 */

#ifdef CONFIG_PROC_FS
static int
cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
Expand All @@ -73,7 +124,6 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,

*beginBuffer = buf + offset;


length =
sprintf(buf,
"Display Internal CIFS Data Structures for Debugging\n"
Expand Down Expand Up @@ -397,10 +447,10 @@ static read_proc_t multiuser_mount_read;
static write_proc_t multiuser_mount_write;
static read_proc_t extended_security_read;
static write_proc_t extended_security_write;
static read_proc_t ntlmv2_enabled_read;
/* static read_proc_t ntlmv2_enabled_read;
static write_proc_t ntlmv2_enabled_write;
static read_proc_t packet_signing_enabled_read;
static write_proc_t packet_signing_enabled_write;
static write_proc_t packet_signing_enabled_write;*/
static read_proc_t experimEnabled_read;
static write_proc_t experimEnabled_write;
static read_proc_t linuxExtensionsEnabled_read;
Expand Down Expand Up @@ -469,7 +519,7 @@ cifs_proc_init(void)
if (pde)
pde->write_proc = lookupFlag_write;

pde =
/* pde =
create_proc_read_entry("NTLMV2Enabled", 0, proc_fs_cifs,
ntlmv2_enabled_read, NULL);
if (pde)
Expand All @@ -479,7 +529,7 @@ cifs_proc_init(void)
create_proc_read_entry("PacketSigningEnabled", 0, proc_fs_cifs,
packet_signing_enabled_read, NULL);
if (pde)
pde->write_proc = packet_signing_enabled_write;
pde->write_proc = packet_signing_enabled_write;*/
}

void
Expand All @@ -496,9 +546,9 @@ cifs_proc_clean(void)
#endif
remove_proc_entry("MultiuserMount", proc_fs_cifs);
remove_proc_entry("OplockEnabled", proc_fs_cifs);
remove_proc_entry("NTLMV2Enabled",proc_fs_cifs);
/* remove_proc_entry("NTLMV2Enabled",proc_fs_cifs); */
remove_proc_entry("ExtendedSecurity",proc_fs_cifs);
remove_proc_entry("PacketSigningEnabled",proc_fs_cifs);
/* remove_proc_entry("PacketSigningEnabled",proc_fs_cifs); */
remove_proc_entry("LinuxExtensionsEnabled",proc_fs_cifs);
remove_proc_entry("Experimental",proc_fs_cifs);
remove_proc_entry("LookupCacheEnabled",proc_fs_cifs);
Expand Down Expand Up @@ -787,7 +837,7 @@ extended_security_read(char *page, char **start, off_t off,
{
int len;

len = sprintf(page, "%d\n", extended_security);
len = sprintf(page, "0x%x\n", extended_security);

len -= off;
*start = page + off;
Expand All @@ -808,19 +858,25 @@ extended_security_write(struct file *file, const char __user *buffer,
{
char c;
int rc;
cERROR(1,("size %ld",count)); /* BB removeme BB */
if((count < 2) || (count > 8))
return -EINVAL;

rc = get_user(c, buffer);

/* BB fixme need to parse more characters in order to handle CIFSSEC flags */

if (rc)
return rc;
if (c == '0' || c == 'n' || c == 'N')
extended_security = 0;
extended_security = CIFSSEC_DEF; /* default */
else if (c == '1' || c == 'y' || c == 'Y')
extended_security = 1;
extended_security = CIFSSEC_MAX;

return count;
}

static int
/* static int
ntlmv2_enabled_read(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
Expand Down Expand Up @@ -855,6 +911,8 @@ ntlmv2_enabled_write(struct file *file, const char __user *buffer,
ntlmv2_support = 0;
else if (c == '1' || c == 'y' || c == 'Y')
ntlmv2_support = 1;
else if (c == '2')
ntlmv2_support = 2;
return count;
}
Expand Down Expand Up @@ -898,7 +956,7 @@ packet_signing_enabled_write(struct file *file, const char __user *buffer,
sign_CIFS_PDUs = 2;
return count;
}
} */


#endif
4 changes: 4 additions & 0 deletions fs/cifs/cifs_debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@
#define _H_CIFS_DEBUG

void cifs_dump_mem(char *label, void *data, int length);
#ifdef CONFIG_CIFS_DEBUG2
void cifs_dump_detail(struct smb_hdr *);
void cifs_dump_mids(struct TCP_Server_Info *);
#endif
extern int traceSMB; /* flag which enables the function below */
void dump_smb(struct smb_hdr *, int);
#define CIFS_INFO 0x01
Expand Down
1 change: 1 addition & 0 deletions fs/cifs/cifs_unicode.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "cifs_unicode.h"
#include "cifs_uniupr.h"
#include "cifspdu.h"
#include "cifsglob.h"
#include "cifs_debug.h"

/*
Expand Down
2 changes: 2 additions & 0 deletions fs/cifs/cifsencrypt.c
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,8 @@ int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses, struct nls_table * nls_
user_name_len = strlen(ses->userName);
if(user_name_len > MAX_USERNAME_SIZE)
return -EINVAL;
if(ses->domainName == NULL)
return -EINVAL; /* BB should we use CIFS_LINUX_DOM */
dom_name_len = strlen(ses->domainName);
if(dom_name_len > MAX_USERNAME_SIZE)
return -EINVAL;
Expand Down
4 changes: 2 additions & 2 deletions fs/cifs/cifsfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ unsigned int experimEnabled = 0;
unsigned int linuxExtEnabled = 1;
unsigned int lookupCacheEnabled = 1;
unsigned int multiuser_mount = 0;
unsigned int extended_security = 0;
unsigned int ntlmv2_support = 0;
unsigned int extended_security = CIFSSEC_DEF;
/* unsigned int ntlmv2_support = 0; */
unsigned int sign_CIFS_PDUs = 1;
extern struct task_struct * oplockThread; /* remove sparse warning */
struct task_struct * oplockThread = NULL;
Expand Down
51 changes: 37 additions & 14 deletions fs/cifs/cifsglob.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ enum statusEnum {
};

enum securityEnum {
NTLM = 0, /* Legacy NTLM012 auth with NTLM hash */
LANMAN = 0, /* Legacy LANMAN auth */
NTLM, /* Legacy NTLM012 auth with NTLM hash */
NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */
RawNTLMSSP, /* NTLMSSP without SPNEGO */
NTLMSSP, /* NTLMSSP via SPNEGO */
Expand Down Expand Up @@ -179,7 +180,9 @@ struct cifsUidInfo {
struct cifsSesInfo {
struct list_head cifsSessionList;
struct semaphore sesSem;
#if 0
struct cifsUidInfo *uidInfo; /* pointer to user info */
#endif
struct TCP_Server_Info *server; /* pointer to server info */
atomic_t inUse; /* # of mounts (tree connections) on this ses */
enum statusEnum status;
Expand All @@ -194,7 +197,7 @@ struct cifsSesInfo {
char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for
TCP names - will ipv6 and sctp addresses fit? */
char userName[MAX_USERNAME_SIZE + 1];
char domainName[MAX_USERNAME_SIZE + 1];
char * domainName;
char * password;
};
/* session flags */
Expand Down Expand Up @@ -391,9 +394,9 @@ struct mid_q_entry {
struct smb_hdr *resp_buf; /* response buffer */
int midState; /* wish this were enum but can not pass to wait_event */
__u8 command; /* smb command code */
unsigned multiPart:1; /* multiple responses to one SMB request */
unsigned largeBuf:1; /* if valid response, is pointer to large buf */
unsigned multiResp:1; /* multiple trans2 responses for one request */
unsigned multiRsp:1; /* multiple trans2 responses for one request */
unsigned multiEnd:1; /* both received */
};

struct oplock_q_entry {
Expand Down Expand Up @@ -430,15 +433,35 @@ struct dir_notify_req {
#define CIFS_LARGE_BUFFER 2
#define CIFS_IOVEC 4 /* array of response buffers */

/* Type of session setup needed */
#define CIFS_PLAINTEXT 0
#define CIFS_LANMAN 1
#define CIFS_NTLM 2
#define CIFS_NTLMSSP_NEG 3
#define CIFS_NTLMSSP_AUTH 4
#define CIFS_SPNEGO_INIT 5
#define CIFS_SPNEGO_TARG 6

/* Security Flags: indicate type of session setup needed */
#define CIFSSEC_MAY_SIGN 0x00001
#define CIFSSEC_MAY_NTLM 0x00002
#define CIFSSEC_MAY_NTLMV2 0x00004
#define CIFSSEC_MAY_KRB5 0x00008
#ifdef CONFIG_CIFS_WEAK_PW_HASH
#define CIFSSEC_MAY_LANMAN 0x00010
#define CIFSSEC_MAY_PLNTXT 0x00020
#endif /* weak passwords */
#define CIFSSEC_MAY_SEAL 0x00040 /* not supported yet */

#define CIFSSEC_MUST_SIGN 0x01001
/* note that only one of the following can be set so the
result of setting MUST flags more than once will be to
require use of the stronger protocol */
#define CIFSSEC_MUST_NTLM 0x02002
#define CIFSSEC_MUST_NTLMV2 0x04004
#define CIFSSEC_MUST_KRB5 0x08008
#ifdef CONFIG_CIFS_WEAK_PW_HASH
#define CIFSSEC_MUST_LANMAN 0x10010
#define CIFSSEC_MUST_PLNTXT 0x20020
#define CIFSSEC_MASK 0x37037 /* current flags supported if weak */
#else
#define CIFSSEC_MASK 0x07007 /* flags supported if no weak config */
#endif /* WEAK_PW_HASH */
#define CIFSSEC_MUST_SEAL 0x40040 /* not supported yet */

#define CIFSSEC_DEF CIFSSEC_MAY_SIGN | CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2
#define CIFSSEC_MAX CIFSSEC_MUST_SIGN | CIFSSEC_MUST_NTLMV2
/*
*****************************************************************
* All constants go here
Expand Down Expand Up @@ -540,8 +563,8 @@ GLOBAL_EXTERN unsigned int experimEnabled;
GLOBAL_EXTERN unsigned int lookupCacheEnabled;
GLOBAL_EXTERN unsigned int extended_security; /* if on, session setup sent
with more secure ntlmssp2 challenge/resp */
GLOBAL_EXTERN unsigned int ntlmv2_support; /* better optional password hash */
GLOBAL_EXTERN unsigned int sign_CIFS_PDUs; /* enable smb packet signing */
GLOBAL_EXTERN unsigned int secFlags;
GLOBAL_EXTERN unsigned int linuxExtEnabled;/*enable Linux/Unix CIFS extensions*/
GLOBAL_EXTERN unsigned int CIFSMaxBufSize; /* max size not including hdr */
GLOBAL_EXTERN unsigned int cifs_min_rcv; /* min size of big ntwrk buf pool */
Expand Down
Loading

0 comments on commit 3979877

Please sign in to comment.