Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 826a95e4 authored by Jeff Layton's avatar Jeff Layton Committed by Steve French
Browse files

cifs: consolidate signature generating code



We have two versions of signature generating code. A vectorized and
non-vectorized version. Eliminate a large chunk of cut-and-paste
code by turning the non-vectorized version into a wrapper around the
vectorized one.

Signed-off-by: default avatarJeff Layton <jlayton@redhat.com>
Signed-off-by: default avatarSteve French <smfrench@gmail.com>
parent 376b43f4
Loading
Loading
Loading
Loading
+21 −82
Original line number Diff line number Diff line
@@ -37,82 +37,7 @@
 * the sequence number before this function is called. Also, this function
 * should be called with the server->srv_mutex held.
 */
static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu,
				struct TCP_Server_Info *server, char *signature)
{
	int rc;

	if (cifs_pdu == NULL || signature == NULL || server == NULL)
		return -EINVAL;

	if (!server->secmech.sdescmd5) {
		cERROR(1, "%s: Can't generate signature\n", __func__);
		return -1;
	}

	rc = crypto_shash_init(&server->secmech.sdescmd5->shash);
	if (rc) {
		cERROR(1, "%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) {
		cERROR(1, "%s: Could not update with response\n", __func__);
		return rc;
	}

	rc = crypto_shash_update(&server->secmech.sdescmd5->shash,
		cifs_pdu->Protocol, be32_to_cpu(cifs_pdu->smb_buf_length));
	if (rc) {
		cERROR(1, "%s: Could not update with payload\n", __func__);
		return rc;
	}

	rc = crypto_shash_final(&server->secmech.sdescmd5->shash, signature);
	if (rc)
		cERROR(1, "%s: Could not generate md5 hash\n", __func__);

	return rc;
}

/* must be called with server->srv_mutex held */
int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
		  __u32 *pexpected_response_sequence_number)
{
	int rc = 0;
	char smb_signature[20];

	if ((cifs_pdu == NULL) || (server == NULL))
		return -EINVAL;

	if (!(cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) ||
	    server->tcpStatus == CifsNeedNegotiate)
		return rc;

	if (!server->session_estab) {
		memcpy(cifs_pdu->Signature.SecuritySignature, "BSRSPYL", 8);
		return rc;
	}

	cifs_pdu->Signature.Sequence.SequenceNumber =
			cpu_to_le32(server->sequence_number);
	cifs_pdu->Signature.Sequence.Reserved = 0;

	*pexpected_response_sequence_number = server->sequence_number++;
	server->sequence_number++;

	rc = cifs_calculate_signature(cifs_pdu, server, smb_signature);
	if (rc)
		memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
	else
		memcpy(cifs_pdu->Signature.SecuritySignature, smb_signature, 8);

	return rc;
}

static int cifs_calc_signature2(const struct kvec *iov, int n_vec,
static int cifs_calc_signature(const struct kvec *iov, int n_vec,
			struct TCP_Server_Info *server, char *signature)
{
	int i;
@@ -179,7 +104,7 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
{
	int rc = 0;
	char smb_signature[20];
	struct smb_hdr *cifs_pdu = iov[0].iov_base;
	struct smb_hdr *cifs_pdu = (struct smb_hdr *)iov[0].iov_base;

	if ((cifs_pdu == NULL) || (server == NULL))
		return -EINVAL;
@@ -200,7 +125,7 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
	*pexpected_response_sequence_number = server->sequence_number++;
	server->sequence_number++;

	rc = cifs_calc_signature2(iov, n_vec, server, smb_signature);
	rc = cifs_calc_signature(iov, n_vec, server, smb_signature);
	if (rc)
		memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
	else
@@ -209,13 +134,27 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
	return rc;
}

int cifs_verify_signature(struct smb_hdr *cifs_pdu,
/* must be called with server->srv_mutex held */
int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
		  __u32 *pexpected_response_sequence_number)
{
	struct kvec iov;

	iov.iov_base = cifs_pdu;
	iov.iov_len = be32_to_cpu(cifs_pdu->smb_buf_length) + 4;

	return cifs_sign_smb2(&iov, 1, server,
			      pexpected_response_sequence_number);
}

int cifs_verify_signature(struct kvec *iov, unsigned int nr_iov,
			  struct TCP_Server_Info *server,
			  __u32 expected_sequence_number)
{
	unsigned int rc;
	char server_response_sig[8];
	char what_we_think_sig_should_be[20];
	struct smb_hdr *cifs_pdu = (struct smb_hdr *)iov[0].iov_base;

	if (cifs_pdu == NULL || server == NULL)
		return -EINVAL;
@@ -247,7 +186,7 @@ int cifs_verify_signature(struct smb_hdr *cifs_pdu,
	cifs_pdu->Signature.Sequence.Reserved = 0;

	mutex_lock(&server->srv_mutex);
	rc = cifs_calculate_signature(cifs_pdu, server,
	rc = cifs_calc_signature(iov, nr_iov, server,
				 what_we_think_sig_should_be);
	mutex_unlock(&server->srv_mutex);

+1 −1
Original line number Diff line number Diff line
@@ -380,7 +380,7 @@ extern void tconInfoFree(struct cifs_tcon *);
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 *,
extern int cifs_verify_signature(struct kvec *iov, unsigned int nr_iov,
				 struct TCP_Server_Info *server,
				__u32 expected_sequence_number);
extern int SMBNTencrypt(unsigned char *, unsigned char *, unsigned char *);
+8 −3
Original line number Diff line number Diff line
@@ -496,13 +496,18 @@ int
cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
		   bool log_error)
{
	dump_smb(mid->resp_buf,
		 min_t(u32, 92, be32_to_cpu(mid->resp_buf->smb_buf_length)));
	unsigned int len = be32_to_cpu(mid->resp_buf->smb_buf_length) + 4;

	dump_smb(mid->resp_buf, min_t(u32, 92, len));

	/* convert the length into a more usable form */
	if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
		struct kvec iov;

		iov.iov_base = mid->resp_buf;
		iov.iov_len = len;
		/* FIXME: add code to kill session */
		if (cifs_verify_signature(mid->resp_buf, server,
		if (cifs_verify_signature(&iov, 1, server,
					  mid->sequence_number + 1) != 0)
			cERROR(1, "Unexpected SMB signature");
	}