]> git.neil.brown.name Git - history.git/commitdiff
Signing fixes part 2
authorSteve French <stevef@linux.local>
Fri, 4 Jul 2003 08:07:32 +0000 (01:07 -0700)
committerSteve French <cifs.adm@hostme.bitkeeper.com>
Fri, 4 Jul 2003 08:07:32 +0000 (01:07 -0700)
fs/cifs/Makefile
fs/cifs/cifsencrypt.c [new file with mode: 0755]
fs/cifs/cifsglob.h
fs/cifs/cifspdu.h
fs/cifs/cifsproto.h
fs/cifs/cifssmb.c
fs/cifs/connect.c
fs/cifs/smbencrypt.c
fs/cifs/transport.c

index 76f667fe61af11eb3d3140da521cec63ae7ad356..94fd2b73c45156dde4bd2c38dc606f91fbb6e2c6 100644 (file)
@@ -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
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
new file mode 100755 (executable)
index 0000000..e7c468f
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ *   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;
+} 
index ae3e49d1de4510f9c4558e7d64934f7bcb72ade0..f79a0695fb36407462d7d60907b852f5353a0351 100644 (file)
@@ -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 */
index 1e6be8054126928b8c36bb6305b76207d5a1f320..bd9e6183deb23ee7c33a38814332d112c3fc45b7 100644 (file)
@@ -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 */
index e557442f61fd2b60518562be535026a78092cd71..ba9d0c64c0e21c0eaab3516116269c1927e53eac 100644 (file)
@@ -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,
index 1d2d347e3adbd260c6b7e0fa24dcea59ec2d2a61..5761b8349297d75d77223dfd0b5bda8639dfba1e 100644 (file)
@@ -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;
index add558cc01afdf8c76072a9c6f351b9453046463..bd4c4e9a309f77760926bf7c8a656e1cb6aa46db 100644 (file)
@@ -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) {
@@ -1094,7 +1092,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                if(user == NULL)
                        bytes_returned = 0; /* skill null user */
         else
-                   bytes_returned =
+               bytes_returned =
                        cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100, nls_codepage);
                bcc_ptr += 2 * bytes_returned;  /* convert num 16 bit words to bytes */
                bcc_ptr += 2;   /* trailing null */
index 83e772647425b135b85d8202212d666493e35932..9c810c517cf0d30d6ab01e3457fddd9c6df1f598 100644 (file)
@@ -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)++;
index 4705a16d9ef5978249868a12fb175216e97c30e8..62d6136f293aaf3f582c3edf2af44f85e1d35fd7 100644 (file)
@@ -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)