402 lines
14 KiB
C
402 lines
14 KiB
C
/*++ BUILD Version: 0009 // Increment this if a change has global effects
|
||
Copyright (c) 1987-1993 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
sessetup.c
|
||
|
||
Abstract:
|
||
|
||
This module implements the Session setup related routines
|
||
|
||
Author:
|
||
|
||
Balan Sethu Raman (SethuR) 06-Mar-95 Created
|
||
|
||
--*/
|
||
|
||
#include "precomp.h"
|
||
#pragma hdrstop
|
||
|
||
#include <exsessup.h>
|
||
#include "ntlsapi.h"
|
||
#include "mrxsec.h"
|
||
|
||
NTSTATUS
|
||
BuildSessionSetupSecurityInformation(
|
||
PSMB_EXCHANGE pExchange,
|
||
PBYTE pSmbBuffer,
|
||
PULONG pSmbBufferSize)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine builds the security related information for the session setup SMB
|
||
|
||
Arguments:
|
||
|
||
pServer - the server instance
|
||
|
||
pSmbBuffer - the SMB buffer
|
||
|
||
pSmbBufferSize - the size of the buffer on input ( modified to size remaining on
|
||
output)
|
||
|
||
Return Value:
|
||
|
||
RXSTATUS - The return status for the operation
|
||
|
||
Notes:
|
||
|
||
Eventhough the genral structure of the code tries to isolate dialect specific issues
|
||
as much as possible this routine takes the opposite approach. This is because of the
|
||
preamble and prologue to security interaction which far outweigh the dialect specific
|
||
work required to be done. Therefore in the interests of a smaller footprint this approach
|
||
has been adopted.
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS Status;
|
||
BOOLEAN fProcessAttached = FALSE;
|
||
|
||
UNICODE_STRING UserName;
|
||
UNICODE_STRING DomainName;
|
||
|
||
STRING CaseSensitiveResponse;
|
||
STRING CaseInsensitiveResponse;
|
||
|
||
PVOID pSecurityBlob;
|
||
USHORT SecurityBlobSize;
|
||
|
||
PSMBCE_SERVER pServer = &pExchange->SmbCeContext.pServerEntry->Server;
|
||
PSMBCE_SESSION pSession = &pExchange->SmbCeContext.pSessionEntry->Session;
|
||
|
||
SECURITY_RESPONSE_CONTEXT ResponseContext;
|
||
|
||
PAGED_CODE();
|
||
RxDbgTrace( +1, Dbg, ("BuildSessionSetupSecurityInformation -- Entry\n"));
|
||
|
||
// Attach to the redirector's FSP to allow us to call into the security impl.
|
||
if (PsGetCurrentProcess() != RxGetRDBSSProcess()) {
|
||
KeAttachProcess(RxGetRDBSSProcess());
|
||
|
||
fProcessAttached = TRUE;
|
||
}
|
||
|
||
if (pServer->DialectFlags & DF_EXTENDED_SECURITY) {
|
||
Status = BuildExtendedSessionSetupResponsePrologue(
|
||
pExchange,
|
||
&pSecurityBlob,
|
||
&SecurityBlobSize,
|
||
&ResponseContext);
|
||
} else {
|
||
Status = BuildNtLanmanResponsePrologue(
|
||
pExchange,
|
||
&UserName,
|
||
&DomainName,
|
||
&CaseSensitiveResponse,
|
||
&CaseInsensitiveResponse,
|
||
&ResponseContext);
|
||
}
|
||
|
||
if (NT_SUCCESS(Status)) {
|
||
PBYTE pBuffer = pSmbBuffer;
|
||
ULONG BufferSize = *pSmbBufferSize;
|
||
|
||
if ((pServer->Dialect == NTLANMAN_DIALECT) &&
|
||
(BooleanFlagOn(pServer->DialectFlags,DF_EXTENDED_SECURITY))) {
|
||
PREQ_NT_EXTENDED_SESSION_SETUP_ANDX pExtendedNtSessionSetupReq;
|
||
|
||
// Position the buffer for copying the security blob
|
||
pBuffer += FIELD_OFFSET(REQ_NT_EXTENDED_SESSION_SETUP_ANDX,Buffer);
|
||
BufferSize -= FIELD_OFFSET(REQ_NT_EXTENDED_SESSION_SETUP_ANDX,Buffer);
|
||
|
||
pExtendedNtSessionSetupReq = (PREQ_NT_EXTENDED_SESSION_SETUP_ANDX)pSmbBuffer;
|
||
|
||
SmbPutUshort(
|
||
&pExtendedNtSessionSetupReq->SecurityBlobLength,
|
||
SecurityBlobSize);
|
||
|
||
if (BufferSize >= SecurityBlobSize) {
|
||
RtlCopyMemory(
|
||
pBuffer,
|
||
pSecurityBlob,
|
||
SecurityBlobSize);
|
||
BufferSize -= SecurityBlobSize;
|
||
} else {
|
||
Status = STATUS_BUFFER_OVERFLOW;
|
||
}
|
||
} else if (pServer->Dialect == NTLANMAN_DIALECT) {
|
||
PREQ_NT_SESSION_SETUP_ANDX pNtSessionSetupReq = (PREQ_NT_SESSION_SETUP_ANDX)pSmbBuffer;
|
||
|
||
// It it is a NT server both the case insensitive and case sensitive passwords
|
||
// need to be copied. for share-level, just copy a token 1-byte NULL password
|
||
|
||
// Position the buffer for copying the password.
|
||
pBuffer += FIELD_OFFSET(REQ_NT_SESSION_SETUP_ANDX,Buffer);
|
||
BufferSize -= FIELD_OFFSET(REQ_NT_SESSION_SETUP_ANDX,Buffer);
|
||
|
||
if (pServer->SecurityMode == SECURITY_MODE_USER_LEVEL){
|
||
|
||
RxDbgTrace( 0, Dbg, ("BuildSessionSetupSecurityInformation -- NtUserPasswords\n"));
|
||
|
||
SmbPutUshort(
|
||
&pNtSessionSetupReq->CaseInsensitivePasswordLength,
|
||
CaseInsensitiveResponse.Length);
|
||
|
||
SmbPutUshort(
|
||
&pNtSessionSetupReq->CaseSensitivePasswordLength,
|
||
CaseSensitiveResponse.Length);
|
||
|
||
Status = SmbPutString(
|
||
&pBuffer,
|
||
&CaseInsensitiveResponse,
|
||
&BufferSize);
|
||
|
||
if (NT_SUCCESS(Status)) {
|
||
Status = SmbPutString(
|
||
&pBuffer,
|
||
&CaseSensitiveResponse,
|
||
&BufferSize);
|
||
}
|
||
} else {
|
||
|
||
RxDbgTrace( 0, Dbg, ("BuildSessionSetupSecurityInformation -- NtSharePasswords\n"));
|
||
|
||
SmbPutUshort(&pNtSessionSetupReq->CaseInsensitivePasswordLength, 1);
|
||
SmbPutUshort(&pNtSessionSetupReq->CaseSensitivePasswordLength, 1);
|
||
*pBuffer = 0;
|
||
*(pBuffer+1) = 0;
|
||
pBuffer += 2;
|
||
BufferSize -= 2;
|
||
}
|
||
} else {
|
||
PREQ_SESSION_SETUP_ANDX pSessionSetupReq = (PREQ_SESSION_SETUP_ANDX)pSmbBuffer;
|
||
|
||
// Position the buffer for copying the password.
|
||
pBuffer += FIELD_OFFSET(REQ_SESSION_SETUP_ANDX,Buffer);
|
||
BufferSize -= FIELD_OFFSET(REQ_SESSION_SETUP_ANDX,Buffer);
|
||
|
||
if (pServer->SecurityMode == SECURITY_MODE_USER_LEVEL) {
|
||
// For othe lanman servers only the case sensitive password is required.
|
||
SmbPutUshort(
|
||
&pSessionSetupReq->PasswordLength,
|
||
CaseSensitiveResponse.Length);
|
||
|
||
// Copy the password
|
||
Status = SmbPutString(
|
||
&pBuffer,
|
||
&CaseSensitiveResponse,
|
||
&BufferSize);
|
||
} else {
|
||
// Share level security. Send a null string for the password
|
||
SmbPutUshort(&pSessionSetupReq->PasswordLength,1);
|
||
*pBuffer++ = '\0';
|
||
BufferSize -= sizeof(CHAR);
|
||
}
|
||
}
|
||
|
||
// The User name and the domain name strings can be either copied from
|
||
// the information returned in the request response or the information
|
||
// that is already present in the session entry.
|
||
if (NT_SUCCESS(Status) &&
|
||
!BooleanFlagOn(pServer->DialectFlags,DF_EXTENDED_SECURITY)) {
|
||
if ((pServer->Dialect == NTLANMAN_DIALECT) &&
|
||
(pServer->NtServer.NtCapabilities & CAP_UNICODE)) {
|
||
// Copy the account/domain names as UNICODE strings
|
||
PBYTE pTempBuffer = pBuffer;
|
||
|
||
RxDbgTrace( 0, Dbg, ("BuildSessionSetupSecurityInformation -- account/domain as unicode\n"));
|
||
pBuffer = ALIGN_SMB_WSTR(pBuffer);
|
||
BufferSize -= (pBuffer - pTempBuffer);
|
||
|
||
Status = SmbPutUnicodeString(
|
||
&pBuffer,
|
||
&UserName,
|
||
&BufferSize);
|
||
|
||
if (NT_SUCCESS(Status)) {
|
||
Status = SmbPutUnicodeString(
|
||
&pBuffer,
|
||
&DomainName,
|
||
&BufferSize);
|
||
|
||
}
|
||
} else {
|
||
// Copy the account/domain names as ASCII strings.
|
||
RxDbgTrace( 0, Dbg, ("BuildSessionSetupSecurityInformation -- account/domain as ascii\n"));
|
||
Status = SmbPutUnicodeStringAsOemString(
|
||
&pBuffer,
|
||
&UserName,
|
||
&BufferSize);
|
||
|
||
if (NT_SUCCESS(Status)) {
|
||
Status = SmbPutUnicodeStringAsOemString(
|
||
&pBuffer,
|
||
&DomainName,
|
||
&BufferSize);
|
||
}
|
||
}
|
||
}
|
||
|
||
if (NT_SUCCESS(Status)) {
|
||
*pSmbBufferSize = BufferSize;
|
||
}
|
||
}
|
||
|
||
// Free the buffer allocated by the security package.
|
||
if (pServer->DialectFlags & DF_EXTENDED_SECURITY) {
|
||
BuildExtendedSessionSetupResponseEpilogue(&ResponseContext);
|
||
} else {
|
||
BuildNtLanmanResponseEpilogue(&ResponseContext);
|
||
}
|
||
|
||
// Detach from the rdr process.
|
||
if (fProcessAttached) {
|
||
KeDetachProcess();
|
||
}
|
||
|
||
RxDbgTrace( -1, Dbg, ("BuildSessionSetupSecurityInformation -- Exit, status=%08lx\n",Status));
|
||
return Status;
|
||
}
|
||
NTSTATUS
|
||
BuildTreeConnectSecurityInformation(
|
||
PSMB_EXCHANGE pExchange,
|
||
PBYTE pBuffer,
|
||
PBYTE pPasswordLength,
|
||
PULONG pSmbBufferSize)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine builds the security related information for the session setup SMB
|
||
|
||
Arguments:
|
||
|
||
pServer - the server instance
|
||
|
||
pLogonId - the logon id. for which the session is being setup
|
||
|
||
pPassword - the user supplied password if any
|
||
|
||
pBuffer - the password buffer
|
||
|
||
pPasswordLength - where the password length is to be stored
|
||
|
||
pSmbBufferSize - the size of the buffer on input ( modified to size remaining on
|
||
output)
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS - The return status for the operation
|
||
|
||
Notes:
|
||
|
||
Eventhough the genral structure of the code tries to isolate dialect specific issues
|
||
as much as possible this routine takes the opposite approach. This is because of the
|
||
preamble and prologue to security interaction which far outweigh the dialect specific
|
||
work required to be done. Therefore in the interests of a smaller footprint this approach
|
||
has been adopted.
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS FinalStatus,Status;
|
||
BOOLEAN fProcessAttached = FALSE;
|
||
|
||
UNICODE_STRING UserName,DomainName;
|
||
STRING CaseSensitiveChallengeResponse,CaseInsensitiveChallengeResponse;
|
||
|
||
SECURITY_RESPONSE_CONTEXT ResponseContext;
|
||
|
||
ULONG PasswordLength = 0;
|
||
|
||
PSMBCE_SERVER pServer = &pExchange->SmbCeContext.pServerEntry->Server;
|
||
PSMBCE_SESSION pSession = &pExchange->SmbCeContext.pSessionEntry->Session;
|
||
|
||
PAGED_CODE();
|
||
|
||
Status = STATUS_SUCCESS;
|
||
|
||
if (pServer->EncryptPasswords) {
|
||
// Attach to the redirector's FSP to allow us to call into the securiy impl.
|
||
if (PsGetCurrentProcess() != RxGetRDBSSProcess()) {
|
||
KeAttachProcess(RxGetRDBSSProcess());
|
||
fProcessAttached = TRUE;
|
||
}
|
||
|
||
Status = BuildNtLanmanResponsePrologue(
|
||
pExchange,
|
||
&UserName,
|
||
&DomainName,
|
||
&CaseSensitiveChallengeResponse,
|
||
&CaseInsensitiveChallengeResponse,
|
||
&ResponseContext);
|
||
|
||
if (NT_SUCCESS(Status)) {
|
||
if (FlagOn(pServer->DialectFlags,DF_MIXEDCASEPW)) {
|
||
RxDbgTrace( 0, Dbg, ("BuildTreeConnectSecurityInformation -- case sensitive password\n"));
|
||
// Copy the password length onto the SMB buffer
|
||
PasswordLength = CaseSensitiveChallengeResponse.Length;
|
||
|
||
// Copy the password
|
||
Status = SmbPutString(
|
||
&pBuffer,
|
||
&CaseSensitiveChallengeResponse,
|
||
pSmbBufferSize);
|
||
} else {
|
||
RxDbgTrace( 0, Dbg, ("BuildTreeConnectSecurityInformation -- case insensitive password\n"));
|
||
// Copy the password length onto the SMB buffer
|
||
PasswordLength = CaseInsensitiveChallengeResponse.Length;
|
||
|
||
// Copy the password
|
||
Status = SmbPutString(
|
||
&pBuffer,
|
||
&CaseInsensitiveChallengeResponse,
|
||
pSmbBufferSize);
|
||
}
|
||
|
||
BuildNtLanmanResponseEpilogue(&ResponseContext);
|
||
}
|
||
|
||
if (fProcessAttached) {
|
||
KeDetachProcess();
|
||
}
|
||
} else {
|
||
if (pSession->pPassword == NULL) {
|
||
// The logon password cannot be sent as plain text. Send a single blank as password.
|
||
|
||
PasswordLength = 2;
|
||
if (*pSmbBufferSize >= 2) {
|
||
*((PCHAR)pBuffer) = ' ';
|
||
pBuffer += sizeof(CHAR);
|
||
*((PCHAR)pBuffer) = '\0';
|
||
pBuffer += sizeof(CHAR);
|
||
Status = STATUS_SUCCESS;
|
||
} else {
|
||
Status = STATUS_BUFFER_OVERFLOW;
|
||
}
|
||
} else {
|
||
OEM_STRING OemString;
|
||
|
||
OemString.Length = OemString.MaximumLength = (USHORT)(*pSmbBufferSize - sizeof(CHAR));
|
||
OemString.Buffer = pBuffer;
|
||
Status = RtlUnicodeStringToOemString(
|
||
&OemString,
|
||
pSession->pPassword,
|
||
FALSE);
|
||
|
||
if (NT_SUCCESS(Status)) {
|
||
PasswordLength = OemString.Length+1;
|
||
}
|
||
}
|
||
|
||
// reduce the byte count
|
||
*pSmbBufferSize -= PasswordLength;
|
||
}
|
||
|
||
SmbPutUshort(pPasswordLength,(USHORT)PasswordLength);
|
||
|
||
return Status;
|
||
}
|
||
|
||
|