Print this page
NEX-19225 SMB client 2.1 hits redzone panic
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
NEX-14666 Need to provide SMB 2.1 Client
NEX-17187 panic in smbfs_acl_store
NEX-17231 smbfs create xattr files finds wrong file
NEX-17224 smbfs lookup EINVAL should be ENOENT
NEX-17260 SMB1 client fails to list directory after NEX-14666
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
and: (cleanup)
NEX-16818 Add fksmbcl development tool
NEX-17264 SMB client test tp_smbutil_013 fails after NEX-14666
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
and: (fix ref leaks)

*** 19,28 **** --- 19,29 ---- * CDDL HEADER END */ /* * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2018 Nexenta Systems, Inc. All rights reserved. */ /* * Support for SMB "signing" (message integrity) */
*** 35,46 **** #include <sys/socket.h> #include <sys/md4.h> #include <sys/md5.h> #include <sys/des.h> #include <sys/kmem.h> - #include <sys/crypto/api.h> - #include <sys/crypto/common.h> #include <sys/cmn_err.h> #include <sys/stream.h> #include <sys/strsun.h> #include <sys/sdt.h> --- 36,45 ----
*** 48,77 **** #include <netsmb/smb.h> #include <netsmb/smb_conn.h> #include <netsmb/smb_subr.h> #include <netsmb/smb_dev.h> #include <netsmb/smb_rq.h> #ifdef DEBUG /* * Set this to a small number to debug sequence numbers * that seem to get out of step. */ int nsmb_signing_fudge = 0; #endif ! /* Mechanism definitions */ ! static crypto_mechanism_t crypto_mech_md5 = { CRYPTO_MECH_INVALID }; ! ! void ! smb_crypto_mech_init(void) { ! crypto_mech_md5.cm_type = crypto_mech2id(SUN_CKM_MD5); ! } #define SMBSIGLEN 8 /* SMB signature length */ #define SMBSIGOFF 14 /* SMB signature offset */ /* * Compute HMAC-MD5 of packet data, using the stored MAC key. --- 47,99 ---- #include <netsmb/smb.h> #include <netsmb/smb_conn.h> #include <netsmb/smb_subr.h> #include <netsmb/smb_dev.h> #include <netsmb/smb_rq.h> + #include <netsmb/smb_signing.h> #ifdef DEBUG /* * Set this to a small number to debug sequence numbers * that seem to get out of step. */ int nsmb_signing_fudge = 0; #endif ! /* ! * This is called just after session setup completes, ! * at the top of smb_iod_vc_work(). Initialize signing. ! */ ! int ! smb_sign_init(smb_vc_t *vcp) { ! int rc; + ASSERT(vcp->vc_ssnkey != NULL); + ASSERT(vcp->vc_mackey == NULL); + rc = smb_md5_getmech(&vcp->vc_signmech); + if (rc != 0) { + cmn_err(CE_NOTE, "smb can't get signing mechanism"); + return (EAUTH); + } + /* + * Convert the session key to the MAC key. + * SMB1 uses the whole session key. + */ + vcp->vc_mackeylen = vcp->vc_ssnkeylen; + vcp->vc_mackey = kmem_zalloc(vcp->vc_mackeylen, KM_SLEEP); + bcopy(vcp->vc_ssnkey, vcp->vc_mackey, vcp->vc_mackeylen); + + /* The initial sequence number is two. */ + vcp->vc_next_seq = 2; + + return (0); + } + + #define SMBSIGLEN 8 /* SMB signature length */ #define SMBSIGOFF 14 /* SMB signature offset */ /* * Compute HMAC-MD5 of packet data, using the stored MAC key.
*** 81,96 **** */ static int smb_compute_MAC(struct smb_vc *vcp, mblk_t *mp, uint32_t seqno, uchar_t *signature) { ! crypto_context_t crypto_ctx; ! crypto_data_t key; ! crypto_data_t data; ! crypto_data_t digest; ! uchar_t mac[16]; ! int status; /* * This union is a little bit of trickery to: * (1) get the sequence number int aligned, and * (2) reduce the number of digest calls, at the * cost of a copying 32 bytes instead of 8. --- 103,118 ---- */ static int smb_compute_MAC(struct smb_vc *vcp, mblk_t *mp, uint32_t seqno, uchar_t *signature) { ! uchar_t digest[MD5_DIGEST_LENGTH]; ! smb_sign_ctx_t ctx = 0; ! mblk_t *m = mp; ! int size; ! int rc; ! /* * This union is a little bit of trickery to: * (1) get the sequence number int aligned, and * (2) reduce the number of digest calls, at the * cost of a copying 32 bytes instead of 8.
*** 107,188 **** uint32_t sig[2]; /* MAC signature, aligned! */ uint16_t ids[5]; /* pad, Tid, Pid, Uid, Mid */ } s; } smbhdr; ! ASSERT(mp != NULL); ! ASSERT(MBLKL(mp) >= SMB_HDRLEN); ! ASSERT(vcp->vc_mackey != NULL); /* ! * Make an aligned copy of the SMB header ! * and fill in the sequence number. */ ! bcopy(mp->b_rptr, smbhdr.r.raw, SMB_HDRLEN); smbhdr.s.sig[0] = htolel(seqno); smbhdr.s.sig[1] = 0; /* ! * Compute the MAC: MD5(concat(Key, message)) */ ! if (crypto_mech_md5.cm_type == CRYPTO_MECH_INVALID) { ! SMBSDEBUG("crypto_mech_md5 invalid\n"); ! return (CRYPTO_MECHANISM_INVALID); ! } ! status = crypto_digest_init(&crypto_mech_md5, &crypto_ctx, 0); ! if (status != CRYPTO_SUCCESS) ! return (status); - /* Digest the MAC Key */ - key.cd_format = CRYPTO_DATA_RAW; - key.cd_offset = 0; - key.cd_length = vcp->vc_mackeylen; - key.cd_miscdata = 0; - key.cd_raw.iov_base = (char *)vcp->vc_mackey; - key.cd_raw.iov_len = vcp->vc_mackeylen; - status = crypto_digest_update(crypto_ctx, &key, 0); - if (status != CRYPTO_SUCCESS) - return (status); - - /* Digest the (copied) SMB header */ - data.cd_format = CRYPTO_DATA_RAW; - data.cd_offset = 0; - data.cd_length = SMB_HDRLEN; - data.cd_miscdata = 0; - data.cd_raw.iov_base = (char *)smbhdr.r.raw; - data.cd_raw.iov_len = SMB_HDRLEN; - status = crypto_digest_update(crypto_ctx, &data, 0); - if (status != CRYPTO_SUCCESS) - return (status); - /* Digest rest of the SMB message. */ ! data.cd_format = CRYPTO_DATA_MBLK; ! data.cd_offset = SMB_HDRLEN; ! data.cd_length = msgdsize(mp) - SMB_HDRLEN; ! data.cd_miscdata = 0; ! data.cd_mp = mp; ! status = crypto_digest_update(crypto_ctx, &data, 0); ! if (status != CRYPTO_SUCCESS) ! return (status); - /* Final */ - digest.cd_format = CRYPTO_DATA_RAW; - digest.cd_offset = 0; - digest.cd_length = sizeof (mac); - digest.cd_miscdata = 0; - digest.cd_raw.iov_base = (char *)mac; - digest.cd_raw.iov_len = sizeof (mac); - status = crypto_digest_final(crypto_ctx, &digest, 0); - if (status != CRYPTO_SUCCESS) - return (status); - /* * Finally, store the signature. * (first 8 bytes of the mac) */ ! if (signature) ! bcopy(mac, signature, SMBSIGLEN); return (0); } /* --- 129,196 ---- uint32_t sig[2]; /* MAC signature, aligned! */ uint16_t ids[5]; /* pad, Tid, Pid, Uid, Mid */ } s; } smbhdr; ! if (vcp->vc_mackey == NULL) ! return (-1); + if ((rc = smb_md5_init(&ctx, &vcp->vc_signmech)) != 0) + return (rc); + + /* Digest the MAC Key */ + rc = smb_md5_update(ctx, vcp->vc_mackey, vcp->vc_mackeylen); + if (rc != 0) + return (rc); + + /* Our caller should ensure mp has a contiguous header */ + ASSERT(m != NULL); + ASSERT(MBLKL(m) >= SMB_HDRLEN); + /* ! * Make an aligned copy of the SMB header, ! * fill in the sequence number, and digest. */ ! size = SMB_HDRLEN; ! bcopy(m->b_rptr, smbhdr.r.raw, size); smbhdr.s.sig[0] = htolel(seqno); smbhdr.s.sig[1] = 0; + rc = smb_md5_update(ctx, &smbhdr.r.raw, size); + if (rc != 0) + return (rc); + /* ! * Digest the rest of the SMB header packet, starting at ! * the data just after the SMB header. */ ! size = MBLKL(m) - SMB_HDRLEN; ! rc = smb_md5_update(ctx, m->b_rptr + SMB_HDRLEN, size); ! if (rc != 0) ! return (rc); ! m = m->b_cont; /* Digest rest of the SMB message. */ ! while (m != NULL) { ! size = MBLKL(m); ! if (size > 0) { ! rc = smb_md5_update(ctx, m->b_rptr, size); ! if (rc != 0) ! return (rc); ! } ! m = m->b_cont; ! } ! rc = smb_md5_final(ctx, digest); ! if (rc != 0) ! return (rc); /* * Finally, store the signature. * (first 8 bytes of the mac) */ ! if (signature != NULL) ! bcopy(digest, signature, SMBSIGLEN); return (0); } /*
*** 195,211 **** mblk_t *mp = rqp->sr_rq.mb_top; uint8_t *sigloc; int status; /* ! * Our mblk allocation ensures this, ! * but just in case... */ ! if (MBLKL(mp) < SMB_HDRLEN) { ! if (!pullupmsg(mp, SMB_HDRLEN)) ! return; ! } sigloc = mp->b_rptr + SMBSIGOFF; if (vcp->vc_mackey == NULL) { /* * Signing is required, but we have no key yet --- 203,216 ---- mblk_t *mp = rqp->sr_rq.mb_top; uint8_t *sigloc; int status; /* ! * smb_rq_new() ensures this, ! * but just in case.. */ ! ASSERT(MBLKL(mp) >= SMB_HDRLEN); sigloc = mp->b_rptr + SMBSIGOFF; if (vcp->vc_mackey == NULL) { /* * Signing is required, but we have no key yet
*** 219,229 **** /* * This will compute the MAC and store it * directly into the message at sigloc. */ status = smb_compute_MAC(vcp, mp, rqp->sr_seqno, sigloc); ! if (status != CRYPTO_SUCCESS) { SMBSDEBUG("Crypto error %d", status); bzero(sigloc, SMBSIGLEN); } } --- 224,234 ---- /* * This will compute the MAC and store it * directly into the message at sigloc. */ status = smb_compute_MAC(vcp, mp, rqp->sr_seqno, sigloc); ! if (status != 0) { SMBSDEBUG("Crypto error %d", status); bzero(sigloc, SMBSIGLEN); } }
*** 254,275 **** */ if (mp == NULL) { SMBSDEBUG("empty reply\n"); return (0); } ! if (MBLKL(mp) < SMB_HDRLEN) { ! if (!pullupmsg(mp, SMB_HDRLEN)) ! return (0); ! } sigloc = mp->b_rptr + SMBSIGOFF; /* * Compute the expected signature in sigbuf. */ rsn = rqp->sr_rseqno; status = smb_compute_MAC(vcp, mp, rsn, sigbuf); ! if (status != CRYPTO_SUCCESS) { SMBSDEBUG("Crypto error %d", status); /* * If we can't compute a MAC, then there's * no point trying other seqno values. */ --- 259,278 ---- */ if (mp == NULL) { SMBSDEBUG("empty reply\n"); return (0); } ! ! ASSERT(MBLKL(mp) >= SMB_HDRLEN); sigloc = mp->b_rptr + SMBSIGOFF; /* * Compute the expected signature in sigbuf. */ rsn = rqp->sr_rseqno; status = smb_compute_MAC(vcp, mp, rsn, sigbuf); ! if (status != 0) { SMBSDEBUG("Crypto error %d", status); /* * If we can't compute a MAC, then there's * no point trying other seqno values. */