da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * CDDL HEADER START
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The contents of this file are subject to the terms of the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Common Development and Distribution License (the "License").
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * You may not use this file except in compliance with the License.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * or http://www.opensolaris.org/os/licensing.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * See the License for the specific language governing permissions
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * and limitations under the License.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * When distributing Covered Code, include this CDDL HEADER in each
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * If applicable, add the following below this CDDL HEADER, with the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * fields enclosed by brackets "[]" replaced with your own identifying
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * information: Portions Copyright [yyyy] [name of copyright owner]
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * CDDL HEADER END
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * These routines provide the SMB MAC signing for the SMB server.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The routines calculate the signature of a SMB message in an mbuf chain.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
c8ec8eea9849cac239663c46be8a7f5d2ba7ca00jose borrego * The following table describes the client server
c8ec8eea9849cac239663c46be8a7f5d2ba7ca00jose borrego * signing registry relationship
c8ec8eea9849cac239663c46be8a7f5d2ba7ca00jose borrego *
c8ec8eea9849cac239663c46be8a7f5d2ba7ca00jose borrego * | Required | Enabled | Disabled
c8ec8eea9849cac239663c46be8a7f5d2ba7ca00jose borrego * -------------+---------------+------------ +--------------
c8ec8eea9849cac239663c46be8a7f5d2ba7ca00jose borrego * Required | Signed | Signed | Fail
c8ec8eea9849cac239663c46be8a7f5d2ba7ca00jose borrego * -------------+---------------+-------------+-----------------
c8ec8eea9849cac239663c46be8a7f5d2ba7ca00jose borrego * Enabled | Signed | Signed | Not Signed
c8ec8eea9849cac239663c46be8a7f5d2ba7ca00jose borrego * -------------+---------------+-------------+----------------
c8ec8eea9849cac239663c46be8a7f5d2ba7ca00jose borrego * Disabled | Fail | Not Signed | Not Signed
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <sys/uio.h>
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown#include <smbsrv/smb_kproto.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <smbsrv/smb_signing.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <sys/isa_defs.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <sys/byteorder.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#define SMB_SIG_SIZE 8
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#define SMB_SIG_OFFS 14
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#define SMB_HDRLEN 32
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#ifdef _LITTLE_ENDIAN
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#define htolel(x) ((uint32_t)(x))
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#else
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#define htolel(x) BSWAP_32(x)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#endif
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
12b65585e720714b31036daaa2b30eb76014048eGordon Rossstatic int
12b65585e720714b31036daaa2b30eb76014048eGordon Rosssmb_sign_calc(smb_request_t *sr, struct mbuf_chain *mbc,
12b65585e720714b31036daaa2b30eb76014048eGordon Ross uint32_t seqnum, unsigned char *sig);
c8ec8eea9849cac239663c46be8a7f5d2ba7ca00jose borrego
c8ec8eea9849cac239663c46be8a7f5d2ba7ca00jose borrego#ifdef DEBUG
12b65585e720714b31036daaa2b30eb76014048eGordon Rossuint32_t smb_sign_debug_search = 10;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross/*
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * Debug code to search +/- for the correct sequence number.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * If found, correct sign->seqnum and return 0, else return -1
12b65585e720714b31036daaa2b30eb76014048eGordon Ross */
12b65585e720714b31036daaa2b30eb76014048eGordon Rossstatic int
c8ec8eea9849cac239663c46be8a7f5d2ba7ca00jose borregosmb_sign_find_seqnum(
12b65585e720714b31036daaa2b30eb76014048eGordon Ross smb_request_t *sr,
12b65585e720714b31036daaa2b30eb76014048eGordon Ross struct mbuf_chain *mbc,
c8ec8eea9849cac239663c46be8a7f5d2ba7ca00jose borrego unsigned char *mac_sig,
12b65585e720714b31036daaa2b30eb76014048eGordon Ross unsigned char *sr_sig)
c8ec8eea9849cac239663c46be8a7f5d2ba7ca00jose borrego{
12b65585e720714b31036daaa2b30eb76014048eGordon Ross struct smb_sign *sign = &sr->session->signing;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross uint32_t i, t;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross for (i = 1; i < smb_sign_debug_search; i++) {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross t = sr->sr_seqnum + i;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross (void) smb_sign_calc(sr, mbc, t, mac_sig);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (memcmp(mac_sig, sr_sig, SMB_SIG_SIZE) == 0) {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross goto found;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross }
12b65585e720714b31036daaa2b30eb76014048eGordon Ross t = sr->sr_seqnum - i;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross (void) smb_sign_calc(sr, mbc, t, mac_sig);
c8ec8eea9849cac239663c46be8a7f5d2ba7ca00jose borrego if (memcmp(mac_sig, sr_sig, SMB_SIG_SIZE) == 0) {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross goto found;
c8ec8eea9849cac239663c46be8a7f5d2ba7ca00jose borrego }
c8ec8eea9849cac239663c46be8a7f5d2ba7ca00jose borrego }
12b65585e720714b31036daaa2b30eb76014048eGordon Ross cmn_err(CE_WARN, "smb_sign_find_seqnum: failed after %d", i);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (-1);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Rossfound:
12b65585e720714b31036daaa2b30eb76014048eGordon Ross cmn_err(CE_WARN, "smb_sign_find_seqnum: found! %d <- %d",
12b65585e720714b31036daaa2b30eb76014048eGordon Ross sign->seqnum, t);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross sign->seqnum = t;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (0);
c8ec8eea9849cac239663c46be8a7f5d2ba7ca00jose borrego}
c8ec8eea9849cac239663c46be8a7f5d2ba7ca00jose borrego#endif
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross/*
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * Called during session destroy.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossstatic void
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rosssmb_sign_fini(smb_session_t *s)
8622ec4569457733001d4982ef7f5b44427069beGordon Ross{
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross smb_sign_mech_t *mech;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if ((mech = s->sign_mech) != NULL) {
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross kmem_free(mech, sizeof (*mech));
12b65585e720714b31036daaa2b30eb76014048eGordon Ross s->sign_mech = NULL;
8622ec4569457733001d4982ef7f5b44427069beGordon Ross }
8622ec4569457733001d4982ef7f5b44427069beGordon Ross}
8622ec4569457733001d4982ef7f5b44427069beGordon Ross
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * smb_sign_begin
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Intializes MAC key based on the user session key and
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * NTLM response and store it in the signing structure.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * This is what begins SMB signing.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossint
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rosssmb_sign_begin(smb_request_t *sr, smb_token_t *token)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross smb_arg_sessionsetup_t *sinfo = sr->sr_ssetup;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross smb_session_t *session = sr->session;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross struct smb_sign *sign = &session->signing;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross smb_sign_mech_t *mech;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross int rc;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
12b65585e720714b31036daaa2b30eb76014048eGordon Ross /*
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * We should normally have a session key here because
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * our caller filters out Anonymous and Guest logons.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * However, buggy clients could get us here without a
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * session key, in which case: just don't sign.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (token->tkn_ssnkey.val == NULL || token->tkn_ssnkey.len == 0)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (0);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross /*
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * Session-level initialization (once per session)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross smb_rwx_rwenter(&session->s_lock, RW_WRITER);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross /*
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * Signing may already have been setup by a prior logon,
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * in which case we're done here.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross if (sign->mackey != NULL) {
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross smb_rwx_rwexit(&session->s_lock);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross /*
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * Get the mech handle
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (session->sign_mech == NULL) {
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross mech = kmem_zalloc(sizeof (*mech), KM_SLEEP);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross rc = smb_md5_getmech(mech);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross if (rc != 0) {
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross kmem_free(mech, sizeof (*mech));
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross smb_rwx_rwexit(&session->s_lock);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross return (rc);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross }
12b65585e720714b31036daaa2b30eb76014048eGordon Ross session->sign_mech = mech;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross session->sign_fini = smb_sign_fini;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross /*
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * Compute and store the signing (MAC) key.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross *
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * With extended security, the MAC key is the same as the
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * session key (and we'll have sinfo->ssi_ntpwlen == 0).
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * With non-extended security, it's the concatenation of
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * the session key and the "NT response" we received.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross sign->mackey_len = token->tkn_ssnkey.len + sinfo->ssi_ntpwlen;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross sign->mackey = kmem_alloc(sign->mackey_len, KM_SLEEP);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross bcopy(token->tkn_ssnkey.val, sign->mackey, token->tkn_ssnkey.len);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (sinfo->ssi_ntpwlen > 0) {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross bcopy(sinfo->ssi_ntpwd, sign->mackey + token->tkn_ssnkey.len,
12b65585e720714b31036daaa2b30eb76014048eGordon Ross sinfo->ssi_ntpwlen);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross session->signing.seqnum = 0;
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright sr->sr_seqnum = 2;
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb sr->reply_seqnum = 1;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross sign->flags = 0;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross if (session->secmode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross sign->flags |= SMB_SIGNING_ENABLED;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross if (session->secmode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross sign->flags |= SMB_SIGNING_CHECK;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross }
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross smb_rwx_rwexit(&session->s_lock);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smb_sign_calc
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Calculates MAC signature for the given buffer and returns
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * it in the mac_sign parameter.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The sequence number is placed in the first four bytes of the signature
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * field of the signature and the other 4 bytes are zeroed.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The signature is the first 8 bytes of the MD5 result of the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * concatenated MAC key and the SMB message.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * MACsig = head(MD5(concat(MACKey, SMBMsg)), 8)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * where
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * MACKey = concat( UserSessionKey, NTLMResp )
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * and
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * SMBMsg is the SMB message containing the sequence number.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * Return 0 if success
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
12b65585e720714b31036daaa2b30eb76014048eGordon Rossstatic int
12b65585e720714b31036daaa2b30eb76014048eGordon Rosssmb_sign_calc(smb_request_t *sr, struct mbuf_chain *mbc,
12b65585e720714b31036daaa2b30eb76014048eGordon Ross uint32_t seqnum, unsigned char *mac_sign)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
12b65585e720714b31036daaa2b30eb76014048eGordon Ross smb_session_t *s = sr->session;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross struct smb_sign *sign = &s->signing;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross smb_sign_ctx_t ctx = 0;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross uchar_t digest[MD5_DIGEST_LENGTH];
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross uchar_t *hdrp;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct mbuf *mbuf = mbc->chain;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int offset = mbc->chain_offset;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int size;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross int rc;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross /*
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * This union is a little bit of trickery to:
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * (1) get the sequence number int aligned, and
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * (2) reduce the number of digest calls, at the
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * cost of a copying 32 bytes instead of 8.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * Both sides of this union are 2+32 bytes.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross union {
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross struct {
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross uint8_t skip[2]; /* not used - just alignment */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross uint8_t raw[SMB_HDRLEN]; /* header length (32) */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross } r;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross struct {
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross uint8_t skip[2]; /* not used - just alignment */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross uint8_t hdr[SMB_SIG_OFFS]; /* sig. offset (14) */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross uint32_t sig[2]; /* MAC signature, aligned! */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross uint16_t ids[5]; /* pad, Tid, Pid, Uid, Mid */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross } s;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross } smbhdr;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (s->sign_mech == NULL || sign->mackey == NULL)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if ((rc = smb_md5_init(&ctx, s->sign_mech)) != 0)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross return (rc);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross /* Digest the MAC Key */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross rc = smb_md5_update(ctx, sign->mackey, sign->mackey_len);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross if (rc != 0)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross return (rc);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * Make an aligned copy of the SMB header,
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * fill in the sequence number, and digest.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross hdrp = (unsigned char *)&smbhdr.r.raw;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross size = SMB_HDRLEN;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross if (smb_mbc_peek(mbc, offset, "#c", size, hdrp) != 0)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross return (-1);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross smbhdr.s.sig[0] = htolel(seqnum);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross smbhdr.s.sig[1] = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross rc = smb_md5_update(ctx, &smbhdr.r.raw, size);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross if (rc != 0)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross return (rc);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross /*
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * Digest the rest of the SMB packet, starting at the data
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * just after the SMB header.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross offset += size;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross while (mbuf != NULL && (offset >= mbuf->m_len)) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw offset -= mbuf->m_len;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw mbuf = mbuf->m_next;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross if (mbuf != NULL && (size = (mbuf->m_len - offset)) > 0) {
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross rc = smb_md5_update(ctx, &mbuf->m_data[offset], size);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross if (rc != 0)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross return (rc);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw offset = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw mbuf = mbuf->m_next;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross while (mbuf != NULL) {
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross rc = smb_md5_update(ctx, mbuf->m_data, mbuf->m_len);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross if (rc != 0)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross return (rc);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw mbuf = mbuf->m_next;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross rc = smb_md5_final(ctx, digest);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross if (rc == 0)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross bcopy(digest, mac_sign, SMB_SIG_SIZE);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross return (rc);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smb_sign_check_request
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Calculates MAC signature for the request mbuf chain
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * using the next expected sequence number and compares
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * it to the given signature.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Note it does not check the signature for secondary transactions
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * as their sequence number is the same as the original request.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Return 0 if the signature verifies, otherwise, returns -1;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwint
faa1795a28a5c712eed6d0a3f84d98c368a316c6jbsmb_sign_check_request(smb_request_t *sr)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
12b65585e720714b31036daaa2b30eb76014048eGordon Ross struct mbuf_chain mbc = sr->command;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw unsigned char mac_sig[SMB_SIG_SIZE];
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Don't check secondary transactions - we dont know the sequence
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * number.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb if (sr->smb_com == SMB_COM_TRANSACTION_SECONDARY ||
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb sr->smb_com == SMB_COM_TRANSACTION2_SECONDARY ||
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb sr->smb_com == SMB_COM_NT_TRANSACT_SECONDARY)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
c8ec8eea9849cac239663c46be8a7f5d2ba7ca00jose borrego /* Reset the offset to begining of header */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross mbc.chain_offset = sr->orig_request_hdr;
c8ec8eea9849cac239663c46be8a7f5d2ba7ca00jose borrego
c8ec8eea9849cac239663c46be8a7f5d2ba7ca00jose borrego /* calculate mac signature */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (smb_sign_calc(sr, &mbc, sr->sr_seqnum, mac_sig) != 0)
c8ec8eea9849cac239663c46be8a7f5d2ba7ca00jose borrego return (-1);
c8ec8eea9849cac239663c46be8a7f5d2ba7ca00jose borrego
c8ec8eea9849cac239663c46be8a7f5d2ba7ca00jose borrego /* compare the signatures */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (memcmp(mac_sig, sr->smb_sig, SMB_SIG_SIZE) == 0) {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross /* They match! OK, we're done. */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (0);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross }
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross DTRACE_PROBE2(smb__signature__mismatch, smb_request_t, sr,
12b65585e720714b31036daaa2b30eb76014048eGordon Ross unsigned char *, mac_sig);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross cmn_err(CE_NOTE, "smb_sign_check_request: bad signature");
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross /*
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * check nearby sequence numbers in debug mode
12b65585e720714b31036daaa2b30eb76014048eGordon Ross */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross#ifdef DEBUG
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (smb_sign_debug) {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (smb_sign_find_seqnum(sr, &mbc, mac_sig, sr->smb_sig));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
12b65585e720714b31036daaa2b30eb76014048eGordon Ross#endif
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smb_sign_check_secondary
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Calculates MAC signature for the secondary transaction mbuf chain
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * and compares it to the given signature.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Return 0 if the signature verifies, otherwise, returns -1;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwint
faa1795a28a5c712eed6d0a3f84d98c368a316c6jbsmb_sign_check_secondary(smb_request_t *sr, unsigned int reply_seqnum)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
12b65585e720714b31036daaa2b30eb76014048eGordon Ross struct mbuf_chain mbc = sr->command;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw unsigned char mac_sig[SMB_SIG_SIZE];
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int rtn = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
c8ec8eea9849cac239663c46be8a7f5d2ba7ca00jose borrego /* Reset the offset to begining of header */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross mbc.chain_offset = sr->orig_request_hdr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
c8ec8eea9849cac239663c46be8a7f5d2ba7ca00jose borrego /* calculate mac signature */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (smb_sign_calc(sr, &mbc, reply_seqnum - 1, mac_sig) != 0)
c8ec8eea9849cac239663c46be8a7f5d2ba7ca00jose borrego return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
c8ec8eea9849cac239663c46be8a7f5d2ba7ca00jose borrego /* compare the signatures */
c8ec8eea9849cac239663c46be8a7f5d2ba7ca00jose borrego if (memcmp(mac_sig, sr->smb_sig, SMB_SIG_SIZE) != 0) {
c8ec8eea9849cac239663c46be8a7f5d2ba7ca00jose borrego cmn_err(CE_WARN, "SmbSignCheckSecond: bad signature");
c8ec8eea9849cac239663c46be8a7f5d2ba7ca00jose borrego rtn = -1;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Save the reply sequence number */
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb sr->reply_seqnum = reply_seqnum;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (rtn);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smb_sign_reply
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Calculates MAC signature for the given mbuf chain,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * and write it to the signature field in the mbuf.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwvoid
faa1795a28a5c712eed6d0a3f84d98c368a316c6jbsmb_sign_reply(smb_request_t *sr, struct mbuf_chain *reply)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
12b65585e720714b31036daaa2b30eb76014048eGordon Ross struct mbuf_chain mbc;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross unsigned char mac[SMB_SIG_SIZE];
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (reply)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross mbc = *reply;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw else
12b65585e720714b31036daaa2b30eb76014048eGordon Ross mbc = sr->reply;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Reset offset to start of reply */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross mbc.chain_offset = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Calculate MAC signature
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (smb_sign_calc(sr, &mbc, sr->reply_seqnum, mac) != 0) {
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright cmn_err(CE_WARN, "smb_sign_reply: error in smb_sign_calc");
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return;
148c5f43199ca0b43fc8e3b643aab11cd66ea327Alan Wright }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Put signature in the response
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross (void) smb_mbc_poke(&mbc, SMB_SIG_OFFS, "#c",
12b65585e720714b31036daaa2b30eb76014048eGordon Ross SMB_SIG_SIZE, mac);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}