diff options
author | Gordon Ross <gwr@nexenta.com> | 2019-06-21 19:22:54 -0400 |
---|---|---|
committer | Gordon Ross <gwr@nexenta.com> | 2019-11-18 11:07:56 -0500 |
commit | 686670eacbe137c7a9e6c85fef8763f8627a27b5 (patch) | |
tree | 63dccf1429c09029d41b0a412bf812ec1146f6d0 /usr/src | |
parent | 9fe633fd812f2df2354dc88fd3f7f50e94bd8eb3 (diff) | |
download | illumos-joyent-686670eacbe137c7a9e6c85fef8763f8627a27b5.tar.gz |
11855 Update SMB client to 3.02
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Andy Fiddaman <andy@omniosce.org>
Approved by: Dan McDonald <danmcd@joyent.com>
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/lib/libsmbfs/smb/ctx.c | 8 | ||||
-rw-r--r-- | usr/src/lib/libsmbfs/smb/rcfile.c | 3 | ||||
-rw-r--r-- | usr/src/lib/smbclnt/libfknsmb/common/fksmb_sign_pkcs.c | 116 | ||||
-rw-r--r-- | usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_sign_pkcs.c | 10 | ||||
-rw-r--r-- | usr/src/uts/common/fs/smbclnt/netsmb/nsmb_sign_kcf.c | 124 | ||||
-rw-r--r-- | usr/src/uts/common/fs/smbclnt/netsmb/smb2_sign.c | 144 | ||||
-rw-r--r-- | usr/src/uts/common/fs/smbclnt/netsmb/smb2_smb.c | 32 | ||||
-rw-r--r-- | usr/src/uts/common/fs/smbclnt/netsmb/smb_conn.h | 8 | ||||
-rw-r--r-- | usr/src/uts/common/fs/smbclnt/netsmb/smb_signing.h | 7 | ||||
-rw-r--r-- | usr/src/uts/common/netsmb/smb_dev.h | 2 |
10 files changed, 392 insertions, 62 deletions
diff --git a/usr/src/lib/libsmbfs/smb/ctx.c b/usr/src/lib/libsmbfs/smb/ctx.c index 3aa67fd5f5..64122e3416 100644 --- a/usr/src/lib/libsmbfs/smb/ctx.c +++ b/usr/src/lib/libsmbfs/smb/ctx.c @@ -1411,10 +1411,16 @@ smb_cf_minauth_from_str(char *str) return (-1); } - +/* + * SMB 2.1 is the oldest SMB2 dialect implemented (we skipped SMB 2.002) + * so if we see a_protocol value of just "2" assume they meant 2.1 + */ static struct nv smbver_table[] = { + { "3.02", SMB2_DIALECT_0302 }, + { "3.0", SMB2_DIALECT_0300 }, { "2.1", SMB2_DIALECT_0210 }, + { "2", SMB2_DIALECT_0210 }, { "1", 1 }, { NULL, 0 } }; diff --git a/usr/src/lib/libsmbfs/smb/rcfile.c b/usr/src/lib/libsmbfs/smb/rcfile.c index d7ee2d15af..da96b13c34 100644 --- a/usr/src/lib/libsmbfs/smb/rcfile.c +++ b/usr/src/lib/libsmbfs/smb/rcfile.c @@ -492,8 +492,7 @@ rc_parse(struct rcfile *rcp) if (home_nsmbrc != 0 && ( strcmp(buf, "nbns") == 0 || strcmp(buf, "nbns_enable") == 0 || - strcmp(buf, "nbns_broadcast") == 0 || - strcmp(buf, "signing") == 0)) { + strcmp(buf, "nbns_broadcast") == 0)) { fprintf(stderr, dgettext(TEXT_DOMAIN, "option %s may not be set " "in user .nsmbrc file\n"), buf); diff --git a/usr/src/lib/smbclnt/libfknsmb/common/fksmb_sign_pkcs.c b/usr/src/lib/smbclnt/libfknsmb/common/fksmb_sign_pkcs.c index 24bb8fccbc..44c6666313 100644 --- a/usr/src/lib/smbclnt/libfknsmb/common/fksmb_sign_pkcs.c +++ b/usr/src/lib/smbclnt/libfknsmb/common/fksmb_sign_pkcs.c @@ -23,22 +23,46 @@ #include <stdlib.h> #include <strings.h> +#include <sys/cmn_err.h> #include <netsmb/smb_signing.h> #include <security/cryptoki.h> #include <security/pkcs11.h> /* + * Common function to see if a mech is available. + */ +static int +find_mech(smb_sign_mech_t *mech, ulong_t mid) +{ + CK_SESSION_HANDLE hdl; + CK_RV rv; + + rv = SUNW_C_GetMechSession(mid, &hdl); + if (rv != CKR_OK) { + cmn_err(CE_NOTE, "PKCS#11: no mech 0x%x", + (unsigned int)mid); + return (-1); + } + (void) C_CloseSession(hdl); + + mech->mechanism = mid; + mech->pParameter = NULL; + mech->ulParameterLen = 0; + return (0); +} + +/* * SMB1 signing helpers: * (getmech, init, update, final) */ +/* + * Find out if we have this mech. + */ int smb_md5_getmech(smb_sign_mech_t *mech) { - mech->mechanism = CKM_MD5; - mech->pParameter = NULL; - mech->ulParameterLen = 0; - return (0); + return (find_mech(mech, CKM_MD5)); } /* @@ -93,13 +117,13 @@ smb_md5_final(smb_sign_ctx_t ctx, uint8_t *digest16) * (getmech, init, update, final) */ +/* + * Find out if we have this mech. + */ int smb2_hmac_getmech(smb_sign_mech_t *mech) { - mech->mechanism = CKM_SHA256_HMAC; - mech->pParameter = NULL; - mech->ulParameterLen = 0; - return (0); + return (find_mech(mech, CKM_SHA256_HMAC)); } /* @@ -161,3 +185,79 @@ smb2_hmac_final(smb_sign_ctx_t ctx, uint8_t *digest16) return (rv == CKR_OK ? 0 : -1); } + +/* + * SMB3 signing helpers: + * (getmech, init, update, final) + */ + +/* + * Find out if we have this mech. + */ +int +smb3_cmac_getmech(smb_sign_mech_t *mech) +{ + return (find_mech(mech, CKM_AES_CMAC)); +} + +/* + * Start PKCS#11 session, load the key. + */ +int +smb3_cmac_init(smb_sign_ctx_t *ctxp, smb_sign_mech_t *mech, + uint8_t *key, size_t key_len) +{ + CK_OBJECT_HANDLE hkey = 0; + CK_RV rv; + + rv = SUNW_C_GetMechSession(mech->mechanism, ctxp); + if (rv != CKR_OK) + return (-1); + + rv = SUNW_C_KeyToObject(*ctxp, mech->mechanism, + key, key_len, &hkey); + if (rv != CKR_OK) { + (void) C_CloseSession(*ctxp); + return (-1); + } + + rv = C_SignInit(*ctxp, mech, hkey); + (void) C_DestroyObject(*ctxp, hkey); + if (rv != CKR_OK) { + (void) C_CloseSession(*ctxp); + return (-1); + } + + return (0); +} + +/* + * Digest one segment + */ +int +smb3_cmac_update(smb_sign_ctx_t ctx, uint8_t *in, size_t len) +{ + CK_RV rv; + + rv = C_SignUpdate(ctx, in, len); + if (rv != CKR_OK) + (void) C_CloseSession(ctx); + + return (rv == CKR_OK ? 0 : -1); +} + +/* + * Note, the SMB2 signature is just the AES CMAC digest. + * (both are 16 bytes long) + */ +int +smb3_cmac_final(smb_sign_ctx_t ctx, uint8_t *digest) +{ + CK_ULONG len = SMB2_SIG_SIZE; + CK_RV rv; + + rv = C_SignFinal(ctx, digest, &len); + (void) C_CloseSession(ctx); + + return (rv == CKR_OK ? 0 : -1); +} diff --git a/usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_sign_pkcs.c b/usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_sign_pkcs.c index e018c6eb0c..f0eb05093c 100644 --- a/usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_sign_pkcs.c +++ b/usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_sign_pkcs.c @@ -215,13 +215,19 @@ smb3_cmac_init(smb_sign_ctx_t *ctxp, smb_crypto_mech_t *mech, rv = SUNW_C_KeyToObject(*ctxp, mech->mechanism, key, key_len, &hkey); - if (rv != CKR_OK) + if (rv != CKR_OK) { + (void) C_CloseSession(*ctxp); return (-1); + } rv = C_SignInit(*ctxp, mech, hkey); (void) C_DestroyObject(*ctxp, hkey); + if (rv != CKR_OK) { + (void) C_CloseSession(*ctxp); + return (-1); + } - return (rv == CKR_OK ? 0 : -1); + return (0); } /* diff --git a/usr/src/uts/common/fs/smbclnt/netsmb/nsmb_sign_kcf.c b/usr/src/uts/common/fs/smbclnt/netsmb/nsmb_sign_kcf.c index 2be033a8fc..4235c94a06 100644 --- a/usr/src/uts/common/fs/smbclnt/netsmb/nsmb_sign_kcf.c +++ b/usr/src/uts/common/fs/smbclnt/netsmb/nsmb_sign_kcf.c @@ -29,23 +29,34 @@ #include <netsmb/smb_signing.h> /* - * SMB1 signing helpers: - * (getmech, init, update, final) + * Common function to see if a mech is available. */ - -int -smb_md5_getmech(smb_sign_mech_t *mech) +static int +find_mech(smb_sign_mech_t *mech, crypto_mech_name_t name) { crypto_mech_type_t t; - t = crypto_mech2id(SUN_CKM_MD5); - if (t == CRYPTO_MECH_INVALID) + t = crypto_mech2id(name); + if (t == CRYPTO_MECH_INVALID) { + cmn_err(CE_NOTE, "nsmb: no kcf mech: %s", name); return (-1); + } mech->cm_type = t; return (0); } /* + * SMB1 signing helpers: + * (getmech, init, update, final) + */ + +int +smb_md5_getmech(smb_sign_mech_t *mech) +{ + return (find_mech(mech, SUN_CKM_MD5)); +} + +/* * Start the KCF session, load the key */ int @@ -75,7 +86,12 @@ smb_md5_update(smb_sign_ctx_t ctx, void *buf, size_t len) rv = crypto_digest_update(ctx, &data, 0); - return (rv == CRYPTO_SUCCESS ? 0 : -1); + if (rv != CRYPTO_SUCCESS) { + crypto_cancel_ctx(ctx); + return (-1); + } + + return (0); } /* @@ -106,13 +122,7 @@ smb_md5_final(smb_sign_ctx_t ctx, uint8_t *digest16) int smb2_hmac_getmech(smb_sign_mech_t *mech) { - crypto_mech_type_t t; - - t = crypto_mech2id(SUN_CKM_SHA256_HMAC); - if (t == CRYPTO_MECH_INVALID) - return (-1); - mech->cm_type = t; - return (0); + return (find_mech(mech, SUN_CKM_SHA256_HMAC)); } /* @@ -152,7 +162,12 @@ smb2_hmac_update(smb_sign_ctx_t ctx, uint8_t *in, size_t len) rv = crypto_mac_update(ctx, &data, 0); - return (rv == CRYPTO_SUCCESS ? 0 : -1); + if (rv != CRYPTO_SUCCESS) { + crypto_cancel_ctx(ctx); + return (-1); + } + + return (0); } /* @@ -178,3 +193,80 @@ smb2_hmac_final(smb_sign_ctx_t ctx, uint8_t *digest16) return (rv == CRYPTO_SUCCESS ? 0 : -1); } + +/* + * SMB3 signing helpers: + * (getmech, init, update, final) + */ + +int +smb3_cmac_getmech(smb_sign_mech_t *mech) +{ + return (find_mech(mech, SUN_CKM_AES_CMAC)); +} + +/* + * Start the KCF session, load the key + */ +int +smb3_cmac_init(smb_sign_ctx_t *ctxp, smb_sign_mech_t *mech, + uint8_t *key, size_t key_len) +{ + crypto_key_t ckey; + int rv; + + bzero(&ckey, sizeof (ckey)); + ckey.ck_format = CRYPTO_KEY_RAW; + ckey.ck_data = key; + ckey.ck_length = key_len * 8; /* in bits */ + + rv = crypto_mac_init(mech, &ckey, NULL, ctxp, NULL); + + return (rv == CRYPTO_SUCCESS ? 0 : -1); +} + +/* + * Digest one segment + */ +int +smb3_cmac_update(smb_sign_ctx_t ctx, uint8_t *in, size_t len) +{ + crypto_data_t data; + int rv; + + bzero(&data, sizeof (data)); + data.cd_format = CRYPTO_DATA_RAW; + data.cd_length = len; + data.cd_raw.iov_base = (void *)in; + data.cd_raw.iov_len = len; + + rv = crypto_mac_update(ctx, &data, 0); + + if (rv != CRYPTO_SUCCESS) { + crypto_cancel_ctx(ctx); + return (-1); + } + + return (0); +} + +/* + * Note, the SMB2 signature is just the AES CMAC digest. + * (both are 16 bytes long) + */ +int +smb3_cmac_final(smb_sign_ctx_t ctx, uint8_t *digest16) +{ + crypto_data_t out; + int rv; + + bzero(&out, sizeof (out)); + out.cd_format = CRYPTO_DATA_RAW; + out.cd_length = SMB2_SIG_SIZE; + out.cd_raw.iov_len = SMB2_SIG_SIZE; + out.cd_raw.iov_base = (void *)digest16; + + rv = crypto_mac_final(ctx, &out, 0); + + return (rv == CRYPTO_SUCCESS ? 0 : -1); +} diff --git a/usr/src/uts/common/fs/smbclnt/netsmb/smb2_sign.c b/usr/src/uts/common/fs/smbclnt/netsmb/smb2_sign.c index 46bf28c370..f7f20bdb5a 100644 --- a/usr/src/uts/common/fs/smbclnt/netsmb/smb2_sign.c +++ b/usr/src/uts/common/fs/smbclnt/netsmb/smb2_sign.c @@ -54,10 +54,45 @@ #define SMB2_SIG_OFF 48 #define SMB2_SIG_LEN 16 +typedef struct smb_mac_ops { + int (*mac_init)(smb_sign_ctx_t *, smb_sign_mech_t *, + uint8_t *, size_t); + int (*mac_update)(smb_sign_ctx_t, uint8_t *, size_t); + int (*mac_final)(smb_sign_ctx_t, uint8_t *); +} smb_mac_ops_t; + +static smb_mac_ops_t +smb2_sign_ops = { + smb2_hmac_init, + smb2_hmac_update, + smb2_hmac_final +}; + +static struct smb_mac_ops +smb3_sign_ops = { + smb3_cmac_init, + smb3_cmac_update, + smb3_cmac_final +}; + +/* + * Input to KDF for SigningKey. + * See comment for smb3_do_kdf for content. + */ +static uint8_t sign_kdf_input[29] = { + 0, 0, 0, 1, 'S', 'M', 'B', '2', + 'A', 'E', 'S', 'C', 'M', 'A', 'C', 0, + 0, 'S', 'm', 'b', 'S', 'i', 'g', 'n', + 0, 0, 0, 0, 0x80 }; + +int smb3_do_kdf(void *outbuf, size_t outbuf_len, + void *input, size_t input_len, + uint8_t *key, uint32_t key_len); + /* * smb2_sign_init * - * Get the mechanism info and initilize SMB2 signing. + * Get the mechanism info and initilize SMB2 or SMB3 signing. */ int smb2_sign_init(smb_vc_t *vcp) @@ -68,31 +103,103 @@ smb2_sign_init(smb_vc_t *vcp) ASSERT(vcp->vc_ssnkey != NULL); ASSERT(vcp->vc_mackey == NULL); - rc = smb2_hmac_getmech(&vcp->vc_signmech); - if (rc != 0) { - cmn_err(CE_NOTE, "smb2 can't get signing mechanism"); + if (SMB_DIALECT(vcp) < SMB2_DIALECT_0300) + rc = smb2_hmac_getmech(&vcp->vc_signmech); + else + rc = smb3_cmac_getmech(&vcp->vc_signmech); + if (rc != 0) return (EAUTH); - } /* * Convert the session key to the MAC key. * * For SMB2, the signing key is just the first 16 bytes * of the session key (truncated or padded with zeros). - * [MS-SMB2] 3.2.5.3.1 - * - * SMB3 would do KDF here. + * For SMB3, the signing key is a "KDF" hash of the + * session key. [MS-SMB2] 3.2.5.3.1 */ vcp->vc_mackeylen = SMB2_SIG_LEN; vcp->vc_mackey = kmem_zalloc(vcp->vc_mackeylen, KM_SLEEP); - copysize = vcp->vc_ssnkeylen; - if (copysize > vcp->vc_mackeylen) - copysize = vcp->vc_mackeylen; - bcopy(vcp->vc_ssnkey, vcp->vc_mackey, copysize); + if (SMB_DIALECT(vcp) < SMB2_DIALECT_0300) { + copysize = vcp->vc_ssnkeylen; + if (copysize > vcp->vc_mackeylen) + copysize = vcp->vc_mackeylen; + bcopy(vcp->vc_ssnkey, vcp->vc_mackey, copysize); + + vcp->vc_sign_ops = &smb2_sign_ops; + } else { + rc = smb3_do_kdf(vcp->vc_mackey, vcp->vc_mackeylen, + sign_kdf_input, sizeof (sign_kdf_input), + vcp->vc_ssnkey, vcp->vc_ssnkeylen); + if (rc != 0) + return (EAUTH); + vcp->vc_sign_ops = &smb3_sign_ops; + } return (0); } +/* + * Derive SMB3 key as described in [MS-SMB2] 3.1.4.2 + * and [NIST SP800-108] + * + * r = 32, L = 128, PRF = HMAC-SHA256, key = (session key) + * + * Note that these describe pre-3.1.1 inputs. + * + * Session.SigningKey for binding a session: + * - Session.SessionKey as K1 + * - label = SMB2AESCMAC (size 12) + * - context = SmbSign (size 8) + * Channel.SigningKey for for all other requests + * - if SMB2_SESSION_FLAG_BINDING, GSS key (in Session.SessionKey?) as K1; + * - otherwise, Session.SessionKey as K1 + * - label = SMB2AESCMAC (size 12) + * - context = SmbSign (size 8) + * Session.ApplicationKey for ... (not sure what yet) + * - Session.SessionKey as K1 + * - label = SMB2APP (size 8) + * - context = SmbRpc (size 7) + * Session.EncryptionKey for encrypting server messages + * - Session.SessionKey as K1 + * - label = "SMB2AESCCM" (size 11) + * - context = "ServerOut" (size 10) + * Session.DecryptionKey for decrypting client requests + * - Session.SessionKey as K1 + * - label = "SMB2AESCCM" (size 11) + * - context = "ServerIn " (size 10) (Note the space) + */ +int +smb3_do_kdf(void *outbuf, size_t outbuf_len, + void *input, size_t input_len, + uint8_t *key, uint32_t key_len) +{ + uint8_t digest32[SHA256_DIGEST_LENGTH]; + smb_sign_mech_t mech; + smb_sign_ctx_t hctx = 0; + int rc; + + bzero(&mech, sizeof (mech)); + if ((rc = smb2_hmac_getmech(&mech)) != 0) + return (rc); + + /* Limit the SessionKey input to its maximum size (16 bytes) */ + if (key_len > SMB2_SIG_SIZE) + key_len = SMB2_SIG_SIZE; + rc = smb2_hmac_init(&hctx, &mech, key, key_len); + if (rc != 0) + return (rc); + + if ((rc = smb2_hmac_update(hctx, input, input_len)) != 0) + return (rc); + + if ((rc = smb2_hmac_final(hctx, digest32)) != 0) + return (rc); + + /* Output is first 16 bytes of digest. */ + bcopy(digest32, outbuf, outbuf_len); + return (0); +} /* * Compute MAC signature of packet data, using the stored MAC key. @@ -109,14 +216,17 @@ smb2_compute_MAC(struct smb_vc *vcp, mblk_t *mp, uchar_t *signature) { uint8_t tmp_hdr[SMB2_HDR_SIZE]; smb_sign_ctx_t ctx = 0; + smb_mac_ops_t *ops; mblk_t *m = mp; int size; int rc; if (vcp->vc_mackey == NULL) return (-1); + if ((ops = vcp->vc_sign_ops) == NULL) + return (-1); - rc = smb2_hmac_init(&ctx, &vcp->vc_signmech, + rc = ops->mac_init(&ctx, &vcp->vc_signmech, vcp->vc_mackey, vcp->vc_mackeylen); if (rc != 0) return (rc); @@ -131,7 +241,7 @@ smb2_compute_MAC(struct smb_vc *vcp, mblk_t *mp, uchar_t *signature) size = SMB2_HDRLEN; bcopy(m->b_rptr, tmp_hdr, size); bzero(tmp_hdr + SMB2_SIG_OFF, SMB2_SIG_LEN); - rc = smb2_hmac_update(ctx, tmp_hdr, size); + rc = ops->mac_update(ctx, tmp_hdr, size); if (rc != 0) return (rc); @@ -140,7 +250,7 @@ smb2_compute_MAC(struct smb_vc *vcp, mblk_t *mp, uchar_t *signature) * the data just after the SMB2 header. */ size = MBLKL(m) - SMB2_HDRLEN; - rc = smb2_hmac_update(ctx, m->b_rptr + SMB2_HDRLEN, size); + rc = ops->mac_update(ctx, m->b_rptr + SMB2_HDRLEN, size); if (rc != 0) return (rc); m = m->b_cont; @@ -149,13 +259,13 @@ smb2_compute_MAC(struct smb_vc *vcp, mblk_t *mp, uchar_t *signature) while (m != NULL) { size = MBLKL(m); if (size > 0) { - rc = smb2_hmac_update(ctx, m->b_rptr, size); + rc = ops->mac_update(ctx, m->b_rptr, size); if (rc != 0) return (rc); } m = m->b_cont; } - rc = smb2_hmac_final(ctx, signature); + rc = ops->mac_final(ctx, signature); return (rc); } diff --git a/usr/src/uts/common/fs/smbclnt/netsmb/smb2_smb.c b/usr/src/uts/common/fs/smbclnt/netsmb/smb2_smb.c index c3df18faa9..52d8661b7a 100644 --- a/usr/src/uts/common/fs/smbclnt/netsmb/smb2_smb.c +++ b/usr/src/uts/common/fs/smbclnt/netsmb/smb2_smb.c @@ -50,9 +50,15 @@ #include <netsmb/smb_rq.h> #include <netsmb/smb2_rq.h> -#define NDIALECTS 1 -static const uint16_t smb2_dialects[1] = { - SMB2_DIALECT_0210 +/* + * Supported dialects. Keep sorted by number because of how the + * vc_maxver check below may truncate this list. + */ +#define NDIALECTS 3 +static const uint16_t smb2_dialects[NDIALECTS] = { + SMB2_DIALECT_0210, + SMB2_DIALECT_0300, + SMB2_DIALECT_0302, }; /* Optional capabilities we advertise (none yet). */ @@ -113,13 +119,13 @@ smb2_parse_smb1nego_resp(struct smb_rq *rqp) md_get_uint16le(mdp, &sp->sv2_security_mode); /* Get Dialect. */ - error = md_get_uint16le(mdp, &sp->sv2_dialect); + error = md_get_uint16le(mdp, &sp->sv_proto); if (error != 0) return (error); /* What dialect did we get? */ - if (sp->sv2_dialect != SMB2_DIALECT_02ff) { - SMBERROR("Unknown dialect 0x%x\n", sp->sv2_dialect); + if (sp->sv_proto != SMB2_DIALECT_02ff) { + SMBERROR("Unknown dialect 0x%x\n", sp->sv_proto); return (EINVAL); } /* Set our (internal) SMB1 dialect also. */ @@ -148,6 +154,7 @@ smb2_smb_negotiate(struct smb_vc *vcp, struct smb_cred *scred) struct smb_rq *rqp = NULL; struct mbchain *mbp = NULL; struct mdchain *mdp = NULL; + uint16_t *ndialects_p; uint16_t ndialects = NDIALECTS; boolean_t will_sign = B_FALSE; uint16_t length = 0; @@ -174,15 +181,18 @@ smb2_smb_negotiate(struct smb_vc *vcp, struct smb_cred *scred) */ smb_rq_getrequest(rqp, &mbp); mb_put_uint16le(mbp, 36); /* Struct Size */ - mb_put_uint16le(mbp, ndialects); /* Dialect Count */ + ndialects_p = mb_reserve(mbp, 2); /* Dialect Count */ mb_put_uint16le(mbp, security_mode); mb_put_uint16le(mbp, 0); /* Reserved */ mb_put_uint32le(mbp, smb2_clnt_caps); mb_put_mem(mbp, vcp->vc_cl_guid, 16, MB_MSYSTEM); mb_put_uint64le(mbp, 0); /* Start Time */ for (i = 0; i < ndialects; i++) { /* Dialects */ + if (smb2_dialects[i] > vcp->vc_maxver) + break; mb_put_uint16le(mbp, smb2_dialects[i]); } + *ndialects_p = htoles(i); /* * Do the OTW call. @@ -209,7 +219,7 @@ smb2_smb_negotiate(struct smb_vc *vcp, struct smb_cred *scred) } md_get_uint16le(mdp, &sp->sv2_security_mode); - md_get_uint16le(mdp, &sp->sv2_dialect); + md_get_uint16le(mdp, &sp->sv_proto); /* dialect */ md_get_uint16le(mdp, NULL); /* reserved */ md_get_mem(mdp, sp->sv2_guid, 16, MB_MSYSTEM); md_get_uint32le(mdp, &sp->sv2_capabilities); @@ -254,7 +264,7 @@ smb2_smb_negotiate(struct smb_vc *vcp, struct smb_cred *scred) } wk->wk_u_auth_rlen = sec_buf_len; err = md_get_mem(mdp, wk->wk_u_auth_rbuf.lp_ptr, - sec_buf_len, MB_MUSER); + sec_buf_len, MB_MUSER); if (err) { goto errout; } @@ -472,7 +482,7 @@ smb2_smb_ssnsetup(struct smb_vc *vcp, struct smb_cred *scred) } wk->wk_u_auth_rlen = sec_buf_len; err = md_get_mem(mdp, wk->wk_u_auth_rbuf.lp_ptr, - sec_buf_len, MB_MUSER); + sec_buf_len, MB_MUSER); if (err != 0) { ret = err; goto out; @@ -813,7 +823,7 @@ smb2_smb_ntcreate( mb_put_uint16le(mbp, StructSize); mb_put_uint8(mbp, 0); /* Security flags */ mb_put_uint8(mbp, SMB2_OPLOCK_LEVEL_NONE); /* Oplock level */ - mb_put_uint32le(mbp, impersonate); /* Impersonation Level */ + mb_put_uint32le(mbp, impersonate); /* Impersonation Level */ mb_put_uint64le(mbp, cr_flags); mb_put_uint64le(mbp, 0); /* Reserved */ mb_put_uint32le(mbp, req_acc); diff --git a/usr/src/uts/common/fs/smbclnt/netsmb/smb_conn.h b/usr/src/uts/common/fs/smbclnt/netsmb/smb_conn.h index d0a8a1dca0..b88e32d781 100644 --- a/usr/src/uts/common/fs/smbclnt/netsmb/smb_conn.h +++ b/usr/src/uts/common/fs/smbclnt/netsmb/smb_conn.h @@ -70,7 +70,7 @@ typedef struct smb_cred { #define SMBV_EXT_SEC 0x0080 /* conn to use extended security */ #define SMBV_SIGNING 0x0100 /* negotiated signing */ #define SMBV_SMB2 0x0200 /* VC using SMB 2 or 3 */ -#define SMBV_HAS_FILEIDS 0x0400 /* Use File IDs for hash and inode numbers */ +#define SMBV_HAS_FILEIDS 0x0400 /* Use File IDs for hash and inums */ #define SMBV_NO_WRITE_THRU 0x0800 /* Can't use ... */ /* @@ -165,7 +165,7 @@ enum smbco_level { * SMB1 Negotiated protocol parameters */ struct smb_sopt { - int16_t sv_proto; /* protocol dialect */ + uint16_t sv_proto; /* protocol dialect */ uchar_t sv_sm; /* security mode */ int16_t sv_tz; /* offset in min relative to UTC */ uint16_t sv_maxmux; /* max number of outstanding rq's */ @@ -178,13 +178,12 @@ struct smb_sopt { /* SMB2+ fields */ uint32_t sv2_sessflags; /* final session setup reply flags */ - uint16_t sv2_dialect; /* dialect (non zero for SMB 2/3 */ uint32_t sv2_capabilities; /* capabilities */ uint32_t sv2_maxtransact; /* max transact size */ uint32_t sv2_maxread; /* max read size */ uint32_t sv2_maxwrite; /* max write size */ - uint8_t sv2_guid[16]; /* GUID */ uint16_t sv2_security_mode; /* security mode */ + uint8_t sv2_guid[16]; /* GUID */ }; typedef struct smb_sopt smb_sopt_t; @@ -226,6 +225,7 @@ typedef struct smb_vc { uint8_t *vc_mackey; /* MAC key buffer */ uint8_t *vc_ssnkey; /* session key buffer */ smb_sign_mech_t vc_signmech; + struct smb_mac_ops *vc_sign_ops; struct smb_tran_desc *vc_tdesc; /* transport ops. vector */ void *vc_tdata; /* transport control block */ diff --git a/usr/src/uts/common/fs/smbclnt/netsmb/smb_signing.h b/usr/src/uts/common/fs/smbclnt/netsmb/smb_signing.h index e1799e3383..81217d5182 100644 --- a/usr/src/uts/common/fs/smbclnt/netsmb/smb_signing.h +++ b/usr/src/uts/common/fs/smbclnt/netsmb/smb_signing.h @@ -48,6 +48,8 @@ typedef CK_MECHANISM smb_sign_mech_t; typedef CK_SESSION_HANDLE smb_sign_ctx_t; #endif /* _KERNEL */ +struct smb_mac_ops; + /* * SMB signing routines used in smb_signing.c */ @@ -66,6 +68,11 @@ int smb2_hmac_init(smb_sign_ctx_t *, smb_sign_mech_t *, uint8_t *, size_t); int smb2_hmac_update(smb_sign_ctx_t, uint8_t *, size_t); int smb2_hmac_final(smb_sign_ctx_t, uint8_t *); +int smb3_cmac_getmech(smb_sign_mech_t *); +int smb3_cmac_init(smb_sign_ctx_t *, smb_sign_mech_t *, uint8_t *, size_t); +int smb3_cmac_update(smb_sign_ctx_t, uint8_t *, size_t); +int smb3_cmac_final(smb_sign_ctx_t, uint8_t *); + #ifdef __cplusplus } #endif diff --git a/usr/src/uts/common/netsmb/smb_dev.h b/usr/src/uts/common/netsmb/smb_dev.h index 817d214b3e..ceb22371b7 100644 --- a/usr/src/uts/common/netsmb/smb_dev.h +++ b/usr/src/uts/common/netsmb/smb_dev.h @@ -126,7 +126,7 @@ #define SMB2_DIALECT_0302 0x0302 /* Maximum supported dialect (for ssn_maxver) */ -#define SMB2_DIALECT_MAX SMB2_DIALECT_0210 +#define SMB2_DIALECT_MAX SMB2_DIALECT_0302 /* * Option flags in smbioc_oshare.ioc_opt |