aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve French <smfrench@austin.rr.com>2005-04-29 01:41:05 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-29 01:41:05 -0400
commitad009ac96509e005d9978d0ae9e9ec4d63ad2990 (patch)
treeeb15ee8333fd7b5816f8fe3d02250ff99601eba0
parentc67593a03129967eae8939c4899767182eb6d6cd (diff)
[PATCH] cifs: Fix multiuser packet signing to use the right sequence number and mac session key
Signed-off-by: Steve French (sfrench@us.ibm.com) Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--fs/cifs/CHANGES3
-rw-r--r--fs/cifs/cifsencrypt.c16
-rw-r--r--fs/cifs/cifsglob.h11
-rw-r--r--fs/cifs/cifsproto.h2
-rw-r--r--fs/cifs/connect.c28
-rw-r--r--fs/cifs/transport.c22
6 files changed, 50 insertions, 32 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 7fd02697b12e..43b3119a16ed 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -5,7 +5,8 @@ transact response for an SMB request and search entry split across two frames.
5Add support for lsattr (getting ext2/ext3/reiserfs attr flags from the server) 5Add support for lsattr (getting ext2/ext3/reiserfs attr flags from the server)
6as new protocol extensions. Do not send Get/Set calls for POSIX ACLs 6as new protocol extensions. Do not send Get/Set calls for POSIX ACLs
7unless server explicitly claims to support them in CIFS Unix extensions 7unless server explicitly claims to support them in CIFS Unix extensions
8POSIX ACL capability bit. 8POSIX ACL capability bit. Fix packet signing when multiuser mounting with
9different users from the same client to the same server.
9 10
10Version 1.31 11Version 1.31
11------------ 12------------
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index 78829e7d8cd0..1959c7c4b185 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -50,7 +50,7 @@ static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu, const char
50 return 0; 50 return 0;
51} 51}
52 52
53int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct cifsSesInfo * ses, 53int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct TCP_Server_Info * server,
54 __u32 * pexpected_response_sequence_number) 54 __u32 * pexpected_response_sequence_number)
55{ 55{
56 int rc = 0; 56 int rc = 0;
@@ -59,21 +59,21 @@ int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct cifsSesInfo * ses,
59 /* BB remember to initialize sequence number elsewhere and initialize mac_signing key elsewhere BB */ 59 /* BB remember to initialize sequence number elsewhere and initialize mac_signing key elsewhere BB */
60 /* BB remember to add code to save expected sequence number in midQ entry BB */ 60 /* BB remember to add code to save expected sequence number in midQ entry BB */
61 61
62 if((cifs_pdu == NULL) || (ses == NULL)) 62 if((cifs_pdu == NULL) || (server == NULL))
63 return -EINVAL; 63 return -EINVAL;
64 64
65 if((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0) 65 if((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0)
66 return rc; 66 return rc;
67 67
68 spin_lock(&GlobalMid_Lock); 68 spin_lock(&GlobalMid_Lock);
69 cifs_pdu->Signature.Sequence.SequenceNumber = cpu_to_le32(ses->sequence_number); 69 cifs_pdu->Signature.Sequence.SequenceNumber = cpu_to_le32(server->sequence_number);
70 cifs_pdu->Signature.Sequence.Reserved = 0; 70 cifs_pdu->Signature.Sequence.Reserved = 0;
71 71
72 *pexpected_response_sequence_number = ses->sequence_number++; 72 *pexpected_response_sequence_number = server->sequence_number++;
73 ses->sequence_number++; 73 server->sequence_number++;
74 spin_unlock(&GlobalMid_Lock); 74 spin_unlock(&GlobalMid_Lock);
75 75
76 rc = cifs_calculate_signature(cifs_pdu, ses->mac_signing_key,smb_signature); 76 rc = cifs_calculate_signature(cifs_pdu, server->mac_signing_key,smb_signature);
77 if(rc) 77 if(rc)
78 memset(cifs_pdu->Signature.SecuritySignature, 0, 8); 78 memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
79 else 79 else
@@ -190,7 +190,7 @@ int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses, struct nls_table * nls_
190 hmac_md5_update((const unsigned char *) unicode_buf, 190 hmac_md5_update((const unsigned char *) unicode_buf,
191 (user_name_len+dom_name_len)*2,&ctx); 191 (user_name_len+dom_name_len)*2,&ctx);
192 192
193 hmac_md5_final(ses->mac_signing_key,&ctx); 193 hmac_md5_final(ses->server->mac_signing_key,&ctx);
194 kfree(ucase_buf); 194 kfree(ucase_buf);
195 kfree(unicode_buf); 195 kfree(unicode_buf);
196 return 0; 196 return 0;
@@ -200,7 +200,7 @@ void CalcNTLMv2_response(const struct cifsSesInfo * ses,char * v2_session_respon
200 struct HMACMD5Context context; 200 struct HMACMD5Context context;
201 memcpy(v2_session_response + 8, ses->server->cryptKey,8); 201 memcpy(v2_session_response + 8, ses->server->cryptKey,8);
202 /* gen_blob(v2_session_response + 16); */ 202 /* gen_blob(v2_session_response + 16); */
203 hmac_md5_init_limK_to_64(ses->mac_signing_key, 16, &context); 203 hmac_md5_init_limK_to_64(ses->server->mac_signing_key, 16, &context);
204 204
205 hmac_md5_update(ses->server->cryptKey,8,&context); 205 hmac_md5_update(ses->server->cryptKey,8,&context);
206/* hmac_md5_update(v2_session_response+16)client thing,8,&context); */ /* BB fix */ 206/* hmac_md5_update(v2_session_response+16)client thing,8,&context); */ /* BB fix */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 69aff1a7da9b..1b3082d79379 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -149,6 +149,8 @@ struct TCP_Server_Info {
149 __u16 timeZone; 149 __u16 timeZone;
150 char cryptKey[CIFS_CRYPTO_KEY_SIZE]; 150 char cryptKey[CIFS_CRYPTO_KEY_SIZE];
151 char workstation_RFC1001_name[16]; /* 16th byte is always zero */ 151 char workstation_RFC1001_name[16]; /* 16th byte is always zero */
152 __u32 sequence_number; /* needed for CIFS PDU signature */
153 char mac_signing_key[CIFS_SESSION_KEY_SIZE + 16];
152}; 154};
153 155
154/* 156/*
@@ -174,17 +176,16 @@ struct cifsSesInfo {
174 struct TCP_Server_Info *server; /* pointer to server info */ 176 struct TCP_Server_Info *server; /* pointer to server info */
175 atomic_t inUse; /* # of mounts (tree connections) on this ses */ 177 atomic_t inUse; /* # of mounts (tree connections) on this ses */
176 enum statusEnum status; 178 enum statusEnum status;
177 __u32 sequence_number; /* needed for CIFS PDU signature */
178 __u16 ipc_tid; /* special tid for connection to IPC share */ 179 __u16 ipc_tid; /* special tid for connection to IPC share */
179 __u16 flags; 180 __u16 flags;
180 char mac_signing_key[CIFS_SESSION_KEY_SIZE + 16]; 181 char *serverOS; /* name of operating system underlying server */
181 char *serverOS; /* name of operating system underlying the server */ 182 char *serverNOS; /* name of network operating system of server */
182 char *serverNOS; /* name of network operating system that the server is running */
183 char *serverDomain; /* security realm of server */ 183 char *serverDomain; /* security realm of server */
184 int Suid; /* remote smb uid */ 184 int Suid; /* remote smb uid */
185 uid_t linux_uid; /* local Linux uid */ 185 uid_t linux_uid; /* local Linux uid */
186 int capabilities; 186 int capabilities;
187 char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for tcp names - will ipv6 and sctp addresses fit here?? */ 187 char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for
188 TCP names - will ipv6 and sctp addresses fit? */
188 char userName[MAX_USERNAME_SIZE + 1]; 189 char userName[MAX_USERNAME_SIZE + 1];
189 char domainName[MAX_USERNAME_SIZE + 1]; 190 char domainName[MAX_USERNAME_SIZE + 1];
190 char * password; 191 char * password;
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 1b0070dfc51c..dd95c2bcbc25 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -230,7 +230,7 @@ extern void tconInfoFree(struct cifsTconInfo *);
230 230
231extern int cifs_reconnect(struct TCP_Server_Info *server); 231extern int cifs_reconnect(struct TCP_Server_Info *server);
232 232
233extern int cifs_sign_smb(struct smb_hdr *, struct cifsSesInfo *,__u32 *); 233extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *,__u32 *);
234extern int cifs_verify_signature(struct smb_hdr *, const char * mac_key, 234extern int cifs_verify_signature(struct smb_hdr *, const char * mac_key,
235 __u32 expected_sequence_number); 235 __u32 expected_sequence_number);
236extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass); 236extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass);
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 40470b9d5477..814e709ca0ca 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -182,7 +182,8 @@ cifs_reconnect(struct TCP_Server_Info *server)
182 spin_lock(&GlobalMid_Lock); 182 spin_lock(&GlobalMid_Lock);
183 if(server->tcpStatus != CifsExiting) 183 if(server->tcpStatus != CifsExiting)
184 server->tcpStatus = CifsGood; 184 server->tcpStatus = CifsGood;
185 spin_unlock(&GlobalMid_Lock); 185 server->sequence_number = 0;
186 spin_unlock(&GlobalMid_Lock);
186 /* atomic_set(&server->inFlight,0);*/ 187 /* atomic_set(&server->inFlight,0);*/
187 wake_up(&server->response_q); 188 wake_up(&server->response_q);
188 } 189 }
@@ -1352,6 +1353,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1352 } else 1353 } else
1353 rc = 0; 1354 rc = 0;
1354 memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16); 1355 memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
1356 srvTcp->sequence_number = 0;
1355 } 1357 }
1356 } 1358 }
1357 1359
@@ -2959,6 +2961,7 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
2959 int rc = 0; 2961 int rc = 0;
2960 char ntlm_session_key[CIFS_SESSION_KEY_SIZE]; 2962 char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
2961 int ntlmv2_flag = FALSE; 2963 int ntlmv2_flag = FALSE;
2964 int first_time = 0;
2962 2965
2963 /* what if server changes its buffer size after dropping the session? */ 2966 /* what if server changes its buffer size after dropping the session? */
2964 if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ { 2967 if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ {
@@ -2977,12 +2980,13 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
2977 spin_unlock(&GlobalMid_Lock); 2980 spin_unlock(&GlobalMid_Lock);
2978 2981
2979 } 2982 }
2983 first_time = 1;
2980 } 2984 }
2981 if (!rc) { 2985 if (!rc) {
2982 pSesInfo->capabilities = pSesInfo->server->capabilities; 2986 pSesInfo->capabilities = pSesInfo->server->capabilities;
2983 if(linuxExtEnabled == 0) 2987 if(linuxExtEnabled == 0)
2984 pSesInfo->capabilities &= (~CAP_UNIX); 2988 pSesInfo->capabilities &= (~CAP_UNIX);
2985 pSesInfo->sequence_number = 0; 2989 /* pSesInfo->sequence_number = 0;*/
2986 cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d", 2990 cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
2987 pSesInfo->server->secMode, 2991 pSesInfo->server->secMode,
2988 pSesInfo->server->capabilities, 2992 pSesInfo->server->capabilities,
@@ -3015,7 +3019,10 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3015 v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL); 3019 v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
3016 if(v2_response) { 3020 if(v2_response) {
3017 CalcNTLMv2_response(pSesInfo,v2_response); 3021 CalcNTLMv2_response(pSesInfo,v2_response);
3018/* cifs_calculate_ntlmv2_mac_key(pSesInfo->mac_signing_key, response, ntlm_session_key, */ 3022 /* if(first_time)
3023 cifs_calculate_ntlmv2_mac_key(
3024 pSesInfo->server->mac_signing_key,
3025 response, ntlm_session_key, */
3019 kfree(v2_response); 3026 kfree(v2_response);
3020 /* BB Put dummy sig in SessSetup PDU? */ 3027 /* BB Put dummy sig in SessSetup PDU? */
3021 } else { 3028 } else {
@@ -3028,9 +3035,11 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3028 pSesInfo->server->cryptKey, 3035 pSesInfo->server->cryptKey,
3029 ntlm_session_key); 3036 ntlm_session_key);
3030 3037
3031 cifs_calculate_mac_key(pSesInfo->mac_signing_key, 3038 if(first_time)
3032 ntlm_session_key, 3039 cifs_calculate_mac_key(
3033 pSesInfo->password); 3040 pSesInfo->server->mac_signing_key,
3041 ntlm_session_key,
3042 pSesInfo->password);
3034 } 3043 }
3035 /* for better security the weaker lanman hash not sent 3044 /* for better security the weaker lanman hash not sent
3036 in AuthSessSetup so we no longer calculate it */ 3045 in AuthSessSetup so we no longer calculate it */
@@ -3046,8 +3055,11 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3046 pSesInfo->server->cryptKey, 3055 pSesInfo->server->cryptKey,
3047 ntlm_session_key); 3056 ntlm_session_key);
3048 3057
3049 cifs_calculate_mac_key(pSesInfo->mac_signing_key, 3058 if(first_time)
3050 ntlm_session_key, pSesInfo->password); 3059 cifs_calculate_mac_key(
3060 pSesInfo->server->mac_signing_key,
3061 ntlm_session_key, pSesInfo->password);
3062
3051 rc = CIFSSessSetup(xid, pSesInfo, 3063 rc = CIFSSessSetup(xid, pSesInfo,
3052 ntlm_session_key, nls_info); 3064 ntlm_session_key, nls_info);
3053 } 3065 }
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index af13e526b150..a9e4f989b7f7 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -346,7 +346,7 @@ CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses,
346 } 346 }
347 347
348 /* BB can we sign efficiently in this path? */ 348 /* BB can we sign efficiently in this path? */
349 rc = cifs_sign_smb(in_buf, ses, &midQ->sequence_number); 349 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
350 350
351 midQ->midState = MID_REQUEST_SUBMITTED; 351 midQ->midState = MID_REQUEST_SUBMITTED;
352/* rc = smb_sendv(ses->server->ssocket, in_buf, in_buf->smb_buf_length, piovec, 352/* rc = smb_sendv(ses->server->ssocket, in_buf, in_buf->smb_buf_length, piovec,
@@ -475,7 +475,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
475 return -EIO; 475 return -EIO;
476 } 476 }
477 477
478 rc = cifs_sign_smb(in_buf, ses, &midQ->sequence_number); 478 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
479 479
480 midQ->midState = MID_REQUEST_SUBMITTED; 480 midQ->midState = MID_REQUEST_SUBMITTED;
481 rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length, 481 rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
@@ -559,8 +559,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
559 } 559 }
560 560
561 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) { 561 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
562 cERROR(1, 562 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
563 ("Frame too large received. Length: %d Xid: %d",
564 receive_len, xid)); 563 receive_len, xid));
565 rc = -EIO; 564 rc = -EIO;
566 } else { /* rcvd frame is ok */ 565 } else { /* rcvd frame is ok */
@@ -575,15 +574,20 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
575 dump_smb(out_buf, 92); 574 dump_smb(out_buf, 92);
576 /* convert the length into a more usable form */ 575 /* convert the length into a more usable form */
577 if((receive_len > 24) && 576 if((receive_len > 24) &&
578 (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))) { 577 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
579 rc = cifs_verify_signature(out_buf, ses->mac_signing_key,midQ->sequence_number); /* BB fix BB */ 578 SECMODE_SIGN_ENABLED))) {
580 if(rc) 579 rc = cifs_verify_signature(out_buf,
581 cFYI(1,("Unexpected signature received from server")); 580 ses->server->mac_signing_key,
581 midQ->sequence_number+1);
582 if(rc) {
583 cERROR(1,("Unexpected packet signature received from server"));
584 /* BB FIXME - add code to kill session here */
585 }
582 } 586 }
583 587
584 *pbytes_returned = out_buf->smb_buf_length; 588 *pbytes_returned = out_buf->smb_buf_length;
585 589
586 /* BB special case reconnect tid and reconnect uid here? */ 590 /* BB special case reconnect tid and uid here? */
587 rc = map_smb_to_linux_error(out_buf); 591 rc = map_smb_to_linux_error(out_buf);
588 592
589 /* convert ByteCount if necessary */ 593 /* convert ByteCount if necessary */