smbrdr_lib.c revision da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0
/*
* 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 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* This file provides some common functionality for SMB Redirector
* module.
*/
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <smbsrv/ntstatus.h>
#include <smbrdr.h>
struct sdb_netuse *netuse);
unsigned char *signature);
void smbrdr_lock_transport() { nb_lock(); }
void smbrdr_unlock_transport() { nb_unlock(); }
/*
* smbrdr_request_init
*
* Setup a handle with given information and then
* setup a SMB header structure.
*
* Returns:
*
* NT_STATUS_NO_MEMORY no memory for creating request
* NT_STATUS_INTERNAL_ERROR header encode failed or crypto failed
* NT_STATUS_SUCCESS successful
*/
unsigned char cmd,
struct sdb_session *session,
struct sdb_netuse *netuse)
{
if (status != NT_STATUS_SUCCESS) {
return (status);
}
return (NT_STATUS_INTERNAL_ERROR);
}
return (NT_STATUS_SUCCESS);
}
/*
* smbrdr_send
*
* Send the SMB packet pointed by the given handle over
* network.
*
* Returns:
*
* NT_STATUS_INTERNAL_ERROR crypto framework failure
* NT_STATUS_UNEXPECTED_NETWORK_ERROR send failed
* NT_STATUS_SUCCESS successful
*/
{
int rc;
return (NT_STATUS_INTERNAL_ERROR);
if (rc < 0) {
/*
* Make the sequence number of the next SMB request even
* to avoid DC from failing the next SMB request with
* ACCESS_DENIED.
*/
return (NT_STATUS_UNEXPECTED_NETWORK_ERROR);
}
return (NT_STATUS_SUCCESS);
}
/*
* smbrdr_rcv
*
* Receive a SMB response and decode the packet header.
*
* "Implementing CIFS" book, SMB requests always have an even sequence
* number and replies always have an odd.
*
* With the original code, if the SMB Redirector skip the counter increment
* in the event of any failure during SmbSessionSetupAndX, it causes the
* domain controller to fail the next SMB request(odd sequence number)
* with ACCESS_DENIED.
*
* Smbrdr module should use the same sequence number (i.e. ssc_seqnum of the
* SMB Sign context) for generating the MAC signature for all incoming
* responses per SmbTransact request. Otherwise, the validation will fail.
* It is now fixed by decrementing the sequence number prior to validating
* the subsequent responses for a single request.
*
* Returns:
*
* status code returned by smbrdr_hdr_process()
* NT_STATUS_UNEXPECTED_NETWORK_ERROR receive failed
* NT_STATUS_SUCCESS successful
*/
{
int rc;
if (rc < 0) {
return (NT_STATUS_UNEXPECTED_NETWORK_ERROR);
}
/* initialize for processing response */
if (status != NT_STATUS_SUCCESS) {
return (status);
}
if (!is_first_rsp)
if (!smbrdr_sign_chk(sign_ctx,
return (NT_STATUS_INVALID_NETWORK_RESPONSE);
}
return (NT_STATUS_SUCCESS);
}
/*
* smbrdr_exchange
*
* Send the SMB packet pointed by the given handle over
* network. Receive the response and decode the packet header.
*
* From "Implementing CIFS" book, SMB requests always have an even sequence
* number and replies always have an odd.
*
* With the original code, if the SMB Redirector skips the counter increment
* in the event of any failure during SmbSessionSetupAndX, it causes the
* domain controller to fail the next SMB request(odd sequence number)
* with ACCESS_DENIED.
*
* Returns:
*
* status code returned by smbrdr_hdr_process()
* NT_STATUS_INTERNAL_ERROR crypto framework failure
* NT_STATUS_SUCCESS successful
*/
{
int rc;
return (NT_STATUS_INTERNAL_ERROR);
if (rc < 0) {
/*
* Since SMB echo is used to check the session
* status then don't destroy the session if it's
* SMB echo.
*/
}
return (NT_STATUS_UNEXPECTED_NETWORK_ERROR);
}
/* initialize for processing response */
if (status != NT_STATUS_SUCCESS) {
return (status);
}
/* Signature validation */
return (NT_STATUS_INVALID_NETWORK_RESPONSE);
}
return (NT_STATUS_SUCCESS);
}
/*
* smbrdr_handle_free
*
* Frees the memories allocated for the given handle.
*/
void
{
if (srh) {
}
}
/*
* smbrdr_sign_init
*
* This function is called from SessionSetup and initialize the
* signing context for the session if the connected user isn't
* anonymous. This has to call before smbrdr_request_init()
* because it modifies smb_flags2.
*
* The following description is taken out from the "Implementing CIFS"
* book(pg. 304):
*
* "Once the MAC signing has been initialized within a session, all
* messages are numbered using the same counters and signed using
* the same Session Key. This is true even if additional SESSION
* SETUP ANDX exchanges occur."
*
* The original SMB packet signing implementation calculates a MAC
* key each time the SMB Redirector sends the SmbSessionSetupAndx
* request for any non-anonymous/non-guest user which is not desired
* whenever there is a change in the user session key.
*
* If NTLMv2 authentication is used, the MAC key generated for each
* SessionSetup is unique. Since the domain controller expects the
* signature of all incoming requests are signed by the same MAC key
* (i.e. the one that generated for the first non-anonymous SessionSetup),
* access denied is returned for any subsequent SmbSessionSetupAndX
* request.
*/
int
{
int rc = 0;
return (-1);
}
rc = 1;
}
return (rc);
}
/*
* smbrdr_sign_fini
*
* Invalidate the MAC key if the first non-anonymous/non-guest user logon
* fail.
*/
int
{
int rc = 0;
sign_ctx->ssc_seqnum = 0;
rc = 1;
}
return (rc);
}
/*
* smbrdr_sign_unset_key
*
* The SMB_SCF_KEY_ISSET_THIS_LOGON should be unset upon the successful
* SmbSessionSetupAndX request for the first non-anonymous/non-guest
* logon.
*/
int
{
int rc = 0;
rc = 1;
}
return (rc);
}
/*
* smbrdr_handle_setup
*
* Initialize a smb_msgbuf structure with the allocated buffer.
* Setup given handle (srh) with the specified information.
*
* Returns:
*
* NT_STATUS_NO_MEMORY not enough memory
* NT_STATUS_SUCCESS successful
*/
static DWORD
unsigned char cmd,
struct sdb_session *session,
struct sdb_netuse *netuse)
{
return (NT_STATUS_NO_MEMORY);
}
? SMB_MSGBUF_UNICODE : 0;
return (NT_STATUS_SUCCESS);
}
/*
* smbrdr_hdr_setup
*
* Build an SMB header based on the information in the given handle.
* The SMB header is described in section 3.2 of the CIFS spec.
* As this is a canned function, no error checking is performed here.
* The return value from smb_msgbuf_encode is simply returned to the caller.
*/
static int
{
static unsigned short my_pid = 0;
if (!my_pid)
0 /* mid */));
}
/*
* Canned SMB header decode.
*/
static int
{
}
/*
* smbrdr_hdr_process
*
* Assuming 'srh->srh_mbuf' contains a response from a Windows client,
* decodes the 32 bytes SMB header.
*
* Returns:
*
* NT_STATUS_INVALID_NETWORK_RESPONSE error decoding the header
* NT_STATUS_REPLY_MESSAGE_MISMATCH response doesn't match the request
* NT_STATUS_SUCCESS successful
* smb_hdr->status.ntstatus error returned by server
*/
static DWORD
{
int rc;
/*
* Returns the number of decoded bytes on success
* or some negative MSGBUF_XXX error code on failure
*/
if (rc < SMB_HEADER_LEN) {
return (NT_STATUS_INVALID_NETWORK_RESPONSE);
}
/*
* MSDN article: 193839
* "The buffer overflow status is usually returned by a Windows
* server to inform the client that there is more data in its
* buffer than it could put in the packet.
*
* The buffer overflow should not be considered as an error.
* Subsequent SmbReadX request is required to obtain the
* remaining data in the server's buffer.
*/
} else {
}
}
return (NT_STATUS_REPLY_MESSAGE_MISMATCH);
}
return (NT_STATUS_SUCCESS);
}
/*
* smbrdr_sign
*
* Signs the given outgoing packet according to the
* specified signing context.
*
* The client and server each maintain an integer counter
* which they initialize to zero. Both counters are
* incremented for every SMB message - that's once for a
* request and once for a reply. As a result, requests sent
* by SMB Redirector always have an even sequence number
* and replies from the Windows server always have an odd
* number.
*
* Based on the observed Windows 2003 behavior, any SMB
* request will fail with NT_STATUS_ACCESS_DENIED if its
* sequence number is not even.
*
* The function can fail if there is trouble with the cryptographic
* framework and if that happens SMBAUTH_FAILURE is returned. In the
* normal case SMBAUTH_SUCCESS is returned.
*/
static int
{
" is expected(%d)",
}
return (SMBAUTH_FAILURE);
sign_ctx->ssc_seqnum++;
}
return (SMBAUTH_SUCCESS);
}
/*
* smbrdr_sign_chk
*
* Validates SMB MAC signature in the in-coming message.
* Return 1 if the signature are match; otherwise, return 0;
*
* When packet signing is enabled, the sequence number kept in the
* sign_ctx structure will be incremented when a SMB request is
* sent and upon the receipt of the first SmbTransact response
* if SMB fragmentation occurs.
*/
static int
unsigned char *signature)
{
int sign_ok = 1;
sign_ctx->ssc_seqnum++;
}
return (sign_ok);
}