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

Signing fixes part 2

parent 0cfb3b99
......@@ -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
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 {
struct TCP_Server_Info *server; /* pointer to server info */
atomic_t inUse; /* # of CURRENT users of this ses */
enum statusEnum status;
__u32 sequence_number; /* needed for CIFS PDU signature */
__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 *serverNOS; /* name of network operating system that the server is running */
char *serverDomain; /* security realm of server */
......@@ -249,6 +251,7 @@ struct mid_q_entry {
struct list_head qhead; /* mids waiting on reply from this server */
__u16 mid; /* multiplex id */
__u16 pid; /* process id */
__u32 sequence_number; /* for CIFS signing */
__u16 command; /* smb command code */
struct timeval when_sent; /* time when smb sent */
struct cifsSesInfo *ses; /* smb was sent to this server */
......
......@@ -307,7 +307,13 @@ struct smb_hdr {
__u8 Flags;
__u16 Flags2; /* 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];
__u16 Tid;
__u16 Pid; /* note: le */
......
......@@ -79,8 +79,7 @@ extern int setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
struct nls_table * nls_info);
extern int CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses);
extern int CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
char *session_key, char *ntlm_session_key,
const struct nls_table *);
char *ntlm_session_key, const struct nls_table *);
extern int CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
char *SecurityBlob,int SecurityBlobLength,
const struct nls_table *);
......@@ -226,6 +225,10 @@ extern void tconInfoFree(struct cifsTconInfo *);
extern int cifs_demultiplex_thread(struct TCP_Server_Info *);
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 */
extern int CIFSBuildServerList(int xid, char *serverBufferList,
......
......@@ -106,9 +106,6 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
if (extended_security)
pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
if (sign_CIFS_PDUs) {
pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
}
pSMB->ByteCount = strlen(protocols[0].name) + 1;
strncpy(pSMB->DialectsArray, protocols[0].name, 30);
......@@ -260,10 +257,13 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
up(&ses->sesSem);
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 */,
(void **) &pSMB, (void **) &smb_buffer_response);
if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
if (rc) {
up(&ses->sesSem);
return rc;
......@@ -1657,8 +1657,6 @@ CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
if (ses->capabilities & CAP_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) {
pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
......
......@@ -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 */
rc = CIFSSMBNegotiate(xid, pSesInfo);
pSesInfo->capabilities = pSesInfo->server->capabilities;
pSesInfo->sequence_number = 0;
if (!rc) {
cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
pSesInfo->server->secMode,
......@@ -690,9 +691,7 @@ int setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, struct nls_tab
pSesInfo->server->cryptKey,
ntlm_session_key);
rc = CIFSSessSetup(xid, pSesInfo,
session_key,
ntlm_session_key,
nls_info);
ntlm_session_key, nls_info);
}
if (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,
int
CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
char session_key[CIFS_SESSION_KEY_SIZE],
char session_key2[CIFS_SESSION_KEY_SIZE],
const struct nls_table *nls_codepage)
{
struct smb_hdr *smb_buffer;
......@@ -1081,9 +1079,9 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
pSMB->req_no_secext.CaseSensitivePasswordLength =
cpu_to_le16(CIFS_SESSION_KEY_SIZE);
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; */
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;
if (ses->capabilities & CAP_UNICODE) {
......
......@@ -520,7 +520,7 @@ cli_caclulate_sign_mac(struct smb_hdr *outbuf, __u8 * mac_key,
be32_to_cpu(outbuf->smb_buf_length));
MD5Final(calc_md5_mac, &md5_ctx);
memcpy(outbuf->SecuritySignature, calc_md5_mac, 8);
memcpy(outbuf->Signature.SecuritySignature, calc_md5_mac, 8);
(*send_seq_num)++;
*reply_seq_num = *send_seq_num;
(*send_seq_num)++;
......
......@@ -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
area, and byte area if necessary, is converted to littleendian in
cifssmb.c and RFC1001 len is converted to bigendian in smb_send */
if (smb_buf_length > 12)
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 */
cifssmb.c and RFC1001 len is converted to bigendian in smb_send
Flags2 is converted in SendReceive */
smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->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,
DeleteMidQEntry(midQ);
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;
rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
(struct sockaddr *) &(ses->server->sockAddr));
......@@ -247,9 +249,11 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
memcpy(out_buf, midQ->resp_buf,
receive_len +
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);
/* convert the length into a more usable form */
out_buf->smb_buf_length =
be32_to_cpu(out_buf->smb_buf_length);
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