The branch, master has been updated via 0ac71061044 s3:smbd: really support AES-256* in the server via 407b458242c s4:torture/smb2: add tests to check all signing and encryption algorithms via 5512416a8fb gnutls: allow gnutls_aead_cipher_encryptv2 with gcm before 3.6.15 via f97f94e93b0 gpo: Improve debug when extension fails to apply via 4a5f6d88ff0 gpo: Warn when fetching the supported templates fails via a92b05ec7b4 gpo: Ensure Network Device Enrollment Service if sscep fails from bedeeb0b596 tdb: version 1.4.5
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 0ac71061044e2ee47f4de3a319ad2386128066fc Author: Stefan Metzmacher <me...@samba.org> Date: Thu Jul 15 13:20:22 2021 +0200 s3:smbd: really support AES-256* in the server BUG: https://bugzilla.samba.org/show_bug.cgi?id=14764 Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> Autobuild-User(master): Jeremy Allison <j...@samba.org> Autobuild-Date(master): Tue Jul 20 16:13:28 UTC 2021 on sn-devel-184 commit 407b458242cd11bdb3ab219dc58b3ffb070b0e7c Author: Stefan Metzmacher <me...@samba.org> Date: Mon Jul 19 18:38:06 2021 +0200 s4:torture/smb2: add tests to check all signing and encryption algorithms BUG: https://bugzilla.samba.org/show_bug.cgi?id=14764 Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit 5512416a8fbe00a7a5343afe0d50846e0a8f342b Author: Stefan Metzmacher <me...@samba.org> Date: Tue Mar 9 10:40:04 2021 +0100 gnutls: allow gnutls_aead_cipher_encryptv2 with gcm before 3.6.15 The memory leak bug up to 3.6.14 was only related to ccm, but gcm was fine. This avoids talloc+memcpy on more systems, e.g. ubuntu 20.04, and brings ~ 20% less cpu overhead, see: https://hackmd.io/@asn/samba_crypto_benchmarks BUG: https://bugzilla.samba.org/show_bug.cgi?id=14764 Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> commit f97f94e93b03495cf03d08873de5f3b912a003a0 Author: David Mulder <dmul...@suse.com> Date: Mon Jul 19 11:36:09 2021 -0600 gpo: Improve debug when extension fails to apply Signed-off-by: David Mulder <dmul...@suse.com> Reviewed-by: Jeremy Allison <j...@samba.org> commit 4a5f6d88ff0b2eebf86403ba25504e1bf2c59d53 Author: David Mulder <dmul...@suse.com> Date: Mon Jul 19 11:18:53 2021 -0600 gpo: Warn when fetching the supported templates fails When Certificate Auto Enrollment fails to fetch the list of supported templates, display a warning. Signed-off-by: David Mulder <dmul...@suse.com> Reviewed-by: Jeremy Allison <j...@samba.org> commit a92b05ec7b407a19da0cd7c2533c5b49dfbe4392 Author: David Mulder <dmul...@suse.com> Date: Mon Jul 19 11:11:56 2021 -0600 gpo: Ensure Network Device Enrollment Service if sscep fails Prompt the user to check that Network Device Enrollment Service is installed and configured if sscep fails to download the certificate root chain. Signed-off-by: David Mulder <dmul...@suse.com> Reviewed-by: Jeremy Allison <j...@samba.org> ----------------------------------------------------------------------- Summary of changes: libcli/smb/smb2_signing.c | 54 +++- python/samba/gp_cert_auto_enroll_ext.py | 18 +- python/samba/gpclass.py | 4 +- source3/smbd/smb2_sesssetup.c | 6 + source4/torture/smb2/session.c | 436 ++++++++++++++++++++++++++++++++ wscript_configure_system_gnutls | 10 +- 6 files changed, 506 insertions(+), 22 deletions(-) Changeset truncated at 500 lines: diff --git a/libcli/smb/smb2_signing.c b/libcli/smb/smb2_signing.c index 830f3bf1570..fdb69e90a07 100644 --- a/libcli/smb/smb2_signing.c +++ b/libcli/smb/smb2_signing.c @@ -324,7 +324,7 @@ static NTSTATUS smb2_signing_gmac(gnutls_aead_cipher_hd_t cipher_hnd, { size_t tag_size = _tag_size; int rc; -#if defined(HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2) +#ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_GCM rc = gnutls_aead_cipher_encryptv2(cipher_hnd, iv, iv_size, @@ -336,7 +336,7 @@ static NTSTATUS smb2_signing_gmac(gnutls_aead_cipher_hd_t cipher_hnd, } return NT_STATUS_OK; -#else /* HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 */ +#else /* ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_GCM */ TALLOC_CTX *tmp_ctx = NULL; size_t atext_size = 0; uint8_t *atext = NULL; @@ -387,7 +387,7 @@ static NTSTATUS smb2_signing_gmac(gnutls_aead_cipher_hd_t cipher_hnd, } return NT_STATUS_OK; -#endif /* HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 */ +#endif /* ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_GCM */ } static NTSTATUS smb2_signing_calc_signature(struct smb2_signing_key *signing_key, @@ -808,6 +808,9 @@ NTSTATUS smb2_signing_encrypt_pdu(struct smb2_signing_key *encryption_key, struct iovec *vector, int count) { +#ifdef HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 + bool use_encryptv2 = false; +#endif uint16_t cipher_id; uint8_t *tf; size_t a_total; @@ -851,18 +854,30 @@ NTSTATUS smb2_signing_encrypt_pdu(struct smb2_signing_key *encryption_key, case SMB2_ENCRYPTION_AES128_CCM: algo = GNUTLS_CIPHER_AES_128_CCM; iv_size = SMB2_AES_128_CCM_NONCE_SIZE; +#ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_CCM + use_encryptv2 = true; +#endif break; case SMB2_ENCRYPTION_AES128_GCM: algo = GNUTLS_CIPHER_AES_128_GCM; iv_size = gnutls_cipher_get_iv_size(algo); +#ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_GCM + use_encryptv2 = true; +#endif break; case SMB2_ENCRYPTION_AES256_CCM: algo = GNUTLS_CIPHER_AES_256_CCM; iv_size = SMB2_AES_128_CCM_NONCE_SIZE; +#ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_CCM + use_encryptv2 = true; +#endif break; case SMB2_ENCRYPTION_AES256_GCM: algo = GNUTLS_CIPHER_AES_256_GCM; iv_size = gnutls_cipher_get_iv_size(algo); +#ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_GCM + use_encryptv2 = true; +#endif break; default: return NT_STATUS_INVALID_PARAMETER; @@ -903,8 +918,8 @@ NTSTATUS smb2_signing_encrypt_pdu(struct smb2_signing_key *encryption_key, 0, 16 - iv_size); -#if defined(HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2) - { +#ifdef HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 + if (use_encryptv2) { uint8_t tag[tag_size]; giovec_t auth_iov[1]; @@ -928,8 +943,8 @@ NTSTATUS smb2_signing_encrypt_pdu(struct smb2_signing_key *encryption_key, } memcpy(tf + SMB2_TF_SIGNATURE, tag, tag_size); - } -#else /* HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 */ + } else +#endif /* HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 */ { size_t ptext_size = m_total; uint8_t *ptext = NULL; @@ -1007,7 +1022,6 @@ NTSTATUS smb2_signing_encrypt_pdu(struct smb2_signing_key *encryption_key, TALLOC_FREE(ptext); TALLOC_FREE(ctext); } -#endif /* HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 */ DBG_INFO("Encrypted SMB2 message\n"); @@ -1020,6 +1034,9 @@ NTSTATUS smb2_signing_decrypt_pdu(struct smb2_signing_key *decryption_key, struct iovec *vector, int count) { +#ifdef HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 + bool use_encryptv2 = false; +#endif uint16_t cipher_id; uint8_t *tf; uint16_t flags; @@ -1073,18 +1090,30 @@ NTSTATUS smb2_signing_decrypt_pdu(struct smb2_signing_key *decryption_key, case SMB2_ENCRYPTION_AES128_CCM: algo = GNUTLS_CIPHER_AES_128_CCM; iv_size = SMB2_AES_128_CCM_NONCE_SIZE; +#ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_CCM + use_encryptv2 = true; +#endif break; case SMB2_ENCRYPTION_AES128_GCM: algo = GNUTLS_CIPHER_AES_128_GCM; iv_size = gnutls_cipher_get_iv_size(algo); +#ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_GCM + use_encryptv2 = true; +#endif break; case SMB2_ENCRYPTION_AES256_CCM: algo = GNUTLS_CIPHER_AES_256_CCM; iv_size = SMB2_AES_128_CCM_NONCE_SIZE; +#ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_CCM + use_encryptv2 = true; +#endif break; case SMB2_ENCRYPTION_AES256_GCM: algo = GNUTLS_CIPHER_AES_256_GCM; iv_size = gnutls_cipher_get_iv_size(algo); +#ifdef ALLOW_GNUTLS_AEAD_CIPHER_ENCRYPTV2_AES_GCM + use_encryptv2 = true; +#endif break; default: return NT_STATUS_INVALID_PARAMETER; @@ -1122,8 +1151,8 @@ NTSTATUS smb2_signing_decrypt_pdu(struct smb2_signing_key *decryption_key, } /* gnutls_aead_cipher_encryptv2() has a bug in version 3.6.10 */ -#if defined(HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2) - { +#ifdef HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 + if (use_encryptv2) { giovec_t auth_iov[1]; auth_iov[0] = (giovec_t) { @@ -1144,8 +1173,8 @@ NTSTATUS smb2_signing_decrypt_pdu(struct smb2_signing_key *decryption_key, status = gnutls_error_to_ntstatus(rc, NT_STATUS_INTERNAL_ERROR); goto out; } - } -#else /* HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 */ + } else +#endif /* HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 */ { size_t ctext_size = m_total + tag_size; uint8_t *ctext = NULL; @@ -1229,7 +1258,6 @@ NTSTATUS smb2_signing_decrypt_pdu(struct smb2_signing_key *decryption_key, TALLOC_FREE(ptext); TALLOC_FREE(ctext); } -#endif /* HAVE_GNUTLS_AEAD_CIPHER_ENCRYPTV2 */ DBG_INFO("Decrypted SMB2 message\n"); diff --git a/python/samba/gp_cert_auto_enroll_ext.py b/python/samba/gp_cert_auto_enroll_ext.py index 556be604621..99465ef01c0 100644 --- a/python/samba/gp_cert_auto_enroll_ext.py +++ b/python/samba/gp_cert_auto_enroll_ext.py @@ -76,13 +76,17 @@ def find_cepces_submit(): '/usr/libexec/certmonger'] return which('cepces-submit', path=':'.join(certmonger_dirs)) -def get_supported_templates(server): +def get_supported_templates(server, logger): cepces_submit = find_cepces_submit() if os.path.exists(cepces_submit): env = os.environ env['CERTMONGER_OPERATION'] = 'GET-SUPPORTED-TEMPLATES' - out, _ = Popen([cepces_submit, '--server=%s' % server], env=env, - stdout=PIPE, stderr=PIPE).communicate() + p = Popen([cepces_submit, '--server=%s' % server], env=env, + stdout=PIPE, stderr=PIPE) + out, err = p.communicate() + if p.returncode != 0: + logger.warn('Failed to fetch the list of supported templates:' + + '\n%s' % err) return out.strip().split() return [] @@ -98,6 +102,8 @@ def cert_enroll(ca, trust_dir, private_dir, logger): root_cert, '-u', url]).wait() if ret != 0: logger.warn('sscep failed to fetch the root certificate chain.') + logger.warn('Ensure you have installed and configured the' + + ' Network Device Enrollment Service.') root_certs = glob('%s*' % root_cert) data['files'].extend(root_certs) for src in root_certs: @@ -126,7 +132,8 @@ def cert_enroll(ca, trust_dir, private_dir, logger): if getcert is not None and os.path.exists(cepces_submit): Popen([getcert, 'add-ca', '-c', ca['cn'][0], '-e', '%s --server=%s' % (cepces_submit, ca['dNSHostName'][0])]).wait() - supported_templates = get_supported_templates(ca['dNSHostName'][0]) + supported_templates = get_supported_templates(ca['dNSHostName'][0], + logger) for template, attrs in ca['certificateTemplates'].items(): if template not in supported_templates: continue @@ -238,7 +245,8 @@ class gp_cert_auto_enroll_ext(gp_pol_ext): output[policy][cn]['Auto Enrollment Server'] = \ ca['dNSHostName'][0] supported_templates = \ - get_supported_templates(ca['dNSHostName'][0]) + get_supported_templates(ca['dNSHostName'][0], + self.logger) output[policy][cn]['Templates'] = \ [t.decode() for t in supported_templates] return output diff --git a/python/samba/gpclass.py b/python/samba/gpclass.py index 6879719847f..17d7d0c9243 100644 --- a/python/samba/gpclass.py +++ b/python/samba/gpclass.py @@ -23,6 +23,7 @@ sys.path.insert(0, "bin/python") from samba import NTSTATUSError from configparser import ConfigParser from io import StringIO +import traceback from samba.common import get_bytes from abc import ABCMeta, abstractmethod import xml.etree.ElementTree as etree @@ -467,7 +468,8 @@ def apply_gp(lp, creds, logger, store, gp_extensions, force=False): ext.process_group_policy(del_gpos, changed_gpos) except Exception as e: logger.error('Failed to apply extension %s' % str(ext)) - logger.error('Message was: ' + str(e)) + logger.error('Message was: %s: %s' % (type(e).__name__, str(e))) + logger.debug(traceback.format_exc()) continue for gpo_obj in gpos: if not gpo_obj.file_sys_path: diff --git a/source3/smbd/smb2_sesssetup.c b/source3/smbd/smb2_sesssetup.c index 8cbad36cc7b..38049e8535f 100644 --- a/source3/smbd/smb2_sesssetup.c +++ b/source3/smbd/smb2_sesssetup.c @@ -346,6 +346,12 @@ static NTSTATUS smbd_smb2_auth_generic_return(struct smbXsrv_session *session, case SMB2_ENCRYPTION_AES128_GCM: nonce_size = gnutls_cipher_get_iv_size(GNUTLS_CIPHER_AES_128_GCM); break; + case SMB2_ENCRYPTION_AES256_CCM: + nonce_size = SMB2_AES_128_CCM_NONCE_SIZE; + break; + case SMB2_ENCRYPTION_AES256_GCM: + nonce_size = gnutls_cipher_get_iv_size(GNUTLS_CIPHER_AES_256_GCM); + break; default: nonce_size = 0; break; diff --git a/source4/torture/smb2/session.c b/source4/torture/smb2/session.c index cc554717ff0..1bf8f83efcc 100644 --- a/source4/torture/smb2/session.c +++ b/source4/torture/smb2/session.c @@ -48,6 +48,13 @@ "out.reserverd2 incorrect"); \ } while(0) +#define WAIT_FOR_ASYNC_RESPONSE(req) \ + while (!req->cancel.can_cancel && req->state <= SMB2_REQUEST_RECV) { \ + if (tevent_loop_once(tctx->ev) != 0) { \ + break; \ + } \ + } + /** * basic test for doing a session reconnect */ @@ -4942,6 +4949,428 @@ static bool test_session_two_logoff(struct torture_context *tctx, return ret; } +static bool test_session_sign_enc(struct torture_context *tctx, + const char *testname, + struct cli_credentials *credentials1, + const struct smbcli_options *options1) +{ + const char *host = torture_setting_string(tctx, "host", NULL); + const char *share = torture_setting_string(tctx, "share", NULL); + NTSTATUS status; + bool ret = false; + struct smb2_tree *tree1 = NULL; + char fname[256]; + struct smb2_handle rh = {{0}}; + struct smb2_handle _h1; + struct smb2_handle *h1 = NULL; + struct smb2_create io1; + union smb_fileinfo qfinfo1; + union smb_notify notify; + struct smb2_request *req = NULL; + + status = smb2_connect(tctx, + host, + lpcfg_smb_ports(tctx->lp_ctx), + share, + lpcfg_resolve_context(tctx->lp_ctx), + credentials1, + &tree1, + tctx->ev, + options1, + lpcfg_socket_options(tctx->lp_ctx), + lpcfg_gensec_settings(tctx, tctx->lp_ctx) + ); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_connect options1 failed"); + + status = smb2_util_roothandle(tree1, &rh); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_util_roothandle failed"); + + /* Add some random component to the file name. */ + snprintf(fname, sizeof(fname), "%s_%s.dat", + testname, generate_random_str(tctx, 8)); + + smb2_util_unlink(tree1, fname); + + smb2_oplock_create_share(&io1, fname, + smb2_util_share_access(""), + smb2_util_oplock_level("b")); + + io1.in.create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE; + status = smb2_create(tree1, tctx, &io1); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_create failed"); + _h1 = io1.out.file.handle; + h1 = &_h1; + CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE); + torture_assert_int_equal(tctx, io1.out.oplock_level, + smb2_util_oplock_level("b"), + "oplock_level incorrect"); + + /* Check the initial session is still alive */ + ZERO_STRUCT(qfinfo1); + qfinfo1.generic.level = RAW_FILEINFO_POSITION_INFORMATION; + qfinfo1.generic.in.file.handle = _h1; + status = smb2_getinfo_file(tree1, tctx, &qfinfo1); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_getinfo_file failed"); + + /* ask for a change notify, + on file or directory name changes */ + ZERO_STRUCT(notify); + notify.smb2.level = RAW_NOTIFY_SMB2; + notify.smb2.in.buffer_size = 1000; + notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME; + notify.smb2.in.file.handle = rh; + notify.smb2.in.recursive = true; + + req = smb2_notify_send(tree1, &(notify.smb2)); + WAIT_FOR_ASYNC_RESPONSE(req); + + status = smb2_cancel(req); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_cancel failed"); + + status = smb2_notify_recv(req, tctx, &(notify.smb2)); + torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_CANCELLED, + ret, done, + "smb2_notify_recv failed"); + + /* Check the initial session is still alive */ + ZERO_STRUCT(qfinfo1); + qfinfo1.generic.level = RAW_FILEINFO_POSITION_INFORMATION; + qfinfo1.generic.in.file.handle = _h1; + status = smb2_getinfo_file(tree1, tctx, &qfinfo1); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_getinfo_file failed"); + + ret = true; +done: + if (h1 != NULL) { + smb2_util_close(tree1, *h1); + } + TALLOC_FREE(tree1); + + return ret; +} + +static bool test_session_signing_hmac_sha_256(struct torture_context *tctx, struct smb2_tree *tree0) +{ + struct cli_credentials *credentials = samba_cmdline_get_creds(); + bool ret = false; + struct smb2_transport *transport0 = tree0->session->transport; + struct smbcli_options options1; + bool encrypted; + + encrypted = smb2cli_tcon_is_encryption_on(tree0->smbXcli); + if (encrypted) { + torture_skip(tctx, + "Can't test signing only if encrytion is required"); + } + + if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) { + torture_skip(tctx, + "Can't test without SMB 3.1.1 support"); + } + + if (smb2cli_conn_server_signing_algo(transport0->conn) < SMB2_SIGNING_AES128_GMAC) { + torture_skip(tctx, + "Can't test without SMB 3.1.1 signing negotiation support"); + } + + options1 = transport0->options; + options1.client_guid = GUID_random(); + options1.min_protocol = PROTOCOL_SMB3_11; + options1.max_protocol = PROTOCOL_SMB3_11; + options1.signing = SMB_SIGNING_REQUIRED; + options1.smb3_capabilities.signing = (struct smb3_signing_capabilities) { + .num_algos = 1, + .algos = { + SMB2_SIGNING_HMAC_SHA256, + }, + }; + + ret = test_session_sign_enc(tctx, + __func__, + credentials, + &options1); + TALLOC_FREE(tree0); + return ret; +} + +static bool test_session_signing_aes_128_cmac(struct torture_context *tctx, struct smb2_tree *tree0) +{ + struct cli_credentials *credentials = samba_cmdline_get_creds(); + bool ret = false; + struct smb2_transport *transport0 = tree0->session->transport; + struct smbcli_options options1; + bool encrypted; + + encrypted = smb2cli_tcon_is_encryption_on(tree0->smbXcli); + if (encrypted) { + torture_skip(tctx, + "Can't test signing only if encrytion is required"); + } + + if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) { + torture_skip(tctx, + "Can't test without SMB 3.1.1 support"); + } + + if (smb2cli_conn_server_signing_algo(transport0->conn) < SMB2_SIGNING_AES128_GMAC) { + torture_skip(tctx, + "Can't test without SMB 3.1.1 signing negotiation support"); + } + + options1 = transport0->options; + options1.client_guid = GUID_random(); + options1.min_protocol = PROTOCOL_SMB3_11; + options1.max_protocol = PROTOCOL_SMB3_11; + options1.signing = SMB_SIGNING_REQUIRED; + options1.smb3_capabilities.signing = (struct smb3_signing_capabilities) { + .num_algos = 1, + .algos = { + SMB2_SIGNING_AES128_CMAC, + }, + }; + + ret = test_session_sign_enc(tctx, + __func__, + credentials, + &options1); + TALLOC_FREE(tree0); + return ret; +} + +static bool test_session_signing_aes_128_gmac(struct torture_context *tctx, struct smb2_tree *tree0) +{ + struct cli_credentials *credentials = samba_cmdline_get_creds(); + bool ret = false; + struct smb2_transport *transport0 = tree0->session->transport; + struct smbcli_options options1; + bool encrypted; + + encrypted = smb2cli_tcon_is_encryption_on(tree0->smbXcli); + if (encrypted) { + torture_skip(tctx, + "Can't test signing only if encrytion is required"); + } + + if (smbXcli_conn_protocol(transport0->conn) < PROTOCOL_SMB3_11) { + torture_skip(tctx, + "Can't test without SMB 3.1.1 support"); + } -- Samba Shared Repository