summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/ksmbd/connection.h2
-rw-r--r--fs/ksmbd/ndr.c12
-rw-r--r--fs/ksmbd/server.c20
-rw-r--r--fs/ksmbd/smb2misc.c9
-rw-r--r--fs/ksmbd/smb2ops.c4
-rw-r--r--fs/ksmbd/smb2pdu.c204
-rw-r--r--fs/ksmbd/smb2pdu.h20
-rw-r--r--fs/ksmbd/transport_rdma.c2
-rw-r--r--fs/ksmbd/transport_rdma.h6
-rw-r--r--fs/ksmbd/transport_tcp.c3
10 files changed, 182 insertions, 100 deletions
diff --git a/fs/ksmbd/connection.h b/fs/ksmbd/connection.h
index 487c2024b0d5..e5403c587a58 100644
--- a/fs/ksmbd/connection.h
+++ b/fs/ksmbd/connection.h
@@ -109,6 +109,8 @@ struct ksmbd_conn {
__le16 cipher_type;
__le16 compress_algorithm;
bool posix_ext_supported;
+ bool signing_negotiated;
+ __le16 signing_algorithm;
bool binding;
};
diff --git a/fs/ksmbd/ndr.c b/fs/ksmbd/ndr.c
index cf0df78259c9..df23dfbaf657 100644
--- a/fs/ksmbd/ndr.c
+++ b/fs/ksmbd/ndr.c
@@ -65,13 +65,15 @@ static int ndr_write_bytes(struct ndr *n, void *value, size_t sz)
return 0;
}
-static int ndr_write_string(struct ndr *n, void *value, size_t sz)
+static int ndr_write_string(struct ndr *n, char *value)
{
+ size_t sz;
+
+ sz = strlen(value) + 1;
if (n->length <= n->offset + sz)
try_to_realloc_ndr_blob(n, sz);
- strncpy(ndr_get_field(n), value, sz);
- sz++;
+ memcpy(ndr_get_field(n), value, sz);
n->offset += sz;
n->offset = ALIGN(n->offset, 2);
return 0;
@@ -134,9 +136,9 @@ int ndr_encode_dos_attr(struct ndr *n, struct xattr_dos_attrib *da)
if (da->version == 3) {
snprintf(hex_attr, 10, "0x%x", da->attr);
- ndr_write_string(n, hex_attr, strlen(hex_attr));
+ ndr_write_string(n, hex_attr);
} else {
- ndr_write_string(n, "", strlen(""));
+ ndr_write_string(n, "");
}
ndr_write_int16(n, da->version);
ndr_write_int32(n, da->version);
diff --git a/fs/ksmbd/server.c b/fs/ksmbd/server.c
index a8c59e96a2f7..e6a9f6aa47eb 100644
--- a/fs/ksmbd/server.c
+++ b/fs/ksmbd/server.c
@@ -101,8 +101,8 @@ static inline int check_conn_state(struct ksmbd_work *work)
return 0;
}
-#define TCP_HANDLER_CONTINUE 0
-#define TCP_HANDLER_ABORT 1
+#define SERVER_HANDLER_CONTINUE 0
+#define SERVER_HANDLER_ABORT 1
static int __process_request(struct ksmbd_work *work, struct ksmbd_conn *conn,
u16 *cmd)
@@ -112,10 +112,10 @@ static int __process_request(struct ksmbd_work *work, struct ksmbd_conn *conn,
int ret;
if (check_conn_state(work))
- return TCP_HANDLER_CONTINUE;
+ return SERVER_HANDLER_CONTINUE;
if (ksmbd_verify_smb_message(work))
- return TCP_HANDLER_ABORT;
+ return SERVER_HANDLER_ABORT;
command = conn->ops->get_cmd_val(work);
*cmd = command;
@@ -123,21 +123,21 @@ static int __process_request(struct ksmbd_work *work, struct ksmbd_conn *conn,
andx_again:
if (command >= conn->max_cmds) {
conn->ops->set_rsp_status(work, STATUS_INVALID_PARAMETER);
- return TCP_HANDLER_CONTINUE;
+ return SERVER_HANDLER_CONTINUE;
}
cmds = &conn->cmds[command];
if (!cmds->proc) {
ksmbd_debug(SMB, "*** not implemented yet cmd = %x\n", command);
conn->ops->set_rsp_status(work, STATUS_NOT_IMPLEMENTED);
- return TCP_HANDLER_CONTINUE;
+ return SERVER_HANDLER_CONTINUE;
}
if (work->sess && conn->ops->is_sign_req(work, command)) {
ret = conn->ops->check_sign_req(work);
if (!ret) {
conn->ops->set_rsp_status(work, STATUS_ACCESS_DENIED);
- return TCP_HANDLER_CONTINUE;
+ return SERVER_HANDLER_CONTINUE;
}
}
@@ -153,8 +153,8 @@ andx_again:
}
if (work->send_no_response)
- return TCP_HANDLER_ABORT;
- return TCP_HANDLER_CONTINUE;
+ return SERVER_HANDLER_ABORT;
+ return SERVER_HANDLER_CONTINUE;
}
static void __handle_ksmbd_work(struct ksmbd_work *work,
@@ -203,7 +203,7 @@ static void __handle_ksmbd_work(struct ksmbd_work *work,
do {
rc = __process_request(work, conn, &command);
- if (rc == TCP_HANDLER_ABORT)
+ if (rc == SERVER_HANDLER_ABORT)
break;
/*
diff --git a/fs/ksmbd/smb2misc.c b/fs/ksmbd/smb2misc.c
index 4508631c5706..9aa46bb3e10d 100644
--- a/fs/ksmbd/smb2misc.c
+++ b/fs/ksmbd/smb2misc.c
@@ -385,6 +385,12 @@ int ksmbd_smb2_check_message(struct ksmbd_work *work)
}
}
+ if ((work->conn->vals->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU) &&
+ smb2_validate_credit_charge(hdr)) {
+ work->conn->ops->set_rsp_status(work, STATUS_INVALID_PARAMETER);
+ return 1;
+ }
+
clc_len = smb2_calc_size(hdr);
if (len != clc_len) {
/* server can return one byte more due to implied bcc[0] */
@@ -423,8 +429,7 @@ int ksmbd_smb2_check_message(struct ksmbd_work *work)
return 1;
}
- return work->conn->vals->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU ?
- smb2_validate_credit_charge(hdr) : 0;
+ return 0;
}
int smb2_negotiate_request(struct ksmbd_work *work)
diff --git a/fs/ksmbd/smb2ops.c b/fs/ksmbd/smb2ops.c
index 8262908e467c..197473871aa4 100644
--- a/fs/ksmbd/smb2ops.c
+++ b/fs/ksmbd/smb2ops.c
@@ -204,6 +204,7 @@ void init_smb2_1_server(struct ksmbd_conn *conn)
conn->cmds = smb2_0_server_cmds;
conn->max_cmds = ARRAY_SIZE(smb2_0_server_cmds);
conn->max_credits = SMB2_MAX_CREDITS;
+ conn->signing_algorithm = SIGNING_ALG_HMAC_SHA256;
if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES)
conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING;
@@ -221,6 +222,7 @@ void init_smb3_0_server(struct ksmbd_conn *conn)
conn->cmds = smb2_0_server_cmds;
conn->max_cmds = ARRAY_SIZE(smb2_0_server_cmds);
conn->max_credits = SMB2_MAX_CREDITS;
+ conn->signing_algorithm = SIGNING_ALG_AES_CMAC;
if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES)
conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING;
@@ -245,6 +247,7 @@ void init_smb3_02_server(struct ksmbd_conn *conn)
conn->cmds = smb2_0_server_cmds;
conn->max_cmds = ARRAY_SIZE(smb2_0_server_cmds);
conn->max_credits = SMB2_MAX_CREDITS;
+ conn->signing_algorithm = SIGNING_ALG_AES_CMAC;
if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES)
conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING;
@@ -269,6 +272,7 @@ int init_smb3_11_server(struct ksmbd_conn *conn)
conn->cmds = smb2_0_server_cmds;
conn->max_cmds = ARRAY_SIZE(smb2_0_server_cmds);
conn->max_credits = SMB2_MAX_CREDITS;
+ conn->signing_algorithm = SIGNING_ALG_AES_CMAC;
if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES)
conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING;
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index c1a594599431..7e6e3d8c20e8 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -786,6 +786,18 @@ static void build_compression_ctxt(struct smb2_compression_ctx *pneg_ctxt,
pneg_ctxt->CompressionAlgorithms[0] = comp_algo;
}
+static void build_sign_cap_ctxt(struct smb2_signing_capabilities *pneg_ctxt,
+ __le16 sign_algo)
+{
+ pneg_ctxt->ContextType = SMB2_SIGNING_CAPABILITIES;
+ pneg_ctxt->DataLength =
+ cpu_to_le16((sizeof(struct smb2_signing_capabilities) + 2)
+ - sizeof(struct smb2_neg_context));
+ pneg_ctxt->Reserved = cpu_to_le32(0);
+ pneg_ctxt->SigningAlgorithmCount = cpu_to_le16(1);
+ pneg_ctxt->SigningAlgorithms[0] = sign_algo;
+}
+
static void build_posix_ctxt(struct smb2_posix_neg_context *pneg_ctxt)
{
pneg_ctxt->ContextType = SMB2_POSIX_EXTENSIONS_AVAILABLE;
@@ -835,10 +847,10 @@ static void assemble_neg_contexts(struct ksmbd_conn *conn,
build_encrypt_ctxt((struct smb2_encryption_neg_context *)pneg_ctxt,
conn->cipher_type);
rsp->NegotiateContextCount = cpu_to_le16(++neg_ctxt_cnt);
- ctxt_size += sizeof(struct smb2_encryption_neg_context);
+ ctxt_size += sizeof(struct smb2_encryption_neg_context) + 2;
/* Round to 8 byte boundary */
pneg_ctxt +=
- round_up(sizeof(struct smb2_encryption_neg_context),
+ round_up(sizeof(struct smb2_encryption_neg_context) + 2,
8);
}
@@ -850,9 +862,10 @@ static void assemble_neg_contexts(struct ksmbd_conn *conn,
build_compression_ctxt((struct smb2_compression_ctx *)pneg_ctxt,
conn->compress_algorithm);
rsp->NegotiateContextCount = cpu_to_le16(++neg_ctxt_cnt);
- ctxt_size += sizeof(struct smb2_compression_ctx);
+ ctxt_size += sizeof(struct smb2_compression_ctx) + 2;
/* Round to 8 byte boundary */
- pneg_ctxt += round_up(sizeof(struct smb2_compression_ctx), 8);
+ pneg_ctxt += round_up(sizeof(struct smb2_compression_ctx) + 2,
+ 8);
}
if (conn->posix_ext_supported) {
@@ -862,6 +875,18 @@ static void assemble_neg_contexts(struct ksmbd_conn *conn,
build_posix_ctxt((struct smb2_posix_neg_context *)pneg_ctxt);
rsp->NegotiateContextCount = cpu_to_le16(++neg_ctxt_cnt);
ctxt_size += sizeof(struct smb2_posix_neg_context);
+ /* Round to 8 byte boundary */
+ pneg_ctxt += round_up(sizeof(struct smb2_posix_neg_context), 8);
+ }
+
+ if (conn->signing_negotiated) {
+ ctxt_size = round_up(ctxt_size, 8);
+ ksmbd_debug(SMB,
+ "assemble SMB2_SIGNING_CAPABILITIES context\n");
+ build_sign_cap_ctxt((struct smb2_signing_capabilities *)pneg_ctxt,
+ conn->signing_algorithm);
+ rsp->NegotiateContextCount = cpu_to_le16(++neg_ctxt_cnt);
+ ctxt_size += sizeof(struct smb2_signing_capabilities) + 2;
}
inc_rfc1001_len(rsp, ctxt_size);
@@ -881,16 +906,23 @@ static __le32 decode_preauth_ctxt(struct ksmbd_conn *conn,
return err;
}
-static int decode_encrypt_ctxt(struct ksmbd_conn *conn,
- struct smb2_encryption_neg_context *pneg_ctxt)
+static void decode_encrypt_ctxt(struct ksmbd_conn *conn,
+ struct smb2_encryption_neg_context *pneg_ctxt,
+ int len_of_ctxts)
{
- int i;
int cph_cnt = le16_to_cpu(pneg_ctxt->CipherCount);
+ int i, cphs_size = cph_cnt * sizeof(__le16);
conn->cipher_type = 0;
+ if (sizeof(struct smb2_encryption_neg_context) + cphs_size >
+ len_of_ctxts) {
+ pr_err("Invalid cipher count(%d)\n", cph_cnt);
+ return;
+ }
+
if (!(server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION))
- goto out;
+ return;
for (i = 0; i < cph_cnt; i++) {
if (pneg_ctxt->Ciphers[i] == SMB2_ENCRYPTION_AES128_GCM ||
@@ -903,90 +935,122 @@ static int decode_encrypt_ctxt(struct ksmbd_conn *conn,
break;
}
}
+}
-out:
- /*
- * Return encrypt context size in request.
- * So need to plus extra number of ciphers size.
- */
- return sizeof(struct smb2_encryption_neg_context) +
- ((cph_cnt - 1) * 2);
+static void decode_compress_ctxt(struct ksmbd_conn *conn,
+ struct smb2_compression_ctx *pneg_ctxt)
+{
+ conn->compress_algorithm = SMB3_COMPRESS_NONE;
}
-static int decode_compress_ctxt(struct ksmbd_conn *conn,
- struct smb2_compression_ctx *pneg_ctxt)
+static void decode_sign_cap_ctxt(struct ksmbd_conn *conn,
+ struct smb2_signing_capabilities *pneg_ctxt,
+ int len_of_ctxts)
{
- int algo_cnt = le16_to_cpu(pneg_ctxt->CompressionAlgorithmCount);
+ int sign_algo_cnt = le16_to_cpu(pneg_ctxt->SigningAlgorithmCount);
+ int i, sign_alos_size = sign_algo_cnt * sizeof(__le16);
- conn->compress_algorithm = SMB3_COMPRESS_NONE;
+ conn->signing_negotiated = false;
- /*
- * Return compression context size in request.
- * So need to plus extra number of CompressionAlgorithms size.
- */
- return sizeof(struct smb2_encryption_neg_context) +
- ((algo_cnt - 1) * 2);
+ if (sizeof(struct smb2_signing_capabilities) + sign_alos_size >
+ len_of_ctxts) {
+ pr_err("Invalid signing algorithm count(%d)\n", sign_algo_cnt);
+ return;
+ }
+
+ for (i = 0; i < sign_algo_cnt; i++) {
+ if (pneg_ctxt->SigningAlgorithms[i] == SIGNING_ALG_HMAC_SHA256 ||
+ pneg_ctxt->SigningAlgorithms[i] == SIGNING_ALG_AES_CMAC) {
+ ksmbd_debug(SMB, "Signing Algorithm ID = 0x%x\n",
+ pneg_ctxt->SigningAlgorithms[i]);
+ conn->signing_negotiated = true;
+ conn->signing_algorithm =
+ pneg_ctxt->SigningAlgorithms[i];
+ break;
+ }
+ }
}
static __le32 deassemble_neg_contexts(struct ksmbd_conn *conn,
struct smb2_negotiate_req *req)
{
- int i = 0;
- __le32 status = 0;
/* +4 is to account for the RFC1001 len field */
- char *pneg_ctxt = (char *)req +
- le32_to_cpu(req->NegotiateContextOffset) + 4;
- __le16 *ContextType = (__le16 *)pneg_ctxt;
+ struct smb2_neg_context *pctx = (struct smb2_neg_context *)((char *)req + 4);
+ int i = 0, len_of_ctxts;
+ int offset = le32_to_cpu(req->NegotiateContextOffset);
int neg_ctxt_cnt = le16_to_cpu(req->NegotiateContextCount);
- int ctxt_size;
+ int len_of_smb = be32_to_cpu(req->hdr.smb2_buf_length);
+ __le32 status = STATUS_INVALID_PARAMETER;
+
+ ksmbd_debug(SMB, "decoding %d negotiate contexts\n", neg_ctxt_cnt);
+ if (len_of_smb <= offset) {
+ ksmbd_debug(SMB, "Invalid response: negotiate context offset\n");
+ return status;
+ }
+
+ len_of_ctxts = len_of_smb - offset;
- ksmbd_debug(SMB, "negotiate context count = %d\n", neg_ctxt_cnt);
- status = STATUS_INVALID_PARAMETER;
while (i++ < neg_ctxt_cnt) {
- if (*ContextType == SMB2_PREAUTH_INTEGRITY_CAPABILITIES) {
+ int clen;
+
+ /* check that offset is not beyond end of SMB */
+ if (len_of_ctxts == 0)
+ break;
+
+ if (len_of_ctxts < sizeof(struct smb2_neg_context))
+ break;
+
+ pctx = (struct smb2_neg_context *)((char *)pctx + offset);
+ clen = le16_to_cpu(pctx->DataLength);
+ if (clen + sizeof(struct smb2_neg_context) > len_of_ctxts)
+ break;
+
+ if (pctx->ContextType == SMB2_PREAUTH_INTEGRITY_CAPABILITIES) {
ksmbd_debug(SMB,
"deassemble SMB2_PREAUTH_INTEGRITY_CAPABILITIES context\n");
if (conn->preauth_info->Preauth_HashId)
break;
status = decode_preauth_ctxt(conn,
- (struct smb2_preauth_neg_context *)pneg_ctxt);
- pneg_ctxt += DIV_ROUND_UP(sizeof(struct smb2_preauth_neg_context), 8) * 8;
- } else if (*ContextType == SMB2_ENCRYPTION_CAPABILITIES) {
+ (struct smb2_preauth_neg_context *)pctx);
+ if (status != STATUS_SUCCESS)
+ break;
+ } else if (pctx->ContextType == SMB2_ENCRYPTION_CAPABILITIES) {
ksmbd_debug(SMB,
"deassemble SMB2_ENCRYPTION_CAPABILITIES context\n");
if (conn->cipher_type)
break;
- ctxt_size = decode_encrypt_ctxt(conn,
- (struct smb2_encryption_neg_context *)pneg_ctxt);
- pneg_ctxt += DIV_ROUND_UP(ctxt_size, 8) * 8;
- } else if (*ContextType == SMB2_COMPRESSION_CAPABILITIES) {
+ decode_encrypt_ctxt(conn,
+ (struct smb2_encryption_neg_context *)pctx,
+ len_of_ctxts);
+ } else if (pctx->ContextType == SMB2_COMPRESSION_CAPABILITIES) {
ksmbd_debug(SMB,
"deassemble SMB2_COMPRESSION_CAPABILITIES context\n");
if (conn->compress_algorithm)
break;
- ctxt_size = decode_compress_ctxt(conn,
- (struct smb2_compression_ctx *)pneg_ctxt);
- pneg_ctxt += DIV_ROUND_UP(ctxt_size, 8) * 8;
- } else if (*ContextType == SMB2_NETNAME_NEGOTIATE_CONTEXT_ID) {
+ decode_compress_ctxt(conn,
+ (struct smb2_compression_ctx *)pctx);
+ } else if (pctx->ContextType == SMB2_NETNAME_NEGOTIATE_CONTEXT_ID) {
ksmbd_debug(SMB,
"deassemble SMB2_NETNAME_NEGOTIATE_CONTEXT_ID context\n");
- ctxt_size = sizeof(struct smb2_netname_neg_context);
- ctxt_size += DIV_ROUND_UP(le16_to_cpu(((struct smb2_netname_neg_context *)
- pneg_ctxt)->DataLength), 8) * 8;
- pneg_ctxt += ctxt_size;
- } else if (*ContextType == SMB2_POSIX_EXTENSIONS_AVAILABLE) {
+ } else if (pctx->ContextType == SMB2_POSIX_EXTENSIONS_AVAILABLE) {
ksmbd_debug(SMB,
"deassemble SMB2_POSIX_EXTENSIONS_AVAILABLE context\n");
conn->posix_ext_supported = true;
- pneg_ctxt += DIV_ROUND_UP(sizeof(struct smb2_posix_neg_context), 8) * 8;
+ } else if (pctx->ContextType == SMB2_SIGNING_CAPABILITIES) {
+ ksmbd_debug(SMB,
+ "deassemble SMB2_SIGNING_CAPABILITIES context\n");
+ decode_sign_cap_ctxt(conn,
+ (struct smb2_signing_capabilities *)pctx,
+ len_of_ctxts);
}
- ContextType = (__le16 *)pneg_ctxt;
- if (status != STATUS_SUCCESS)
- break;
+ /* offsets must be 8 byte aligned */
+ clen = (clen + 7) & ~0x7;
+ offset = clen + sizeof(struct smb2_neg_context);
+ len_of_ctxts -= clen + sizeof(struct smb2_neg_context);
}
return status;
}
@@ -1338,8 +1402,7 @@ static int ntlm_authenticate(struct ksmbd_work *work)
user = session_user(conn, req);
if (!user) {
ksmbd_debug(SMB, "Unknown user name or an error\n");
- rsp->hdr.Status = STATUS_LOGON_FAILURE;
- return -EINVAL;
+ return -EPERM;
}
/* Check for previous session */
@@ -1363,8 +1426,7 @@ static int ntlm_authenticate(struct ksmbd_work *work)
if (user_guest(sess->user)) {
if (conn->sign) {
ksmbd_debug(SMB, "Guest login not allowed when signing enabled\n");
- rsp->hdr.Status = STATUS_LOGON_FAILURE;
- return -EACCES;
+ return -EPERM;
}
rsp->SessionFlags = SMB2_SESSION_FLAG_IS_GUEST_LE;
@@ -1377,8 +1439,7 @@ static int ntlm_authenticate(struct ksmbd_work *work)
if (rc) {
set_user_flag(sess->user, KSMBD_USER_FLAG_BAD_PASSWORD);
ksmbd_debug(SMB, "authentication failed\n");
- rsp->hdr.Status = STATUS_LOGON_FAILURE;
- return -EINVAL;
+ return -EPERM;
}
/*
@@ -1403,8 +1464,7 @@ static int ntlm_authenticate(struct ksmbd_work *work)
if (rc) {
ksmbd_debug(SMB,
"SMB3 encryption key generation failed\n");
- rsp->hdr.Status = STATUS_LOGON_FAILURE;
- return rc;
+ return -EINVAL;
}
sess->enc = true;
rsp->SessionFlags = SMB2_SESSION_FLAG_ENCRYPT_DATA_LE;
@@ -1434,16 +1494,14 @@ binding_session:
rc = conn->ops->generate_signingkey(sess, conn);
if (rc) {
ksmbd_debug(SMB, "SMB3 signing key generation failed\n");
- rsp->hdr.Status = STATUS_LOGON_FAILURE;
- return rc;
+ return -EINVAL;
}
}
if (conn->dialect > SMB20_PROT_ID) {
if (!ksmbd_conn_lookup_dialect(conn)) {
pr_err("fail to verify the dialect\n");
- rsp->hdr.Status = STATUS_USER_SESSION_DELETED;
- return -EPERM;
+ return -ENOENT;
}
}
return 0;
@@ -1483,8 +1541,7 @@ static int krb5_authenticate(struct ksmbd_work *work)
out_blob, &out_len);
if (retval) {
ksmbd_debug(SMB, "krb5 authentication failed\n");
- rsp->hdr.Status = STATUS_LOGON_FAILURE;
- return retval;
+ return -EINVAL;
}
rsp->SecurityBufferLength = cpu_to_le16(out_len);
inc_rfc1001_len(rsp, out_len - 1);
@@ -1499,8 +1556,7 @@ static int krb5_authenticate(struct ksmbd_work *work)
if (retval) {
ksmbd_debug(SMB,
"SMB3 encryption key generation failed\n");
- rsp->hdr.Status = STATUS_LOGON_FAILURE;
- return retval;
+ return -EINVAL;
}
sess->enc = true;
rsp->SessionFlags = SMB2_SESSION_FLAG_ENCRYPT_DATA_LE;
@@ -1524,16 +1580,14 @@ static int krb5_authenticate(struct ksmbd_work *work)
retval = conn->ops->generate_signingkey(sess, conn);
if (retval) {
ksmbd_debug(SMB, "SMB3 signing key generation failed\n");
- rsp->hdr.Status = STATUS_LOGON_FAILURE;
- return retval;
+ return -EINVAL;
}
}
if (conn->dialect > SMB20_PROT_ID) {
if (!ksmbd_conn_lookup_dialect(conn)) {
pr_err("fail to verify the dialect\n");
- rsp->hdr.Status = STATUS_USER_SESSION_DELETED;
- return -EPERM;
+ return -ENOENT;
}
}
return 0;
@@ -1709,6 +1763,8 @@ out_err:
rsp->hdr.Status = STATUS_REQUEST_NOT_ACCEPTED;
else if (rc == -EFAULT)
rsp->hdr.Status = STATUS_NETWORK_SESSION_EXPIRED;
+ else if (rc == -ENOMEM)
+ rsp->hdr.Status = STATUS_INSUFFICIENT_RESOURCES;
else if (rc)
rsp->hdr.Status = STATUS_LOGON_FAILURE;
diff --git a/fs/ksmbd/smb2pdu.h b/fs/ksmbd/smb2pdu.h
index 0eac40e1ba65..89019f67234c 100644
--- a/fs/ksmbd/smb2pdu.h
+++ b/fs/ksmbd/smb2pdu.h
@@ -268,6 +268,7 @@ struct preauth_integrity_info {
#define SMB2_ENCRYPTION_CAPABILITIES cpu_to_le16(2)
#define SMB2_COMPRESSION_CAPABILITIES cpu_to_le16(3)
#define SMB2_NETNAME_NEGOTIATE_CONTEXT_ID cpu_to_le16(5)
+#define SMB2_SIGNING_CAPABILITIES cpu_to_le16(8)
#define SMB2_POSIX_EXTENSIONS_AVAILABLE cpu_to_le16(0x100)
struct smb2_neg_context {
@@ -299,7 +300,7 @@ struct smb2_encryption_neg_context {
__le32 Reserved;
/* CipherCount usally 2, but can be 3 when AES256-GCM enabled */
__le16 CipherCount; /* AES-128-GCM and AES-128-CCM by default */
- __le16 Ciphers[1];
+ __le16 Ciphers[];
} __packed;
#define SMB3_COMPRESS_NONE cpu_to_le16(0x0000)
@@ -314,7 +315,7 @@ struct smb2_compression_ctx {
__le16 CompressionAlgorithmCount;
__u16 Padding;
__le32 Reserved1;
- __le16 CompressionAlgorithms[1];
+ __le16 CompressionAlgorithms[];
} __packed;
#define POSIX_CTXT_DATA_LEN 16
@@ -329,7 +330,20 @@ struct smb2_netname_neg_context {
__le16 ContextType; /* 0x100 */
__le16 DataLength;
__le32 Reserved;
- __le16 NetName[0]; /* hostname of target converted to UCS-2 */
+ __le16 NetName[]; /* hostname of target converted to UCS-2 */
+} __packed;
+
+/* Signing algorithms */
+#define SIGNING_ALG_HMAC_SHA256 cpu_to_le16(0)
+#define SIGNING_ALG_AES_CMAC cpu_to_le16(1)
+#define SIGNING_ALG_AES_GMAC cpu_to_le16(2)
+
+struct smb2_signing_capabilities {
+ __le16 ContextType; /* 8 */
+ __le16 DataLength;
+ __le32 Reserved;
+ __le16 SigningAlgorithmCount;
+ __le16 SigningAlgorithms[];
} __packed;
struct smb2_negotiate_rsp {
diff --git a/fs/ksmbd/transport_rdma.c b/fs/ksmbd/transport_rdma.c
index f818fe358f31..f2ae6bae83f1 100644
--- a/fs/ksmbd/transport_rdma.c
+++ b/fs/ksmbd/transport_rdma.c
@@ -58,7 +58,7 @@
/*
* User configurable initial values per SMB_DIRECT transport connection
- * as defined in [MS-KSMBD] 3.1.1.1
+ * as defined in [MS-SMBD] 3.1.1.1
* Those may change after a SMB_DIRECT negotiation
*/
/* The local peer's maximum number of credits to grant to the peer */
diff --git a/fs/ksmbd/transport_rdma.h b/fs/ksmbd/transport_rdma.h
index 72e2574079f3..0fa8adc0776f 100644
--- a/fs/ksmbd/transport_rdma.h
+++ b/fs/ksmbd/transport_rdma.h
@@ -9,7 +9,7 @@
#define SMB_DIRECT_PORT 5445
-/* SMB DIRECT negotiation request packet [MS-KSMBD] 2.2.1 */
+/* SMB DIRECT negotiation request packet [MS-SMBD] 2.2.1 */
struct smb_direct_negotiate_req {
__le16 min_version;
__le16 max_version;
@@ -20,7 +20,7 @@ struct smb_direct_negotiate_req {
__le32 max_fragmented_size;
} __packed;
-/* SMB DIRECT negotiation response packet [MS-KSMBD] 2.2.2 */
+/* SMB DIRECT negotiation response packet [MS-SMBD] 2.2.2 */
struct smb_direct_negotiate_resp {
__le16 min_version;
__le16 max_version;
@@ -37,7 +37,7 @@ struct smb_direct_negotiate_resp {
#define SMB_DIRECT_RESPONSE_REQUESTED 0x0001
-/* SMB DIRECT data transfer packet with payload [MS-KSMBD] 2.2.3 */
+/* SMB DIRECT data transfer packet with payload [MS-SMBD] 2.2.3 */
struct smb_direct_data_transfer {
__le16 credits_requested;
__le16 credits_granted;
diff --git a/fs/ksmbd/transport_tcp.c b/fs/ksmbd/transport_tcp.c
index 56ec11ff5a9f..dc15a5ecd2e0 100644
--- a/fs/ksmbd/transport_tcp.c
+++ b/fs/ksmbd/transport_tcp.c
@@ -381,8 +381,7 @@ static void tcp_destroy_socket(struct socket *ksmbd_socket)
ret = kernel_sock_shutdown(ksmbd_socket, SHUT_RDWR);
if (ret)
pr_err("Failed to shutdown socket: %d\n", ret);
- else
- sock_release(ksmbd_socket);
+ sock_release(ksmbd_socket);
}
/**