windows-nt/Source/XPSP1/NT/ds/security/services/scerpc/fileshr/smbsvc.cpp
2020-09-26 16:20:57 +08:00

3923 lines
118 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
smbsvc.cpp
Abstract:
File sharing security engine attachment for Security Configuration Editor
Author:
Jin Huang (jinhuang) 11-Jul-1997
Revision History:
--*/
#include "smbsvcp.h"
#include "util.h"
#include "smbdllrc.h"
#include <lmapibuf.h>
#pragma hdrstop
#define SMBSVC_BUF_LEN 1024
#define SCESMB_ROOT_PATH SCE_ROOT_SERVICE_PATH TEXT("\\LanManServer")
#define SmbsvcServerKey L"System\\CurrentControlSet\\Services\\LanManServer\\Parameters"
#define SmbsvcRdrKey L"System\\CurrentControlSet\\Services\\MrxSmb\\Parameters"
#define SmbsvcEnableSS L"EnableSecuritySignature"
#define SmbsvcRequireSS L"RequireSecuritySignature"
#define SmbsvcPlainPassword L"EnablePlainTextPassword"
#define SmbsvcRequireECR L"RequireEnhancedChallengeResponse"
#define SmbsvcNTResponse L"SendNTResponseOnly"
#define SmbsvcRestrictNull L"RestrictNullSessAccess"
#define SmbsvcAutoShareServer L"AutoShareServer"
#define SmbsvcAutoShareWks L"AutoShareWks"
#define SmbsvcForcedLogOff L"EnableForcedLogOff"
#define SmbsvcAutoDisconnect L"AutoDisconnect"
#define NUM_COMP 14
#if defined(_NT4BACK_PORT)
HINSTANCE MyModuleHandle = NULL;
#else
/*
#if !defined(Thread)
#define Thread __declspec( thread )
#endif
HINSTANCE Thread MyModuleHandle=NULL;
*/
HINSTANCE MyModuleHandle=NULL;
#endif
static NT_PRODUCT_TYPE ProductType;
GENERIC_MAPPING ShareGenMap = {
STANDARD_RIGHTS_READ | SYNCHRONIZE | 0x1,
STANDARD_RIGHTS_WRITE | SYNCHRONIZE | 0x2,
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | 0x4,
STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1FF
};
SCESTATUS
SmbsvcpResetInfo(
IN PSMBSVC_SEC_INFO pInfo
);
SCESTATUS
SmbsvcpGetInformation(
IN PSCESVC_CALLBACK_INFO pSceCbInfo,
OUT PSMBSVC_SEC_INFO pSmbInfo
);
SCESTATUS
SmbsvcpAddAShareToList(
OUT PSMBSVC_SHARES *pShareList,
IN PWSTR ShareName,
IN DWORD Status,
IN PSECURITY_DESCRIPTOR pSD
);
SCESTATUS
SmbsvcpFree(
IN PSMBSVC_SEC_INFO pSmbInfo
);
SCESTATUS
SmbsvcpFreeShareList(
PSMBSVC_SHARES pShares
);
SCESTATUS
SmbsvcpWriteError(
IN PFSCE_LOG_INFO pfLogCallback,
IN INT ErrLevel,
IN DWORD ErrCode,
IN PWSTR Mes
);
SCESTATUS
SmbsvcpWriteError2(
IN PFSCE_LOG_INFO pfLogCallback,
IN INT ErrLevel,
IN DWORD ErrCode,
IN UINT nId,
...
);
SCESTATUS
SmbsvcpConfigureValue(
IN PCWSTR RegKey,
IN PCWSTR ValueName,
IN DWORD Value
);
SCESTATUS
SmbsvcpQueryShareList(
OUT PSMBSVC_SHARES *pShareList,
OUT PDWORD ShareCount
);
SCESTATUS
SmbsvcpAnalyzeValue(
IN PCWSTR RegKey,
IN PCWSTR RegValueName,
IN PCWSTR KeyName,
IN DWORD ConfigValue,
OUT PSCESVC_ANALYSIS_LINE pLineInfo,
IN OUT PDWORD pCount
);
DWORD
SmbsvcpConvertStringToMultiSz(
IN PWSTR theStr,
IN DWORD theLen,
OUT PBYTE *outValue,
OUT PDWORD outLen
);
SCESTATUS
SmbsvcpAnalyzeMultiSzString(
IN PCWSTR RegKey,
IN PCWSTR RegValueName,
IN PWSTR pConfigInfo,
IN DWORD InfoLength,
OUT PSCESVC_ANALYSIS_LINE pLineInfo,
IN OUT PDWORD pCount
);
DWORD
SmbsvcpChangeMultiSzToString(
IN PWSTR Value
);
DWORD
SmbsvcpCompareMultiSzString(
IN PWSTR pConfigInfo,
IN PWSTR Value,
OUT PDWORD pValueLen,
OUT PBOOL pDiff
);
DWORD
SmbsvcpCountComponents(
IN PWSTR Value,
OUT PDWORD ValueLen,
OUT PDWORD Count
);
SCESTATUS
SmbsvcpUpdateMultiSzString(
IN PSCESVC_CALLBACK_INFO pSceCbInfo,
IN SCESVC_CONFIGURATION_LINE NewLine,
IN PSCESVC_CONFIGURATION_INFO pConfigInfo OPTIONAL,
IN PSCESVC_ANALYSIS_INFO pAnaInfo OPTIONAL
);
SCESTATUS
SmbsvcpUpdateShareValue(
IN PSCESVC_CALLBACK_INFO pSceCbInfo,
IN SCESVC_CONFIGURATION_LINE NewLine,
IN PSCESVC_CONFIGURATION_INFO pConfigInfo OPTIONAL,
IN PSCESVC_ANALYSIS_INFO pAnaInfo OPTIONAL
);
SCESTATUS
SmbsvcpEqualSecurityDescriptor(
IN PSECURITY_DESCRIPTOR pSD1,
IN PSECURITY_DESCRIPTOR pSD2,
IN BOOL bExplicitOnly,
OUT PBOOL pbEqual
);
DWORD
SmbsvcEveryoneFullAccess(
IN PACL pAcl,
IN BOOL bExplicit,
OUT PBOOL pbEqual
);
DWORD
SmbsvcpCompareAcl(
IN PACL pAcl1,
IN PACL pAcl2,
IN BOOL bExplicitOnly,
OUT PBOOL pDifferent
);
DWORD
SmbsvcpAnyExplicitAcl(
IN PACL Acl,
IN DWORD Processed,
OUT PBOOL pExist
);
BOOL
SmbsvcpEqualAce(
IN ACE_HEADER *pAce1,
IN ACE_HEADER *pAce2
);
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// Implementation of well-known interfaces
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
SCESTATUS
WINAPI
SceSvcAttachmentConfig(
IN PSCESVC_CALLBACK_INFO pSceCbInfo
)
/*
Routine Description:
Arguments:
pSceCbInfo - the callback info structure which contains the database handle,
callback functions to query info, set info, and free info.
All configuration information for SMB server is stored in the storage.
Return Value:
SCESTATUS
*/
{
if ( pSceCbInfo == NULL ||
pSceCbInfo->sceHandle == NULL ||
pSceCbInfo->pfQueryInfo == NULL ||
pSceCbInfo->pfSetInfo == NULL ||
pSceCbInfo->pfFreeInfo == NULL ) {
return(SCESTATUS_INVALID_PARAMETER);
}
if ( !RtlGetNtProductType(&ProductType) ) {
return(SmbsvcpDosErrorToSceStatus(GetLastError()));
}
SCESTATUS rc;
SMBSVC_SEC_INFO SmbInfo;
PSMBSVC_SEC_INFO pSmbInfo=&SmbInfo;
SmbsvcpResetInfo(&SmbInfo);
SmbsvcpWriteError2(
pSceCbInfo->pfLogInfo,
SCE_LOG_LEVEL_DETAIL,
0,
SMBSVC_QUERY_INFO
);
rc = SmbsvcpGetInformation(
pSceCbInfo,
pSmbInfo
);
if ( rc == SCESTATUS_SUCCESS ) {
//
// configure the registry keys first
//
SmbsvcpWriteError2(
pSceCbInfo->pfLogInfo,
SCE_LOG_LEVEL_DETAIL,
0,
SMBSVC_CONFIGURE_CLIENT_START
);
SCESTATUS rc2;
//
// EnableSecuritySignature for client
//
rc2 = SmbsvcpConfigureValue(
SmbsvcRdrKey,
SmbsvcEnableSS,
pSmbInfo->EnableClientSecuritySignature
);
if ( rc2 != SCESTATUS_SUCCESS ) {
SmbsvcpWriteError2(pSceCbInfo->pfLogInfo,
SCE_LOG_LEVEL_ERROR,
SmbsvcpSceStatusToDosError(rc2),
SMBSVC_ERROR_CONFIGURE,
SmbsvcEnableSS);
if ( rc == SCESTATUS_SUCCESS &&
rc2 != SCESTATUS_PROFILE_NOT_FOUND ) {
rc = rc2;
}
}
//
// RequireSecuritySignature for client
//
rc2 = SmbsvcpConfigureValue(
SmbsvcRdrKey,
SmbsvcRequireSS,
pSmbInfo->RequireClientSecuritySignature
);
if ( rc2 != SCESTATUS_SUCCESS ) {
SmbsvcpWriteError2(pSceCbInfo->pfLogInfo,
SCE_LOG_LEVEL_ERROR,
SmbsvcpSceStatusToDosError(rc2),
SMBSVC_ERROR_CONFIGURE,
SmbsvcRequireSS);
if ( rc == SCESTATUS_SUCCESS && rc2 != SCESTATUS_PROFILE_NOT_FOUND )
rc = rc2;
}
//
// EnablePlainTextPassword (client only)
//
rc2 = SmbsvcpConfigureValue(
SmbsvcRdrKey,
SmbsvcPlainPassword,
pSmbInfo->EnablePlainTextPassword
);
if ( rc2 != SCESTATUS_SUCCESS ) {
SmbsvcpWriteError2(pSceCbInfo->pfLogInfo,
SCE_LOG_LEVEL_ERROR,
SmbsvcpSceStatusToDosError(rc2),
SMBSVC_ERROR_CONFIGURE,
SmbsvcPlainPassword);
if ( rc == SCESTATUS_SUCCESS && rc2 != SCESTATUS_PROFILE_NOT_FOUND )
rc = rc2;
}
//
// RequireEnhancedChallengeResponse (client only)
//
rc2 = SmbsvcpConfigureValue(
SmbsvcRdrKey,
SmbsvcRequireECR,
pSmbInfo->RequireEnhancedChallengeResponse
);
if ( rc2 != SCESTATUS_SUCCESS ) {
SmbsvcpWriteError2(pSceCbInfo->pfLogInfo,
SCE_LOG_LEVEL_ERROR,
SmbsvcpSceStatusToDosError(rc2),
SMBSVC_ERROR_CONFIGURE,
SmbsvcRequireECR);
if ( rc == SCESTATUS_SUCCESS && rc2 != SCESTATUS_PROFILE_NOT_FOUND )
rc = rc2;
}
//
// SendNTResponseOnly (client only)
//
rc2 = SmbsvcpConfigureValue(
SmbsvcRdrKey,
SmbsvcNTResponse,
pSmbInfo->SendNTResponseOnly
);
if ( rc2 != SCESTATUS_SUCCESS ) {
SmbsvcpWriteError2(pSceCbInfo->pfLogInfo,
SCE_LOG_LEVEL_ERROR,
SmbsvcpSceStatusToDosError(rc2),
SMBSVC_ERROR_CONFIGURE,
SmbsvcNTResponse);
if ( rc == SCESTATUS_SUCCESS && rc2 != SCESTATUS_PROFILE_NOT_FOUND )
rc = rc2;
}
if ( SCESTATUS_SUCCESS == rc ) {
SmbsvcpWriteError2(
pSceCbInfo->pfLogInfo,
SCE_LOG_LEVEL_DETAIL,
0,
SMBSVC_CONFIGURE_CLIENT_DONE
);
}
//
// !!!!!!!! server settings !!!!!!!!!
//
SmbsvcpWriteError2(
pSceCbInfo->pfLogInfo,
SCE_LOG_LEVEL_DETAIL,
0,
SMBSVC_CONFIGURE_SERVER_START
);
SCESTATUS rc3 = rc;
rc = SCESTATUS_SUCCESS;
//
// EnableSecuritySignature for server
//
rc2 = SmbsvcpConfigureValue(
SmbsvcServerKey,
SmbsvcEnableSS,
pSmbInfo->EnableServerSecuritySignature
);
if ( rc2 != SCESTATUS_SUCCESS ) {
SmbsvcpWriteError2(pSceCbInfo->pfLogInfo,
SCE_LOG_LEVEL_ERROR,
SmbsvcpSceStatusToDosError(rc2),
SMBSVC_ERROR_CONFIGURE,
SmbsvcEnableSS);
if ( rc == SCESTATUS_SUCCESS && rc2 != SCESTATUS_PROFILE_NOT_FOUND )
rc = rc2;
}
//
// RequireSecuritySignature for server
//
rc2 = SmbsvcpConfigureValue(
SmbsvcServerKey,
SmbsvcRequireSS,
pSmbInfo->RequireServerSecuritySignature
);
if ( rc2 != SCESTATUS_SUCCESS ) {
SmbsvcpWriteError2(pSceCbInfo->pfLogInfo,
SCE_LOG_LEVEL_ERROR,
SmbsvcpSceStatusToDosError(rc2),
SMBSVC_ERROR_CONFIGURE,
SmbsvcRequireSS);
if ( rc == SCESTATUS_SUCCESS && rc2 != SCESTATUS_PROFILE_NOT_FOUND )
rc = rc2;
}
//
// RestrictNullSessionAccess
//
rc2 = SmbsvcpConfigureValue(
SmbsvcServerKey,
SmbsvcRestrictNull,
pSmbInfo->RestrictNullSessionAccess
);
if ( rc2 != SCESTATUS_SUCCESS ) {
SmbsvcpWriteError2(pSceCbInfo->pfLogInfo,
SCE_LOG_LEVEL_ERROR,
SmbsvcpSceStatusToDosError(rc2),
SMBSVC_ERROR_CONFIGURE,
SmbsvcRestrictNull);
if ( rc == SCESTATUS_SUCCESS && rc2 != SCESTATUS_PROFILE_NOT_FOUND )
rc = rc2;
}
//
// AutoShareServer or AutoShareWks
//
PCWSTR AutoValueName;
if ( ProductType == NtProductLanManNt ||
ProductType == NtProductServer) {
AutoValueName = SmbsvcAutoShareServer;
} else {
AutoValueName = SmbsvcAutoShareWks;
}
rc2 = SmbsvcpConfigureValue(
SmbsvcServerKey,
AutoValueName,
pSmbInfo->EnableAutoShare
);
if ( rc2 != SCESTATUS_SUCCESS ) {
SmbsvcpWriteError2(pSceCbInfo->pfLogInfo,
SCE_LOG_LEVEL_ERROR,
SmbsvcpSceStatusToDosError(rc2),
SMBSVC_ERROR_CONFIGURE,
(PWSTR)AutoValueName);
if ( rc == SCESTATUS_SUCCESS && rc2 != SCESTATUS_PROFILE_NOT_FOUND )
rc = rc2;
}
//
// EnableForcedLogOff
//
rc2 = SmbsvcpConfigureValue(
SmbsvcServerKey,
SmbsvcForcedLogOff,
pSmbInfo->EnableForcedLogOff
);
if ( rc2 != SCESTATUS_SUCCESS ) {
SmbsvcpWriteError2(pSceCbInfo->pfLogInfo,
SCE_LOG_LEVEL_ERROR,
SmbsvcpSceStatusToDosError(rc2),
SMBSVC_ERROR_CONFIGURE,
SmbsvcForcedLogOff);
if ( rc == SCESTATUS_SUCCESS && rc2 != SCESTATUS_PROFILE_NOT_FOUND )
rc = rc2;
}
//
// AutoDisconnectTime
//
rc2 = SmbsvcpConfigureValue(
SmbsvcServerKey,
SmbsvcAutoDisconnect,
pSmbInfo->AutoDisconnect
);
if ( rc2 != SCESTATUS_SUCCESS ) {
SmbsvcpWriteError2(pSceCbInfo->pfLogInfo,
SCE_LOG_LEVEL_ERROR,
SmbsvcpSceStatusToDosError(rc2),
SMBSVC_ERROR_CONFIGURE,
SmbsvcAutoDisconnect);
if ( rc == SCESTATUS_SUCCESS && rc2 != SCESTATUS_PROFILE_NOT_FOUND )
rc = rc2;
}
//
// configure Null Session Pipes and Shares
//
// buffer NullSessionPipes and NullSessionShares are already in MULTI_SZ format
//
DWORD Win32rc;
PBYTE MultiSzValue=NULL;
DWORD MultiSzLength=0;
if ( pSmbInfo->LengthPipes != SMBSVC_NO_VALUE ) {
Win32rc = SmbsvcpConvertStringToMultiSz(
pSmbInfo->NullSessionPipes,
pSmbInfo->LengthPipes,
&MultiSzValue,
&MultiSzLength
);
if ( Win32rc == ERROR_SUCCESS ) {
Win32rc = SmbsvcpRegSetValue(
HKEY_LOCAL_MACHINE,
SmbsvcServerKey,
L"NullSessionPipes",
REG_MULTI_SZ,
MultiSzValue,
MultiSzLength
);
}
if ( Win32rc != ERROR_SUCCESS ) {
SmbsvcpWriteError2(pSceCbInfo->pfLogInfo,
SCE_LOG_LEVEL_ERROR,
Win32rc,
SMBSVC_ERROR_CONFIGURE,
L"NullSessionPipes");
if ( rc == SCESTATUS_SUCCESS && Win32rc != ERROR_FILE_NOT_FOUND )
rc = SmbsvcpDosErrorToSceStatus(Win32rc);;
}
}
if ( pSmbInfo->LengthShares != SMBSVC_NO_VALUE ) {
Win32rc = SmbsvcpConvertStringToMultiSz(
pSmbInfo->NullSessionShares,
pSmbInfo->LengthShares,
&MultiSzValue,
&MultiSzLength
);
if ( Win32rc == ERROR_SUCCESS ) {
Win32rc = SmbsvcpRegSetValue(
HKEY_LOCAL_MACHINE,
SmbsvcServerKey,
L"NullSessionShares",
REG_MULTI_SZ,
(PBYTE)(pSmbInfo->NullSessionShares),
pSmbInfo->LengthShares
);
}
if ( Win32rc != ERROR_SUCCESS ) {
SmbsvcpWriteError2(pSceCbInfo->pfLogInfo,
SCE_LOG_LEVEL_ERROR,
Win32rc,
SMBSVC_ERROR_CONFIGURE,
L"NullSessionShares");
if ( rc == SCESTATUS_SUCCESS && Win32rc != ERROR_FILE_NOT_FOUND )
rc = SmbsvcpDosErrorToSceStatus(Win32rc);;
}
}
//
// configure security on existing shares
//
SHARE_INFO_1501 ShareInfo;
PSMBSVC_SHARES pTemp;
for ( pTemp=pSmbInfo->pShares; pTemp != NULL;
pTemp = pTemp->Next) {
ShareInfo.shi1501_reserved = 0;
ShareInfo.shi1501_security_descriptor = pTemp->pShareSD;
Win32rc = NetShareSetInfo (
NULL,
pTemp->ShareName,
1501,
(LPBYTE)&ShareInfo,
NULL
);
if ( Win32rc != ERROR_SUCCESS ) {
SmbsvcpWriteError2(pSceCbInfo->pfLogInfo,
SCE_LOG_LEVEL_ERROR,
Win32rc,
SMBSVC_ERROR_CONFIGURE,
pTemp->ShareName);
if ( rc == SCESTATUS_SUCCESS )
rc = SmbsvcpDosErrorToSceStatus(Win32rc);;
}
//
// continue to configure even if error occurs
//
}
if ( SCESTATUS_SUCCESS == rc ) {
SmbsvcpWriteError2(pSceCbInfo->pfLogInfo,
SCE_LOG_LEVEL_DETAIL,
0,
SMBSVC_CONFIGURE_SERVER_DONE
);
rc = rc3; // saved status for client configuration
}
//
// free memory
//
SmbsvcpFree(pSmbInfo);
}
return(rc);
}
SCESTATUS
WINAPI
SceSvcAttachmentAnalyze(
IN PSCESVC_CALLBACK_INFO pSceCbInfo
)
/*
Routine Description:
Arguments:
pSceCbInfo - the callback info structure which contains a opaque database handle
and callback function pointers to query info, set info, and free info.
Only mismatched info for SMB server is stored in the storage.
Return Value:
SCESTATUS
*/
{
if ( pSceCbInfo == NULL ||
pSceCbInfo->sceHandle == NULL ||
pSceCbInfo->pfQueryInfo == NULL ||
pSceCbInfo->pfSetInfo == NULL ||
pSceCbInfo->pfFreeInfo == NULL ) {
return(SCESTATUS_INVALID_PARAMETER);
}
if ( !RtlGetNtProductType(&ProductType) )
return(SmbsvcpDosErrorToSceStatus(GetLastError()));
SCESTATUS rc, Saverc;
SMBSVC_SEC_INFO SmbInfo;
PSMBSVC_SEC_INFO pSmbInfo=&SmbInfo;
PWSTR ErrPoint=NULL;
WCHAR Errbuf[64];
//
// reset the Smb buffer
//
SmbsvcpResetInfo(&SmbInfo);
SmbsvcpWriteError2(
pSceCbInfo->pfLogInfo,
SCE_LOG_LEVEL_DETAIL,
0,
SMBSVC_QUERY_INFO
);
//
// get configuration information
//
rc = SmbsvcpGetInformation(
pSceCbInfo,
pSmbInfo
);
if ( rc == SCESTATUS_SUCCESS ) {
// rc == SCESTATUS_RECORD_NOT_FOUND ) {
//
// analyze share information to a buffer
//
PSMBSVC_SHARES pShares=NULL;
DWORD ShareCount=0;
//
// get all shares
//
rc = SmbsvcpQueryShareList(&pShares, &ShareCount);
if ( rc == SCESTATUS_SUCCESS ) {
//
// Allocate PSCESVC_ANALYSIS_INFO buffer
//
PSCESVC_ANALYSIS_INFO pAnaInfo;
DWORD nCount;
pAnaInfo = (PSCESVC_ANALYSIS_INFO)LocalAlloc(LMEM_FIXED, sizeof(SCESVC_ANALYSIS_INFO));
if ( pAnaInfo != NULL ) {
pAnaInfo->Count = 0;
pAnaInfo->Lines = (PSCESVC_ANALYSIS_LINE)LocalAlloc(LMEM_ZEROINIT,
(NUM_COMP+ShareCount)*sizeof(SCESVC_ANALYSIS_LINE));
if ( pAnaInfo->Lines != NULL ) {
nCount = 0;
SmbsvcpWriteError2(pSceCbInfo->pfLogInfo,
SCE_LOG_LEVEL_DETAIL,
0,
SMBSVC_ANALYZE_CLIENT_START
);
//
// EnableSecuritySignature for client
//
rc = SmbsvcpAnalyzeValue(
SmbsvcRdrKey,
SmbsvcEnableSS,
L"EnableClientSecuritySignature",
pSmbInfo->EnableClientSecuritySignature,
&(pAnaInfo->Lines[nCount]),
&nCount
);
ErrPoint = SmbsvcEnableSS;
if ( rc == SCESTATUS_SUCCESS || rc == SCESTATUS_PROFILE_NOT_FOUND) {
//
// RequireSecuritySignature for client
//
rc = SmbsvcpAnalyzeValue(
SmbsvcRdrKey,
SmbsvcRequireSS,
L"RequireClientSecuritySignature",
pSmbInfo->RequireClientSecuritySignature,
&(pAnaInfo->Lines[nCount]),
&nCount
);
ErrPoint = SmbsvcRequireSS;
}
if ( rc == SCESTATUS_SUCCESS || rc == SCESTATUS_PROFILE_NOT_FOUND) {
//
// EnablePlainTextPassword (client only)
//
rc = SmbsvcpAnalyzeValue(
SmbsvcRdrKey,
SmbsvcPlainPassword,
L"EnablePlainTextPassword",
pSmbInfo->EnablePlainTextPassword,
&(pAnaInfo->Lines[nCount]),
&nCount
);
ErrPoint = SmbsvcPlainPassword;
}
if ( rc == SCESTATUS_SUCCESS || rc == SCESTATUS_PROFILE_NOT_FOUND) {
//
// RequireEnhancedChallengeResponse
//
rc = SmbsvcpAnalyzeValue(
SmbsvcRdrKey,
SmbsvcRequireECR,
L"RequireEnhancedChallengeResponse",
pSmbInfo->RequireEnhancedChallengeResponse,
&(pAnaInfo->Lines[nCount]),
&nCount
);
ErrPoint = SmbsvcRequireECR;
}
if ( rc == SCESTATUS_SUCCESS || rc == SCESTATUS_PROFILE_NOT_FOUND) {
//
// SendNTResponseOnly
//
rc = SmbsvcpAnalyzeValue(
SmbsvcRdrKey,
SmbsvcNTResponse,
L"SendNTResponseOnly",
pSmbInfo->SendNTResponseOnly,
&(pAnaInfo->Lines[nCount]),
&nCount
);
ErrPoint = SmbsvcNTResponse;
}
if ( rc == SCESTATUS_PROFILE_NOT_FOUND ) {
rc = SCESTATUS_SUCCESS;
}
if ( rc == SCESTATUS_SUCCESS ) {
SmbsvcpWriteError2(pSceCbInfo->pfLogInfo,
SCE_LOG_LEVEL_DETAIL,
0,
SMBSVC_ANALYZE_CLIENT_DONE
);
} else {
SmbsvcpWriteError2(pSceCbInfo->pfLogInfo,
SCE_LOG_LEVEL_ERROR,
SmbsvcpSceStatusToDosError(rc),
SMBSVC_ERROR_ANALYZE,
ErrPoint
);
}
Saverc = rc;
SmbsvcpWriteError2(pSceCbInfo->pfLogInfo,
SCE_LOG_LEVEL_DETAIL,
0,
SMBSVC_ANALYZE_SERVER_START
);
//
// EnableSecuritySignature for server
//
rc = SmbsvcpAnalyzeValue(
SmbsvcServerKey,
SmbsvcEnableSS,
L"EnableServerSecuritySignature",
pSmbInfo->EnableServerSecuritySignature,
&(pAnaInfo->Lines[nCount]),
&nCount
);
ErrPoint = SmbsvcEnableSS;
if ( rc == SCESTATUS_SUCCESS || rc == SCESTATUS_PROFILE_NOT_FOUND) {
//
// RequireSecuritySignature for server
//
rc = SmbsvcpAnalyzeValue(
SmbsvcServerKey,
SmbsvcRequireSS,
L"RequireServerSecuritySignature",
pSmbInfo->RequireServerSecuritySignature,
&(pAnaInfo->Lines[nCount]),
&nCount
);
ErrPoint = SmbsvcRequireSS;
}
if ( rc == SCESTATUS_SUCCESS || rc == SCESTATUS_PROFILE_NOT_FOUND) {
//
// RestrictNullSessionAccess
//
rc = SmbsvcpAnalyzeValue(
SmbsvcServerKey,
SmbsvcRestrictNull,
L"RestrictNullSessionAccess",
pSmbInfo->RestrictNullSessionAccess,
&(pAnaInfo->Lines[nCount]),
&nCount
);
ErrPoint = SmbsvcRestrictNull;
}
if ( rc == SCESTATUS_SUCCESS || rc == SCESTATUS_PROFILE_NOT_FOUND) {
//
// AutoShareServer or AutoShareWks
//
PCWSTR AutoValueName;
if ( ProductType == NtProductLanManNt ||
ProductType == NtProductServer ) {
AutoValueName = SmbsvcAutoShareServer;
} else {
AutoValueName = SmbsvcAutoShareWks;
}
rc = SmbsvcpAnalyzeValue(
SmbsvcServerKey,
AutoValueName,
L"EnableAutoShare",
pSmbInfo->EnableAutoShare,
&(pAnaInfo->Lines[nCount]),
&nCount
);
ErrPoint = (PWSTR)AutoValueName;
}
if ( rc == SCESTATUS_SUCCESS || rc == SCESTATUS_PROFILE_NOT_FOUND) {
//
// EnableForcedLogOff
//
rc = SmbsvcpAnalyzeValue(
SmbsvcServerKey,
SmbsvcForcedLogOff,
L"EnableForcedLogOff",
pSmbInfo->EnableForcedLogOff,
&(pAnaInfo->Lines[nCount]),
&nCount
);
ErrPoint = SmbsvcForcedLogOff;
}
if ( rc == SCESTATUS_SUCCESS || rc == SCESTATUS_PROFILE_NOT_FOUND) {
//
// AutoDisconnectTime
//
rc = SmbsvcpAnalyzeValue(
SmbsvcServerKey,
SmbsvcAutoDisconnect,
L"AutoDisconnect",
pSmbInfo->AutoDisconnect,
&(pAnaInfo->Lines[nCount]),
&nCount
);
ErrPoint = SmbsvcAutoDisconnect;
}
if ( rc == SCESTATUS_PROFILE_NOT_FOUND ) {
//
// the key does not exist
//
rc = SCESTATUS_SUCCESS;
}
if ( rc == SCESTATUS_SUCCESS ) {
//
// analyze Null Session Pipes and Shares
//
rc = SmbsvcpAnalyzeMultiSzString(
SmbsvcServerKey,
L"NullSessionPipes",
pSmbInfo->NullSessionPipes,
pSmbInfo->LengthPipes,
&(pAnaInfo->Lines[nCount]),
&nCount
);
wcscpy(Errbuf, L"NullSessionPipes");
ErrPoint = Errbuf;
if ( rc == SCESTATUS_SUCCESS ) {
rc = SmbsvcpAnalyzeMultiSzString(
SmbsvcServerKey,
L"NullSessionShares",
pSmbInfo->NullSessionShares,
pSmbInfo->LengthShares,
&(pAnaInfo->Lines[nCount]),
&nCount
);
wcscpy(Errbuf, L"NullSessionShares");
ErrPoint = Errbuf;
}
}
//
// analyze existing shares
//
if ( rc == SCESTATUS_SUCCESS ) {
PSMBSVC_SHARES pTemp, pConfigShare;
//
// process each share
//
for ( pTemp=pShares; pTemp != NULL;
pTemp = pTemp->Next) {
//
// Compare with configuration data
//
for ( pConfigShare=pSmbInfo->pShares;
pConfigShare != NULL; pConfigShare = pConfigShare->Next ) {
if ( _wcsicmp(pTemp->ShareName, pConfigShare->ShareName) == 0 ) {
//
// find the share in configuation data, compare security descriptor
//
break;
}
}
BOOL bEqual = FALSE;
DWORD Status;
if ( pConfigShare != NULL ) {
rc = SmbsvcpEqualSecurityDescriptor(
pTemp->pShareSD,
pConfigShare->pShareSD,
FALSE,
&bEqual
);
wcscpy(Errbuf, pTemp->ShareName);
ErrPoint = Errbuf;
Status = SMBSVC_STATUS_MISMATCH;
} else
Status = SMBSVC_STATUS_NOT_CONFIGURED;
if ( rc == SCESTATUS_SUCCESS && !bEqual ) {
//
// different, save this share
//
if ( pSmbInfo->pShares == NULL ) {
SmbsvcpWriteError2(pSceCbInfo->pfLogInfo,
SCE_LOG_LEVEL_DETAIL,
0,
SMBSVC_NOT_CONFIGURED,
pTemp->ShareName
);
} else {
SmbsvcpWriteError2(pSceCbInfo->pfLogInfo,
SCE_LOG_LEVEL_DETAIL,
0,
SMBSVC_MISMATCH,
pTemp->ShareName
);
}
PWSTR TextSD=NULL;
DWORD SDsize=0;
if ( pTemp->pShareSD != NULL ) {
#if defined(_NT4BACK_PORT)
rc = SceSvcConvertSDToText(
pTemp->pShareSD,
DACL_SECURITY_INFORMATION,
&TextSD,
&SDsize
);
rc = SmbsvcpDosErrorToSceStatus(rc);
#else
if ( !ConvertSecurityDescriptorToStringSecurityDescriptor(
pTemp->pShareSD,
SDDL_REVISION,
DACL_SECURITY_INFORMATION,
&TextSD,
&SDsize
) ) {
rc = SmbsvcpDosErrorToSceStatus(GetLastError());
} else {
rc = SCESTATUS_SUCCESS;
}
#endif
wcscpy(Errbuf, pTemp->ShareName);
ErrPoint = Errbuf;
}
PWSTR Value;
Value = (PWSTR)LocalAlloc(LMEM_FIXED, (SDsize+9)*sizeof(WCHAR));
if ( Value != NULL ) {
if ( TextSD != NULL )
swprintf(Value, L"Share,%1d,%s", Status, TextSD);
else
swprintf(Value, L"Share,%1d,", Status);
Value[SDsize+8] = L'\0';
pAnaInfo->Lines[nCount].Key = pTemp->ShareName;
pAnaInfo->Lines[nCount].Value = (PBYTE)Value;
pAnaInfo->Lines[nCount].ValueLen = (SDsize+8)*sizeof(WCHAR);
pTemp->ShareName = NULL;
nCount++;
} else {
wcscpy(Errbuf, pTemp->ShareName);
ErrPoint = Errbuf;
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
}
if ( TextSD != NULL )
LocalFree(TextSD);
TextSD = NULL;
} else {
SmbsvcpWriteError2(pSceCbInfo->pfLogInfo,
SCE_LOG_LEVEL_DETAIL,
0,
SMBSVC_MATCH,
pTemp->ShareName
);
}
if ( rc != SCESTATUS_SUCCESS ) {
break;
}
}
}
if ( rc == SCESTATUS_SUCCESS ) {
SmbsvcpWriteError2(pSceCbInfo->pfLogInfo,
SCE_LOG_LEVEL_DETAIL,
0,
SMBSVC_ANALYZE_SERVER_DONE
);
rc = Saverc; // saved status for client analysis
} else {
SmbsvcpWriteError2(pSceCbInfo->pfLogInfo,
SCE_LOG_LEVEL_ERROR,
SmbsvcpSceStatusToDosError(rc),
SMBSVC_ERROR_ANALYZE,
ErrPoint
);
}
//
// Now save the information to the database
//
if ( rc == SCESTATUS_SUCCESS ) {
SmbsvcpWriteError2(
pSceCbInfo->pfLogInfo,
SCE_LOG_LEVEL_DETAIL,
0,
SMBSVC_SAVE_INFO
);
pAnaInfo->Count = nCount;
__try {
rc = (*(pSceCbInfo->pfSetInfo))(
pSceCbInfo->sceHandle,
SceSvcAnalysisInfo,
NULL,
FALSE,
(PVOID)pAnaInfo
);
} __except (EXCEPTION_EXECUTE_HANDLER) {
rc = SCESTATUS_SERVICE_NOT_SUPPORT;
}
if ( SCESTATUS_SUCCESS != rc ) {
SmbsvcpWriteError2(
pSceCbInfo->pfLogInfo,
SCE_LOG_LEVEL_ERROR,
SmbsvcpSceStatusToDosError(rc),
SMBSVC_ERROR_SAVE_INFO
);
}
}
//
// free pAnaInfo
//
__try {
(*(pSceCbInfo->pfFreeInfo))((PVOID)pAnaInfo);
} __except (EXCEPTION_EXECUTE_HANDLER) {
//
// BUGBUG: buffer is not freed ??
//
}
} else {
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
LocalFree(pAnaInfo);
}
} else
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
SmbsvcpFreeShareList(pShares);
} else {
SmbsvcpWriteError2(
pSceCbInfo->pfLogInfo,
SCE_LOG_LEVEL_ERROR,
SmbsvcpSceStatusToDosError(rc),
SMBSVC_ERROR_ENUM_SHARE
);
}
//
// free memory
//
SmbsvcpFree(pSmbInfo);
}
return(rc);
}
SCESTATUS
WINAPI
SceSvcAttachmentUpdate(
IN PSCESVC_CALLBACK_INFO pSceCbInfo,
IN SCESVC_CONFIGURATION_INFO *ServiceInfo
)
/*
Routine Description:
Arguments:
pSceCbInfo - the callback handle and function pointers to SCE.
ServiceInfo - The update configuration information for SMB server to process.
Return Value:
SCESTATUS
*/
{
if ( pSceCbInfo == NULL ||
pSceCbInfo->sceHandle == NULL ||
pSceCbInfo->pfQueryInfo == NULL ||
pSceCbInfo->pfSetInfo == NULL ||
pSceCbInfo->pfFreeInfo == NULL ||
ServiceInfo == NULL ) {
return(SCESTATUS_INVALID_PARAMETER);
}
SCESTATUS rc=SCESTATUS_SUCCESS;
PSCESVC_CONFIGURATION_INFO pConfigInfo=NULL;
SCE_ENUMERATION_CONTEXT EnumHandle;
PSCESVC_ANALYSIS_INFO pAnaInfo=NULL;
//
// prepare two buffers for update
//
SCESVC_ANALYSIS_INFO UpdtAnaInfo;
SCESVC_ANALYSIS_LINE UpdtAnaLine;
SCESVC_CONFIGURATION_INFO UpdtConfigInfo;
SCESVC_CONFIGURATION_LINE UpdtConfigLine;
UpdtAnaInfo.Count = 1;
UpdtAnaInfo.Lines = &UpdtAnaLine;
UpdtConfigInfo.Count = 1;
UpdtConfigInfo.Lines = &UpdtConfigLine;
//
// process each line
//
for ( DWORD i=0; i<ServiceInfo->Count; i++ ) {
SmbsvcpWriteError2(pSceCbInfo->pfLogInfo,
SCE_LOG_LEVEL_DETAIL,
0,
SMBSVC_UPDATE_INFO,
ServiceInfo->Lines[i].Key
);
//
// query the configuration setting
//
EnumHandle = 0;
__try {
rc = (*(pSceCbInfo->pfQueryInfo))(
pSceCbInfo->sceHandle,
SceSvcConfigurationInfo,
ServiceInfo->Lines[i].Key,
TRUE,
(PVOID *)&pConfigInfo,
&EnumHandle
);
} __except (EXCEPTION_EXECUTE_HANDLER) {
rc = SCESTATUS_SERVICE_NOT_SUPPORT;
}
if ( rc == SCESTATUS_SUCCESS || rc == SCESTATUS_RECORD_NOT_FOUND ) {
// if ( ServiceInfo->Lines[i].Value == NULL ) {
if ( ServiceInfo->Lines[i].ValueLen == SMBSVC_NO_VALUE ) {
//
// delete is requested
//
if ( rc == SCESTATUS_SUCCESS ) {
//
// delete the configuration, but make sure analysis is ok
//
EnumHandle = 0;
__try {
rc = (*(pSceCbInfo->pfQueryInfo))(
pSceCbInfo->sceHandle,
SceSvcAnalysisInfo,
ServiceInfo->Lines[i].Key,
TRUE,
(PVOID *)&pAnaInfo,
&EnumHandle
);
} __except (EXCEPTION_EXECUTE_HANDLER) {
rc = SCESTATUS_SERVICE_NOT_SUPPORT;
}
if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
//
// analysis info does not exist, matched.
// should save configuration info as analysis
//
UpdtAnaLine.Key = ServiceInfo->Lines[i].Key;
UpdtAnaLine.Value = (PBYTE)(pConfigInfo->Lines[0].Value);
UpdtAnaLine.ValueLen = pConfigInfo->Lines[0].ValueLen;
if ( pConfigInfo->Lines[0].ValueLen > 14 &&
pConfigInfo->Lines[0].Value != NULL &&
_wcsnicmp(L"Share,", pConfigInfo->Lines[0].Value, 6) == 0 ) {
//
// this is a share, needs to update status
//
*(pConfigInfo->Lines[0].Value+6) = L'2';
}
__try {
rc = (*(pSceCbInfo->pfSetInfo))(
pSceCbInfo->sceHandle,
SceSvcAnalysisInfo,
NULL,
TRUE,
(PVOID)&UpdtAnaInfo
);
} __except (EXCEPTION_EXECUTE_HANDLER) {
rc = SCESTATUS_SERVICE_NOT_SUPPORT;
}
}
if ( rc == SCESTATUS_SUCCESS ) {
//
// delete the configuration info
//
__try {
rc = (*(pSceCbInfo->pfSetInfo))(
pSceCbInfo->sceHandle,
SceSvcConfigurationInfo,
ServiceInfo->Lines[i].Key,
TRUE,
NULL
);
} __except (EXCEPTION_EXECUTE_HANDLER) {
rc = SCESTATUS_SERVICE_NOT_SUPPORT;
}
}
} // if configuration is not found, just continue
} else {
if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
//
// no configuration setting for this one,
// either a new added share, or other configuration settings.
// BUGBUG: need to validate the key for other settings.
//
// if not valid, break out here
}
//
// query the analysis setting
//
EnumHandle = 0;
__try {
rc = (*(pSceCbInfo->pfQueryInfo))(
pSceCbInfo->sceHandle,
SceSvcAnalysisInfo,
ServiceInfo->Lines[i].Key,
TRUE,
(PVOID *)&pAnaInfo,
&EnumHandle
);
} __except (EXCEPTION_EXECUTE_HANDLER) {
rc = SCESTATUS_SERVICE_NOT_SUPPORT;
}
if ( rc == SCESTATUS_SUCCESS || rc == SCESTATUS_RECORD_NOT_FOUND ) {
//
// mismatch is found for this one, or a matched item
//
if ( _wcsicmp(L"NullSessionShares", ServiceInfo->Lines[i].Key ) == 0 ||
_wcsicmp(L"NullSessionPipes", ServiceInfo->Lines[i].Key ) == 0 ) {
rc = SmbsvcpUpdateMultiSzString(
pSceCbInfo,
ServiceInfo->Lines[i],
pConfigInfo,
pAnaInfo
);
} else if ( ServiceInfo->Lines[i].ValueLen > 14 &&
ServiceInfo->Lines[i].Value != NULL &&
_wcsnicmp(L"Share,", ServiceInfo->Lines[i].Value, 6) == 0 ) {
//
// shares
//
rc = SmbsvcpUpdateShareValue(pSceCbInfo,
ServiceInfo->Lines[i],
pConfigInfo,
pAnaInfo
);
} else {
//
// other BYTE or DWORD type fields
//
DWORD NewValue = SMBSVC_NO_VALUE;
if ( swscanf(ServiceInfo->Lines[i].Value, L"%d", &NewValue) != EOF ) {
DWORD ConfigValue = SMBSVC_NO_VALUE;
DWORD AnaValue = SMBSVC_NO_VALUE;
if ( pConfigInfo != NULL && pConfigInfo->Lines != NULL )
swscanf(pConfigInfo->Lines[0].Value, L"%d", &ConfigValue);
if ( pAnaInfo != NULL && pAnaInfo->Lines != NULL ) {
swscanf((PWSTR)(pAnaInfo->Lines[0].Value), L"%d", &AnaValue);
}
if ( AnaValue != SMBSVC_NO_VALUE ) {
//
// old status is mismatch for this item
//
if ( NewValue == AnaValue ) {
//
// now it is matched, delete the analysis entry
//
SmbsvcpWriteError(pSceCbInfo->pfLogInfo,
SCE_LOG_LEVEL_DEBUG,
0,
L"mismatch->match"
);
__try {
rc = (*(pSceCbInfo->pfSetInfo))(
pSceCbInfo->sceHandle,
SceSvcAnalysisInfo,
ServiceInfo->Lines[i].Key,
TRUE,
NULL
);
} __except (EXCEPTION_EXECUTE_HANDLER) {
rc = SCESTATUS_SERVICE_NOT_SUPPORT;
}
}
if ( NewValue != ConfigValue ) {
//
// update the configuration setting
//
UpdtConfigLine.Key = ServiceInfo->Lines[i].Key;
UpdtConfigLine.Value = ServiceInfo->Lines[i].Value;
UpdtConfigLine.ValueLen = ServiceInfo->Lines[i].ValueLen;
__try {
rc = (*(pSceCbInfo->pfSetInfo))(
pSceCbInfo->sceHandle,
SceSvcConfigurationInfo,
NULL,
TRUE,
(PVOID)&UpdtConfigInfo
);
} __except (EXCEPTION_EXECUTE_HANDLER) {
rc = SCESTATUS_SERVICE_NOT_SUPPORT;
}
}
} else {
//
// old status is match, or a new added configuration key
//
if ( NewValue != ConfigValue ) {
SmbsvcpWriteError(pSceCbInfo->pfLogInfo,
SCE_LOG_LEVEL_DEBUG,
0,
L"match->mismatch"
);
//
// mismatch should be raised with ConfigValue
//
UpdtAnaLine.Key = ServiceInfo->Lines[i].Key;
UpdtAnaLine.Value = ( pConfigInfo != NULL ) ? (PBYTE)(pConfigInfo->Lines[0].Value) : NULL ;
UpdtAnaLine.ValueLen = ( pConfigInfo != NULL ) ? pConfigInfo->Lines[0].ValueLen : 0;
__try {
rc = (*(pSceCbInfo->pfSetInfo))(
pSceCbInfo->sceHandle,
SceSvcAnalysisInfo,
NULL,
TRUE,
(PVOID)&UpdtAnaInfo
);
} __except (EXCEPTION_EXECUTE_HANDLER) {
rc = SCESTATUS_SERVICE_NOT_SUPPORT;
}
if ( rc == SCESTATUS_SUCCESS ) {
if ( NewValue == SMBSVC_NO_VALUE ) {
SmbsvcpWriteError(pSceCbInfo->pfLogInfo,
SCE_LOG_LEVEL_DEBUG,
0,
L"delelte base setting"
);
//
// delete configuration setting
//
__try {
rc = (*(pSceCbInfo->pfSetInfo))(
pSceCbInfo->sceHandle,
SceSvcConfigurationInfo,
ServiceInfo->Lines[i].Key,
TRUE,
NULL
);
} __except (EXCEPTION_EXECUTE_HANDLER) {
rc = SCESTATUS_SERVICE_NOT_SUPPORT;
}
} else {
//
// update configuration setting with NewValue
//
UpdtConfigLine.Key = ServiceInfo->Lines[i].Key;
UpdtConfigLine.Value = ServiceInfo->Lines[i].Value;
UpdtConfigLine.ValueLen = ServiceInfo->Lines[i].ValueLen;
__try {
rc = (*(pSceCbInfo->pfSetInfo))(
pSceCbInfo->sceHandle,
SceSvcConfigurationInfo,
NULL,
TRUE,
(PVOID)&UpdtConfigInfo
);
} __except (EXCEPTION_EXECUTE_HANDLER) {
rc = SCESTATUS_SERVICE_NOT_SUPPORT;
}
}
}
}
}
} else
rc = SCESTATUS_INVALID_DATA;
}
if ( pAnaInfo != NULL ) {
__try {
(*(pSceCbInfo->pfFreeInfo))((PVOID)pAnaInfo);
} __except (EXCEPTION_EXECUTE_HANDLER) {
}
}
pAnaInfo = NULL;
}
}
if ( pConfigInfo != NULL ) {
__try {
(*(pSceCbInfo->pfFreeInfo))((PVOID)pConfigInfo);
} __except (EXCEPTION_EXECUTE_HANDLER) {
}
}
pConfigInfo = NULL;
}
if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
rc = SCESTATUS_SUCCESS;
}
if ( rc != SCESTATUS_SUCCESS ) {
break;
}
}
return(rc);
}
SCESTATUS
SmbsvcpResetInfo(
IN PSMBSVC_SEC_INFO pInfo
)
/*
Routine Description:
This routine resets or initializes the buffer. All BYTE and DWORD
type fields are set to SMBSVC_NO_VALUE and all othe pointers are
set to NULL
Arguments:
pInfo - the buffer to reset.
Return Value:
SCESTATUS
*/
{
if ( pInfo == NULL ) {
return(SCESTATUS_INVALID_PARAMETER);
}
pInfo->EnableClientSecuritySignature = SMBSVC_NO_VALUE;
pInfo->RequireClientSecuritySignature = SMBSVC_NO_VALUE;
pInfo->EnablePlainTextPassword = SMBSVC_NO_VALUE;
pInfo->RequireEnhancedChallengeResponse = SMBSVC_NO_VALUE;
pInfo->SendNTResponseOnly = SMBSVC_NO_VALUE;
pInfo->EnableAutoShare = SMBSVC_NO_VALUE;
pInfo->EnableServerSecuritySignature = SMBSVC_NO_VALUE;
pInfo->RequireServerSecuritySignature = SMBSVC_NO_VALUE;
pInfo->RestrictNullSessionAccess = SMBSVC_NO_VALUE;
pInfo->EnableForcedLogOff = SMBSVC_NO_VALUE;
pInfo->AutoDisconnect = SMBSVC_NO_VALUE;
pInfo->NullSessionShares = NULL;
pInfo->LengthShares = SMBSVC_NO_VALUE;
pInfo->NullSessionPipes = NULL;
pInfo->LengthPipes = SMBSVC_NO_VALUE;
pInfo->pShares=NULL;
return(SCESTATUS_SUCCESS);
}
SCESTATUS
SmbsvcpGetInformation(
IN PSCESVC_CALLBACK_INFO pSceCbInfo,
OUT PSMBSVC_SEC_INFO pSmbInfo
)
/*
Routine Description:
This routine queries information from the storage pointed by sceHandle.
Infomration is loaded into each field in the buffer pSmbInfo. Type argument
indicates configuration information or analysis information to query.
Arguments:
pSceCbInfo - the callback info structure
Type - SceSvcConfigurationInfo or SceSvcAnalysisInfo
pSmbInfo - the buffer to hold information. Note, this buffer must be allocated
before this call
Return Value:
SCESTATUS
*/
{
if ( pSceCbInfo == NULL ||
pSceCbInfo->sceHandle == NULL ||
pSceCbInfo->pfQueryInfo == NULL ||
pSmbInfo == NULL ) {
return(SCESTATUS_INVALID_PARAMETER);
}
SCESTATUS rc;
SCE_ENUMERATION_CONTEXT EnumHandle=0;
PSCESVC_CONFIGURATION_INFO pConfigInfo=NULL;
SMBSVC_KEY_LOOKUP LookupKeys[] = {
{(PWSTR)TEXT("EnableForcedLogOff"), offsetof(struct _SMBSVC_SEC_INFO_, EnableForcedLogOff), 'B'},
{(PWSTR)TEXT("AutoDisconnect"), offsetof(struct _SMBSVC_SEC_INFO_, AutoDisconnect),'D'},
{(PWSTR)TEXT("EnableAutoShare"), offsetof(struct _SMBSVC_SEC_INFO_, EnableAutoShare), 'B'},
{(PWSTR)TEXT("EnableServerSecuritySignature"),offsetof(struct _SMBSVC_SEC_INFO_, EnableServerSecuritySignature),'B'},
{(PWSTR)TEXT("RequireServerSecuritySignature"),offsetof(struct _SMBSVC_SEC_INFO_, RequireServerSecuritySignature), 'B'},
{(PWSTR)TEXT("RestrictNullSessionAccess"), offsetof(struct _SMBSVC_SEC_INFO_, RestrictNullSessionAccess), 'B'},
{(PWSTR)TEXT("EnableClientSecuritySignature"),offsetof(struct _SMBSVC_SEC_INFO_, EnableClientSecuritySignature),'B'},
{(PWSTR)TEXT("RequireClientSecuritySignature"),offsetof(struct _SMBSVC_SEC_INFO_, RequireClientSecuritySignature), 'B'},
{(PWSTR)TEXT("EnablePlainTextPassword"), offsetof(struct _SMBSVC_SEC_INFO_, EnablePlainTextPassword), 'B'},
{(PWSTR)TEXT("RequireEnhancedChallengeResponse"),offsetof(struct _SMBSVC_SEC_INFO_, RequireEnhancedChallengeResponse),'B'},
{(PWSTR)TEXT("SendNTResponseOnly"),offsetof(struct _SMBSVC_SEC_INFO_, SendNTResponseOnly), 'B'},
{(PWSTR)TEXT("NullSessionPipes"), offsetof(struct _SMBSVC_SEC_INFO_, NullSessionPipes), 'M'},
{(PWSTR)TEXT("NullSessionShares"), offsetof(struct _SMBSVC_SEC_INFO_, NullSessionShares), 'M'}
};
DWORD cKeys = sizeof(LookupKeys) / sizeof(SMBSVC_KEY_LOOKUP);
DWORD CountReturned;
PSMBSVC_SHARES pShareList=NULL;
//
// read configuration information for smb server
//
do {
CountReturned = 0;
__try {
rc = (*(pSceCbInfo->pfQueryInfo))(
pSceCbInfo->sceHandle,
SceSvcConfigurationInfo,
NULL,
FALSE,
(PVOID *)&pConfigInfo,
&EnumHandle
);
} __except (EXCEPTION_EXECUTE_HANDLER) {
rc = SCESTATUS_SERVICE_NOT_SUPPORT;
}
if ( rc == SCESTATUS_SUCCESS && pConfigInfo != NULL &&
pConfigInfo->Count > 0 ) {
//
// got something
//
CountReturned = pConfigInfo->Count;
DWORD i, j;
PSECURITY_DESCRIPTOR pTempSD=NULL;
DWORD KeyValue, ValueLen, k;
PCHAR StrValue=NULL;
for ( i=0; i<pConfigInfo->Count; i++ ) {
if ( pConfigInfo->Lines[i].Key == NULL )
continue;
for (j=0; j<cKeys; j++) {
if ( _wcsicmp( pConfigInfo->Lines[i].Key, LookupKeys[j].KeyString) == 0 ) {
//
// find the matched string
//
switch ( LookupKeys[j].BufferType ) {
case 'B':
if ( pConfigInfo->Lines[i].Value != NULL ) {
KeyValue = _wtoi(pConfigInfo->Lines[i].Value);
*((BYTE *)pSmbInfo+LookupKeys[j].Offset) = (BYTE)KeyValue;
}
break;
case 'D':
if ( pConfigInfo->Lines[i].Value != NULL ) {
KeyValue = _wtol(pConfigInfo->Lines[i].Value);
*((DWORD *)((BYTE *)pSmbInfo+LookupKeys[j].Offset)) = KeyValue;
}
break;
case 'M':
// comma separated strings,
ValueLen = pConfigInfo->Lines[i].ValueLen;
if ( pConfigInfo->Lines[i].Value != NULL ) {
StrValue = (PCHAR)LocalAlloc(LMEM_FIXED, ValueLen + 4 );
if ( StrValue != NULL ) {
memcpy((PVOID)StrValue, (PVOID)(pConfigInfo->Lines[i].Value),
ValueLen);
//
// terminate the buffer by two L'\0's
//
*((WCHAR *)(StrValue+ValueLen)) = L'\0';
*((WCHAR *)(StrValue+ValueLen+2)) = L'\0';
/*
//
// replace ',' with '\0's
//
for ( k=0; k<ValueLen; k++ ) {
if ( StrValue[k] == ',' ) {
StrValue[k] = '\0';
}
}
*/
*((PVOID *)((BYTE *)pSmbInfo+LookupKeys[j].Offset)) = (PVOID)StrValue;
StrValue = NULL;
*((DWORD *)((BYTE *)pSmbInfo+LookupKeys[j].Offset+sizeof(PVOID))) = ValueLen;
} else {
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
}
}
break;
default:
//
// unknown type, should not occur, ignore!!!
//
break;
}
break;
}
}
if ( j >= cKeys && rc == SCESTATUS_SUCCESS ) {
//
// did not find a match for pre-defined keywords
//
if ( pConfigInfo->Lines[i].Value != NULL && pConfigInfo->Lines[i].ValueLen > 14 &&
_wcsnicmp(L"Share,", pConfigInfo->Lines[i].Value, 6) == 0 ) {
//
// shares and security
//
if ( wcslen(pConfigInfo->Lines[i].Value) > 8) {
#if defined(_NT4BACK_PORT)
DWORD SDsize;
SECURITY_INFORMATION SeInfo;
rc = SceSvcConvertTextToSD(
pConfigInfo->Lines[i].Value+8,
&pTempSD,
&SDsize,
&SeInfo
);
rc = SmbsvcpDosErrorToSceStatus(rc);
#else
if ( !ConvertStringSecurityDescriptorToSecurityDescriptor(
(PCWSTR)(pConfigInfo->Lines[i].Value+8),
SDDL_REVISION,
&pTempSD,
NULL
) ) {
rc = SmbsvcpDosErrorToSceStatus(GetLastError());
}
#endif
} else {
pTempSD = NULL;
}
DWORD Status = *(pConfigInfo->Lines[i].Value+6)-L'0';
if ( rc == SCESTATUS_SUCCESS ) {
rc = SmbsvcpAddAShareToList(&pShareList,
pConfigInfo->Lines[i].Key,
Status,
pTempSD
);
if ( rc != SCESTATUS_SUCCESS && pTempSD != NULL ) {
LocalFree(pTempSD);
}
}
if ( rc != SCESTATUS_SUCCESS && pSceCbInfo->pfLogInfo != NULL ) {
SmbsvcpWriteError2(pSceCbInfo->pfLogInfo,
SCE_LOG_LEVEL_ERROR,
SmbsvcpSceStatusToDosError(rc),
SMBSVC_ERROR_QUERY,
pConfigInfo->Lines[i]
);
}
} else if (pSceCbInfo->pfLogInfo != NULL ) {
//
// did not find a match
// warning for unknown data, but return success
//
SmbsvcpWriteError2(pSceCbInfo->pfLogInfo,
SCE_LOG_LEVEL_ERROR,
0,
SMBSVC_UNKNOWN_KEYWORD,
pConfigInfo->Lines[i].Key
);
}
} else if ( rc != SCESTATUS_SUCCESS &&
pSceCbInfo->pfLogInfo != NULL ) {
SmbsvcpWriteError2(pSceCbInfo->pfLogInfo,
SCE_LOG_LEVEL_ERROR,
SmbsvcpSceStatusToDosError(rc),
SMBSVC_ERROR_QUERY,
pConfigInfo->Lines[i]
);
}
if ( rc != SCESTATUS_SUCCESS )
break;
}
__try {
(*(pSceCbInfo->pfFreeInfo))((PVOID)pConfigInfo);
} __except (EXCEPTION_EXECUTE_HANDLER) {
}
pConfigInfo = NULL;
}
} while ( rc == SCESTATUS_SUCCESS && CountReturned >= SCESVC_ENUMERATION_MAX ); //0
if ( pShareList != NULL ) {
pSmbInfo->pShares = pShareList;
}
if ( rc != SCESTATUS_SUCCESS ) {
//
// free memory
//
SmbsvcpFree(pSmbInfo);
}
return(rc);
}
SCESTATUS
SmbsvcpAddAShareToList(
OUT PSMBSVC_SHARES *pShareList,
IN PWSTR ShareName,
IN DWORD Status,
IN PSECURITY_DESCRIPTOR pSD
)
/*
Routine Description:
This routine adds a share's information (Name, Security descriptor, and
security information) to the list of shares. Memory allocated for the
share node must be freed using LocalFree
Arguments:
pShareList - The ouput list of shares
ShareName - The name of the share
pSD - The security descriptor of the share object
Return Value:
SCESTATUS
*/
{
if ( pShareList == NULL || ShareName == NULL ) {
return(SCESTATUS_INVALID_PARAMETER);
}
PSMBSVC_SHARES pTempShare;
pTempShare = (PSMBSVC_SHARES)LocalAlloc(LMEM_FIXED, sizeof(SMBSVC_SHARES));
if ( pTempShare == NULL ) {
return(SCESTATUS_NOT_ENOUGH_RESOURCE);
} else {
SCESTATUS rc=SCESTATUS_SUCCESS;
pTempShare->ShareName = (PWSTR)LocalAlloc(LMEM_FIXED, (wcslen(ShareName)+1)*sizeof(WCHAR));
if ( pTempShare->ShareName == NULL ) {
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
} else {
wcscpy(pTempShare->ShareName, ShareName);
pTempShare->pShareSD = pSD;
pTempShare->Status = Status;
pTempShare->Next = *pShareList;
*pShareList = pTempShare;
}
if ( rc != SCESTATUS_SUCCESS ) {
LocalFree(pTempShare);
}
return(rc);
}
}
SCESTATUS
SmbsvcpFree(
IN PSMBSVC_SEC_INFO pSmbInfo
)
/*
Routine Description:
This routine frees the memory allocated for the components in the buffer.
Arguments:
pSmbInfo - the buffer to free.
Return Value:
SCESTATUS
*/
{
if ( pSmbInfo == NULL ) {
return(SCESTATUS_SUCCESS);
}
if ( pSmbInfo->NullSessionPipes != NULL ) {
LocalFree(pSmbInfo->NullSessionPipes);
}
if ( pSmbInfo->NullSessionShares != NULL ) {
LocalFree(pSmbInfo->NullSessionShares);
}
SmbsvcpFreeShareList(pSmbInfo->pShares);
return( SmbsvcpResetInfo( pSmbInfo ) );
}
SCESTATUS
SmbsvcpFreeShareList(
PSMBSVC_SHARES pShares
)
{
PSMBSVC_SHARES pTemp, pTemp2;
pTemp = pShares;
while (pTemp != NULL ) {
if ( pTemp->ShareName != NULL )
LocalFree(pTemp->ShareName);
if (pTemp->pShareSD != NULL )
LocalFree(pTemp->pShareSD);
pTemp2 = pTemp;
pTemp = pTemp->Next;
LocalFree(pTemp2);
}
return(SCESTATUS_SUCCESS);
}
SCESTATUS
SmbsvcpWriteError(
IN PFSCE_LOG_INFO pfLogCallback,
IN INT ErrLevel,
IN DWORD ErrCode,
IN PWSTR Mes
)
{
if ( Mes == NULL || pfLogCallback == NULL ) {
return(SCESTATUS_SUCCESS);
}
SCESTATUS rc;
__try {
rc = (*pfLogCallback)(ErrLevel,
ErrCode,
Mes);
} __except (EXCEPTION_EXECUTE_HANDLER) {
rc = SCESTATUS_SERVICE_NOT_SUPPORT;
}
return(rc);
}
SCESTATUS
SmbsvcpWriteError2(
IN PFSCE_LOG_INFO pfLogCallback,
IN INT ErrLevel,
IN DWORD ErrCode,
IN UINT nId,
...
)
{
WCHAR szTempString[256];
TCHAR buf[SMBSVC_BUF_LEN];
va_list args;
if ( nId > 0 && pfLogCallback ) {
szTempString[0] = L'\0';
if ( MyModuleHandle != NULL ) {
LoadString( MyModuleHandle,
nId,
szTempString,
256
);
}
//
// check arguments
//
va_start( args, nId );
vswprintf( buf, szTempString, args );
va_end( args );
return ( SmbsvcpWriteError(pfLogCallback,
ErrLevel,
ErrCode,
buf) );
}
return(SCESTATUS_SUCCESS);
}
SCESTATUS
SmbsvcpConfigureValue(
IN PCWSTR RegKey,
IN PCWSTR ValueName,
IN DWORD Value
)
{
if ( Value == (DWORD)SMBSVC_NO_VALUE ||
(BYTE)Value == (BYTE)SMBSVC_NO_VALUE ) {
return(SCESTATUS_SUCCESS);
}
DWORD Win32rc;
Win32rc = SmbsvcpRegSetIntValue(
HKEY_LOCAL_MACHINE,
(PWSTR)RegKey,
(PWSTR)ValueName,
Value
);
return(SmbsvcpDosErrorToSceStatus(Win32rc));
}
SCESTATUS
SmbsvcpQueryShareList(
OUT PSMBSVC_SHARES *pShareList,
OUT PDWORD ShareCount
)
{
if ( pShareList == NULL || ShareCount == NULL ) {
return(SCESTATUS_INVALID_PARAMETER);
}
LPSHARE_INFO_502 pShareInfo=NULL;
DWORD EntriesRead, TotalEntries, ResumeHandle=0;
SCESTATUS rc=SCESTATUS_SUCCESS;
DWORD Win32rc;
DWORD nCount=0;
*ShareCount = 0;
do {
Win32rc = NetShareEnum (
NULL,
502,
(LPBYTE *)&pShareInfo,
0xFFFFFFFF,
&EntriesRead,
&TotalEntries,
&ResumeHandle
);
if ( Win32rc == ERROR_SUCCESS ) {
nCount += EntriesRead;
for( DWORD i=0; i < EntriesRead; i++ ) {
if( (pShareInfo + i)->shi502_type == STYPE_DISKTREE )
{
PSECURITY_DESCRIPTOR pSD=NULL;
if ( (pShareInfo + i)->shi502_security_descriptor != NULL ) {
NTSTATUS status;
DWORD RequireLength=0;
status = RtlMakeSelfRelativeSD(
(pShareInfo + i)->shi502_security_descriptor,
NULL,
&RequireLength
);
if ( status == STATUS_BUFFER_TOO_SMALL ) {
pSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LMEM_FIXED, RequireLength+1);
status = RtlMakeSelfRelativeSD(
(pShareInfo + i)->shi502_security_descriptor,
pSD,
&RequireLength
);
}
rc = SmbsvcpDosErrorToSceStatus(RtlNtStatusToDosError(status));
}
if ( rc == SCESTATUS_SUCCESS ) {
rc = SmbsvcpAddAShareToList(pShareList,
(pShareInfo + i)->shi502_netname,
0,
pSD
);
if ( rc == SCESTATUS_SUCCESS ) {
(*ShareCount)++;
} else if ( pSD != NULL ) {
LocalFree(pSD);
pSD = NULL;
}
}
if ( rc != SCESTATUS_SUCCESS ) {
break;
}
}
}
//
// free the buffer
//
NetApiBufferFree(pShareInfo);
pShareInfo = NULL;
} else
rc = SmbsvcpDosErrorToSceStatus(Win32rc);
} while ( rc == SCESTATUS_SUCCESS && nCount < TotalEntries );
if ( rc != SCESTATUS_SUCCESS && *pShareList != NULL ) {
SmbsvcpFreeShareList(*pShareList);
*pShareList = NULL;
*ShareCount = 0;
}
return(rc);
}
SCESTATUS
SmbsvcpAnalyzeValue(
IN PCWSTR RegKey,
IN PCWSTR RegValueName,
IN PCWSTR KeyName,
IN DWORD ConfigValue,
OUT PSCESVC_ANALYSIS_LINE pLineInfo,
IN OUT PDWORD pCount
)
{
if ( RegKey == NULL || RegValueName == NULL ||
KeyName == NULL || pLineInfo == NULL || pCount == NULL ) {
return(SCESTATUS_INVALID_PARAMETER);
}
if ( ConfigValue == (DWORD)SMBSVC_NO_VALUE ||
(BYTE)ConfigValue == (BYTE)SMBSVC_NO_VALUE ) {
return(SCESTATUS_SUCCESS);
}
//
// query the registry value
//
DWORD Value=0;
DWORD Win32rc = SmbsvcpRegQueryIntValue(
HKEY_LOCAL_MACHINE,
(PWSTR)RegKey,
(PWSTR)RegValueName,
&Value
);
if ( Win32rc == ERROR_SUCCESS || Win32rc == ERROR_FILE_NOT_FOUND ) {
Win32rc = ERROR_SUCCESS;
if ( ConfigValue != Value ) {
//
// mismatched
//
PWSTR Key, StrValue;
DWORD ValueLen;
//
// allocate buffer for key and value
//
Key = (PWSTR)LocalAlloc(LMEM_FIXED, (wcslen(KeyName)+1)*sizeof(WCHAR));
if ( Key != NULL ) {
WCHAR TempBuf[16];
memset(TempBuf, '\0', 32);
swprintf(TempBuf, L"%d", Value);
DWORD Len = wcslen(TempBuf);
StrValue = (PWSTR)LocalAlloc(LMEM_FIXED, (Len+1)*sizeof(WCHAR));
if ( StrValue != NULL ) {
//
// assign to the line buffer and increment the count
//
wcsncpy(StrValue, TempBuf, Len);
StrValue[Len] = L'\0';
wcscpy(Key, KeyName);
pLineInfo->Key = Key;
pLineInfo->Value = (PBYTE)StrValue;
pLineInfo->ValueLen = Len*sizeof(WCHAR);
(*pCount)++;
} else {
Win32rc = ERROR_NOT_ENOUGH_MEMORY;
LocalFree(Key);
}
} else
Win32rc = ERROR_NOT_ENOUGH_MEMORY;
}
}
return(SmbsvcpDosErrorToSceStatus(Win32rc));
}
DWORD
SmbsvcpConvertStringToMultiSz(
IN PWSTR theStr,
IN DWORD theLen,
OUT PBYTE *outValue,
OUT PDWORD outLen
)
{
if ( outValue == NULL || outLen == NULL ) {
return(ERROR_INVALID_PARAMETER);
}
*outValue = NULL;
*outLen = 0;
if ( theStr == NULL || theLen == 0 || theLen == SMBSVC_NO_VALUE ) {
return ERROR_SUCCESS;
}
*outValue = (PBYTE)LocalAlloc(0, theLen+4);
if ( *outValue != NULL ) {
wcscpy((PWSTR)(*outValue), theStr);
// terminate the last w-char with 0 for Multi-Sz format
*((PWSTR)(*outValue+theLen+2)) = L'\0';
// replace ',' with '\0'
PWSTR pTemp = (PWSTR)(*outValue);
while ( pTemp != NULL ) {
pTemp = wcschr(pTemp, L',');
if ( pTemp != NULL ) {
*pTemp = L'\0';
pTemp++;
}
}
return ERROR_SUCCESS;
} else
return ERROR_NOT_ENOUGH_MEMORY;
}
SCESTATUS
SmbsvcpAnalyzeMultiSzString(
IN PCWSTR RegKey,
IN PCWSTR RegValueName,
IN PWSTR pConfigInfo,
IN DWORD InfoLength,
OUT PSCESVC_ANALYSIS_LINE pLineInfo,
IN OUT PDWORD pCount
)
{
if ( RegKey == NULL || RegValueName == NULL ||
pLineInfo == NULL || pCount == NULL ) {
return(SCESTATUS_INVALID_PARAMETER);
}
if ( InfoLength == SMBSVC_NO_VALUE ) {
// do not configure
return(SCESTATUS_SUCCESS);
}
//
// query the registry value
//
DWORD RegType;
PWSTR Value=NULL;
DWORD Win32rc = SmbsvcpRegQueryValue(
HKEY_LOCAL_MACHINE,
(PWSTR)RegKey,
(PWSTR)RegValueName,
(PVOID *)&Value,
&RegType
);
if ( Win32rc == ERROR_SUCCESS || Win32rc == ERROR_FILE_NOT_FOUND ) {
BOOL Diff;
DWORD ValueLen;
//
// change multi-sz to comma separated strings IN PLACE
//
SmbsvcpChangeMultiSzToString(Value);
Win32rc = SmbsvcpCompareMultiSzString(pConfigInfo, Value, &ValueLen, &Diff);
if (Win32rc == ERROR_SUCCESS && Diff ) {
//
// mismatched
//
PWSTR Key;
//
// allocate buffer for key and value
//
Key = (PWSTR)LocalAlloc(LMEM_FIXED, (wcslen(RegValueName)+1)*sizeof(WCHAR));
if ( Key != NULL ) {
//
// assign to the line buffer and increment the count
//
wcscpy(Key, RegValueName);
pLineInfo->Key = Key;
pLineInfo->Value = (PBYTE)Value;
pLineInfo->ValueLen = ValueLen*sizeof(WCHAR);
(*pCount)++;
Value = NULL;
} else
Win32rc = ERROR_NOT_ENOUGH_MEMORY;
}
//
// free Value is not NULL
//
if ( Value != NULL ) {
LocalFree(Value);
}
}
return(SmbsvcpDosErrorToSceStatus(Win32rc));
}
DWORD
SmbsvcpChangeMultiSzToString(
IN PWSTR Value
)
{
if ( Value == NULL )
return ERROR_SUCCESS;
//
// replace '\0' with ','s
//
PWSTR pTemp=Value;
while ( pTemp ) {
if ( *pTemp == L'\0' ) {
if ( *(pTemp+1) != L'\0' )
*pTemp = L',';
else
break;
}
pTemp++;
}
return ERROR_SUCCESS;
}
DWORD
SmbsvcpCompareMultiSzString(
IN PWSTR pConfigInfo,
IN PWSTR Value,
OUT PDWORD pValueLen,
OUT PBOOL pDiff
)
{
if ( pDiff == NULL || pValueLen == NULL ) {
return(ERROR_INVALID_PARAMETER);
}
*pDiff = FALSE;
*pValueLen = 0;
if ( pConfigInfo == NULL && Value == NULL ) {
return(ERROR_SUCCESS);
}
if ( (pConfigInfo == NULL && Value != NULL) ||
(pConfigInfo != NULL && Value == NULL) ) {
*pDiff = TRUE;
return ERROR_SUCCESS;
}
DWORD CountValue=0, ValueLen=0;
DWORD ConfigLen=0, CountConfig=0;
DWORD Win32rc;
Win32rc = SmbsvcpCountComponents(Value, &ValueLen, &CountValue);
//
// both pConfigInfo and Value are not NULL
//
if ( Win32rc == ERROR_SUCCESS ) {
*pValueLen = ValueLen;
Win32rc = SmbsvcpCountComponents(pConfigInfo, &ConfigLen, &CountConfig);
}
if ( Win32rc == ERROR_SUCCESS ) {
if ( ConfigLen != ValueLen ||
CountConfig != CountValue ) {
*pDiff = TRUE;
return(Win32rc);
}
if ( CountConfig == 0 ) {
//
// No component, return FALSE for *pDiff
//
return(Win32rc);
}
//
// both value are not empty, have the same count and same length
// build the pointers into array to compare
//
PWSTR *ConfigPtr;
PWSTR *ValuePtr;
ConfigPtr = (PWSTR *)LocalAlloc(LMEM_FIXED, CountConfig*sizeof(PWSTR));
if ( ConfigPtr != NULL ) {
ValuePtr = (PWSTR *)LocalAlloc(LMEM_FIXED, CountValue*2*sizeof(PWSTR));
if ( ValuePtr != NULL ) {
PWSTR pTemp = (PWSTR)pConfigInfo;
DWORD i = 0;
//
// build the pointers from pConfigInfo into ConfigPtr
//
do {
ConfigPtr[i++] = pTemp;
pTemp = wcschr(pTemp, L',');
if ( pTemp != NULL ) {
pTemp++;
}
} while ( pTemp != NULL );
pTemp = (PWSTR)Value;
i = 0;
//
// build the pointers from Value into ValuePtr
//
do {
ValuePtr[i++] = pTemp;
pTemp = wcschr(pTemp, L',');
if ( pTemp != NULL ) {
ValuePtr[i] = (PWSTR)((DWORD_PTR)pTemp-(DWORD_PTR)(ValuePtr[i-1]));
i++;
pTemp++;
} else {
ValuePtr[i] = (PWSTR)(wcslen(ValuePtr[i-1]));
i++;
}
} while ( pTemp != NULL );
DWORD j, nLen;
//
// compare two pointer arrays. if a match is found, the pointer element is set to NULL
// so next time it won't be compared again.
//
for ( i=0; i<CountConfig; i++ ) {
if ( i == CountConfig-1 )
// the last one
nLen = wcslen(ConfigPtr[i]);
else
nLen = (DWORD)(ConfigPtr[i+1]-ConfigPtr[i]-1);
for ( j=0; j<CountValue*2; j+=2) {
if ( ValuePtr[j] != NULL ) {
if ( (DWORD_PTR)(ValuePtr[j+1]) == nLen &&
_wcsnicmp(ConfigPtr[i], ValuePtr[j], nLen) == 0 ) {
ValuePtr[j] = NULL;
break;
}
}
}
if ( j >= CountValue*2 ) {
//
// did not find a match
//
*pDiff = TRUE;
break;
}
}
for ( j=0; j < CountValue*2; j+=2 ) {
if ( ValuePtr[j] != NULL ) {
*pDiff = TRUE;
break;
}
}
LocalFree(ValuePtr);
} else
Win32rc = ERROR_NOT_ENOUGH_MEMORY;
LocalFree(ConfigPtr);
} else
Win32rc = ERROR_NOT_ENOUGH_MEMORY;
}
return(Win32rc);
}
DWORD
SmbsvcpCountComponents(
IN PWSTR Value,
OUT PDWORD ValueLen,
OUT PDWORD Count
)
{
if ( ValueLen == NULL ||
Count == NULL ) {
return(ERROR_INVALID_PARAMETER);
}
if ( Value == NULL ) {
*ValueLen = 0;
*Count = 0;
return(ERROR_SUCCESS);
}
PWSTR pTemp = (PWSTR)Value;
DWORD Len = 0;
*Count = 0;
*ValueLen = wcslen(pTemp);
do {
(*Count)++;
pTemp = wcschr(pTemp, L',');
if ( pTemp != NULL ) {
pTemp++;
}
} while ( pTemp != NULL );
return(ERROR_SUCCESS);
}
SCESTATUS
SmbsvcpUpdateMultiSzString(
IN PSCESVC_CALLBACK_INFO pSceCbInfo,
IN SCESVC_CONFIGURATION_LINE NewLine,
IN PSCESVC_CONFIGURATION_INFO pConfigInfo OPTIONAL,
IN PSCESVC_ANALYSIS_INFO pAnaInfo OPTIONAL
)
{
//
// the value in the structure is Multi-Sz
//
if ( pSceCbInfo == NULL ||
pSceCbInfo->sceHandle == NULL ||
pSceCbInfo->pfSetInfo == NULL ) {
return(SCESTATUS_INVALID_PARAMETER);
}
SCESTATUS rc=SCESTATUS_SUCCESS;
DWORD Win32rc;
BOOL bDiff, bDiff2;
DWORD ValueLen;
//
// prepare an update buffer
//
SCESVC_ANALYSIS_INFO UpdtAnaInfo;
SCESVC_ANALYSIS_LINE UpdtAnaLine;
UpdtAnaInfo.Count = 1;
UpdtAnaInfo.Lines = &UpdtAnaLine;
SCESVC_CONFIGURATION_INFO UpdtConfigInfo;
SCESVC_CONFIGURATION_LINE UpdtConfigLine;
UpdtConfigInfo.Count = 1;
UpdtConfigInfo.Lines = &UpdtConfigLine;
if ( pAnaInfo == NULL ) {
//
// old status is match, or new added configuration key
//
if ( pConfigInfo != NULL && pConfigInfo->Lines != NULL ) {
// match item
Win32rc = SmbsvcpCompareMultiSzString(
NewLine.Value,
pConfigInfo->Lines[0].Value,
&ValueLen,
&bDiff
);
if ( Win32rc != ERROR_SUCCESS ) {
return(SmbsvcpDosErrorToSceStatus(Win32rc));
}
} else {
// new add
bDiff = TRUE;
ValueLen = 0;
}
if ( bDiff ) {
SmbsvcpWriteError(pSceCbInfo->pfLogInfo,
SCE_LOG_LEVEL_DEBUG,
0,
L"match->mismatch"
);
//
// mismatch should be raised with ConfigValue
//
UpdtAnaLine.Key = NewLine.Key;
UpdtAnaLine.Value = ( pConfigInfo != NULL ) ? (PBYTE)(pConfigInfo->Lines[0].Value) : NULL;
UpdtAnaLine.ValueLen = ( pConfigInfo != NULL ) ? pConfigInfo->Lines[0].ValueLen : 0;
__try {
rc = (*(pSceCbInfo->pfSetInfo))(
pSceCbInfo->sceHandle,
SceSvcAnalysisInfo,
NULL,
TRUE,
(PVOID)&UpdtAnaInfo
);
} __except (EXCEPTION_EXECUTE_HANDLER) {
rc = SCESTATUS_SERVICE_NOT_SUPPORT;
}
if ( rc == SCESTATUS_SUCCESS ) {
//
// update configuration setting with NewValue
//
UpdtConfigLine.Key = NewLine.Key;
UpdtConfigLine.Value = NewLine.Value;
UpdtConfigLine.ValueLen = NewLine.ValueLen;
__try {
rc = (*(pSceCbInfo->pfSetInfo))(
pSceCbInfo->sceHandle,
SceSvcConfigurationInfo,
NULL,
TRUE,
(PVOID)&UpdtConfigInfo
);
} __except (EXCEPTION_EXECUTE_HANDLER) {
rc = SCESTATUS_SERVICE_NOT_SUPPORT;
}
}
}
} else {
//
// old status is mismatch for this item
//
Win32rc = SmbsvcpCompareMultiSzString(
NewLine.Value,
(PWSTR)(pAnaInfo->Lines[0].Value),
&ValueLen,
&bDiff
);
if ( Win32rc == ERROR_SUCCESS ) {
if (pConfigInfo != NULL && pConfigInfo->Lines != NULL ) {
Win32rc = SmbsvcpCompareMultiSzString(
NewLine.Value,
pConfigInfo->Lines[0].Value,
&ValueLen,
&bDiff2
);
} else {
bDiff2 = TRUE;
ValueLen = 0;
}
}
if ( Win32rc != ERROR_SUCCESS ) {
return(SmbsvcpDosErrorToSceStatus(Win32rc));
}
if ( !bDiff ) {
SmbsvcpWriteError(pSceCbInfo->pfLogInfo,
SCE_LOG_LEVEL_DEBUG,
0,
L"mismatch->match"
);
//
// now it is matched, delete the analysis entry
//
__try {
rc = (*(pSceCbInfo->pfSetInfo))(
pSceCbInfo->sceHandle,
SceSvcAnalysisInfo,
NewLine.Key,
TRUE,
NULL
);
} __except (EXCEPTION_EXECUTE_HANDLER) {
rc = SCESTATUS_SERVICE_NOT_SUPPORT;
}
}
if ( bDiff2 ) {
//
// update the configuration setting
//
UpdtConfigLine.Key = NewLine.Key;
UpdtConfigLine.Value = NewLine.Value;
UpdtConfigLine.ValueLen = NewLine.ValueLen;
__try {
rc = (*(pSceCbInfo->pfSetInfo))(
pSceCbInfo->sceHandle,
SceSvcConfigurationInfo,
NULL,
TRUE,
(PVOID)&UpdtConfigInfo
);
} __except (EXCEPTION_EXECUTE_HANDLER) {
rc = SCESTATUS_SERVICE_NOT_SUPPORT;
}
}
}
return(rc);
}
SCESTATUS
SmbsvcpUpdateShareValue(
IN PSCESVC_CALLBACK_INFO pSceCbInfo,
IN SCESVC_CONFIGURATION_LINE NewLine,
IN PSCESVC_CONFIGURATION_INFO pConfigInfo OPTIONAL,
IN PSCESVC_ANALYSIS_INFO pAnaInfo OPTIONAL
)
{
//
// the value in the structure is "Share," followed by a security descriptor text
//
if ( pSceCbInfo == NULL ||
pSceCbInfo->sceHandle == NULL ||
pSceCbInfo->pfSetInfo == NULL ) {
return(SCESTATUS_INVALID_PARAMETER);
}
SCESTATUS rc=SCESTATUS_SUCCESS;
//
// prepare an update buffer
//
SCESVC_ANALYSIS_INFO UpdtAnaInfo;
SCESVC_ANALYSIS_LINE UpdtAnaLine;
UpdtAnaInfo.Count = 1;
UpdtAnaInfo.Lines = &UpdtAnaLine;
SCESVC_CONFIGURATION_INFO UpdtConfigInfo;
SCESVC_CONFIGURATION_LINE UpdtConfigLine;
UpdtConfigInfo.Count = 1;
UpdtConfigInfo.Lines = &UpdtConfigLine;
PSECURITY_DESCRIPTOR pSD1=NULL, pSD2=NULL;
DWORD SDsize;
BOOL bEqual;
if ( pAnaInfo == NULL ) {
//
// old status is match, or a new added share
//
if ( pConfigInfo == NULL ) {
//
// a new share, query the current setting in the system
//
PSHARE_INFO_1501 ShareInfo=NULL;
DWORD Win32rc;
Win32rc = NetShareGetInfo (
NULL,
NewLine.Key,
1501,
(LPBYTE *)&ShareInfo
);
if ( Win32rc == ERROR_SUCCESS ) {
PWSTR TextSD=NULL;
DWORD SDsize=0;
if ( ShareInfo->shi1501_security_descriptor != NULL ) {
#if defined(_NT4BACK_PORT)
rc = SceSvcConvertSDToText(
ShareInfo->shi1501_security_descriptor,
DACL_SECURITY_INFORMATION,
&TextSD,
&SDsize
);
rc = SmbsvcpDosErrorToSceStatus(rc);
#else
if ( !ConvertSecurityDescriptorToStringSecurityDescriptor(
ShareInfo->shi1501_security_descriptor,
SDDL_REVISION,
DACL_SECURITY_INFORMATION,
&TextSD,
&SDsize
) ) {
rc = SmbsvcpDosErrorToSceStatus(GetLastError());
} else {
rc = SCESTATUS_SUCCESS;
}
#endif
}
if ( rc == SCESTATUS_SUCCESS ) {
PWSTR Value;
Value = (PWSTR)LocalAlloc(LMEM_FIXED, (SDsize+9)*sizeof(WCHAR));
if ( Value != NULL ) {
if ( TextSD != NULL )
swprintf(Value, L"Share,%1d,%s", SMBSVC_STATUS_NOT_CONFIGURED, TextSD );
else
swprintf(Value, L"Share,%1d,",SMBSVC_STATUS_NOT_CONFIGURED);
Value[SDsize+8] = L'\0';
UpdtAnaLine.Key = NewLine.Key;
UpdtAnaLine.Value = (PBYTE)Value;
UpdtAnaLine.ValueLen = (SDsize+8)*sizeof(WCHAR);
__try {
rc = (*(pSceCbInfo->pfSetInfo))(
pSceCbInfo->sceHandle,
SceSvcAnalysisInfo,
NULL,
TRUE,
(PVOID)&UpdtAnaInfo
);
} __except (EXCEPTION_EXECUTE_HANDLER) {
rc = SCESTATUS_SERVICE_NOT_SUPPORT;
}
LocalFree(Value);
} else
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
}
NetApiBufferFree(ShareInfo);
} else
rc = SmbsvcpDosErrorToSceStatus(Win32rc);
} else {
//
// matched item.
//
bEqual = FALSE;
SECURITY_INFORMATION SeInfo;
if ( NewLine.ValueLen > 14 &&
NewLine.Value != NULL &&
NewLine.Value[8] != L'\0' ) {
#if defined(_NT4BACK_PORT)
rc = SceSvcConvertTextToSD(
NewLine.Value+8,
&pSD1,
&SDsize,
&SeInfo
);
rc = SmbsvcpDosErrorToSceStatus(rc);
#else
if ( !ConvertStringSecurityDescriptorToSecurityDescriptor(
(PCWSTR)(NewLine.Value+8),
SDDL_REVISION,
&pSD1,
NULL
) ) {
rc = SmbsvcpDosErrorToSceStatus(GetLastError());
} else {
rc = SCESTATUS_SUCCESS;
}
#endif
}
if ( rc == SCESTATUS_SUCCESS && pConfigInfo->Lines != NULL &&
pConfigInfo->Lines[0].ValueLen > 14 &&
pConfigInfo->Lines[0].Value != NULL &&
pConfigInfo->Lines[0].Value[8] != L'\0' ) {
#if defined(_NT4BACK_PORT)
rc = SceSvcConvertTextToSD(
pConfigInfo->Lines[0].Value+8,
&pSD2,
&SDsize,
&SeInfo
);
rc = SmbsvcpDosErrorToSceStatus(rc);
#else
if ( !ConvertStringSecurityDescriptorToSecurityDescriptor(
(PCWSTR)(pConfigInfo->Lines[0].Value+8),
SDDL_REVISION,
&pSD2,
NULL
) ) {
rc = SmbsvcpDosErrorToSceStatus(GetLastError());
}
#endif
}
if ( rc == SCESTATUS_SUCCESS ) {
rc = SmbsvcpEqualSecurityDescriptor(
pSD1,
pSD2,
FALSE,
&bEqual
);
}
if ( rc == SCESTATUS_SUCCESS && !bEqual ) {
SmbsvcpWriteError(pSceCbInfo->pfLogInfo,
SCE_LOG_LEVEL_DEBUG,
0,
L"match->mismatch"
);
//
// mismatch should be raised with ConfigValue
//
UpdtAnaLine.Key = NewLine.Key;
UpdtAnaLine.Value = (PBYTE)(pConfigInfo->Lines[0].Value);
UpdtAnaLine.ValueLen = pConfigInfo->Lines[0].ValueLen;
__try {
rc = (*(pSceCbInfo->pfSetInfo))(
pSceCbInfo->sceHandle,
SceSvcAnalysisInfo,
NULL,
TRUE,
(PVOID)&UpdtAnaInfo
);
} __except (EXCEPTION_EXECUTE_HANDLER) {
rc = SCESTATUS_SERVICE_NOT_SUPPORT;
}
}
}
if ( rc == SCESTATUS_SUCCESS ) {
//
// update configuration setting with NewValue
//
UpdtConfigLine.Key = NewLine.Key;
UpdtConfigLine.Value = NewLine.Value;
UpdtConfigLine.ValueLen = NewLine.ValueLen;
__try {
rc = (*(pSceCbInfo->pfSetInfo))(
pSceCbInfo->sceHandle,
SceSvcConfigurationInfo,
NULL,
TRUE,
(PVOID)&UpdtConfigInfo
);
} __except (EXCEPTION_EXECUTE_HANDLER) {
rc = SCESTATUS_SERVICE_NOT_SUPPORT;
}
}
} else {
//
// old status is mismatch for this item
//
bEqual = FALSE;
if ( NewLine.ValueLen > 14 &&
NewLine.Value != NULL &&
NewLine.Value[8] != L'\0' ) {
#if defined(_NT4BACK_PORT)
SECURITY_INFORMATION SeInfo;
rc = SceSvcConvertTextToSD(
NewLine.Value+8,
&pSD1,
&SDsize,
&SeInfo
);
rc = SmbsvcpDosErrorToSceStatus(rc);
#else
if ( !ConvertStringSecurityDescriptorToSecurityDescriptor(
(PCWSTR)(NewLine.Value+8),
SDDL_REVISION,
&pSD1,
NULL
) ) {
rc = SmbsvcpDosErrorToSceStatus(GetLastError());
} else {
rc = SCESTATUS_SUCCESS;
}
#endif
}
if ( rc == SCESTATUS_SUCCESS && pAnaInfo->Lines != NULL &&
pAnaInfo->Lines[0].ValueLen > 14 &&
pAnaInfo->Lines[0].Value != NULL &&
((PWSTR)(pAnaInfo->Lines[0].Value))[8] != L'\0' ) {
#if defined(_NT4BACK_PORT)
SECURITY_INFORMATION SeInfo;
rc = SceSvcConvertTextToSD(
(PWSTR)(pAnaInfo->Lines[0].Value+8),
&pSD2,
&SDsize,
&SeInfo
);
rc = SmbsvcpDosErrorToSceStatus(rc);
#else
if ( !ConvertStringSecurityDescriptorToSecurityDescriptor(
(PCWSTR)(pAnaInfo->Lines[0].Value+8),
SDDL_REVISION,
&pSD2,
NULL
) ) {
rc = SmbsvcpDosErrorToSceStatus(GetLastError());
} else {
rc = SCESTATUS_SUCCESS;
}
#endif
}
if ( rc == SCESTATUS_SUCCESS ) {
rc = SmbsvcpEqualSecurityDescriptor(
pSD1,
pSD2,
FALSE,
&bEqual
);
}
if ( rc == SCESTATUS_SUCCESS && bEqual ) {
SmbsvcpWriteError(pSceCbInfo->pfLogInfo,
SCE_LOG_LEVEL_DEBUG,
0,
L"mismatch->match"
);
//
// now it is matched, delete the analysis entry
//
__try {
rc = (*(pSceCbInfo->pfSetInfo))(
pSceCbInfo->sceHandle,
SceSvcAnalysisInfo,
NewLine.Key,
TRUE,
NULL
);
} __except (EXCEPTION_EXECUTE_HANDLER) {
rc = SCESTATUS_SERVICE_NOT_SUPPORT;
}
}
if ( rc == SCESTATUS_SUCCESS ) {
//
// update the configuration setting
//
UpdtConfigLine.Key = NewLine.Key;
UpdtConfigLine.Value = NewLine.Value;
UpdtConfigLine.ValueLen = NewLine.ValueLen;
__try {
rc = (*(pSceCbInfo->pfSetInfo))(
pSceCbInfo->sceHandle,
SceSvcConfigurationInfo,
NULL,
TRUE,
(PVOID)&UpdtConfigInfo
);
} __except (EXCEPTION_EXECUTE_HANDLER) {
rc = SCESTATUS_SERVICE_NOT_SUPPORT;
}
}
}
if ( pSD1 != NULL ) {
LocalFree(pSD1);
}
if ( pSD2 != NULL ) {
LocalFree(pSD2);
}
return(rc);
}
SCESTATUS
SmbsvcpEqualSecurityDescriptor(
IN PSECURITY_DESCRIPTOR pSD1,
IN PSECURITY_DESCRIPTOR pSD2,
IN BOOL bExplicitOnly,
OUT PBOOL pbEqual
)
{
if ( pbEqual == NULL ) {
return(SCESTATUS_INVALID_PARAMETER);
}
*pbEqual = TRUE;
if ( pSD1 == NULL && pSD2 == NULL )
return(SCESTATUS_SUCCESS);
BOOLEAN aclPresent, tFlag;
PACL pAcl1=NULL, pAcl2=NULL;
//
// get the DACL in each SD
//
if ( pSD1 == NULL ||
!NT_SUCCESS( RtlGetDaclSecurityDescriptor(
pSD1,
&aclPresent,
&pAcl1,
&tFlag)
) ) {
pAcl1 = NULL;
} else if ( !aclPresent )
pAcl1 = NULL;
if ( pSD2 == NULL ||
!NT_SUCCESS( RtlGetDaclSecurityDescriptor(
pSD2,
&aclPresent,
&pAcl2,
&tFlag)
) ) {
pAcl2 = NULL;
} else if ( !aclPresent )
pAcl2 = NULL;
//
// NOTE:
// if SD is NULL, it is Everyone Full Control
//
if ( pSD1 == NULL ) {
//
// check if pAcl2 has only Everyone Full Access
//
return( SmbsvcpDosErrorToSceStatus(
SmbsvcEveryoneFullAccess(pAcl2, bExplicitOnly, pbEqual) ));
}
if ( pSD2 == NULL ) {
//
// check if pAcl1 has only Everyone Full Access
//
return(SmbsvcpDosErrorToSceStatus(
SmbsvcEveryoneFullAccess(pAcl1, bExplicitOnly, pbEqual) ));
}
if ( pAcl1 == NULL && pAcl2 == NULL ) {
return(SCESTATUS_SUCCESS);
}
// if DACL is NULL, it is deny everyone access
if ( !bExplicitOnly) {
//
// if all aces are checked, they are different when one is NULL
//
if ( (pAcl1 == NULL && pAcl2 != NULL) ||
(pAcl1 != NULL && pAcl2 == NULL) ) {
*pbEqual = FALSE;
return(SCESTATUS_SUCCESS);
}
}
//
// compare two ACLs
//
BOOL bDifferent = FALSE;
DWORD rc;
rc = SmbsvcpCompareAcl( pAcl1, pAcl2, bExplicitOnly, &bDifferent );
if ( rc == ERROR_SUCCESS ) {
if (bDifferent )
*pbEqual = FALSE;
} else
*pbEqual = FALSE;
return(SmbsvcpDosErrorToSceStatus(rc));
}
DWORD
SmbsvcEveryoneFullAccess(
IN PACL pAcl,
IN BOOL bExplicit,
OUT PBOOL pbEqual
)
{
if ( pbEqual == NULL ) {
return(ERROR_INVALID_PARAMETER);
}
*pbEqual = FALSE;
if ( pAcl == NULL ) {
return(ERROR_SUCCESS);
}
NTSTATUS NtStatus;
PSID pSidEveryone=NULL;
SID_IDENTIFIER_AUTHORITY IdentifierAuthority=SECURITY_WORLD_SID_AUTHORITY;
//
// build everyone sid
//
pSidEveryone = (PSID) LocalAlloc(LMEM_FIXED, RtlLengthRequiredSid(1));
if (NULL == pSidEveryone )
return(ERROR_NOT_ENOUGH_MEMORY);
NtStatus = RtlInitializeSid(pSidEveryone, &IdentifierAuthority, (UCHAR)1);
if ( !NT_SUCCESS(NtStatus) ) {
LocalFree(pSidEveryone);
return(RtlNtStatusToDosError(NtStatus));
}
*(RtlSubAuthoritySid(pSidEveryone, 0)) = SECURITY_WORLD_RID;
ACE_HEADER *pAce=NULL;
PSID pSid;
ACCESS_MASK Access;
DWORD nAceCount, j;
for ( j=0, nAceCount=0; j<pAcl->AceCount; j++ ) {
NtStatus = RtlGetAce(pAcl, j, (PVOID *)&pAce);
if ( !NT_SUCCESS(NtStatus) )
break;
if ( pAce == NULL )
continue;
if ( bExplicit && (pAce->AceFlags & INHERITED_ACE) ) {
//
// find a inherit Ace in Acl
//
continue;
}
nAceCount++;
if ( nAceCount == 1 && pAce->AceType == ACCESS_ALLOWED_ACE_TYPE ) {
pSid = (PSID)&((PACCESS_ALLOWED_ACE)pAce)->SidStart;
Access = ((PACCESS_ALLOWED_ACE)pAce)->Mask;
if ( pSid != NULL ) {
if ( Access == FILE_ALL_ACCESS || Access == GENERIC_ALL ) {
if ( EqualSid(pSid, pSidEveryone) )
*pbEqual = TRUE;
}
}
}
if ( !*pbEqual)
break;
if ( nAceCount > 1 ) { // should only allow one ace
*pbEqual = FALSE;
break;
}
}
LocalFree(pSidEveryone);
return(RtlNtStatusToDosError(NtStatus));
}
DWORD
SmbsvcpCompareAcl(
IN PACL pAcl1,
IN PACL pAcl2,
IN BOOL bExplicitOnly,
OUT PBOOL pDifferent
)
/*
Routine Description:
This routine compares explicit aces of two ACLs for exact match. Exact
match means: same access type, same inheritance flag, same access mask,
same GUID/Object GUID (if available), and same SID.
Inherited aces (INHERITED_ACE is set) are ignored.
Arguments:
pAcl1 - The first ACL
pAcl2 - The 2nd ACL
pDifferent - The output flag to indicate different
Return Value:
Win32 error codes
*/
{
NTSTATUS NtStatus=STATUS_SUCCESS;
DWORD i, j;
ACE_HEADER *pAce1=NULL;
ACE_HEADER *pAce2=NULL;
DWORD ProcessAce=0;
*pDifferent = FALSE;
//
// if pAcl1 is NULL, pAcl2 should have 0 explicit Ace
//
if ( pAcl1 == NULL ) {
return( SmbsvcpAnyExplicitAcl( pAcl2, 0, pDifferent ) );
}
//
// if pAcl2 is NULL, pAcl1 should have 0 explicit Ace
//
if ( pAcl2 == NULL ) {
return( SmbsvcpAnyExplicitAcl( pAcl1, 0, pDifferent ) );
}
//
// both ACLs are not NULL
// BUGBUG: note there is a limit of AceCount because of DWORD (32 bits)
//
for ( i=0; i<pAcl1->AceCount; i++) {
NtStatus = RtlGetAce(pAcl1, i, (PVOID *)&pAce1);
if ( !NT_SUCCESS(NtStatus) )
goto Done;
//
// ignore inherited Aces
//
if ( bExplicitOnly && (pAce1->AceFlags & INHERITED_ACE) )
continue;
//
// try to find a match in pAcl2
//
for ( j=0; j<pAcl2->AceCount; j++ ) {
if ( ProcessAce & (1 << j) )
// this one is already processed
continue;
NtStatus = RtlGetAce(pAcl2, j, (PVOID *)&pAce2);
if ( !NT_SUCCESS(NtStatus) )
goto Done;
//
// ignore inherited Aces too
//
if ( bExplicitOnly && (pAce2->AceFlags & INHERITED_ACE) ) {
ProcessAce |= (1 << j);
continue;
}
//
// compare two Aces (pAce1 and pAce2)
//
if ( SmbsvcpEqualAce(pAce1, pAce2) ) {
//
// find a match
//
ProcessAce |= (1 << j);
break;
}
}
if ( j >= pAcl2->AceCount ) {
//
// did not find a match for pAce1
//
*pDifferent = TRUE;
return(ERROR_SUCCESS);
}
}
if ( i >= pAcl1->AceCount ) {
//
// every Ace in pAcl1 finds a match in pAcl2
// see if every Ace in pAcl2 has a match
//
return( SmbsvcpAnyExplicitAcl( pAcl2, ProcessAce, pDifferent ) );
}
Done:
return(RtlNtStatusToDosError(NtStatus));
}
DWORD
SmbsvcpAnyExplicitAcl(
IN PACL Acl,
IN DWORD Processed,
OUT PBOOL pExist
)
/*
Routine Description:
This routine detects if there is any explicit ace in the Acl. The DWORD
Processed is a bit mask of the aces already checked.
Arguments:
Acl - The Acl
Processed - The bit mask for the processed aces (so it won't be checked again)
pExist - The output flag to indicate if there is any explicit ace
Return Value:
win32 error codes
*/
{
NTSTATUS NtStatus=STATUS_SUCCESS;
DWORD j;
ACE_HEADER *pAce=NULL;
//
// check output argument
//
if ( pExist == NULL )
return(ERROR_INVALID_PARAMETER);
*pExist = FALSE;
if ( Acl == NULL )
return(ERROR_SUCCESS);
for ( j=0; j<Acl->AceCount; j++ ) {
if ( Processed & (1 << j) )
continue;
NtStatus = RtlGetAce(Acl, j, (PVOID *)&pAce);
if ( !NT_SUCCESS(NtStatus) )
return(RtlNtStatusToDosError(NtStatus));
if ( pAce == NULL )
continue;
if ( !(pAce->AceFlags & INHERITED_ACE) ) {
//
// find a explicit Ace in Acl
//
*pExist = TRUE;
break;
}
}
return(RtlNtStatusToDosError(NtStatus));
}
BOOL
SmbsvcpEqualAce(
IN ACE_HEADER *pAce1,
IN ACE_HEADER *pAce2
)
// compare two aces for exact match. The return BOOL value indicates the
// match or not
{
PSID pSid1=NULL, pSid2=NULL;
ACCESS_MASK Access1=0, Access2=0;
if ( pAce1 == NULL && pAce2 == NULL )
return(TRUE);
if ( pAce1 == NULL || pAce2 == NULL )
return(FALSE);
//
// compare ace access type
//
if ( pAce1->AceType != pAce2->AceType )
return(FALSE);
//
// compare ace inheritance flag
//
if ( pAce1->AceFlags != pAce2->AceFlags )
return(FALSE);
switch ( pAce1->AceType ) {
case ACCESS_ALLOWED_ACE_TYPE:
case ACCESS_DENIED_ACE_TYPE:
case SYSTEM_AUDIT_ACE_TYPE:
case SYSTEM_ALARM_ACE_TYPE:
pSid1 = (PSID)&((PACCESS_ALLOWED_ACE)pAce1)->SidStart;
pSid2 = (PSID)&((PACCESS_ALLOWED_ACE)pAce2)->SidStart;
Access1 = ((PACCESS_ALLOWED_ACE)pAce1)->Mask;
Access2 = ((PACCESS_ALLOWED_ACE)pAce2)->Mask;
break;
case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
case ACCESS_DENIED_OBJECT_ACE_TYPE:
case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
case SYSTEM_ALARM_OBJECT_ACE_TYPE:
pSid1 = (PSID)&((PACCESS_ALLOWED_OBJECT_ACE)pAce1)->SidStart;
pSid2 = (PSID)&((PACCESS_ALLOWED_OBJECT_ACE)pAce2)->SidStart;
Access1 = ((PACCESS_ALLOWED_OBJECT_ACE)pAce1)->Mask;
Access2 = ((PACCESS_ALLOWED_OBJECT_ACE)pAce2)->Mask;
//
// ignore the guids
//
break;
default:
return(FALSE); // not recognized Ace type
}
if ( pSid1 == NULL || pSid2 == NULL )
//
// no Sid, ignore the Ace
//
return(FALSE);
//
// compare the sids
//
if ( !EqualSid(pSid1, pSid2) )
return(FALSE);
//
// access mask
//
// Translation is already done when calculating security descriptor
// for file objects and registry objects
//
if ( Access1 != Access2 ) {
RtlMapGenericMask (
&Access2,
&ShareGenMap
);
if ( Access1 != Access2)
return(FALSE);
}
return(TRUE);
}
/*=============================================================================
** Procedure Name: DllMain
**
** Arguments:
**
**
**
** Returns: 0 = SUCCESS
** !0 = ERROR
**
** Abstract:
**
** Notes:
**
**===========================================================================*/
BOOL WINAPI DllMain(
IN HANDLE DllHandle,
IN ULONG ulReason,
IN LPVOID Reserved )
{
switch(ulReason) {
case DLL_PROCESS_ATTACH:
MyModuleHandle = (HINSTANCE)DllHandle;
//
// Fall through to process first thread
//
case DLL_THREAD_ATTACH:
break;
case DLL_PROCESS_DETACH:
break;
case DLL_THREAD_DETACH:
break;
}
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// DllRegisterServer - Adds entries to the system registry
STDAPI DllRegisterServer(void)
{
HKEY hKey;
LONG lResult;
DWORD dwDisp;
lResult = RegCreateKeyEx (HKEY_LOCAL_MACHINE, SCESMB_ROOT_PATH, 0, NULL,
REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL,
&hKey, &dwDisp);
if (lResult != ERROR_SUCCESS)
{
return lResult;
}
RegSetValueEx (hKey, TEXT("ServiceAttachmentPath"), 0, REG_SZ, (LPBYTE)TEXT("seFilShr.dll"),
(lstrlen(TEXT("seFilShr.dll")) + 1) * sizeof(TCHAR));
RegCloseKey (hKey);
return S_OK;
}
/////////////////////////////////////////////////////////////////////////////
// DllUnregisterServer - Removes entries from the system registry
STDAPI DllUnregisterServer(void)
{
RegDeleteKey (HKEY_LOCAL_MACHINE, SCESMB_ROOT_PATH);
return S_OK;
}