diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-09-13 12:47:08 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-09-13 12:47:08 -0700 |
commit | ed8f425f546a2242a97f61fabcbe9e50a2559a19 (patch) | |
tree | 5e580d4c654191b73fc5981785ebf1e52e575b4a /fs | |
parent | 1421e98662f1cab802e0fa39d16b8dc6b874a4eb (diff) | |
parent | 32670396e7fc6e4f37451a69339968985461a374 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6:
cifs: prevent possible memory corruption in cifs_demultiplex_thread
cifs: eliminate some more premature cifsd exits
cifs: prevent cifsd from exiting prematurely
[CIFS] ntlmv2/ntlmssp remove-unused-function CalcNTLMv2_partial_mac_key
cifs: eliminate redundant xdev check in cifs_rename
Revert "[CIFS] Fix ntlmv2 auth with ntlmssp"
Revert "missing changes during ntlmv2/ntlmssp auth and sign"
Revert "Eliminate sparse warning - bad constant expression"
Revert "[CIFS] Eliminate unused variable warning"
Diffstat (limited to 'fs')
-rw-r--r-- | fs/cifs/Kconfig | 2 | ||||
-rw-r--r-- | fs/cifs/asn1.c | 6 | ||||
-rw-r--r-- | fs/cifs/cifsencrypt.c | 418 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 25 | ||||
-rw-r--r-- | fs/cifs/cifspdu.h | 7 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 13 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 13 | ||||
-rw-r--r-- | fs/cifs/connect.c | 71 | ||||
-rw-r--r-- | fs/cifs/inode.c | 30 | ||||
-rw-r--r-- | fs/cifs/netmisc.c | 22 | ||||
-rw-r--r-- | fs/cifs/ntlmssp.h | 13 | ||||
-rw-r--r-- | fs/cifs/sess.c | 132 | ||||
-rw-r--r-- | fs/cifs/transport.c | 6 |
13 files changed, 166 insertions, 592 deletions
diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig index 0da1debd499..917b7d449bb 100644 --- a/fs/cifs/Kconfig +++ b/fs/cifs/Kconfig @@ -2,8 +2,6 @@ config CIFS tristate "CIFS support (advanced network filesystem, SMBFS successor)" depends on INET select NLS - select CRYPTO_MD5 - select CRYPTO_ARC4 help This is the client VFS module for the Common Internet File System (CIFS) protocol which is the successor to the Server Message Block diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c index 21f0fbd8698..cfd1ce34e0b 100644 --- a/fs/cifs/asn1.c +++ b/fs/cifs/asn1.c @@ -597,13 +597,13 @@ decode_negTokenInit(unsigned char *security_blob, int length, if (compare_oid(oid, oidlen, MSKRB5_OID, MSKRB5_OID_LEN)) server->sec_mskerberos = true; - if (compare_oid(oid, oidlen, KRB5U2U_OID, + else if (compare_oid(oid, oidlen, KRB5U2U_OID, KRB5U2U_OID_LEN)) server->sec_kerberosu2u = true; - if (compare_oid(oid, oidlen, KRB5_OID, + else if (compare_oid(oid, oidlen, KRB5_OID, KRB5_OID_LEN)) server->sec_kerberos = true; - if (compare_oid(oid, oidlen, NTLMSSP_OID, + else if (compare_oid(oid, oidlen, NTLMSSP_OID, NTLMSSP_OID_LEN)) server->sec_ntlmssp = true; diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c index 709f2296bdb..35042d8f733 100644 --- a/fs/cifs/cifsencrypt.c +++ b/fs/cifs/cifsencrypt.c @@ -27,7 +27,6 @@ #include "md5.h" #include "cifs_unicode.h" #include "cifsproto.h" -#include "ntlmssp.h" #include <linux/ctype.h> #include <linux/random.h> @@ -43,43 +42,21 @@ extern void SMBencrypt(unsigned char *passwd, const unsigned char *c8, unsigned char *p24); static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu, - struct TCP_Server_Info *server, char *signature) + const struct mac_key *key, char *signature) { - int rc; + struct MD5Context context; - if (cifs_pdu == NULL || server == NULL || signature == NULL) + if ((cifs_pdu == NULL) || (signature == NULL) || (key == NULL)) return -EINVAL; - if (!server->ntlmssp.sdescmd5) { - cERROR(1, - "cifs_calculate_signature: can't generate signature\n"); - return -1; - } - - rc = crypto_shash_init(&server->ntlmssp.sdescmd5->shash); - if (rc) { - cERROR(1, "cifs_calculate_signature: oould not init md5\n"); - return rc; - } - - if (server->secType == RawNTLMSSP) - crypto_shash_update(&server->ntlmssp.sdescmd5->shash, - server->session_key.data.ntlmv2.key, - CIFS_NTLMV2_SESSKEY_SIZE); - else - crypto_shash_update(&server->ntlmssp.sdescmd5->shash, - (char *)&server->session_key.data, - server->session_key.len); - - crypto_shash_update(&server->ntlmssp.sdescmd5->shash, - cifs_pdu->Protocol, cifs_pdu->smb_buf_length); + cifs_MD5_init(&context); + cifs_MD5_update(&context, (char *)&key->data, key->len); + cifs_MD5_update(&context, cifs_pdu->Protocol, cifs_pdu->smb_buf_length); - rc = crypto_shash_final(&server->ntlmssp.sdescmd5->shash, signature); - - return rc; + cifs_MD5_final(signature, &context); + return 0; } - int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server, __u32 *pexpected_response_sequence_number) { @@ -101,7 +78,8 @@ int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server, server->sequence_number++; spin_unlock(&GlobalMid_Lock); - rc = cifs_calculate_signature(cifs_pdu, server, smb_signature); + rc = cifs_calculate_signature(cifs_pdu, &server->mac_signing_key, + smb_signature); if (rc) memset(cifs_pdu->Signature.SecuritySignature, 0, 8); else @@ -111,39 +89,21 @@ int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server, } static int cifs_calc_signature2(const struct kvec *iov, int n_vec, - struct TCP_Server_Info *server, char *signature) + const struct mac_key *key, char *signature) { + struct MD5Context context; int i; - int rc; - if (iov == NULL || server == NULL || signature == NULL) + if ((iov == NULL) || (signature == NULL) || (key == NULL)) return -EINVAL; - if (!server->ntlmssp.sdescmd5) { - cERROR(1, "cifs_calc_signature2: can't generate signature\n"); - return -1; - } - - rc = crypto_shash_init(&server->ntlmssp.sdescmd5->shash); - if (rc) { - cERROR(1, "cifs_calc_signature2: oould not init md5\n"); - return rc; - } - - if (server->secType == RawNTLMSSP) - crypto_shash_update(&server->ntlmssp.sdescmd5->shash, - server->session_key.data.ntlmv2.key, - CIFS_NTLMV2_SESSKEY_SIZE); - else - crypto_shash_update(&server->ntlmssp.sdescmd5->shash, - (char *)&server->session_key.data, - server->session_key.len); - + cifs_MD5_init(&context); + cifs_MD5_update(&context, (char *)&key->data, key->len); for (i = 0; i < n_vec; i++) { if (iov[i].iov_len == 0) continue; if (iov[i].iov_base == NULL) { - cERROR(1, "cifs_calc_signature2: null iovec entry"); + cERROR(1, "null iovec entry"); return -EIO; } /* The first entry includes a length field (which does not get @@ -151,18 +111,18 @@ static int cifs_calc_signature2(const struct kvec *iov, int n_vec, if (i == 0) { if (iov[0].iov_len <= 8) /* cmd field at offset 9 */ break; /* nothing to sign or corrupt header */ - crypto_shash_update(&server->ntlmssp.sdescmd5->shash, - iov[i].iov_base + 4, iov[i].iov_len - 4); + cifs_MD5_update(&context, iov[0].iov_base+4, + iov[0].iov_len-4); } else - crypto_shash_update(&server->ntlmssp.sdescmd5->shash, - iov[i].iov_base, iov[i].iov_len); + cifs_MD5_update(&context, iov[i].iov_base, iov[i].iov_len); } - rc = crypto_shash_final(&server->ntlmssp.sdescmd5->shash, signature); + cifs_MD5_final(signature, &context); - return rc; + return 0; } + int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server, __u32 *pexpected_response_sequence_number) { @@ -185,7 +145,8 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server, server->sequence_number++; spin_unlock(&GlobalMid_Lock); - rc = cifs_calc_signature2(iov, n_vec, server, smb_signature); + rc = cifs_calc_signature2(iov, n_vec, &server->mac_signing_key, + smb_signature); if (rc) memset(cifs_pdu->Signature.SecuritySignature, 0, 8); else @@ -195,14 +156,14 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server, } int cifs_verify_signature(struct smb_hdr *cifs_pdu, - struct TCP_Server_Info *server, + const struct mac_key *mac_key, __u32 expected_sequence_number) { - int rc; + unsigned int rc; char server_response_sig[8]; char what_we_think_sig_should_be[20]; - if (cifs_pdu == NULL || server == NULL) + if ((cifs_pdu == NULL) || (mac_key == NULL)) return -EINVAL; if (cifs_pdu->Command == SMB_COM_NEGOTIATE) @@ -231,7 +192,7 @@ int cifs_verify_signature(struct smb_hdr *cifs_pdu, cpu_to_le32(expected_sequence_number); cifs_pdu->Signature.Sequence.Reserved = 0; - rc = cifs_calculate_signature(cifs_pdu, server, + rc = cifs_calculate_signature(cifs_pdu, mac_key, what_we_think_sig_should_be); if (rc) @@ -248,7 +209,7 @@ int cifs_verify_signature(struct smb_hdr *cifs_pdu, } /* We fill in key by putting in 40 byte array which was allocated by caller */ -int cifs_calculate_session_key(struct session_key *key, const char *rn, +int cifs_calculate_mac_key(struct mac_key *key, const char *rn, const char *password) { char temp_key[16]; @@ -306,52 +267,38 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses, { int rc = 0; int len; - char nt_hash[CIFS_NTHASH_SIZE]; + char nt_hash[16]; + struct HMACMD5Context *pctxt; wchar_t *user; wchar_t *domain; - wchar_t *server; - if (!ses->server->ntlmssp.sdeschmacmd5) { - cERROR(1, "calc_ntlmv2_hash: can't generate ntlmv2 hash\n"); - return -1; - } + pctxt = kmalloc(sizeof(struct HMACMD5Context), GFP_KERNEL); + + if (pctxt == NULL) + return -ENOMEM; /* calculate md4 hash of password */ E_md4hash(ses->password, nt_hash); - crypto_shash_setkey(ses->server->ntlmssp.hmacmd5, nt_hash, - CIFS_NTHASH_SIZE); - - rc = crypto_shash_init(&ses->server->ntlmssp.sdeschmacmd5->shash); - if (rc) { - cERROR(1, "calc_ntlmv2_hash: could not init hmacmd5\n"); - return rc; - } + /* convert Domainname to unicode and uppercase */ + hmac_md5_init_limK_to_64(nt_hash, 16, pctxt); /* convert ses->userName to unicode and uppercase */ len = strlen(ses->userName); user = kmalloc(2 + (len * 2), GFP_KERNEL); - if (user == NULL) { - cERROR(1, "calc_ntlmv2_hash: user mem alloc failure\n"); - rc = -ENOMEM; + if (user == NULL) goto calc_exit_2; - } len = cifs_strtoUCS((__le16 *)user, ses->userName, len, nls_cp); UniStrupr(user); - - crypto_shash_update(&ses->server->ntlmssp.sdeschmacmd5->shash, - (char *)user, 2 * len); + hmac_md5_update((char *)user, 2*len, pctxt); /* convert ses->domainName to unicode and uppercase */ if (ses->domainName) { len = strlen(ses->domainName); domain = kmalloc(2 + (len * 2), GFP_KERNEL); - if (domain == NULL) { - cERROR(1, "calc_ntlmv2_hash: domain mem alloc failure"); - rc = -ENOMEM; + if (domain == NULL) goto calc_exit_1; - } len = cifs_strtoUCS((__le16 *)domain, ses->domainName, len, nls_cp); /* the following line was removed since it didn't work well @@ -359,292 +306,65 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses, Maybe converting the domain name earlier makes sense */ /* UniStrupr(domain); */ - crypto_shash_update(&ses->server->ntlmssp.sdeschmacmd5->shash, - (char *)domain, 2 * len); + hmac_md5_update((char *)domain, 2*len, pctxt); kfree(domain); - } else if (ses->serverName) { - len = strlen(ses->serverName); - - server = kmalloc(2 + (len * 2), GFP_KERNEL); - if (server == NULL) { - cERROR(1, "calc_ntlmv2_hash: server mem alloc failure"); - rc = -ENOMEM; - goto calc_exit_1; - } - len = cifs_strtoUCS((__le16 *)server, ses->serverName, len, - nls_cp); - /* the following line was removed since it didn't work well - with lower cased domain name that passed as an option. - Maybe converting the domain name earlier makes sense */ - /* UniStrupr(domain); */ - - crypto_shash_update(&ses->server->ntlmssp.sdeschmacmd5->shash, - (char *)server, 2 * len); - - kfree(server); } - - rc = crypto_shash_final(&ses->server->ntlmssp.sdeschmacmd5->shash, - ses->server->ntlmv2_hash); - calc_exit_1: kfree(user); calc_exit_2: /* BB FIXME what about bytes 24 through 40 of the signing key? compare with the NTLM example */ + hmac_md5_final(ses->server->ntlmv2_hash, pctxt); + kfree(pctxt); return rc; } -static int -find_domain_name(struct cifsSesInfo *ses) -{ - int rc = 0; - unsigned int attrsize; - unsigned int type; - unsigned char *blobptr; - struct ntlmssp2_name *attrptr; - - if (ses->server->tiblob) { - blobptr = ses->server->tiblob; - attrptr = (struct ntlmssp2_name *) blobptr; - - while ((type = attrptr->type) != 0) { - blobptr += 2; /* advance attr type */ - attrsize = attrptr->length; - blobptr += 2; /* advance attr size */ - if (type == NTLMSSP_AV_NB_DOMAIN_NAME) { - if (!ses->domainName) { - ses->domainName = - kmalloc(attrptr->length + 1, - GFP_KERNEL); - if (!ses->domainName) - return -ENOMEM; - cifs_from_ucs2(ses->domainName, - (__le16 *)blobptr, - attrptr->length, - attrptr->length, - load_nls_default(), false); - } - } - blobptr += attrsize; /* advance attr value */ - attrptr = (struct ntlmssp2_name *) blobptr; - } - } else { - ses->server->tilen = 2 * sizeof(struct ntlmssp2_name); - ses->server->tiblob = kmalloc(ses->server->tilen, GFP_KERNEL); - if (!ses->server->tiblob) { - ses->server->tilen = 0; - cERROR(1, "Challenge target info allocation failure"); - return -ENOMEM; - } - memset(ses->server->tiblob, 0x0, ses->server->tilen); - attrptr = (struct ntlmssp2_name *) ses->server->tiblob; - attrptr->type = cpu_to_le16(NTLMSSP_DOMAIN_TYPE); - } - - return rc; -} - -static int -CalcNTLMv2_response(const struct TCP_Server_Info *server, - char *v2_session_response) -{ - int rc; - - if (!server->ntlmssp.sdeschmacmd5) { - cERROR(1, "calc_ntlmv2_hash: can't generate ntlmv2 hash\n"); - return -1; - } - - crypto_shash_setkey(server->ntlmssp.hmacmd5, server->ntlmv2_hash, - CIFS_HMAC_MD5_HASH_SIZE); - - rc = crypto_shash_init(&server->ntlmssp.sdeschmacmd5->shash); - if (rc) { - cERROR(1, "CalcNTLMv2_response: could not init hmacmd5"); - return rc; - } - - memcpy(v2_session_response + CIFS_SERVER_CHALLENGE_SIZE, - server->cryptKey, CIFS_SERVER_CHALLENGE_SIZE); - crypto_shash_update(&server->ntlmssp.sdeschmacmd5->shash, - v2_session_response + CIFS_SERVER_CHALLENGE_SIZE, - sizeof(struct ntlmv2_resp) - CIFS_SERVER_CHALLENGE_SIZE); - - if (server->tilen) - crypto_shash_update(&server->ntlmssp.sdeschmacmd5->shash, - server->tiblob, server->tilen); - - rc = crypto_shash_final(&server->ntlmssp.sdeschmacmd5->shash, - v2_session_response); - - return rc; -} - -int -setup_ntlmv2_rsp(struct cifsSesInfo *ses, char *resp_buf, +void setup_ntlmv2_rsp(struct cifsSesInfo *ses, char *resp_buf, const struct nls_table *nls_cp) { - int rc = 0; + int rc; struct ntlmv2_resp *buf = (struct ntlmv2_resp *)resp_buf; + struct HMACMD5Context context; buf->blob_signature = cpu_to_le32(0x00000101); buf->reserved = 0; buf->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); get_random_bytes(&buf->client_chal, sizeof(buf->client_chal)); buf->reserved2 = 0; - - if (!ses->domainName) { - rc = find_domain_name(ses); - if (rc) { - cERROR(1, "could not get domain/server name rc %d", rc); - return rc; - } - } + buf->names[0].type = cpu_to_le16(NTLMSSP_DOMAIN_TYPE); + buf->names[0].length = 0; + buf->names[1].type = 0; + buf->names[1].length = 0; /* calculate buf->ntlmv2_hash */ rc = calc_ntlmv2_hash(ses, nls_cp); - if (rc) { - cERROR(1, "could not get v2 hash rc %d", rc); - return rc; - } - rc = CalcNTLMv2_response(ses->server, resp_buf); - if (rc) { + if (rc) cERROR(1, "could not get v2 hash rc %d", rc); - return rc; - } - - if (!ses->server->ntlmssp.sdeschmacmd5) { - cERROR(1, "calc_ntlmv2_hash: can't generate ntlmv2 hash\n"); - return -1; - } - - crypto_shash_setkey(ses->server->ntlmssp.hmacmd5, - ses->server->ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE); + CalcNTLMv2_response(ses, resp_buf); - rc = crypto_shash_init(&ses->server->ntlmssp.sdeschmacmd5->shash); - if (rc) { - cERROR(1, "setup_ntlmv2_rsp: could not init hmacmd5\n"); - return rc; - } + /* now calculate the MAC key for NTLMv2 */ + hmac_md5_init_limK_to_64(ses->server->ntlmv2_hash, 16, &context); + hmac_md5_update(resp_buf, 16, &context); + hmac_md5_final(ses->server->mac_signing_key.data.ntlmv2.key, &context); - crypto_shash_update(&ses->server->ntlmssp.sdeschmacmd5->shash, - resp_buf, CIFS_HMAC_MD5_HASH_SIZE); - - rc = crypto_shash_final(&ses->server->ntlmssp.sdeschmacmd5->shash, - ses->server->session_key.data.ntlmv2.key); - - memcpy(&ses->server->session_key.data.ntlmv2.resp, resp_buf, - sizeof(struct ntlmv2_resp)); - ses->server->session_key.len = 16 + sizeof(struct ntlmv2_resp); - - return rc; + memcpy(&ses->server->mac_signing_key.data.ntlmv2.resp, resp_buf, + sizeof(struct ntlmv2_resp)); + ses->server->mac_signing_key.len = 16 + sizeof(struct ntlmv2_resp); } -int -calc_seckey(struct TCP_Server_Info *server) -{ - int rc; - unsigned char sec_key[CIFS_NTLMV2_SESSKEY_SIZE]; - struct crypto_blkcipher *tfm_arc4; - struct scatterlist sgin, sgout; - struct blkcipher_desc desc; - - get_random_bytes(sec_key, CIFS_NTLMV2_SESSKEY_SIZE); - - tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", - 0, CRYPTO_ALG_ASYNC); - if (!tfm_arc4 || IS_ERR(tfm_arc4)) { - cERROR(1, "could not allocate " "master crypto API arc4\n"); - return 1; - } - - desc.tfm = tfm_arc4; - - crypto_blkcipher_setkey(tfm_arc4, - server->session_key.data.ntlmv2.key, CIFS_CPHTXT_SIZE); - sg_init_one(&sgin, sec_key, CIFS_CPHTXT_SIZE); - sg_init_one(&sgout, server->ntlmssp.ciphertext, CIFS_CPHTXT_SIZE); - rc = crypto_blkcipher_encrypt(&desc, &sgout, &sgin, CIFS_CPHTXT_SIZE); - - if (!rc) - memcpy(server->session_key.data.ntlmv2.key, - sec_key, CIFS_NTLMV2_SESSKEY_SIZE); - - crypto_free_blkcipher(tfm_arc4); - - return 0; -} - -void -cifs_crypto_shash_release(struct TCP_Server_Info *server) -{ - if (server->ntlmssp.md5) - crypto_free_shash(server->ntlmssp.md5); - - if (server->ntlmssp.hmacmd5) - crypto_free_shash(server->ntlmssp.hmacmd5); - - kfree(server->ntlmssp.sdeschmacmd5); - - kfree(server->ntlmssp.sdescmd5); -} - -int -cifs_crypto_shash_allocate(struct TCP_Server_Info *server) +void CalcNTLMv2_response(const struct cifsSesInfo *ses, + char *v2_session_response) { - int rc; - unsigned int size; - - server->ntlmssp.hmacmd5 = crypto_alloc_shash("hmac(md5)", 0, 0); - if (!server->ntlmssp.hmacmd5 || - IS_ERR(server->ntlmssp.hmacmd5)) { - cERROR(1, "could not allocate crypto hmacmd5\n"); - return 1; - } - - server->ntlmssp.md5 = crypto_alloc_shash("md5", 0, 0); - if (!server->ntlmssp.md5 || IS_ERR(server->ntlmssp.md5)) { - cERROR(1, "could not allocate crypto md5\n"); - rc = 1; - goto cifs_crypto_shash_allocate_ret1; - } - - size = sizeof(struct shash_desc) + - crypto_shash_descsize(server->ntlmssp.hmacmd5); - server->ntlmssp.sdeschmacmd5 = kmalloc(size, GFP_KERNEL); - if (!server->ntlmssp.sdeschmacmd5) { - cERROR(1, "cifs_crypto_shash_allocate: can't alloc hmacmd5\n"); - rc = -ENOMEM; - goto cifs_crypto_shash_allocate_ret2; - } - server->ntlmssp.sdeschmacmd5->shash.tfm = server->ntlmssp.hmacmd5; - server->ntlmssp.sdeschmacmd5->shash.flags = 0x0; + struct HMACMD5Context context; + /* rest of v2 struct already generated */ + memcpy(v2_session_response + 8, ses->server->cryptKey, 8); + hmac_md5_init_limK_to_64(ses->server->ntlmv2_hash, 16, &context); + hmac_md5_update(v2_session_response+8, + sizeof(struct ntlmv2_resp) - 8, &context); - size = sizeof(struct shash_desc) + - crypto_shash_descsize(server->ntlmssp.md5); - server->ntlmssp.sdescmd5 = kmalloc(size, GFP_KERNEL); - if (!server->ntlmssp.sdescmd5) { - cERROR(1, "cifs_crypto_shash_allocate: can't alloc md5\n"); - rc = -ENOMEM; - goto cifs_crypto_shash_allocate_ret3; - } - server->ntlmssp.sdescmd5->shash.tfm = server->ntlmssp.md5; - server->ntlmssp.sdescmd5->shash.flags = 0x0; - - return 0; - -cifs_crypto_shash_allocate_ret3: - kfree(server->ntlmssp.sdeschmacmd5); - -cifs_crypto_shash_allocate_ret2: - crypto_free_shash(server->ntlmssp.md5); - -cifs_crypto_shash_allocate_ret1: - crypto_free_shash(server->ntlmssp.hmacmd5); - - return rc; + hmac_md5_final(v2_session_response, &context); +/* cifs_dump_mem("v2_sess_rsp: ", v2_session_response, 32); */ } diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index c9d0cfc086e..0cdfb8c32ac 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -25,9 +25,6 @@ #include <linux/workqueue.h> #include "cifs_fs_sb.h" #include "cifsacl.h" -#include <crypto/internal/hash.h> -#include <linux/scatterlist.h> - /* * The sizes of various internal tables and strings */ @@ -100,7 +97,7 @@ enum protocolEnum { /* Netbios frames protocol not supported at this time */ }; -struct session_key { +struct mac_key { unsigned int len; union { char ntlm[CIFS_SESS_KEY_SIZE + 16]; @@ -123,21 +120,6 @@ struct cifs_cred { struct cifs_ace *aces; }; -struct sdesc { - struct shash_desc shash; - char ctx[]; -}; - -struct ntlmssp_auth { - __u32 client_flags; - __u32 server_flags; - unsigned char ciphertext[CIFS_CPHTXT_SIZE]; - struct crypto_shash *hmacmd5; - struct crypto_shash *md5; - struct sdesc *sdeschmacmd5; - struct sdesc *sdescmd5; -}; - /* ***************************************************************** * Except the CIFS PDUs themselves all the @@ -200,14 +182,11 @@ struct TCP_Server_Info { /* 16th byte of RFC1001 workstation name is always null */ char workstation_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL]; __u32 sequence_number; /* needed for CIFS PDU signature */ - struct session_key session_key; + struct mac_key mac_signing_key; char ntlmv2_hash[16]; unsigned long lstrp; /* when we got last response from this server */ u16 dialect; /* dialect index that server chose */ /* extended security flavors that server supports */ - unsigned int tilen; /* length of the target info blob */ - unsigned char *tiblob; /* target info blob in challenge response */ - struct ntlmssp_auth ntlmssp; /* various keys, ciphers, flags */ bool sec_kerberos; /* supports plain Kerberos */ bool sec_mskerberos; /* supports legacy MS Kerberos */ bool sec_kerberosu2u; /* supports U2U Kerberos */ diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index 320e0fd0ba7..14d036d8db1 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h @@ -134,12 +134,6 @@ * Size of the session key (crypto key encrypted with the password */ #define CIFS_SESS_KEY_SIZE (24) -#define CIFS_CLIENT_CHALLENGE_SIZE (8) -#define CIFS_SERVER_CHALLENGE_SIZE (8) -#define CIFS_HMAC_MD5_HASH_SIZE (16) -#define CIFS_CPHTXT_SIZE (16) -#define CIFS_NTLMV2_SESSKEY_SIZE (16) -#define CIFS_NTHASH_SIZE (16) /* * Maximum user name length @@ -669,6 +663,7 @@ struct ntlmv2_resp { __le64 time; __u64 client_chal; /* random */ __u32 reserved2; + struct ntlmssp2_name names[2]; /* array of name entries could follow ending in minimum 4 byte struct */ } __attribute__((packed)); diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 1378d913384..1d60c655e3e 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -87,8 +87,9 @@ extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr); extern int decode_negTokenInit(unsigned char *security_blob, int length, struct TCP_Server_Info *server); extern int cifs_convert_address(struct sockaddr *dst, const char *src, int len); +extern int cifs_set_port(struct sockaddr *addr, const unsigned short int port); extern int cifs_fill_sockaddr(struct sockaddr *dst, const char *src, int len, - unsigned short int port); + const unsigned short int port); extern int map_smb_to_linux_error(struct smb_hdr *smb, int logErr); extern void header_assemble(struct smb_hdr *, char /* command */ , const struct cifsTconInfo *, int /* length of @@ -361,15 +362,13 @@ extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *, __u32 *); extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *, __u32 *); extern int cifs_verify_signature(struct smb_hdr *, - struct TCP_Server_Info *server, + const struct mac_key *mac_key, __u32 expected_sequence_number); -extern int cifs_calculate_session_key(struct session_key *key, const char *rn, +extern int cifs_calculate_mac_key(struct mac_key *key, const char *rn, const char *pass); -extern int setup_ntlmv2_rsp(struct cifsSesInfo *, char *, +extern void CalcNTLMv2_response(const struct cifsSesInfo *, char *); +extern void setup_ntlmv2_rsp(struct cifsSesInfo *, char *, const struct nls_table *); -extern int cifs_crypto_shash_allocate(struct TCP_Server_Info *); -extern void cifs_crypto_shash_release(struct TCP_Server_Info *); -extern int calc_seckey(struct TCP_Server_Info *); #ifdef CONFIG_CIFS_WEAK_PW_HASH extern void calc_lanman_hash(const char *password, const char *cryptkey, bool encrypt, char *lnm_session_key); diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 4bda920d1f7..c65c3419dd3 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -604,14 +604,11 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) else rc = -EINVAL; - if (server->secType == Kerberos) { - if (!server->sec_kerberos && - !server->sec_mskerberos) - rc = -EOPNOTSUPP; - } else if (server->secType == RawNTLMSSP) { - if (!server->sec_ntlmssp) - rc = -EOPNOTSUPP; - } else + if (server->sec_kerberos || server->sec_mskerberos) + server->secType = Kerberos; + else if (server->sec_ntlmssp) + server->secType = RawNTLMSSP; + else rc = -EOPNOTSUPP; } } else diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index ec0ea4a43bd..67dad54fbfa 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -400,7 +400,9 @@ incomplete_rcv: cFYI(1, "call to reconnect done"); csocket = server->ssocket; continue; - } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) { + } else if (length == -ERESTARTSYS || + length == -EAGAIN || + length == -EINTR) { msleep(1); /* minimum sleep to prevent looping allowing socket to clear and app threads to set tcpStatus CifsNeedReconnect if server hung */ @@ -414,18 +416,6 @@ incomplete_rcv: } else continue; } else if (length <= 0) { - if (server->tcpStatus == CifsNew) { - cFYI(1, "tcp session abend after SMBnegprot"); - /* some servers kill the TCP session rather than - returning an SMB negprot error, in which - case reconnecting here is not going to help, - and so simply return error to mount */ - break; - } - if (!try_to_freeze() && (length == -EINTR)) { - cFYI(1, "cifsd thread killed"); - break; - } cFYI(1, "Reconnect after unexpected peek error %d", length); cifs_reconnect(server); @@ -466,27 +456,19 @@ incomplete_rcv: an error on SMB negprot response */ cFYI(1, "Negative RFC1002 Session Response Error 0x%x)", pdu_length); - if (server->tcpStatus == CifsNew) { - /* if nack on negprot (rather than - ret of smb negprot error) reconnecting - not going to help, ret error to mount */ - break; - } else { - /* give server a second to - clean up before reconnect attempt */ - msleep(1000); - /* always try 445 first on reconnect - since we get NACK on some if we ever - connected to port 139 (the NACK is - since we do not begin with RFC1001 - session initialize frame) */ - server->addr.sockAddr.sin_port = - htons(CIFS_PORT); - cifs_reconnect(server); - csocket = server->ssocket; - wake_up(&server->response_q); - continue; - } + /* give server a second to clean up */ + msleep(1000); + /* always try 445 first on reconnect since we get NACK + * on some if we ever connected to port 139 (the NACK + * is since we do not begin with RFC1001 session + * initialize frame) + */ + cifs_set_port((struct sockaddr *) + &server->addr.sockAddr, CIFS_PORT); + cifs_reconnect(server); + csocket = server->ssocket; + wake_up(&server->response_q); + continue; } else if (temp != (char) 0) { cERROR(1, "Unknown RFC 1002 frame"); cifs_dump_mem(" Received Data: ", (char *)smb_buffer, @@ -522,8 +504,7 @@ incomplete_rcv: total_read += length) { length = kernel_recvmsg(csocket, &smb_msg, &iov, 1, pdu_length - total_read, 0); - if ((server->tcpStatus == CifsExiting) || - (length == -EINTR)) { + if (server->tcpStatus == CifsExiting) { /* then will exit */ reconnect = 2; break; @@ -534,8 +515,9 @@ incomplete_rcv: /* Now we will reread sock */ reconnect = 1; break; - } else if ((length == -ERESTARTSYS) || - (length == -EAGAIN)) { + } else if (length == -ERESTARTSYS || + length == -EAGAIN || + length == -EINTR) { msleep(1); /* minimum sleep to prevent looping, allowing socket to clear and app threads to set tcpStatus @@ -1708,7 +1690,6 @@ cifs_put_smb_ses(struct cifsSesInfo *ses) CIFSSMBLogoff(xid, ses); _FreeXid(xid); } - cifs_crypto_shash_release(server); sesInfoFree(ses); cifs_put_tcp_session(server); } @@ -1788,23 +1769,13 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info) ses->linux_uid = volume_info->linux_uid; ses->overrideSecFlg = volume_info->secFlg; - rc = cifs_crypto_shash_allocate(server); - if (rc) { - cERROR(1, "could not setup hash structures rc %d", rc); - goto get_ses_fail; - } - server->tilen = 0; - server->tiblob = NULL; - mutex_lock(&ses->session_mutex); rc = cifs_negotiate_protocol(xid, ses); if (!rc) rc = cifs_setup_session(xid, ses, volume_info->local_nls); mutex_unlock(&ses->session_mutex); - if (rc) { - cifs_crypto_shash_release(ses->server); + if (rc) goto get_ses_fail; - } /* success, put it on the list */ write_lock(&cifs_tcp_ses_lock); diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 86a164f08a7..93f77d438d3 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -1462,29 +1462,18 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry, { char *fromName = NULL; char *toName = NULL; - struct cifs_sb_info *cifs_sb_source; - struct cifs_sb_info *cifs_sb_target; + struct cifs_sb_info *cifs_sb; struct cifsTconInfo *tcon; FILE_UNIX_BASIC_INFO *info_buf_source = NULL; FILE_UNIX_BASIC_INFO *info_buf_target; int xid, rc, tmprc; - cifs_sb_target = CIFS_SB(target_dir->i_sb); - cifs_sb_source = CIFS_SB(source_dir->i_sb); - tcon = cifs_sb_source->tcon; + cifs_sb = CIFS_SB(source_dir->i_sb); + tcon = cifs_sb->tcon; xid = GetXid(); /* - * BB: this might be allowed if same server, but different share. - * Consider adding support for this - */ - if (tcon != cifs_sb_target->tcon) { - rc = -EXDEV; - goto cifs_rename_exit; - } - - /* * we already have the rename sem so we do not need to * grab it again here to protect the path integrity */ @@ -1519,17 +1508,16 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry, info_buf_target = info_buf_source + 1; tmprc = CIFSSMBUnixQPathInfo(xid, tcon, fromName, info_buf_source, - cifs_sb_source->local_nls, - cifs_sb_source->mnt_cifs_flags & + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); if (tmprc != 0) goto unlink_target; - tmprc = CIFSSMBUnixQPathInfo(xid, tcon, - toName, info_buf_target, - cifs_sb_target->local_nls, - /* remap based on source sb */ - cifs_sb_source->mnt_cifs_flags & + tmprc = CIFSSMBUnixQPathInfo(xid, tcon, toName, + info_buf_target, + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); |