int ret;
if (smb3_capabilities != NULL) {
+ const struct smb3_signing_capabilities *sign_algos =
+ &smb3_capabilities->signing;
const struct smb3_encryption_capabilities *ciphers =
&smb3_capabilities->encryption;
+ SMB_ASSERT(sign_algos->num_algos <= SMB3_SIGNING_CAPABILITIES_MAX_ALGOS);
SMB_ASSERT(ciphers->num_algos <= SMB3_ENCRYTION_CAPABILITIES_MAX_ALGOS);
}
}
if (state->conn->max_protocol >= PROTOCOL_SMB3_11) {
+ const struct smb3_signing_capabilities *client_sign_algos =
+ &state->conn->smb2.client.smb3_capabilities.signing;
const struct smb3_encryption_capabilities *client_ciphers =
&state->conn->smb2.client.smb3_capabilities.encryption;
NTSTATUS status;
}
}
+ if (client_sign_algos->num_algos > 0) {
+ size_t ofs = 0;
+ SSVAL(p, ofs, client_sign_algos->num_algos);
+ ofs += 2;
+
+ for (i = 0; i < client_sign_algos->num_algos; i++) {
+ size_t next_ofs = ofs + 2;
+ SMB_ASSERT(next_ofs < ARRAY_SIZE(p));
+ SSVAL(p, ofs, client_sign_algos->algos[i]);
+ ofs = next_ofs;
+ }
+
+ status = smb2_negotiate_context_add(
+ state, &c, SMB2_SIGNING_CAPABILITIES, p, ofs);
+ if (!NT_STATUS_IS_OK(status)) {
+ return NULL;
+ }
+ }
+
ok = convert_string_talloc(state, CH_UNIX, CH_UTF16,
state->conn->remote_name,
strlen(state->conn->remote_name),
uint16_t salt_length;
uint16_t hash_selected;
gnutls_hash_hd_t hash_hnd = NULL;
+ struct smb2_negotiate_context *sign_algo = NULL;
struct smb2_negotiate_context *cipher = NULL;
struct iovec sent_iov[3] = {{0}, {0}, {0}};
static const struct smb2cli_req_expected_response expected[] = {
return;
}
+ sign_algo = smb2_negotiate_context_find(&c, SMB2_SIGNING_CAPABILITIES);
+ if (sign_algo != NULL) {
+ const struct smb3_signing_capabilities *client_sign_algos =
+ &state->conn->smb2.client.smb3_capabilities.signing;
+ bool found_selected = false;
+ uint16_t sign_algo_count;
+ uint16_t sign_algo_selected;
+
+ if (client_sign_algos->num_algos == 0) {
+ /*
+ * We didn't ask for SMB2_ENCRYPTION_CAPABILITIES
+ */
+ tevent_req_nterror(req,
+ NT_STATUS_INVALID_NETWORK_RESPONSE);
+ return;
+ }
+
+ if (sign_algo->data.length < 2) {
+ tevent_req_nterror(req,
+ NT_STATUS_INVALID_NETWORK_RESPONSE);
+ return;
+ }
+
+ sign_algo_count = SVAL(sign_algo->data.data, 0);
+ if (sign_algo_count != 1) {
+ tevent_req_nterror(req,
+ NT_STATUS_INVALID_NETWORK_RESPONSE);
+ return;
+ }
+
+ if (sign_algo->data.length < (2 + 2 * sign_algo_count)) {
+ tevent_req_nterror(req,
+ NT_STATUS_INVALID_NETWORK_RESPONSE);
+ return;
+ }
+ sign_algo_selected = SVAL(sign_algo->data.data, 2);
+
+ for (i = 0; i < client_sign_algos->num_algos; i++) {
+ if (client_sign_algos->algos[i] == sign_algo_selected) {
+ /*
+ * We found a match
+ */
+ found_selected = true;
+ break;
+ }
+ }
+
+ if (!found_selected) {
+ /*
+ * The server send a sign_algo we didn't offer.
+ */
+ tevent_req_nterror(req,
+ NT_STATUS_INVALID_NETWORK_RESPONSE);
+ return;
+ }
+
+ conn->smb2.server.sign_algo = sign_algo_selected;
+ }
+
cipher = smb2_negotiate_context_find(&c, SMB2_ENCRYPTION_CAPABILITIES);
if (cipher != NULL) {
const struct smb3_encryption_capabilities *client_ciphers =
return encryption_state;
}
+static const struct enum_list enum_smb3_signing_algorithms[] = {
+ {SMB2_SIGNING_AES128_CMAC, "aes-128-cmac"},
+ {SMB2_SIGNING_HMAC_SHA256, "hmac-sha-256"},
+ {-1, NULL}
+};
+
+const char *smb3_signing_algorithm_name(uint16_t algo)
+{
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE(enum_smb3_signing_algorithms); i++) {
+ if (enum_smb3_signing_algorithms[i].value != algo) {
+ continue;
+ }
+
+ return enum_smb3_signing_algorithms[i].name;
+ }
+
+ return NULL;
+}
+
static const struct enum_list enum_smb3_encryption_algorithms[] = {
{SMB2_ENCRYPTION_AES128_GCM, "aes-128-gcm"},
{SMB2_ENCRYPTION_AES128_CCM, "aes-128-ccm"},
struct smb311_capabilities smb311_capabilities_parse(const char *role,
const char * const *encryption_algos)
{
+ const char * const *signing_algos = NULL;
struct smb311_capabilities c = {
+ .signing = {
+ .num_algos = 0,
+ },
.encryption = {
.num_algos = 0,
},
};
+ char sign_param[64] = { 0, };
char enc_param[64] = { 0, };
size_t ai;
+ snprintf(sign_param, sizeof(sign_param),
+ "%s smb3 signing algorithms", role);
snprintf(enc_param, sizeof(enc_param),
"%s smb3 encryption algorithms", role);
+ for (ai = 0; signing_algos != NULL && signing_algos[ai] != NULL; ai++) {
+ const char *algoname = signing_algos[ai];
+ int32_t v32;
+ uint16_t algo;
+ size_t di;
+ bool ignore = false;
+
+ if (c.signing.num_algos >= SMB3_ENCRYTION_CAPABILITIES_MAX_ALGOS) {
+ DBG_ERR("WARNING: Ignoring trailing value '%s' for parameter '%s'\n",
+ algoname, sign_param);
+ continue;
+ }
+
+ v32 = parse_enum_val(enum_smb3_signing_algorithms,
+ sign_param, algoname);
+ if (v32 == INT32_MAX) {
+ continue;
+ }
+ algo = v32;
+
+ for (di = 0; di < c.signing.num_algos; di++) {
+ if (algo != c.signing.algos[di]) {
+ continue;
+ }
+
+ ignore = true;
+ break;
+ }
+
+ if (ignore) {
+ DBG_ERR("WARNING: Ignoring duplicate value '%s' for parameter '%s'\n",
+ algoname, sign_param);
+ continue;
+ }
+
+ c.signing.algos[c.signing.num_algos] = algo;
+ c.signing.num_algos += 1;
+ }
+
for (ai = 0; encryption_algos != NULL && encryption_algos[ai] != NULL; ai++) {
const char *algoname = encryption_algos[ai];
int32_t v32;