Commit fdcd7356 authored by Steve French's avatar Steve French Committed by Steve French

Signing fixes part 2

parent 0cfb3b99
...@@ -3,4 +3,4 @@ ...@@ -3,4 +3,4 @@
# #
obj-$(CONFIG_CIFS) += cifs.o 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 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
/*
* fs/cifs/cifsencrypt.c
*
* Copyright (c) International Business Machines Corp., 2003
* Author(s): Steve French (sfrench@us.ibm.com)
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/fs.h>
#include "cifspdu.h"
#include "cifsglob.h"
#include "cifs_debug.h"
/* Calculate and return the CIFS signature based on the mac key and the smb pdu */
/* the eight byte signature must be allocated by the caller. */
/* Note that the smb header signature field on input contains the
sequence number before this function is called */
static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu, const char * mac_key, char * signature)
{
if((cifs_pdu == NULL) || (signature == NULL))
return -EINVAL;
/* MD5(mac_key, text) */
/* return 1st eight bytes in signature */
return 0;
}
int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct cifsSesInfo * ses)
{
int rc = 0;
char smb_signature[8];
/* BB remember to initialize sequence number elsewhere and initialize mac_signing key elsewhere BB */
/* BB remember to add code to save expected sequence number in midQ entry BB */
if((cifs_pdu == NULL) || (ses == NULL))
return -EINVAL;
if((le32_to_cpu(cifs_pdu->Flags2) & SMBFLG2_SECURITY_SIGNATURE) == 0)
return rc;
cifs_pdu->Signature.Sequence.SequenceNumber = ses->sequence_number;
cifs_pdu->Signature.Sequence.Reserved = 0;
rc = cifs_calculate_signature(cifs_pdu, ses->mac_signing_key,smb_signature);
if(rc)
memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
else
memcpy(cifs_pdu->Signature.SecuritySignature, smb_signature, 8);
return rc;
}
int cifs_verify_signature(const struct smb_hdr * cifs_pdu, const char * mac_key,
__u32 expected_sequence_number)
{
unsigned int rc = 0;
if((cifs_pdu == NULL) || (mac_key == NULL))
return -EINVAL;
/* BB no need to verify negprot or if flag is not on for session (or for frame?? */
/* BB what if signatures are supposed to be on for session but server does not
send one? BB */
/* BB also do not verify oplock breaks for signature */
return rc;
}
...@@ -149,7 +149,9 @@ struct cifsSesInfo { ...@@ -149,7 +149,9 @@ struct cifsSesInfo {
struct TCP_Server_Info *server; /* pointer to server info */ struct TCP_Server_Info *server; /* pointer to server info */
atomic_t inUse; /* # of CURRENT users of this ses */ atomic_t inUse; /* # of CURRENT users of this ses */
enum statusEnum status; enum statusEnum status;
__u32 sequence_number; /* needed for CIFS PDU signature */
__u16 ipc_tid; /* special tid for connection to IPC share */ __u16 ipc_tid; /* special tid for connection to IPC share */
char mac_signing_key[CIFS_SESSION_KEY_SIZE];
char *serverOS; /* name of operating system underlying the server */ char *serverOS; /* name of operating system underlying the server */
char *serverNOS; /* name of network operating system that the server is running */ char *serverNOS; /* name of network operating system that the server is running */
char *serverDomain; /* security realm of server */ char *serverDomain; /* security realm of server */
...@@ -249,6 +251,7 @@ struct mid_q_entry { ...@@ -249,6 +251,7 @@ struct mid_q_entry {
struct list_head qhead; /* mids waiting on reply from this server */ struct list_head qhead; /* mids waiting on reply from this server */
__u16 mid; /* multiplex id */ __u16 mid; /* multiplex id */
__u16 pid; /* process id */ __u16 pid; /* process id */
__u32 sequence_number; /* for CIFS signing */
__u16 command; /* smb command code */ __u16 command; /* smb command code */
struct timeval when_sent; /* time when smb sent */ struct timeval when_sent; /* time when smb sent */
struct cifsSesInfo *ses; /* smb was sent to this server */ struct cifsSesInfo *ses; /* smb was sent to this server */
......
...@@ -307,7 +307,13 @@ struct smb_hdr { ...@@ -307,7 +307,13 @@ struct smb_hdr {
__u8 Flags; __u8 Flags;
__u16 Flags2; /* note: le */ __u16 Flags2; /* note: le */
__u16 PidHigh; /* note: le */ __u16 PidHigh; /* note: le */
__u8 SecuritySignature[8]; /* note le */ union {
struct {
__u32 SequenceNumber; /* le */
__u32 Reserved; /* zero */
} Sequence;
__u8 SecuritySignature[8]; /* le */
} Signature;
__u8 pad[2]; __u8 pad[2];
__u16 Tid; __u16 Tid;
__u16 Pid; /* note: le */ __u16 Pid; /* note: le */
......
...@@ -79,8 +79,7 @@ extern int setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, ...@@ -79,8 +79,7 @@ extern int setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
struct nls_table * nls_info); struct nls_table * nls_info);
extern int CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses); extern int CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses);
extern int CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, extern int CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
char *session_key, char *ntlm_session_key, char *ntlm_session_key, const struct nls_table *);
const struct nls_table *);
extern int CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses, extern int CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
char *SecurityBlob,int SecurityBlobLength, char *SecurityBlob,int SecurityBlobLength,
const struct nls_table *); const struct nls_table *);
...@@ -226,6 +225,10 @@ extern void tconInfoFree(struct cifsTconInfo *); ...@@ -226,6 +225,10 @@ extern void tconInfoFree(struct cifsTconInfo *);
extern int cifs_demultiplex_thread(struct TCP_Server_Info *); extern int cifs_demultiplex_thread(struct TCP_Server_Info *);
extern int cifs_reconnect(struct TCP_Server_Info *server); extern int cifs_reconnect(struct TCP_Server_Info *server);
extern int cifs_sign_smb(struct smb_hdr *, struct cifsSesInfo *);
extern int cifs_verify_signature(const struct smb_hdr *, const char * mac_key,
__u32 expected_sequence_number);
/* BB routines below not implemented yet BB */ /* BB routines below not implemented yet BB */
extern int CIFSBuildServerList(int xid, char *serverBufferList, extern int CIFSBuildServerList(int xid, char *serverBufferList,
......
...@@ -106,9 +106,6 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) ...@@ -106,9 +106,6 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
pSMB->hdr.Flags2 |= SMBFLG2_UNICODE; pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
if (extended_security) if (extended_security)
pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
if (sign_CIFS_PDUs) {
pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
}
pSMB->ByteCount = strlen(protocols[0].name) + 1; pSMB->ByteCount = strlen(protocols[0].name) + 1;
strncpy(pSMB->DialectsArray, protocols[0].name, 30); strncpy(pSMB->DialectsArray, protocols[0].name, 30);
...@@ -260,10 +257,13 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses) ...@@ -260,10 +257,13 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
up(&ses->sesSem); up(&ses->sesSem);
return -EBUSY; return -EBUSY;
} }
if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
rc = smb_init(SMB_COM_LOGOFF_ANDX, 2, 0 /* no tcon anymore */, rc = smb_init(SMB_COM_LOGOFF_ANDX, 2, 0 /* no tcon anymore */,
(void **) &pSMB, (void **) &smb_buffer_response); (void **) &pSMB, (void **) &smb_buffer_response);
if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
if (rc) { if (rc) {
up(&ses->sesSem); up(&ses->sesSem);
return rc; return rc;
...@@ -1657,8 +1657,6 @@ CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses, ...@@ -1657,8 +1657,6 @@ CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
if (ses->capabilities & CAP_DFS) { if (ses->capabilities & CAP_DFS) {
pSMB->hdr.Flags2 |= SMBFLG2_DFS; pSMB->hdr.Flags2 |= SMBFLG2_DFS;
} }
if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
if (ses->capabilities & CAP_UNICODE) { if (ses->capabilities & CAP_UNICODE) {
pSMB->hdr.Flags2 |= SMBFLG2_UNICODE; pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
......
...@@ -641,6 +641,7 @@ int setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, struct nls_tab ...@@ -641,6 +641,7 @@ int setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, struct nls_tab
if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */
rc = CIFSSMBNegotiate(xid, pSesInfo); rc = CIFSSMBNegotiate(xid, pSesInfo);
pSesInfo->capabilities = pSesInfo->server->capabilities; pSesInfo->capabilities = pSesInfo->server->capabilities;
pSesInfo->sequence_number = 0;
if (!rc) { if (!rc) {
cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d", cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
pSesInfo->server->secMode, pSesInfo->server->secMode,
...@@ -690,9 +691,7 @@ int setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, struct nls_tab ...@@ -690,9 +691,7 @@ int setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, struct nls_tab
pSesInfo->server->cryptKey, pSesInfo->server->cryptKey,
ntlm_session_key); ntlm_session_key);
rc = CIFSSessSetup(xid, pSesInfo, rc = CIFSSessSetup(xid, pSesInfo,
session_key, ntlm_session_key, nls_info);
ntlm_session_key,
nls_info);
} }
if (rc) { if (rc) {
cERROR(1,("Send error in SessSetup = %d",rc)); cERROR(1,("Send error in SessSetup = %d",rc));
...@@ -1024,7 +1023,6 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, ...@@ -1024,7 +1023,6 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
int int
CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
char session_key[CIFS_SESSION_KEY_SIZE], char session_key[CIFS_SESSION_KEY_SIZE],
char session_key2[CIFS_SESSION_KEY_SIZE],
const struct nls_table *nls_codepage) const struct nls_table *nls_codepage)
{ {
struct smb_hdr *smb_buffer; struct smb_hdr *smb_buffer;
...@@ -1081,9 +1079,9 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, ...@@ -1081,9 +1079,9 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
pSMB->req_no_secext.CaseSensitivePasswordLength = pSMB->req_no_secext.CaseSensitivePasswordLength =
cpu_to_le16(CIFS_SESSION_KEY_SIZE); cpu_to_le16(CIFS_SESSION_KEY_SIZE);
bcc_ptr = pByteArea(smb_buffer); bcc_ptr = pByteArea(smb_buffer);
/* memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE); /* memcpy(bcc_ptr, (char *) lm_session_key, CIFS_SESSION_KEY_SIZE);
bcc_ptr += CIFS_SESSION_KEY_SIZE; */ bcc_ptr += CIFS_SESSION_KEY_SIZE; */
memcpy(bcc_ptr, (char *) session_key2, CIFS_SESSION_KEY_SIZE); memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
bcc_ptr += CIFS_SESSION_KEY_SIZE; bcc_ptr += CIFS_SESSION_KEY_SIZE;
if (ses->capabilities & CAP_UNICODE) { if (ses->capabilities & CAP_UNICODE) {
......
...@@ -520,7 +520,7 @@ cli_caclulate_sign_mac(struct smb_hdr *outbuf, __u8 * mac_key, ...@@ -520,7 +520,7 @@ cli_caclulate_sign_mac(struct smb_hdr *outbuf, __u8 * mac_key,
be32_to_cpu(outbuf->smb_buf_length)); be32_to_cpu(outbuf->smb_buf_length));
MD5Final(calc_md5_mac, &md5_ctx); MD5Final(calc_md5_mac, &md5_ctx);
memcpy(outbuf->SecuritySignature, calc_md5_mac, 8); memcpy(outbuf->Signature.SecuritySignature, calc_md5_mac, 8);
(*send_seq_num)++; (*send_seq_num)++;
*reply_seq_num = *send_seq_num; *reply_seq_num = *send_seq_num;
(*send_seq_num)++; (*send_seq_num)++;
......
...@@ -154,12 +154,8 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer, ...@@ -154,12 +154,8 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
/* smb header is converted in header_assemble. bcc and rest of SMB word /* smb header is converted in header_assemble. bcc and rest of SMB word
area, and byte area if necessary, is converted to littleendian in area, and byte area if necessary, is converted to littleendian in
cifssmb.c and RFC1001 len is converted to bigendian in smb_send */ cifssmb.c and RFC1001 len is converted to bigendian in smb_send
if (smb_buf_length > 12) Flags2 is converted in SendReceive */
smb_buffer->Flags2 = cpu_to_le16(smb_buffer->Flags2);
/* if(smb_buffer->Flags2 & SMBFLG2_SECURITY_SIGNATURE)
sign_smb(smb_buffer); */ /* BB enable when signing tested more */
smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length); smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
cFYI(1, ("Sending smb of length %d ", smb_buf_length)); cFYI(1, ("Sending smb of length %d ", smb_buf_length));
...@@ -200,6 +196,12 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, ...@@ -200,6 +196,12 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
DeleteMidQEntry(midQ); DeleteMidQEntry(midQ);
return -EIO; return -EIO;
} }
if (in_buf->smb_buf_length > 12)
in_buf->Flags2 = cpu_to_le16(in_buf->Flags2);
rc = cifs_sign_smb(in_buf, ses);
midQ->midState = MID_REQUEST_SUBMITTED; midQ->midState = MID_REQUEST_SUBMITTED;
rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length, rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
(struct sockaddr *) &(ses->server->sockAddr)); (struct sockaddr *) &(ses->server->sockAddr));
...@@ -247,9 +249,11 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, ...@@ -247,9 +249,11 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
memcpy(out_buf, midQ->resp_buf, memcpy(out_buf, midQ->resp_buf,
receive_len + receive_len +
4 /* include 4 byte RFC1001 header */ ); 4 /* include 4 byte RFC1001 header */ );
/* convert the length back to a form that we can use */
/* int cifs_verify_signature(out_buf, ses->mac_signing_key,
__u32 expected_sequence_number); */
dump_smb(out_buf, 92); dump_smb(out_buf, 92);
/* convert the length into a more usable form */
out_buf->smb_buf_length = out_buf->smb_buf_length =
be32_to_cpu(out_buf->smb_buf_length); be32_to_cpu(out_buf->smb_buf_length);
if (out_buf->smb_buf_length > 12) if (out_buf->smb_buf_length > 12)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment