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

Commit 373512ec authored by Steve French's avatar Steve French Committed by Steve French
Browse files

Prepare for encryption support (first part). Add decryption and encryption key...


Prepare for encryption support (first part). Add decryption and encryption key generation. Thanks to Metze for helping with this.

Reviewed-by: default avatarStefan Metzmacher <metze@samba.org>
Signed-off-by: default avatarSteve French <steve.french@primarydata.com>
parent 882137c4
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -227,7 +227,7 @@ struct smb_version_operations {
	void (*print_stats)(struct seq_file *m, struct cifs_tcon *);
	void (*dump_share_caps)(struct seq_file *, struct cifs_tcon *);
	/* verify the message */
	int (*check_message)(char *, unsigned int);
	int (*check_message)(char *, unsigned int, struct TCP_Server_Info *);
	bool (*is_oplock_break)(char *, struct TCP_Server_Info *);
	void (*downgrade_oplock)(struct TCP_Server_Info *,
					struct cifsInodeInfo *, bool);
@@ -630,6 +630,7 @@ struct TCP_Server_Info {
#ifdef CONFIG_CIFS_SMB2
	unsigned int	max_read;
	unsigned int	max_write;
	__u8		preauth_hash[512];
#endif /* CONFIG_CIFS_SMB2 */
	unsigned long echo_interval;
};
@@ -813,7 +814,10 @@ struct cifs_ses {
	bool need_reconnect:1; /* connection reset, uid now invalid */
#ifdef CONFIG_CIFS_SMB2
	__u16 session_flags;
	char smb3signingkey[SMB3_SIGN_KEY_SIZE]; /* for signing smb3 packets */
	__u8 smb3signingkey[SMB3_SIGN_KEY_SIZE];
	__u8 smb3encryptionkey[SMB3_SIGN_KEY_SIZE];
	__u8 smb3decryptionkey[SMB3_SIGN_KEY_SIZE];
	__u8 preauth_hash[512];
#endif /* CONFIG_CIFS_SMB2 */
};

+3 −2
Original line number Diff line number Diff line
@@ -102,7 +102,7 @@ extern int SendReceiveBlockingLock(const unsigned int xid,
			struct smb_hdr *out_buf,
			int *bytes_returned);
extern int cifs_reconnect(struct TCP_Server_Info *server);
extern int checkSMB(char *buf, unsigned int length);
extern int checkSMB(char *buf, unsigned int len, struct TCP_Server_Info *srvr);
extern bool is_valid_oplock_break(char *, struct TCP_Server_Info *);
extern bool backup_cred(struct cifs_sb_info *);
extern bool is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof);
@@ -439,7 +439,8 @@ extern int setup_ntlm_response(struct cifs_ses *, const struct nls_table *);
extern int setup_ntlmv2_rsp(struct cifs_ses *, const struct nls_table *);
extern void cifs_crypto_shash_release(struct TCP_Server_Info *);
extern int calc_seckey(struct cifs_ses *);
extern int generate_smb3signingkey(struct cifs_ses *);
extern int generate_smb30signingkey(struct cifs_ses *);
extern int generate_smb311signingkey(struct cifs_ses *);

#ifdef CONFIG_CIFS_WEAK_PW_HASH
extern int calc_lanman_hash(const char *password, const char *cryptkey,
+1 −1
Original line number Diff line number Diff line
@@ -831,7 +831,7 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
	 * 48 bytes is enough to display the header and a little bit
	 * into the payload for debugging purposes.
	 */
	length = server->ops->check_message(buf, server->total_read);
	length = server->ops->check_message(buf, server->total_read, server);
	if (length != 0)
		cifs_dump_mem("Bad SMB: ", buf,
			min_t(unsigned int, server->total_read, 48));
+1 −1
Original line number Diff line number Diff line
@@ -310,7 +310,7 @@ check_smb_hdr(struct smb_hdr *smb)
}

int
checkSMB(char *buf, unsigned int total_read)
checkSMB(char *buf, unsigned int total_read, struct TCP_Server_Info *server)
{
	struct smb_hdr *smb = (struct smb_hdr *)buf;
	__u32 rfclen = be32_to_cpu(smb->smb_buf_length);
+30 −6
Original line number Diff line number Diff line
@@ -38,7 +38,7 @@ check_smb2_hdr(struct smb2_hdr *hdr, __u64 mid)
	 * Make sure that this really is an SMB, that it is a response,
	 * and that the message ids match.
	 */
	if ((*(__le32 *)hdr->ProtocolId == SMB2_PROTO_NUMBER) &&
	if ((hdr->ProtocolId == SMB2_PROTO_NUMBER) &&
	    (mid == wire_mid)) {
		if (hdr->Flags & SMB2_FLAGS_SERVER_TO_REDIR)
			return 0;
@@ -50,9 +50,9 @@ check_smb2_hdr(struct smb2_hdr *hdr, __u64 mid)
				cifs_dbg(VFS, "Received Request not response\n");
		}
	} else { /* bad signature or mid */
		if (*(__le32 *)hdr->ProtocolId != SMB2_PROTO_NUMBER)
		if (hdr->ProtocolId != SMB2_PROTO_NUMBER)
			cifs_dbg(VFS, "Bad protocol string signature header %x\n",
				 *(unsigned int *) hdr->ProtocolId);
				 le32_to_cpu(hdr->ProtocolId));
		if (mid != wire_mid)
			cifs_dbg(VFS, "Mids do not match: %llu and %llu\n",
				 mid, wire_mid);
@@ -93,11 +93,11 @@ static const __le16 smb2_rsp_struct_sizes[NUMBER_OF_SMB2_COMMANDS] = {
};

int
smb2_check_message(char *buf, unsigned int length)
smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
{
	struct smb2_hdr *hdr = (struct smb2_hdr *)buf;
	struct smb2_pdu *pdu = (struct smb2_pdu *)hdr;
	__u64 mid = le64_to_cpu(hdr->MessageId);
	__u64 mid;
	__u32 len = get_rfc1002_length(buf);
	__u32 clc_len;  /* calculated length */
	int command;
@@ -111,6 +111,30 @@ smb2_check_message(char *buf, unsigned int length)
	 * ie Validate the wct via smb2_struct_sizes table above
	 */

	if (hdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) {
		struct smb2_transform_hdr *thdr =
			(struct smb2_transform_hdr *)buf;
		struct cifs_ses *ses = NULL;
		struct list_head *tmp;

		/* decrypt frame now that it is completely read in */
		spin_lock(&cifs_tcp_ses_lock);
		list_for_each(tmp, &srvr->smb_ses_list) {
			ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
			if (ses->Suid == thdr->SessionId)
				break;

			ses = NULL;
		}
		spin_unlock(&cifs_tcp_ses_lock);
		if (ses == NULL) {
			cifs_dbg(VFS, "no decryption - session id not found\n");
			return 1;
		}
	}


	mid = le64_to_cpu(hdr->MessageId);
	if (length < sizeof(struct smb2_pdu)) {
		if ((length >= sizeof(struct smb2_hdr)) && (hdr->Status != 0)) {
			pdu->StructureSize2 = 0;
@@ -322,7 +346,7 @@ smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr)

	/* return pointer to beginning of data area, ie offset from SMB start */
	if ((*off != 0) && (*len != 0))
		return (char *)(&hdr->ProtocolId[0]) + *off;
		return (char *)(&hdr->ProtocolId) + *off;
	else
		return NULL;
}
Loading