|
@@ -66,45 +66,15 @@ cifs_crypto_shash_md5_allocate(struct TCP_Server_Info *server)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * Calculate and return the CIFS signature based on the mac key and SMB PDU.
|
|
|
- * The 16 byte signature must be allocated by the caller. Note we only use the
|
|
|
- * 1st eight bytes and that the smb header signature field on input contains
|
|
|
- * the sequence number before this function is called. Also, this function
|
|
|
- * should be called with the server->srv_mutex held.
|
|
|
- */
|
|
|
-static int cifs_calc_signature(struct smb_rqst *rqst,
|
|
|
- struct TCP_Server_Info *server, char *signature)
|
|
|
+int __cifs_calc_signature(struct smb_rqst *rqst,
|
|
|
+ struct TCP_Server_Info *server, char *signature,
|
|
|
+ struct shash_desc *shash)
|
|
|
{
|
|
|
int i;
|
|
|
int rc;
|
|
|
struct kvec *iov = rqst->rq_iov;
|
|
|
int n_vec = rqst->rq_nvec;
|
|
|
|
|
|
- if (iov == NULL || signature == NULL || server == NULL)
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
- if (!server->secmech.sdescmd5) {
|
|
|
- rc = cifs_crypto_shash_md5_allocate(server);
|
|
|
- if (rc) {
|
|
|
- cifs_dbg(VFS, "%s: Can't alloc md5 crypto\n", __func__);
|
|
|
- return -1;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- rc = crypto_shash_init(&server->secmech.sdescmd5->shash);
|
|
|
- if (rc) {
|
|
|
- cifs_dbg(VFS, "%s: Could not init md5\n", __func__);
|
|
|
- return rc;
|
|
|
- }
|
|
|
-
|
|
|
- rc = crypto_shash_update(&server->secmech.sdescmd5->shash,
|
|
|
- server->session_key.response, server->session_key.len);
|
|
|
- if (rc) {
|
|
|
- cifs_dbg(VFS, "%s: Could not update with response\n", __func__);
|
|
|
- return rc;
|
|
|
- }
|
|
|
-
|
|
|
for (i = 0; i < n_vec; i++) {
|
|
|
if (iov[i].iov_len == 0)
|
|
|
continue;
|
|
@@ -117,12 +87,10 @@ static int cifs_calc_signature(struct smb_rqst *rqst,
|
|
|
if (i == 0) {
|
|
|
if (iov[0].iov_len <= 8) /* cmd field at offset 9 */
|
|
|
break; /* nothing to sign or corrupt header */
|
|
|
- rc =
|
|
|
- crypto_shash_update(&server->secmech.sdescmd5->shash,
|
|
|
+ rc = crypto_shash_update(shash,
|
|
|
iov[i].iov_base + 4, iov[i].iov_len - 4);
|
|
|
} else {
|
|
|
- rc =
|
|
|
- crypto_shash_update(&server->secmech.sdescmd5->shash,
|
|
|
+ rc = crypto_shash_update(shash,
|
|
|
iov[i].iov_base, iov[i].iov_len);
|
|
|
}
|
|
|
if (rc) {
|
|
@@ -134,21 +102,64 @@ static int cifs_calc_signature(struct smb_rqst *rqst,
|
|
|
|
|
|
/* now hash over the rq_pages array */
|
|
|
for (i = 0; i < rqst->rq_npages; i++) {
|
|
|
- struct kvec p_iov;
|
|
|
+ void *kaddr = kmap(rqst->rq_pages[i]);
|
|
|
+ size_t len = rqst->rq_pagesz;
|
|
|
+
|
|
|
+ if (i == rqst->rq_npages - 1)
|
|
|
+ len = rqst->rq_tailsz;
|
|
|
+
|
|
|
+ crypto_shash_update(shash, kaddr, len);
|
|
|
|
|
|
- cifs_rqst_page_to_kvec(rqst, i, &p_iov);
|
|
|
- crypto_shash_update(&server->secmech.sdescmd5->shash,
|
|
|
- p_iov.iov_base, p_iov.iov_len);
|
|
|
kunmap(rqst->rq_pages[i]);
|
|
|
}
|
|
|
|
|
|
- rc = crypto_shash_final(&server->secmech.sdescmd5->shash, signature);
|
|
|
+ rc = crypto_shash_final(shash, signature);
|
|
|
if (rc)
|
|
|
- cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
|
|
|
+ cifs_dbg(VFS, "%s: Could not generate hash\n", __func__);
|
|
|
|
|
|
return rc;
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * Calculate and return the CIFS signature based on the mac key and SMB PDU.
|
|
|
+ * The 16 byte signature must be allocated by the caller. Note we only use the
|
|
|
+ * 1st eight bytes and that the smb header signature field on input contains
|
|
|
+ * the sequence number before this function is called. Also, this function
|
|
|
+ * should be called with the server->srv_mutex held.
|
|
|
+ */
|
|
|
+static int cifs_calc_signature(struct smb_rqst *rqst,
|
|
|
+ struct TCP_Server_Info *server, char *signature)
|
|
|
+{
|
|
|
+ int rc;
|
|
|
+
|
|
|
+ if (!rqst->rq_iov || !signature || !server)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ if (!server->secmech.sdescmd5) {
|
|
|
+ rc = cifs_crypto_shash_md5_allocate(server);
|
|
|
+ if (rc) {
|
|
|
+ cifs_dbg(VFS, "%s: Can't alloc md5 crypto\n", __func__);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ rc = crypto_shash_init(&server->secmech.sdescmd5->shash);
|
|
|
+ if (rc) {
|
|
|
+ cifs_dbg(VFS, "%s: Could not init md5\n", __func__);
|
|
|
+ return rc;
|
|
|
+ }
|
|
|
+
|
|
|
+ rc = crypto_shash_update(&server->secmech.sdescmd5->shash,
|
|
|
+ server->session_key.response, server->session_key.len);
|
|
|
+ if (rc) {
|
|
|
+ cifs_dbg(VFS, "%s: Could not update with response\n", __func__);
|
|
|
+ return rc;
|
|
|
+ }
|
|
|
+
|
|
|
+ return __cifs_calc_signature(rqst, server, signature,
|
|
|
+ &server->secmech.sdescmd5->shash);
|
|
|
+}
|
|
|
+
|
|
|
/* must be called with server->srv_mutex held */
|
|
|
int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server,
|
|
|
__u32 *pexpected_response_sequence_number)
|