3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
  24  */
  25 /*
  26  * These routines provide the SMB MAC signing for the SMB server.
  27  * The routines calculate the signature of a SMB message in an mbuf chain.
  28  *
  29  * The following table describes the client server
  30  * signing registry relationship
  31  *
  32  *              | Required      | Enabled     | Disabled
  33  * -------------+---------------+------------ +--------------
  34  * Required     | Signed        | Signed      | Fail
  35  * -------------+---------------+-------------+-----------------
  36  * Enabled      | Signed        | Signed      | Not Signed
  37  * -------------+---------------+-------------+----------------
  38  * Disabled     | Fail          | Not Signed  | Not Signed
  39  */
  40 
  41 #include <sys/uio.h>
  42 #include <smbsrv/smb_kproto.h>
  43 #include <smbsrv/smb_signing.h>
  44 #include <sys/isa_defs.h>
  45 #include <sys/byteorder.h>
  46 
  47 #define SMB_SIG_SIZE    8
  48 #define SMB_SIG_OFFS    14
  49 #define SMB_HDRLEN      32
  50 
  51 #ifdef _LITTLE_ENDIAN
  52 #define htolel(x)       ((uint32_t)(x))
  53 #else
  54 #define htolel(x)       BSWAP_32(x)
  55 #endif
  56 
  57 static int
  58 smb_sign_calc(smb_request_t *sr, struct mbuf_chain *mbc,
  59     uint32_t seqnum, unsigned char *sig);
  60 
  61 #ifdef DEBUG
  62 uint32_t smb_sign_debug_search = 10;
  63 
 
 
  87                         goto found;
  88                 }
  89         }
  90         cmn_err(CE_WARN, "smb_sign_find_seqnum: failed after %d", i);
  91         return (-1);
  92 
  93 found:
  94         cmn_err(CE_WARN, "smb_sign_find_seqnum: found! %d <- %d",
  95             sign->seqnum, t);
  96         sign->seqnum = t;
  97         return (0);
  98 }
  99 #endif
 100 
 101 /*
 102  * Called during session destroy.
 103  */
 104 static void
 105 smb_sign_fini(smb_session_t *s)
 106 {
 107         smb_sign_mech_t *mech;
 108 
 109         if ((mech = s->sign_mech) != NULL) {
 110                 kmem_free(mech, sizeof (*mech));
 111                 s->sign_mech = NULL;
 112         }
 113 }
 114 
 115 /*
 116  * smb_sign_begin
 117  *
 118  * Intializes MAC key based on the user session key and
 119  * NTLM response and store it in the signing structure.
 120  * This is what begins SMB signing.
 121  */
 122 int
 123 smb_sign_begin(smb_request_t *sr, smb_token_t *token)
 124 {
 125         smb_arg_sessionsetup_t *sinfo = sr->sr_ssetup;
 126         smb_session_t *session = sr->session;
 127         struct smb_sign *sign = &session->signing;
 128         smb_sign_mech_t *mech;
 129         int rc;
 130 
 131         /*
 132          * We should normally have a session key here because
 133          * our caller filters out Anonymous and Guest logons.
 134          * However, buggy clients could get us here without a
 135          * session key, in which case: just don't sign.
 136          */
 137         if (token->tkn_ssnkey.val == NULL || token->tkn_ssnkey.len == 0)
 138                 return (0);
 139 
 140         /*
 141          * Session-level initialization (once per session)
 142          */
 143         smb_rwx_rwenter(&session->s_lock, RW_WRITER);
 144 
 145         /*
 146          * Signing may already have been setup by a prior logon,
 147          * in which case we're done here.
 148          */
 149         if (sign->mackey != NULL) {
 150                 smb_rwx_rwexit(&session->s_lock);
 151                 return (0);
 152         }
 153 
 154         /*
 155          * Get the mech handle
 156          */
 157         if (session->sign_mech == NULL) {
 158                 mech = kmem_zalloc(sizeof (*mech), KM_SLEEP);
 159                 rc = smb_md5_getmech(mech);
 160                 if (rc != 0) {
 161                         kmem_free(mech, sizeof (*mech));
 162                         smb_rwx_rwexit(&session->s_lock);
 163                         return (rc);
 164                 }
 165                 session->sign_mech = mech;
 166                 session->sign_fini = smb_sign_fini;
 167         }
 168 
 169         /*
 170          * Compute and store the signing (MAC) key.
 171          *
 172          * With extended security, the MAC key is the same as the
 173          * session key (and we'll have sinfo->ssi_ntpwlen == 0).
 174          * With non-extended security, it's the concatenation of
 175          * the session key and the "NT response" we received.
 176          */
 177         sign->mackey_len = token->tkn_ssnkey.len + sinfo->ssi_ntpwlen;
 178         sign->mackey = kmem_alloc(sign->mackey_len, KM_SLEEP);
 179         bcopy(token->tkn_ssnkey.val, sign->mackey, token->tkn_ssnkey.len);
 180         if (sinfo->ssi_ntpwlen > 0) {
 181                 bcopy(sinfo->ssi_ntpwd, sign->mackey + token->tkn_ssnkey.len,
 182                     sinfo->ssi_ntpwlen);
 183         }
 184 
 185         session->signing.seqnum = 0;
 186         sr->sr_seqnum = 2;
 187         sr->reply_seqnum = 1;
 188         sign->flags = 0;
 189 
 190         if (session->secmode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
 191                 sign->flags |= SMB_SIGNING_ENABLED;
 192                 if (session->secmode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED)
 193                         sign->flags |= SMB_SIGNING_CHECK;
 194         }
 195 
 196         smb_rwx_rwexit(&session->s_lock);
 197         return (0);
 198 }
 199 
 200 /*
 201  * smb_sign_calc
 202  *
 203  * Calculates MAC signature for the given buffer and returns
 204  * it in the mac_sign parameter.
 205  *
 206  * The sequence number is placed in the first four bytes of the signature
 207  * field of the signature and the other 4 bytes are zeroed.
 208  * The signature is the first 8 bytes of the MD5 result of the
 209  * concatenated MAC key and the SMB message.
 210  *
 211  * MACsig = head(MD5(concat(MACKey, SMBMsg)), 8)
 212  *
 213  * where
 214  *
 215  *      MACKey = concat( UserSessionKey, NTLMResp )
 216  *
 217  * and
 
 | 
 
 
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
  24  */
  25 /*
  26  * These routines provide the SMB MAC signing for the SMB server.
  27  * The routines calculate the signature of a SMB message in an mbuf chain.
  28  *
  29  * The following table describes the client server
  30  * signing registry relationship
  31  *
  32  *              | Required      | Enabled     | Disabled
  33  * -------------+---------------+------------ +--------------
  34  * Required     | Signed        | Signed      | Fail
  35  * -------------+---------------+-------------+-----------------
  36  * Enabled      | Signed        | Signed      | Not Signed
  37  * -------------+---------------+-------------+----------------
  38  * Disabled     | Fail          | Not Signed  | Not Signed
  39  */
  40 
  41 #include <sys/uio.h>
  42 #include <smbsrv/smb_kproto.h>
  43 #include <smbsrv/smb_kcrypt.h>
  44 #include <sys/isa_defs.h>
  45 #include <sys/byteorder.h>
  46 
  47 #define SMB_SIG_SIZE    8
  48 #define SMB_SIG_OFFS    14
  49 #define SMB_HDRLEN      32
  50 
  51 #ifdef _LITTLE_ENDIAN
  52 #define htolel(x)       ((uint32_t)(x))
  53 #else
  54 #define htolel(x)       BSWAP_32(x)
  55 #endif
  56 
  57 static int
  58 smb_sign_calc(smb_request_t *sr, struct mbuf_chain *mbc,
  59     uint32_t seqnum, unsigned char *sig);
  60 
  61 #ifdef DEBUG
  62 uint32_t smb_sign_debug_search = 10;
  63 
 
 
  87                         goto found;
  88                 }
  89         }
  90         cmn_err(CE_WARN, "smb_sign_find_seqnum: failed after %d", i);
  91         return (-1);
  92 
  93 found:
  94         cmn_err(CE_WARN, "smb_sign_find_seqnum: found! %d <- %d",
  95             sign->seqnum, t);
  96         sign->seqnum = t;
  97         return (0);
  98 }
  99 #endif
 100 
 101 /*
 102  * Called during session destroy.
 103  */
 104 static void
 105 smb_sign_fini(smb_session_t *s)
 106 {
 107         smb_crypto_mech_t *mech;
 108 
 109         if ((mech = s->sign_mech) != NULL) {
 110                 kmem_free(mech, sizeof (*mech));
 111                 s->sign_mech = NULL;
 112         }
 113 }
 114 
 115 /*
 116  * smb_sign_begin
 117  *
 118  * Intializes MAC key based on the user session key and
 119  * NTLM response and store it in the signing structure.
 120  * This is what begins SMB signing.
 121  */
 122 void
 123 smb_sign_begin(smb_request_t *sr, smb_token_t *token)
 124 {
 125         smb_arg_sessionsetup_t *sinfo = sr->sr_ssetup;
 126         smb_session_t *session = sr->session;
 127         struct smb_sign *sign = &session->signing;
 128         smb_crypto_mech_t *mech;
 129         int rc;
 130 
 131         /*
 132          * We should normally have a session key here because
 133          * our caller filters out Anonymous and Guest logons.
 134          * However, buggy clients could get us here without a
 135          * session key, in which case: just don't sign.
 136          */
 137         if (token->tkn_ssnkey.val == NULL || token->tkn_ssnkey.len == 0)
 138                 return;
 139 
 140         /*
 141          * Session-level initialization (once per session)
 142          */
 143         smb_rwx_rwenter(&session->s_lock, RW_WRITER);
 144 
 145         /*
 146          * Signing may already have been setup by a prior logon,
 147          * in which case we're done here.
 148          */
 149         if (sign->mackey != NULL) {
 150                 smb_rwx_rwexit(&session->s_lock);
 151                 return;
 152         }
 153 
 154         /*
 155          * Get the mech handle
 156          */
 157         if (session->sign_mech == NULL) {
 158                 mech = kmem_zalloc(sizeof (*mech), KM_SLEEP);
 159                 rc = smb_md5_getmech(mech);
 160                 if (rc != 0) {
 161                         kmem_free(mech, sizeof (*mech));
 162                         smb_rwx_rwexit(&session->s_lock);
 163                         return;
 164                 }
 165                 session->sign_mech = mech;
 166                 session->sign_fini = smb_sign_fini;
 167         }
 168 
 169         /*
 170          * Compute and store the signing (MAC) key.
 171          *
 172          * With extended security, the MAC key is the same as the
 173          * session key (and we'll have sinfo->ssi_ntpwlen == 0).
 174          * With non-extended security, it's the concatenation of
 175          * the session key and the "NT response" we received.
 176          */
 177         sign->mackey_len = token->tkn_ssnkey.len + sinfo->ssi_ntpwlen;
 178         sign->mackey = kmem_alloc(sign->mackey_len, KM_SLEEP);
 179         bcopy(token->tkn_ssnkey.val, sign->mackey, token->tkn_ssnkey.len);
 180         if (sinfo->ssi_ntpwlen > 0) {
 181                 bcopy(sinfo->ssi_ntpwd, sign->mackey + token->tkn_ssnkey.len,
 182                     sinfo->ssi_ntpwlen);
 183         }
 184 
 185         session->signing.seqnum = 0;
 186         sr->sr_seqnum = 2;
 187         sr->reply_seqnum = 1;
 188         sign->flags = 0;
 189 
 190         if (session->srv_secmode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
 191                 sign->flags |= SMB_SIGNING_ENABLED;
 192                 if (session->srv_secmode &
 193                     NEGOTIATE_SECURITY_SIGNATURES_REQUIRED)
 194                         sign->flags |= SMB_SIGNING_CHECK;
 195         }
 196 
 197         smb_rwx_rwexit(&session->s_lock);
 198 }
 199 
 200 /*
 201  * smb_sign_calc
 202  *
 203  * Calculates MAC signature for the given buffer and returns
 204  * it in the mac_sign parameter.
 205  *
 206  * The sequence number is placed in the first four bytes of the signature
 207  * field of the signature and the other 4 bytes are zeroed.
 208  * The signature is the first 8 bytes of the MD5 result of the
 209  * concatenated MAC key and the SMB message.
 210  *
 211  * MACsig = head(MD5(concat(MACKey, SMBMsg)), 8)
 212  *
 213  * where
 214  *
 215  *      MACKey = concat( UserSessionKey, NTLMResp )
 216  *
 217  * and
 
 |