/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2015 Nexenta Systems, Inc. All rights reserved.
*/
/*
* These routines provide the SMB MAC signing for the SMB server.
* The routines calculate the signature of a SMB message in an mbuf chain.
*
* The following table describes the client server
* signing registry relationship
*
* | Required | Enabled | Disabled
* -------------+---------------+------------ +--------------
* Required | Signed | Signed | Fail
* -------------+---------------+-------------+-----------------
* Enabled | Signed | Signed | Not Signed
* -------------+---------------+-------------+----------------
* Disabled | Fail | Not Signed | Not Signed
*/
#include <smbsrv/smb_kproto.h>
#include <smbsrv/smb_signing.h>
#include <sys/isa_defs.h>
#include <sys/byteorder.h>
#ifdef _LITTLE_ENDIAN
#else
#endif
static int
#ifdef DEBUG
/*
* Debug code to search +/- for the correct sequence number.
* If found, correct sign->seqnum and return 0, else return -1
*/
static int
struct mbuf_chain *mbc,
unsigned char *mac_sig,
unsigned char *sr_sig)
{
uint32_t i, t;
for (i = 1; i < smb_sign_debug_search; i++) {
goto found;
}
goto found;
}
}
return (-1);
return (0);
}
#endif
/*
* Called during session destroy.
*/
static void
{
}
}
/*
* smb_sign_begin
*
* Intializes MAC key based on the user session key and
* NTLM response and store it in the signing structure.
* This is what begins SMB signing.
*/
int
{
int rc;
/*
* We should normally have a session key here because
* our caller filters out Anonymous and Guest logons.
* However, buggy clients could get us here without a
* session key, in which case: just don't sign.
*/
return (0);
/*
* Session-level initialization (once per session)
*/
/*
* Signing may already have been setup by a prior logon,
* in which case we're done here.
*/
return (0);
}
/*
* Get the mech handle
*/
if (rc != 0) {
return (rc);
}
}
/*
* Compute and store the signing (MAC) key.
*
* With extended security, the MAC key is the same as the
* session key (and we'll have sinfo->ssi_ntpwlen == 0).
* With non-extended security, it's the concatenation of
* the session key and the "NT response" we received.
*/
if (sinfo->ssi_ntpwlen > 0) {
sinfo->ssi_ntpwlen);
}
}
return (0);
}
/*
* smb_sign_calc
*
* Calculates MAC signature for the given buffer and returns
* it in the mac_sign parameter.
*
* The sequence number is placed in the first four bytes of the signature
* field of the signature and the other 4 bytes are zeroed.
* The signature is the first 8 bytes of the MD5 result of the
* concatenated MAC key and the SMB message.
*
* MACsig = head(MD5(concat(MACKey, SMBMsg)), 8)
*
* where
*
* MACKey = concat( UserSessionKey, NTLMResp )
*
* and
*
* SMBMsg is the SMB message containing the sequence number.
*
* Return 0 if success
*
*/
static int
{
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.
* Both sides of this union are 2+32 bytes.
*/
union {
struct {
} r;
struct {
} s;
} smbhdr;
return (-1);
return (rc);
/* Digest the MAC Key */
if (rc != 0)
return (rc);
/*
* Make an aligned copy of the SMB header,
* fill in the sequence number, and digest.
*/
size = SMB_HDRLEN;
return (-1);
if (rc != 0)
return (rc);
/*
* Digest the rest of the SMB packet, starting at the data
* just after the SMB header.
*/
}
if (rc != 0)
return (rc);
offset = 0;
}
if (rc != 0)
return (rc);
}
if (rc == 0)
return (rc);
}
/*
* smb_sign_check_request
*
* Calculates MAC signature for the request mbuf chain
* using the next expected sequence number and compares
* it to the given signature.
*
* Note it does not check the signature for secondary transactions
* as their sequence number is the same as the original request.
*
* Return 0 if the signature verifies, otherwise, returns -1;
*
*/
int
{
/*
* Don't check secondary transactions - we dont know the sequence
* number.
*/
return (0);
/* Reset the offset to begining of header */
/* calculate mac signature */
return (-1);
/* compare the signatures */
/* They match! OK, we're done. */
return (0);
}
unsigned char *, mac_sig);
/*
* check nearby sequence numbers in debug mode
*/
#ifdef DEBUG
if (smb_sign_debug) {
}
#endif
return (-1);
}
/*
* smb_sign_check_secondary
*
* Calculates MAC signature for the secondary transaction mbuf chain
* and compares it to the given signature.
* Return 0 if the signature verifies, otherwise, returns -1;
*
*/
int
{
int rtn = 0;
/* Reset the offset to begining of header */
/* calculate mac signature */
return (-1);
/* compare the signatures */
rtn = -1;
}
/* Save the reply sequence number */
return (rtn);
}
/*
* smb_sign_reply
*
* Calculates MAC signature for the given mbuf chain,
* and write it to the signature field in the mbuf.
*
*/
void
{
if (reply)
else
/* Reset offset to start of reply */
mbc.chain_offset = 0;
/*
* Calculate MAC signature
*/
return;
}
/*
* Put signature in the response
*/
SMB_SIG_SIZE, mac);
}