/*
* 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 SMB2 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>
/*
* Called during session destroy.
*/
static void
{
}
}
/*
* smb2_sign_begin
*
* Get the mechanism info.
* Intializes MAC key based on the user session key and store it in
* the signing structure. This begins signing on this session.
*/
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 we'll fail later when a
* request that requires signing can't be checked.
*/
return (0);
/*
* Session-level initialization (once per session)
* Get mech handle, sign_fini function.
*/
if (rc != 0) {
smb_rwx_rwexit(&s->s_lock);
return (rc);
}
s->sign_fini = smb2_sign_fini;
}
smb_rwx_rwexit(&s->s_lock);
/*
* Compute and store the signing key, which lives in
* the user structure.
*/
/*
* 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
*/
mutex_enter(&u->u_mutex);
if (s->secmode & SMB2_NEGOTIATE_SIGNING_ENABLED)
u->u_sign_flags |= SMB_SIGNING_ENABLED;
if (s->secmode & SMB2_NEGOTIATE_SIGNING_REQUIRED)
u->u_sign_flags |=
mutex_exit(&u->u_mutex);
/*
* If we just turned on signing, the current request
* (an SMB2 session setup) will have come in without
* SMB2_FLAGS_SIGNED (and not signed) but the response
* is is supposed to be signed. [MS-SMB2] 3.3.5.5
*/
if (u->u_sign_flags & SMB_SIGNING_ENABLED)
return (0);
}
/*
* smb2_sign_calc
*
* Calculates MAC signature for the given buffer and returns
* it in the mac_sign parameter.
*
* The signature is in the last 16 bytes of the SMB2 header.
* The signature algorighm is to compute HMAC SHA256 over the
* entire command, with the signature field set to zeros.
*
* Return 0 if success else -1
*/
static int
{
return (-1);
if (rc != 0)
return (rc);
/*
* Work with a copy of the SMB2 header so we can
* clear the signature field without modifying
* the original message.
*/
return (-1);
return (rc);
/*
* Digest the rest of the SMB packet, starting at the data
* just after the SMB header.
*
* Advance to the src mbuf where we start digesting.
*/
}
return (-1);
/*
* Digest the remainder of this mbuf, limited to the
* residual count, and starting at the current offset.
* (typically SMB2_HDR_SIZE)
*/
if (rc != 0)
return (rc);
/*
* Digest any more mbufs in the chain.
*/
while (resid > 0) {
return (-1);
if (rc != 0)
return (rc);
}
/*
* Note: digest is _always_ SMB2_SIG_SIZE,
* even if the mech uses a longer one.
*/
return (rc);
return (0);
}
/*
* smb2_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
{
int sig_off;
/*
* Don't check commands with a zero session ID.
* [MS-SMB2] 3.3.4.1.1
*/
return (0);
/* Get the request signature. */
return (-1);
/*
* Compute the correct signature and compare.
*/
return (-1);
return (-1);
}
return (0);
}
/*
* smb2_sign_reply
*
* Calculates MAC signature for the given mbuf chain,
* and write it to the signature field in the mbuf.
*
*/
void
{
if (u == NULL)
return;
/*
* Calculate the MAC signature for this reply.
*/
return;
/*
* Poke the signature into the response.
*/
}