6832 lines
128 KiB
C++
6832 lines
128 KiB
C++
/*++
|
|
|
|
Copyright (c) 1996 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
iismap.cxx
|
|
|
|
Abstract:
|
|
|
|
Classes to handle mapping
|
|
|
|
Author:
|
|
|
|
Philippe Choquier (phillich) 17-may-1996
|
|
|
|
--*/
|
|
|
|
#include <windows.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <wincrypt.h>
|
|
//#include <crypt32l.h>
|
|
|
|
#include "xbf.hxx"
|
|
extern "C" {
|
|
#include "immd5.h"
|
|
}
|
|
#include <iis64.h>
|
|
#include <iismap.hxx>
|
|
#include "iismaprc.h"
|
|
#include "mapmsg.h"
|
|
#include "iiscmr.hxx"
|
|
#include <refb.hxx>
|
|
#include <icrypt.hxx>
|
|
#include "dbgutil.h"
|
|
|
|
//
|
|
// global vars
|
|
//
|
|
|
|
CRITICAL_SECTION g_csIisMap;
|
|
DWORD g_dwGuid = 0;
|
|
HKEY g_hKey = NULL;
|
|
LPSTR g_pszInstallPath = NULL;
|
|
|
|
DECLARE_DEBUG_PRINTS_OBJECT();
|
|
|
|
//
|
|
//
|
|
//
|
|
|
|
#if defined(DECODE_ASN1)
|
|
PRDN_VALUE_BLOB
|
|
CertGetNameField(
|
|
UINT iEncoding,
|
|
IN LPCTSTR pszObjId,
|
|
IN PNAME_INFO pInfo
|
|
);
|
|
UINT DecodeNames(
|
|
IN PNAME_BLOB pNameBlob,
|
|
IN LPSTR* pFields,
|
|
IN LPSTR pStore
|
|
);
|
|
UINT DecodeCert(
|
|
IN PBYTE pbEncodedCert,
|
|
IN DWORD cbEncodedCert,
|
|
LPSTR* pFields,
|
|
LPSTR pStore
|
|
);
|
|
#endif
|
|
|
|
//
|
|
// global functions
|
|
//
|
|
|
|
extern "C" int __cdecl
|
|
QsortIisMappingCmp(
|
|
const void *pA,
|
|
const void *pB )
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Compare function for 2 CIisMapping entries
|
|
compare using mask, then all fields as defined in
|
|
the linked CIisAcctMapper hierarchy
|
|
|
|
Arguments:
|
|
|
|
pA -- ptr to 1st element
|
|
pB -- ptr tp 2nd elemet
|
|
|
|
Returns:
|
|
|
|
-1 if *pA < *pB, 0 if *pA == *pB, 1 if *pA > *pB
|
|
|
|
--*/
|
|
{
|
|
return (*(CIisMapping**)pA)->Cmp( *(CIisMapping**)pB, FALSE );
|
|
}
|
|
|
|
|
|
extern "C" int __cdecl
|
|
MatchIisMappingCmp(
|
|
const void *pA,
|
|
const void *pB )
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Compare function for 2 CIisMapping entries
|
|
do not uses mask, uses all fields as defined in
|
|
the linked CIisAcctMapper hierarchy
|
|
|
|
Arguments:
|
|
|
|
pA -- ptr to 1st element
|
|
pB -- ptr tp 2nd elemet
|
|
|
|
Returns:
|
|
|
|
-1 if *pA < *pB, 0 if *pA == *pB, 1 if *pA > *pB
|
|
|
|
--*/
|
|
{
|
|
return ( *(CIisMapping**)pA)->Cmp( *(CIisMapping**)pB, TRUE );
|
|
}
|
|
|
|
|
|
HRESULT
|
|
GetSecurityDescriptorForMetabaseExtensionFile(
|
|
PSECURITY_DESCRIPTOR * ppsdStorage
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Build security descriptor that will be set for the extension file
|
|
*.mp (includes Administrators and System )
|
|
|
|
Arguments:
|
|
|
|
ppsdStorage - Security Descriptor to be set for extension file
|
|
|
|
Returns:
|
|
HRESULT
|
|
--*/
|
|
|
|
{
|
|
HRESULT hr = ERROR_SUCCESS;
|
|
BOOL fRet = FALSE;
|
|
DWORD dwDaclSize = 0;
|
|
SID_IDENTIFIER_AUTHORITY ntAuthority = SECURITY_NT_AUTHORITY;
|
|
|
|
PSID psidSystem = NULL;
|
|
PSID psidAdmin = NULL;
|
|
PACL paclDiscretionary = NULL;
|
|
|
|
DBG_ASSERT( ppsdStorage != NULL );
|
|
|
|
*ppsdStorage = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
|
|
|
|
if ( *ppsdStorage == NULL )
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// Initialize the security descriptor.
|
|
//
|
|
|
|
fRet = InitializeSecurityDescriptor(
|
|
*ppsdStorage,
|
|
SECURITY_DESCRIPTOR_REVISION
|
|
);
|
|
|
|
if( !fRet )
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// Create the SIDs for the local system and admin group.
|
|
//
|
|
|
|
fRet = AllocateAndInitializeSid(
|
|
&ntAuthority,
|
|
1,
|
|
SECURITY_LOCAL_SYSTEM_RID,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
&psidSystem
|
|
);
|
|
|
|
if( !fRet )
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto exit;
|
|
}
|
|
|
|
fRet= AllocateAndInitializeSid(
|
|
&ntAuthority,
|
|
2,
|
|
SECURITY_BUILTIN_DOMAIN_RID,
|
|
DOMAIN_ALIAS_RID_ADMINS,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
&psidAdmin
|
|
);
|
|
|
|
if( !fRet )
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// Create the DACL containing an access-allowed ACE
|
|
// for the local system and admin SIDs.
|
|
//
|
|
|
|
dwDaclSize = sizeof(ACL)
|
|
+ sizeof(ACCESS_ALLOWED_ACE)
|
|
+ GetLengthSid(psidAdmin)
|
|
+ sizeof(ACCESS_ALLOWED_ACE)
|
|
+ GetLengthSid(psidSystem)
|
|
- sizeof(DWORD);
|
|
|
|
paclDiscretionary = (PACL)LocalAlloc(LPTR, dwDaclSize );
|
|
|
|
if ( paclDiscretionary == NULL )
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto exit;
|
|
}
|
|
|
|
fRet = InitializeAcl(
|
|
paclDiscretionary,
|
|
dwDaclSize,
|
|
ACL_REVISION
|
|
);
|
|
|
|
if( !fRet )
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto exit;
|
|
}
|
|
|
|
fRet = AddAccessAllowedAce(
|
|
paclDiscretionary,
|
|
ACL_REVISION,
|
|
FILE_ALL_ACCESS,
|
|
psidSystem
|
|
);
|
|
|
|
if ( !fRet )
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto exit;
|
|
}
|
|
|
|
fRet = AddAccessAllowedAce(
|
|
paclDiscretionary,
|
|
ACL_REVISION,
|
|
FILE_ALL_ACCESS,
|
|
psidAdmin
|
|
);
|
|
|
|
if ( !fRet )
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// Set the DACL into the security descriptor.
|
|
//
|
|
|
|
fRet = SetSecurityDescriptorDacl(
|
|
*ppsdStorage,
|
|
TRUE,
|
|
paclDiscretionary,
|
|
FALSE
|
|
);
|
|
|
|
if ( !fRet ) {
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto exit;
|
|
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
exit:
|
|
|
|
if ( psidAdmin != NULL )
|
|
{
|
|
FreeSid( psidAdmin );
|
|
psidAdmin = NULL;
|
|
}
|
|
|
|
if ( psidSystem != NULL )
|
|
{
|
|
FreeSid( psidSystem );
|
|
psidSystem = NULL;
|
|
}
|
|
|
|
if ( FAILED( hr ) ) {
|
|
if ( paclDiscretionary != NULL )
|
|
{
|
|
LocalFree( paclDiscretionary );
|
|
paclDiscretionary = NULL;
|
|
}
|
|
|
|
if ( *ppsdStorage != NULL )
|
|
{
|
|
LocalFree( *ppsdStorage );
|
|
*ppsdStorage = NULL;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
HRESULT
|
|
FreeSecurityDescriptorForMetabaseExtensionFile(
|
|
PSECURITY_DESCRIPTOR psdStorage
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Free security descriptor generated by
|
|
GetSecurityDescriptorForMetabaseExtentionFile()
|
|
|
|
Arguments:
|
|
|
|
psdStorage - Security Descriptor to be freed
|
|
|
|
Returns:
|
|
HRESULT
|
|
--*/
|
|
|
|
{
|
|
HRESULT hr = ERROR_SUCCESS;
|
|
BOOL fRet = FALSE;
|
|
BOOL fDaclPresent;
|
|
PACL paclDiscretionary = NULL;
|
|
BOOL fDaclDefaulted;
|
|
|
|
//
|
|
// Get the DACL from the security descriptor.
|
|
//
|
|
|
|
if ( psdStorage == NULL )
|
|
{
|
|
hr = S_OK;
|
|
goto exit;
|
|
}
|
|
|
|
fRet = GetSecurityDescriptorDacl(
|
|
psdStorage,
|
|
&fDaclPresent,
|
|
&paclDiscretionary,
|
|
&fDaclDefaulted
|
|
);
|
|
|
|
if ( !fRet )
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto exit;
|
|
}
|
|
|
|
if ( fDaclPresent && paclDiscretionary != NULL )
|
|
{
|
|
LocalFree( paclDiscretionary );
|
|
paclDiscretionary = NULL;
|
|
}
|
|
|
|
LocalFree( psdStorage );
|
|
|
|
hr = S_OK;
|
|
|
|
exit:
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
INT
|
|
Iisfputs(
|
|
const char* pBuf,
|
|
FILE* fOut
|
|
)
|
|
{
|
|
return (fputs( pBuf, fOut ) == EOF || fputc( '\n', fOut ) == EOF)
|
|
? EOF
|
|
: 0;
|
|
}
|
|
|
|
|
|
LPSTR
|
|
Iisfgets(
|
|
LPSTR pBuf,
|
|
INT cMax,
|
|
FILE* fIn
|
|
)
|
|
{
|
|
LPSTR pszWas = pBuf;
|
|
INT ch = 0;
|
|
|
|
while ( cMax > 1 && (ch=fgetc(fIn))!= EOF && ch != '\n' )
|
|
{
|
|
*pBuf++ = (CHAR)ch;
|
|
--cMax;
|
|
}
|
|
|
|
if ( ch != EOF )
|
|
{
|
|
*pBuf = '\0';
|
|
return pszWas;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
//
|
|
// Fields for the Certificate mapper
|
|
//
|
|
|
|
IISMDB_Fields IisCertMappingFields[] = {
|
|
{IISMDB_TYPE_ISSUER_O, NULL, IDS_IISMAP_FLD0, 40 },
|
|
{IISMDB_TYPE_ISSUER_OU, NULL, IDS_IISMAP_FLD1, 40 },
|
|
{IISMDB_TYPE_ISSUER_C, NULL, IDS_IISMAP_FLD2, 40 },
|
|
|
|
{IISMDB_TYPE_SUBJECT_O, NULL, IDS_IISMAP_FLD3, 40 },
|
|
{IISMDB_TYPE_SUBJECT_OU, NULL, IDS_IISMAP_FLD4, 40 },
|
|
{IISMDB_TYPE_SUBJECT_C, NULL, IDS_IISMAP_FLD5, 40 },
|
|
{IISMDB_TYPE_SUBJECT_CN, NULL, IDS_IISMAP_FLD6, 40 },
|
|
|
|
{IISMDB_TYPE_NTACCT, NULL, IDS_IISMAP_FLD7, 40 },
|
|
} ;
|
|
|
|
//
|
|
// default hierarchy for the Certificate mapper
|
|
//
|
|
|
|
IISMDB_HEntry IisCertMappingHierarchy[] = {
|
|
{IISMDB_INDEX_ISSUER_O, TRUE},
|
|
{IISMDB_INDEX_ISSUER_OU, FALSE},
|
|
{IISMDB_INDEX_ISSUER_C, FALSE},
|
|
|
|
{IISMDB_INDEX_SUBJECT_O, TRUE},
|
|
{IISMDB_INDEX_SUBJECT_OU, FALSE},
|
|
{IISMDB_INDEX_SUBJECT_C, FALSE},
|
|
{IISMDB_INDEX_SUBJECT_CN, TRUE},
|
|
} ;
|
|
|
|
|
|
//
|
|
// Fields for the Certificate 1:1 mapper
|
|
//
|
|
|
|
IISMDB_Fields IisCert11MappingFields[] = {
|
|
#if defined(CERT11_FULL_CERT)
|
|
{IISMDB_INDEX_CERT11_CERT, NULL, IDS_IISMAP11_FLDC, 40 },
|
|
#else
|
|
{IISMDB_INDEX_CERT11_SUBJECT, NULL, IDS_IISMAP11_FLDS, 40 },
|
|
{IISMDB_INDEX_CERT11_ISSUER, NULL, IDS_IISMAP11_FLDI, 40 },
|
|
#endif
|
|
{IISMDB_INDEX_CERT11_NT_ACCT, NULL, IDS_IISMAP11_FLDA, 40 },
|
|
#if defined(CERT11_FULL_CERT)
|
|
{IISMDB_INDEX_CERT11_NAME, NULL, IDS_IISMAP11_FLDN, 40 },
|
|
{IISMDB_INDEX_CERT11_ENABLED, NULL, IDS_IISMAP11_FLDE, 40 },
|
|
{IISMDB_INDEX_CERT11_NT_PWD, NULL, IDS_IISMAP11_FLDP, 40 },
|
|
#endif
|
|
} ;
|
|
|
|
//
|
|
// default hierarchy for the Certificate 1:1 mapper
|
|
//
|
|
|
|
IISMDB_HEntry IisCert11MappingHierarchy[] = {
|
|
#if defined(CERT11_FULL_CERT)
|
|
{IISMDB_INDEX_CERT11_CERT, TRUE},
|
|
#else
|
|
{IISMDB_INDEX_CERT11_ISSUER, TRUE},
|
|
{IISMDB_INDEX_CERT11_SUBJECT, FALSE},
|
|
#endif
|
|
} ;
|
|
|
|
|
|
//
|
|
// Fields for the Ita mapper
|
|
//
|
|
|
|
IISMDB_Fields IisItaMappingFields[] = {
|
|
{IISMDB_TYPE_ITACCT, NULL, IDS_ITAIISMAP_FLD0, 40 },
|
|
{IISMDB_TYPE_ITPWD, NULL, IDS_ITAIISMAP_FLD1, 40 },
|
|
|
|
{IISMDB_TYPE_NTACCT, NULL, IDS_ITAIISMAP_FLD2, 40 },
|
|
} ;
|
|
|
|
//
|
|
// default hierarchy for the Ita mapper
|
|
//
|
|
|
|
IISMDB_HEntry IisItaMappingHierarchy[] = {
|
|
{IISIMDB_INDEX_IT_ACCT, TRUE},
|
|
{IISIMDB_INDEX_IT_PWD, TRUE},
|
|
} ;
|
|
|
|
|
|
//
|
|
// Fields for the Md5 mapper
|
|
//
|
|
|
|
IISMDB_Fields IisMd5MappingFields[] = {
|
|
{IISMDB_TYPE_ITREALM, NULL, IDS_MD5IISMAP_FLD0, 40 },
|
|
{IISMDB_TYPE_ITACCT, NULL, IDS_MD5IISMAP_FLD1, 40 },
|
|
{IISMDB_TYPE_ITMD5PWD, NULL, IDS_MD5IISMAP_FLD2, 40 },
|
|
|
|
{IISMDB_TYPE_NTACCT, NULL, IDS_MD5IISMAP_FLD3, 40 },
|
|
{IISMMDB_INDEX_IT_CLRPWD, NULL, IDS_MD5IISMAP_FLD4, 40 },
|
|
{IISMMDB_INDEX_NT_PWD, NULL, IDS_MD5IISMAP_FLD5, 40 },
|
|
} ;
|
|
|
|
//
|
|
// default hierarchy for the Md5 mapper
|
|
//
|
|
|
|
IISMDB_HEntry IisMd5MappingHierarchy[] = {
|
|
{IISMMDB_INDEX_IT_REALM, TRUE},
|
|
{IISMMDB_INDEX_IT_ACCT, TRUE},
|
|
} ;
|
|
|
|
|
|
HINSTANCE g_hModule = (HINSTANCE)INVALID_HANDLE_VALUE;
|
|
|
|
|
|
|
|
// CIisAcctMapper
|
|
|
|
CIisAcctMapper::CIisAcctMapper(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Constructor for CIisAcctMapper
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Returns:
|
|
|
|
Nothing
|
|
|
|
--*/
|
|
{
|
|
m_cInit = -1;
|
|
|
|
m_pMapping = NULL;
|
|
m_cMapping = 0;
|
|
|
|
m_pAltMapping = NULL;
|
|
m_cAltMapping = 0;
|
|
|
|
m_pHierarchy = NULL;
|
|
m_cHierarchy = 0;
|
|
|
|
m_achFileName[0] = '\0';
|
|
|
|
m_pClasses = NULL;
|
|
m_pSesKey = NULL;
|
|
m_dwSesKey = 0;
|
|
|
|
m_hNotifyEvent = NULL;
|
|
m_fRequestTerminate = FALSE;
|
|
|
|
INITIALIZE_CRITICAL_SECTION( &csLock );
|
|
}
|
|
|
|
|
|
CIisAcctMapper::~CIisAcctMapper(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Destructor for CIisAcctMapper
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Returns:
|
|
|
|
Nothing
|
|
|
|
--*/
|
|
{
|
|
Reset();
|
|
|
|
if ( m_pHierarchy != NULL )
|
|
{
|
|
LocalFree( m_pHierarchy );
|
|
}
|
|
|
|
if ( m_pSesKey != NULL )
|
|
{
|
|
LocalFree( m_pSesKey );
|
|
}
|
|
|
|
DeleteCriticalSection( &csLock );
|
|
}
|
|
|
|
|
|
VOID
|
|
FreeCIisAcctMapper(
|
|
LPVOID pMapper
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Delete a CIisAcctMapper
|
|
|
|
Arguments:
|
|
|
|
pMapper - ptr to mapper
|
|
|
|
Returns:
|
|
|
|
Nothing
|
|
|
|
--*/
|
|
{
|
|
delete (CIisAcctMapper*)pMapper;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CIisAcctMapper::Create(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create file for CIisAcctMapper with proper SD
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
--*/
|
|
{
|
|
// create file name, store in m_achFileName
|
|
// from g_dwGuid
|
|
// and g_pszInstallPath
|
|
|
|
UINT cLen;
|
|
UINT cIter;
|
|
HANDLE hF;
|
|
HRESULT hr = E_FAIL;
|
|
BOOL fRet = FALSE;
|
|
PSECURITY_DESCRIPTOR psdForMetabaseExtensionFile = NULL;
|
|
SECURITY_ATTRIBUTES saStorage;
|
|
PSECURITY_ATTRIBUTES psaStorage = NULL;
|
|
|
|
|
|
Reset();
|
|
|
|
if ( g_pszInstallPath )
|
|
{
|
|
cLen = strlen(g_pszInstallPath);
|
|
memcpy( m_achFileName, g_pszInstallPath, cLen );
|
|
if ( cLen && m_achFileName[cLen-1] != '\\' )
|
|
{
|
|
m_achFileName[cLen++] = '\\';
|
|
}
|
|
}
|
|
else
|
|
{
|
|
cLen = 0;
|
|
}
|
|
|
|
wsprintf( m_achFileName+cLen, "%08x.mp", g_dwGuid );
|
|
|
|
//
|
|
// build security descriptor (Administrators and SYSTEM)
|
|
// to be set on metabase extension file
|
|
//
|
|
|
|
hr = GetSecurityDescriptorForMetabaseExtensionFile(
|
|
&psdForMetabaseExtensionFile );
|
|
|
|
if ( SUCCEEDED(hr) && psdForMetabaseExtensionFile != NULL )
|
|
{
|
|
saStorage.nLength = sizeof(SECURITY_ATTRIBUTES);
|
|
saStorage.lpSecurityDescriptor = psdForMetabaseExtensionFile;
|
|
saStorage.bInheritHandle = FALSE;
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
//
|
|
// Open file and close it right away
|
|
// If file didn't exist, then empty file with good SD (Security Descriptor)
|
|
// will be created. That will later be opened using C runtime (fopen)
|
|
// in Save() method and good SD will persist.
|
|
// Ideally Save() should be using Win32 CreateFile()
|
|
// instead fopen and it could set SD itself. But since this is legacy
|
|
// source file and rather unsafe for making too many changes, pragmatic
|
|
// approach was chosen to set SD here in Create() method
|
|
//
|
|
|
|
if ( (hF = CreateFile( m_achFileName,
|
|
GENERIC_READ,
|
|
FILE_SHARE_READ|FILE_SHARE_WRITE,
|
|
&saStorage,
|
|
OPEN_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL ) ) != INVALID_HANDLE_VALUE )
|
|
{
|
|
CloseHandle( hF );
|
|
fRet = TRUE;
|
|
}
|
|
else
|
|
{
|
|
fRet = FALSE;
|
|
}
|
|
|
|
if ( psdForMetabaseExtensionFile != NULL )
|
|
{
|
|
FreeSecurityDescriptorForMetabaseExtensionFile(
|
|
psdForMetabaseExtensionFile );
|
|
psdForMetabaseExtensionFile = NULL;
|
|
}
|
|
return fRet;
|
|
|
|
}
|
|
|
|
|
|
BOOL
|
|
CIisAcctMapper::Delete(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Delete external storage used by this mapper ( i.e. file )
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
--*/
|
|
{
|
|
BOOL fSt = TRUE;
|
|
|
|
Lock();
|
|
|
|
if ( m_achFileName[0] )
|
|
{
|
|
fSt = DeleteFile( m_achFileName );
|
|
m_achFileName[0] = '\0';
|
|
}
|
|
|
|
Unlock();
|
|
|
|
return fSt;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CIisAcctMapper::Serialize(
|
|
CStoreXBF* pXbf
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Serialize mapper reference ( NOT mapping info ) to buffer
|
|
Save() must be called to save mapping info before calling Serialize()
|
|
|
|
Arguments:
|
|
|
|
pXbf - ptr to extensible buffer to serialize to
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
--*/
|
|
{
|
|
return pXbf->Append( (DWORD)strlen(m_achFileName) ) &&
|
|
pXbf->Append( (LPBYTE)m_achFileName, (DWORD)strlen(m_achFileName) ) &&
|
|
pXbf->Append( (LPBYTE)m_md5.digest, (DWORD)sizeof(m_md5.digest) ) &&
|
|
pXbf->Append( (DWORD)m_dwSesKey ) &&
|
|
pXbf->Append( (LPBYTE)m_pSesKey, (DWORD)m_dwSesKey ) ;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CIisAcctMapper::Unserialize(
|
|
CStoreXBF* pXBF
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Unserialize mapper reference ( NOT mapping info ) from extensible buffer
|
|
Load() must be called to load mapping info
|
|
|
|
Arguments:
|
|
|
|
pXBF - ptr to extensible buffer
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
--*/
|
|
{
|
|
LPBYTE pb = pXBF->GetBuff();
|
|
DWORD c = pXBF->GetUsed();
|
|
|
|
return Unserialize( &pb, &c );
|
|
}
|
|
|
|
|
|
BOOL
|
|
CIisAcctMapper::Unserialize(
|
|
LPBYTE* ppb,
|
|
LPDWORD pc
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Unserialize mapper reference ( NOT mapping info ) from buffer
|
|
Load() must be called to load mapping info
|
|
|
|
Arguments:
|
|
|
|
ppb - ptr to buffer
|
|
pc - ptr to buffer length
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
--*/
|
|
{
|
|
DWORD cName;
|
|
|
|
if ( ::Unserialize( ppb, pc, &cName ) &&
|
|
cName <= *pc )
|
|
{
|
|
memcpy( m_achFileName, *ppb, cName );
|
|
m_achFileName[ cName ] = '\0';
|
|
*ppb += cName;
|
|
*pc -= cName;
|
|
if ( sizeof(m_md5.digest) <= *pc )
|
|
{
|
|
memcpy( m_md5.digest, *ppb, sizeof(m_md5.digest) );
|
|
*ppb += sizeof(m_md5.digest);
|
|
*pc -= sizeof(m_md5.digest);
|
|
|
|
if ( ::Unserialize( ppb, pc, &m_dwSesKey ) &&
|
|
cName <= *pc )
|
|
{
|
|
if ( m_pSesKey != NULL )
|
|
{
|
|
LocalFree( m_pSesKey );
|
|
}
|
|
|
|
if ( !(m_pSesKey = (LPBYTE)LocalAlloc( LMEM_FIXED, m_dwSesKey )) )
|
|
{
|
|
m_dwSesKey = 0;
|
|
return FALSE;
|
|
}
|
|
memcpy( m_pSesKey, *ppb, m_dwSesKey );
|
|
*ppb += m_dwSesKey;
|
|
*pc -= m_dwSesKey;
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CIisAcctMapper::Serialize(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Serialize mapper reference ( NOT mapping info ) to registry
|
|
Save() must be called to save mapping info before calling Serialize()
|
|
Warning : this allow only 1 instance
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
--*/
|
|
{
|
|
BOOL fSt = TRUE;
|
|
HKEY hKey;
|
|
LONG st;
|
|
|
|
if ( (st = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
|
|
GetRegKeyName(),
|
|
0,
|
|
KEY_WRITE,
|
|
&hKey )) != ERROR_SUCCESS )
|
|
{
|
|
SetLastError( st );
|
|
return FALSE;
|
|
}
|
|
|
|
if ( RegSetValueEx( hKey,
|
|
FILE_VALIDATOR,
|
|
NULL,
|
|
REG_BINARY,
|
|
(LPBYTE)m_md5.digest,
|
|
sizeof(m_md5.digest) ) != ERROR_SUCCESS ||
|
|
RegSetValueEx( hKey,
|
|
FILE_LOCATION,
|
|
NULL,
|
|
REG_SZ,
|
|
(LPBYTE)m_achFileName,
|
|
strlen(m_achFileName) ) != ERROR_SUCCESS )
|
|
{
|
|
fSt = FALSE;
|
|
}
|
|
|
|
RegCloseKey( hKey );
|
|
|
|
return fSt;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CIisAcctMapper::Unserialize(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Unserialize mapper reference ( NOT mapping info ) From registry
|
|
Load() must be called to load mapping info
|
|
Warning : this allow only 1 instance
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
--*/
|
|
{
|
|
BOOL fSt = FALSE;
|
|
HKEY hKey;
|
|
DWORD dwLen;
|
|
DWORD dwType;
|
|
LONG st;
|
|
|
|
// Check registry
|
|
|
|
if ( (st = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
|
|
GetRegKeyName(),
|
|
0,
|
|
KEY_READ,
|
|
&hKey )) != ERROR_SUCCESS )
|
|
{
|
|
SetLastError( st );
|
|
return FALSE;
|
|
}
|
|
|
|
dwLen = sizeof(m_md5.digest);
|
|
|
|
if ( RegQueryValueEx( hKey,
|
|
FILE_VALIDATOR,
|
|
NULL,
|
|
&dwType,
|
|
(LPBYTE)m_md5.digest,
|
|
&dwLen ) == ERROR_SUCCESS &&
|
|
dwType == REG_BINARY &&
|
|
(( dwLen = sizeof(m_achFileName) ), TRUE ) &&
|
|
RegQueryValueEx( hKey,
|
|
FILE_LOCATION,
|
|
NULL,
|
|
&dwType,
|
|
(LPBYTE)m_achFileName,
|
|
&dwLen ) == ERROR_SUCCESS &&
|
|
dwType == REG_SZ )
|
|
{
|
|
fSt = TRUE;
|
|
}
|
|
|
|
RegCloseKey( hKey );
|
|
|
|
return fSt;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CIisAcctMapper::UpdateClasses(
|
|
BOOL fComputeMask
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Constructor for CIisAcctMapper
|
|
|
|
Arguments:
|
|
|
|
fComputeMask -- TRUE if mask to be recomputed
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
--*/
|
|
{
|
|
UINT x;
|
|
UINT mx = 1 << m_cHierarchy;
|
|
|
|
if ( fComputeMask )
|
|
{
|
|
for ( x = 0 ; x < m_cMapping ; ++x )
|
|
{
|
|
m_pMapping[x]->UpdateMask( m_pHierarchy, m_cHierarchy );
|
|
}
|
|
}
|
|
|
|
SortMappings();
|
|
|
|
if ( m_pClasses == NULL )
|
|
{
|
|
m_pClasses = (MappingClass*)LocalAlloc(
|
|
LMEM_FIXED,
|
|
sizeof(MappingClass)*(mx+1) );
|
|
if ( m_pClasses == NULL )
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
DWORD dwN = 0; // current class index in m_pClasses
|
|
DWORD dwLastClass = 0;
|
|
DWORD dwFirst = 0; // first entry for current dwLastClass
|
|
for ( x = 0 ; x <= m_cMapping ; ++x )
|
|
{
|
|
DWORD dwCur;
|
|
dwCur = (x==m_cMapping) ? dwLastClass+1: m_pMapping[x]->GetMask();
|
|
if ( dwCur > dwLastClass )
|
|
{
|
|
if ( x > dwFirst )
|
|
{
|
|
m_pClasses[dwN].dwClass = dwLastClass;
|
|
m_pClasses[dwN].dwFirst = dwFirst;
|
|
m_pClasses[dwN].dwLast = x - 1;
|
|
++dwN;
|
|
}
|
|
dwLastClass = dwCur;
|
|
dwFirst = x;
|
|
}
|
|
}
|
|
|
|
m_pClasses[dwN].dwClass = 0xffffffff;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CIisAcctMapper::SortMappings(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Sort the mappings. Masks for mapping objects are assumed
|
|
to be already computed.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
--*/
|
|
{
|
|
qsort( (LPVOID)m_pMapping,
|
|
m_cMapping,
|
|
sizeof(CIisMapping*),
|
|
QsortIisMappingCmp
|
|
);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CIisAcctMapper::FindMatch(
|
|
CIisMapping* pQuery,
|
|
CIisMapping** pResult,
|
|
LPDWORD piResult
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Find a match base on field contents in CIisMapping
|
|
|
|
Arguments:
|
|
|
|
pQuery -- describe fields to consider for mapping
|
|
pResult -- updated with result if found mapping
|
|
|
|
Returns:
|
|
|
|
TRUE if mapping found, else FALSE
|
|
|
|
Lock:
|
|
mapper must be locked for ptr to remain valid
|
|
|
|
--*/
|
|
{
|
|
// iterate through classes, do bsearch on each
|
|
|
|
MappingClass *pH = m_pClasses;
|
|
|
|
if ( pH == NULL )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
while ( pH->dwClass != 0xffffffff )
|
|
{
|
|
CIisMapping **pRes = (CIisMapping **)bsearch( (LPVOID)&pQuery,
|
|
(LPVOID)(m_pMapping+pH->dwFirst),
|
|
pH->dwLast - pH->dwFirst + 1,
|
|
sizeof(CIisMapping*),
|
|
MatchIisMappingCmp );
|
|
if ( piResult != NULL )
|
|
{
|
|
*piResult = DIFF(pRes - m_pMapping);
|
|
}
|
|
|
|
if ( pRes != NULL )
|
|
{
|
|
*pResult = *pRes;
|
|
return TRUE;
|
|
}
|
|
|
|
++pH;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
#if 0
|
|
DWORD
|
|
WINAPI IisMappingUpdateIndication(
|
|
LPVOID pV )
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Shell for registry update notification
|
|
|
|
Arguments:
|
|
|
|
pV -- ptr to CIisAcctMapper to be notified
|
|
|
|
Returns:
|
|
|
|
NT error code ( 0 if no error )
|
|
|
|
--*/
|
|
{
|
|
return ((CIisAcctMapper*)pV)->UpdateIndication();
|
|
}
|
|
|
|
|
|
DWORD
|
|
CIisAcctMapper::UpdateIndication(
|
|
VOID )
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Thread monitoring authentication methods update in registry
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Returns:
|
|
|
|
NT error
|
|
|
|
--*/
|
|
{
|
|
for ( ;; )
|
|
{
|
|
if ( RegNotifyChangeKeyValue( m_hKey,
|
|
FALSE,
|
|
REG_NOTIFY_CHANGE_LAST_SET,
|
|
m_hNotifyEvent,
|
|
TRUE ) != ERROR_SUCCESS )
|
|
{
|
|
break;
|
|
}
|
|
if ( WaitForSingleObject( m_hNotifyEvent, INFINITE)
|
|
!= WAIT_OBJECT_0 )
|
|
{
|
|
break;
|
|
}
|
|
if ( m_fRequestTerminate )
|
|
{
|
|
break;
|
|
}
|
|
|
|
// re-load mapper
|
|
|
|
Lock();
|
|
if ( !Load() && GetLastError() == ERROR_INVALID_ACCESS )
|
|
{
|
|
Reset();
|
|
}
|
|
Unlock();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
|
|
#if 0
|
|
BOOL
|
|
CIisAcctMapper::Init(
|
|
BOOL *pfFirst,
|
|
BOOL fMonitorChange
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Initialize mappings, optionally load map file
|
|
|
|
Arguments:
|
|
|
|
fLoad -- TRUE to load mappings from file
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
--*/
|
|
{
|
|
*pfFirst = FALSE;
|
|
BOOL fSt = TRUE;
|
|
|
|
if ( !InterlockedIncrement( &m_cInit ) )
|
|
{
|
|
*pfFirst = TRUE;
|
|
|
|
if ( fMonitorChange )
|
|
{
|
|
m_hNotifyEvent = IIS_CREATE_EVENT(
|
|
"CIisAcctMapper::m_hNotifyEvent",
|
|
this,
|
|
FALSE,
|
|
FALSE
|
|
);
|
|
}
|
|
m_fRequestTerminate = FALSE;
|
|
|
|
if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE,
|
|
GetRegKeyName(),
|
|
0,
|
|
KEY_READ,
|
|
&m_hKey ) == ERROR_SUCCESS )
|
|
{
|
|
DWORD dwLen = sizeof( m_achFileName );
|
|
DWORD dwType;
|
|
if ( RegQueryValueEx( m_hKey,
|
|
FILE_LOCATION,
|
|
NULL,
|
|
&dwType,
|
|
(LPBYTE)m_achFileName,
|
|
&dwLen ) != ERROR_SUCCESS
|
|
|| dwType != REG_SZ )
|
|
{
|
|
strcpy( m_achFileName, IIS_CERT_FILENAME );
|
|
}
|
|
|
|
if ( fMonitorChange )
|
|
{
|
|
// create registry monitoring thread
|
|
DWORD dwID;
|
|
if ( (m_hThread = CreateThread( NULL,
|
|
0,
|
|
(LPTHREAD_START_ROUTINE)::IisMappingUpdateIndication,
|
|
(LPVOID)this,
|
|
0,
|
|
&dwID )) == NULL )
|
|
{
|
|
fSt = FALSE;
|
|
goto ex;
|
|
}
|
|
}
|
|
|
|
fSt = Reset();
|
|
}
|
|
else
|
|
{
|
|
SetLastError( ERROR_CANTOPEN );
|
|
fSt = FALSE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// log event if error
|
|
//
|
|
|
|
if ( !fSt )
|
|
{
|
|
char achErr[32];
|
|
LPCTSTR pA[1];
|
|
pA[0] = achErr;
|
|
_itoa( GetLastError(), achErr, 10 );
|
|
ReportIisMapEvent( EVENTLOG_ERROR_TYPE,
|
|
IISMAP_EVENT_INIT_ERROR,
|
|
1,
|
|
pA );
|
|
}
|
|
|
|
return fSt;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CIisAcctMapper::Terminate(
|
|
BOOL fForce
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Terminate mapping
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
--*/
|
|
{
|
|
BOOL fSt = TRUE;
|
|
|
|
if ( InterlockedDecrement( &m_cInit ) < 0 || fForce )
|
|
{
|
|
#if 0
|
|
if ( m_hNotifyEvent && m_hThread )
|
|
{
|
|
m_fRequestTerminate = TRUE;
|
|
SetEvent( m_hNotifyEvent );
|
|
|
|
if ( m_hThread != NULL )
|
|
{
|
|
fSt = WaitForSingleObject( m_hThread, 1000 * 3 )
|
|
== WAIT_OBJECT_0;
|
|
|
|
if ( !fSt )
|
|
{
|
|
TerminateThread( m_hThread, 0 );
|
|
}
|
|
|
|
CloseHandle( m_hThread );
|
|
m_hThread = NULL;
|
|
|
|
if ( m_hKey != NULL )
|
|
{
|
|
RegCloseKey( m_hKey );
|
|
m_hKey = NULL;
|
|
}
|
|
if ( m_hNotifyEvent != NULL )
|
|
{
|
|
CloseHandle( m_hNotifyEvent );
|
|
m_hNotifyEvent = NULL;
|
|
}
|
|
|
|
return fSt;
|
|
}
|
|
}
|
|
|
|
if ( m_hKey != NULL )
|
|
{
|
|
RegCloseKey( m_hKey );
|
|
m_hKey = NULL;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
#endif
|
|
|
|
|
|
void
|
|
CIisAcctMapper::Lock(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Prevent access to mapper from other threads
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Returns:
|
|
|
|
Nothing
|
|
|
|
--*/
|
|
{
|
|
EnterCriticalSection( &csLock );
|
|
}
|
|
|
|
|
|
void
|
|
CIisAcctMapper::Unlock(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Re-enabled access to mapper from other threads
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Returns:
|
|
|
|
Nothing
|
|
|
|
--*/
|
|
{
|
|
LeaveCriticalSection( &csLock );
|
|
}
|
|
|
|
|
|
BOOL
|
|
CIisAcctMapper::FlushAlternate(
|
|
BOOL fApply
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Flush alternate list, optionaly commiting it to the main list
|
|
|
|
Arguments:
|
|
|
|
fApply -- TRUE to commit changes made in alternate list
|
|
|
|
Returns:
|
|
|
|
TRUE if success, otherwise FALSE
|
|
|
|
--*/
|
|
{
|
|
UINT i;
|
|
UINT iM;
|
|
BOOL fSt = TRUE;
|
|
|
|
if ( m_pAltMapping )
|
|
{
|
|
if ( fApply )
|
|
{
|
|
//
|
|
// Transfer non existing objects from regular to alternate list
|
|
//
|
|
|
|
iM = min( m_cMapping, m_cAltMapping );
|
|
|
|
for ( i = 0 ; i < iM ; ++ i )
|
|
{
|
|
if ( m_pAltMapping[i] == NULL )
|
|
{
|
|
m_pAltMapping[i] = m_pMapping[i];
|
|
}
|
|
else
|
|
{
|
|
delete m_pMapping[i];
|
|
}
|
|
}
|
|
|
|
//
|
|
// delete extra objects
|
|
//
|
|
|
|
if ( m_cMapping > m_cAltMapping )
|
|
{
|
|
for ( i = m_cAltMapping ; i < m_cMapping ; ++i )
|
|
{
|
|
delete m_pMapping[i];
|
|
}
|
|
}
|
|
|
|
if ( m_pMapping )
|
|
{
|
|
LocalFree( m_pMapping );
|
|
}
|
|
|
|
m_pMapping = m_pAltMapping;
|
|
m_cMapping = m_cAltMapping;
|
|
|
|
fSt = UpdateClasses( TRUE );
|
|
}
|
|
else
|
|
{
|
|
for ( i = 0 ; i < m_cAltMapping ; ++i )
|
|
{
|
|
if ( m_pAltMapping[i] )
|
|
{
|
|
delete m_pAltMapping;
|
|
}
|
|
}
|
|
LocalFree( m_pAltMapping );
|
|
}
|
|
}
|
|
|
|
m_pAltMapping = NULL;
|
|
m_cAltMapping = 0;
|
|
|
|
return fSt;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CIisAcctMapper::GetMapping(
|
|
DWORD iIndex,
|
|
CIisMapping** pM,
|
|
BOOL fGetFromAlternate,
|
|
BOOL fPutOnAlternate
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get mapping entry based on index
|
|
|
|
Arguments:
|
|
|
|
iIndex -- index in mapping array
|
|
pM -- updated with pointer to mapping. mapping object
|
|
still owned by the mapper object.
|
|
fGetFromAlternate -- TRUE if retrieve from alternate list
|
|
fPutOnAlternate -- TRUE if put returned mapping on alternate list
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
--*/
|
|
{
|
|
if ( fPutOnAlternate )
|
|
{
|
|
// create alternate list if not exist
|
|
|
|
if ( !m_pAltMapping && m_cMapping )
|
|
{
|
|
m_pAltMapping = (CIisMapping**)LocalAlloc( LMEM_FIXED, sizeof(CIisMapping*)*(m_cMapping) );
|
|
if ( m_pAltMapping == NULL )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
memset( m_pAltMapping, '\0', sizeof(CIisMapping*) * m_cMapping );
|
|
|
|
m_cAltMapping = m_cMapping;
|
|
}
|
|
|
|
if ( iIndex < m_cAltMapping )
|
|
{
|
|
if ( m_pAltMapping[iIndex] == NULL &&
|
|
m_pMapping != NULL ) // work-around for compiler bug
|
|
{
|
|
// duplicate mapping to alternate list if not exist
|
|
if ( m_pMapping[iIndex]->Clone( pM ) )
|
|
{
|
|
m_pAltMapping[iIndex] = *pM;
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*pM = m_pAltMapping[iIndex];
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
if ( fGetFromAlternate &&
|
|
m_pAltMapping &&
|
|
iIndex < m_cAltMapping )
|
|
{
|
|
if ( m_pAltMapping[iIndex] )
|
|
{
|
|
*pM = m_pAltMapping[iIndex];
|
|
}
|
|
else
|
|
{
|
|
*pM = m_pMapping[iIndex];
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
if ( iIndex < m_cMapping )
|
|
{
|
|
*pM = m_pMapping[iIndex];
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CIisAcctMapper::GetMappingForUpdate(
|
|
DWORD iIndex,
|
|
CIisMapping** pM
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get mapping entry based on index
|
|
returns a copy of the mapping so update is cancelable
|
|
|
|
Arguments:
|
|
|
|
iIndex -- index in mapping array
|
|
pM -- updated with pointer to mapping. mapping object
|
|
still owned by the mapper object.
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
--*/
|
|
{
|
|
if ( iIndex < m_cMapping )
|
|
{
|
|
if ( (*pM = CreateNewMapping()) == NULL )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return (*pM)->Copy( m_pMapping[iIndex] );
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CIisAcctMapper::Update(
|
|
DWORD iIndex,
|
|
CIisMapping* pM
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Update a mapping
|
|
|
|
Arguments:
|
|
|
|
iIndex -- index in mapping array
|
|
pM -- pointer to mapping.
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
--*/
|
|
{
|
|
if ( iIndex < m_cMapping )
|
|
{
|
|
pM->UpdateMask( m_pHierarchy, m_cHierarchy);
|
|
|
|
return m_pMapping[iIndex]->Copy( pM ) && UpdateClasses( FALSE );
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CIisAcctMapper::Update(
|
|
DWORD iIndex
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Update a mapping
|
|
|
|
Arguments:
|
|
|
|
iIndex -- index in mapping array
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
--*/
|
|
{
|
|
if ( iIndex < m_cMapping )
|
|
{
|
|
return m_pMapping[iIndex]->UpdateMask( m_pHierarchy, m_cHierarchy);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CIisAcctMapper::Add(
|
|
CIisMapping* pM,
|
|
BOOL fAlternate
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Add a mapping entry to mapping array
|
|
Transfer ownership of mapping object to mapper
|
|
|
|
Arguments:
|
|
|
|
pM -- pointer to mapping to be added to mapper
|
|
fAlternate - TRUE if add to alternate list
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
--*/
|
|
{
|
|
CIisMapping **pMapping;
|
|
|
|
if ( fAlternate )
|
|
{
|
|
DWORD dwC = m_pAltMapping ? m_cAltMapping : m_cMapping;
|
|
CIisMapping** pMap = m_pAltMapping ? m_pAltMapping : m_pMapping;
|
|
|
|
pMapping = (CIisMapping**)LocalAlloc( LMEM_FIXED, sizeof(CIisMapping*)*(dwC+1) );
|
|
if ( pMapping == NULL )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if ( m_pAltMapping )
|
|
{
|
|
memcpy( pMapping, pMap, sizeof(CIisMapping*) * dwC );
|
|
LocalFree( m_pAltMapping );
|
|
}
|
|
else
|
|
{
|
|
memset( pMapping, '\0', dwC * sizeof(LPVOID) );
|
|
}
|
|
m_pAltMapping = pMapping;
|
|
m_pAltMapping[dwC] = pM;
|
|
m_cAltMapping = dwC + 1;
|
|
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
pMapping = (CIisMapping**)LocalAlloc( LMEM_FIXED, sizeof(CIisMapping*)*(m_cMapping+1) );
|
|
if ( pMapping == NULL )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if ( m_pMapping )
|
|
{
|
|
memcpy( pMapping, m_pMapping, sizeof(CIisMapping*) * m_cMapping );
|
|
LocalFree( m_pMapping );
|
|
}
|
|
m_pMapping = pMapping;
|
|
pM->UpdateMask( m_pHierarchy, m_cHierarchy );
|
|
m_pMapping[m_cMapping] = pM;
|
|
++m_cMapping;
|
|
|
|
SortMappings();
|
|
|
|
return UpdateClasses( FALSE );
|
|
}
|
|
}
|
|
|
|
|
|
DWORD
|
|
CIisAcctMapper::AddEx(
|
|
CIisMapping* pM
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Add a mapping entry to mapping array
|
|
Transfer ownership of mapping object to mapper
|
|
|
|
Arguments:
|
|
|
|
pM -- pointer to mapping to be added to mapper
|
|
|
|
Returns:
|
|
|
|
Index of entry if success, otherwise 0xffffffff
|
|
|
|
--*/
|
|
{
|
|
CIisMapping **pMapping = (CIisMapping**)LocalAlloc( LMEM_FIXED, sizeof(CIisMapping*)*(m_cMapping+1) );
|
|
if ( pMapping == NULL )
|
|
{
|
|
return 0xffffffff;
|
|
}
|
|
|
|
if ( m_pMapping )
|
|
{
|
|
memcpy( pMapping, m_pMapping, sizeof(CIisMapping*) * m_cMapping );
|
|
LocalFree( m_pMapping );
|
|
}
|
|
m_pMapping = pMapping;
|
|
pM->UpdateMask( m_pHierarchy, m_cHierarchy );
|
|
m_pMapping[m_cMapping] = pM;
|
|
++m_cMapping;
|
|
|
|
SortMappings();
|
|
|
|
if ( UpdateClasses( FALSE ) )
|
|
{
|
|
return m_cMapping-1;
|
|
}
|
|
|
|
return 0xffffffff;
|
|
}
|
|
|
|
|
|
VOID
|
|
CIisAcctMapper::DeleteMappingObject(
|
|
CIisMapping *pM
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Delete a mapping object
|
|
|
|
Arguments:
|
|
|
|
pM - ptr to mapping object
|
|
|
|
Returns:
|
|
|
|
Nothing
|
|
|
|
--*/
|
|
{
|
|
delete pM;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CIisAcctMapper::Delete(
|
|
DWORD dwIndex,
|
|
BOOL fUseAlternate
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Delete a mapping entry based on index
|
|
|
|
Arguments:
|
|
|
|
iIndex -- index in mapping array
|
|
fUseAlternate -- TRUE if update alternate list
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
--*/
|
|
{
|
|
UINT i;
|
|
UINT iM;
|
|
|
|
if ( fUseAlternate )
|
|
{
|
|
//
|
|
// clone all entries from main to alternate list
|
|
//
|
|
|
|
if ( !m_pAltMapping )
|
|
{
|
|
m_pAltMapping = (CIisMapping**)LocalAlloc( LMEM_FIXED, sizeof(CIisMapping*)*(m_cMapping) );
|
|
if ( m_pAltMapping == NULL )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
memset( m_pAltMapping, '\0', sizeof(CIisMapping*) * m_cMapping );
|
|
m_cAltMapping = m_cMapping;
|
|
}
|
|
|
|
iM = min( m_cMapping, m_cAltMapping );
|
|
|
|
for ( i = 0 ; i < iM ; ++i )
|
|
{
|
|
if ( m_pAltMapping[i] == NULL )
|
|
{
|
|
if ( !m_pMapping[i]->Clone( &m_pAltMapping[i] ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( dwIndex < m_cAltMapping )
|
|
{
|
|
delete m_pAltMapping[dwIndex];
|
|
|
|
memmove( m_pAltMapping+dwIndex,
|
|
m_pAltMapping+dwIndex+1,
|
|
(m_cAltMapping - dwIndex - 1) * sizeof(CIisMapping*) );
|
|
|
|
--m_cAltMapping;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
if ( dwIndex < m_cMapping )
|
|
{
|
|
delete m_pMapping[dwIndex];
|
|
|
|
memmove( m_pMapping+dwIndex,
|
|
m_pMapping+dwIndex+1,
|
|
(m_cMapping - dwIndex - 1) * sizeof(CIisMapping*) );
|
|
|
|
--m_cMapping;
|
|
|
|
return UpdateClasses( FALSE );
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CIisAcctMapper::Save(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Save mapper ( mappings, hierarchy, derived class private data )
|
|
to a file, updating registry entry with MD5 signature
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
--*/
|
|
{
|
|
UINT x;
|
|
FILE * fOut = NULL;
|
|
BOOL fSt = TRUE;
|
|
DWORD dwVal;
|
|
DWORD st;
|
|
IIS_CRYPTO_STORAGE storage;
|
|
PIIS_CRYPTO_BLOB blob;
|
|
|
|
Lock();
|
|
|
|
MD5Init( &m_md5 );
|
|
|
|
if ( FAILED(storage.Initialize()) )
|
|
{
|
|
fSt = FALSE;
|
|
goto cleanup;
|
|
}
|
|
|
|
if ( m_pSesKey != NULL )
|
|
{
|
|
LocalFree( m_pSesKey );
|
|
m_pSesKey = NULL;
|
|
m_dwSesKey = 0;
|
|
}
|
|
if ( FAILED( storage.GetSessionKeyBlob( &blob ) ) )
|
|
{
|
|
fSt = FALSE;
|
|
goto cleanup;
|
|
}
|
|
m_dwSesKey = IISCryptoGetBlobLength( blob );
|
|
if ( (m_pSesKey = (LPBYTE)LocalAlloc( LMEM_FIXED, m_dwSesKey)) == NULL )
|
|
{
|
|
m_dwSesKey = 0;
|
|
fSt = FALSE;
|
|
goto cleanup;
|
|
}
|
|
memcpy( m_pSesKey, (LPBYTE)blob, m_dwSesKey );
|
|
|
|
if ( (fOut = fopen( m_achFileName, "wb" )) == NULL )
|
|
{
|
|
fSt = FALSE;
|
|
goto cleanup;
|
|
}
|
|
|
|
// magic value & version
|
|
|
|
dwVal = IISMDB_FILE_MAGIC_VALUE;
|
|
if( fwrite( (LPVOID)&dwVal, sizeof(dwVal), 1, fOut ) != 1 )
|
|
{
|
|
fSt = FALSE;
|
|
goto cleanup;
|
|
}
|
|
MD5Update( &m_md5, (LPBYTE)&dwVal, sizeof(dwVal) );
|
|
|
|
dwVal = IISMDB_CURRENT_VERSION;
|
|
if( fwrite( (LPVOID)&dwVal, sizeof(dwVal), 1, fOut ) != 1 )
|
|
{
|
|
fSt = FALSE;
|
|
goto cleanup;
|
|
}
|
|
MD5Update( &m_md5, (LPBYTE)&dwVal, sizeof(dwVal) );
|
|
|
|
// mappings
|
|
|
|
if( fwrite( (LPVOID)&m_cMapping, sizeof(m_cMapping), 1, fOut ) != 1 )
|
|
{
|
|
fSt = FALSE;
|
|
goto cleanup;
|
|
}
|
|
|
|
MD5Update( &m_md5, (LPBYTE)&m_cMapping, sizeof(m_cMapping) );
|
|
|
|
for ( x = 0 ; x < m_cMapping ; ++x )
|
|
{
|
|
if ( !m_pMapping[x]->Serialize( fOut ,(VALID_CTX)&m_md5, (LPVOID)&storage) )
|
|
{
|
|
fSt = FALSE;
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
// save hierarchy
|
|
|
|
if( fwrite( (LPVOID)&m_cHierarchy, sizeof(m_cHierarchy), 1, fOut ) != 1 )
|
|
{
|
|
fSt = FALSE;
|
|
goto cleanup;
|
|
}
|
|
|
|
MD5Update( &m_md5, (LPBYTE)&m_cHierarchy, sizeof(m_cHierarchy) );
|
|
|
|
if( fwrite( (LPVOID)m_pHierarchy, sizeof(IISMDB_HEntry), m_cHierarchy, fOut ) != m_cHierarchy )
|
|
{
|
|
fSt = FALSE;
|
|
goto cleanup;
|
|
}
|
|
|
|
MD5Update( &m_md5, (LPBYTE)m_pHierarchy, sizeof(IISMDB_HEntry)*m_cHierarchy );
|
|
|
|
// save private data
|
|
|
|
fSt = SavePrivate( fOut, (VALID_CTX)&m_md5 );
|
|
|
|
MD5Final( &m_md5 );
|
|
|
|
cleanup:
|
|
if ( fOut != NULL )
|
|
{
|
|
fclose( fOut );
|
|
}
|
|
|
|
// update registry
|
|
|
|
if ( !fSt )
|
|
{
|
|
memset( m_md5.digest, '\0', sizeof(m_md5.digest) );
|
|
}
|
|
|
|
Unlock();
|
|
|
|
return fSt;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CIisAcctMapper::Reset(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Reset mapper to empty state
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
--*/
|
|
{
|
|
UINT x;
|
|
|
|
// free all mapping
|
|
if ( m_pMapping != NULL )
|
|
{
|
|
for ( x = 0 ; x < m_cMapping ; ++x )
|
|
{
|
|
delete m_pMapping[x];
|
|
}
|
|
|
|
LocalFree( m_pMapping );
|
|
m_pMapping = NULL;
|
|
}
|
|
m_cMapping = 0;
|
|
|
|
if ( m_pClasses != NULL )
|
|
{
|
|
LocalFree( m_pClasses );
|
|
m_pClasses = NULL;
|
|
}
|
|
|
|
// default hierarchy
|
|
|
|
if ( m_pHierarchy == NULL )
|
|
{
|
|
IISMDB_HEntry *pH = GetDefaultHierarchy( &m_cHierarchy );
|
|
m_pHierarchy = (IISMDB_HEntry*)LocalAlloc( LMEM_FIXED, sizeof(IISMDB_HEntry)*m_cHierarchy );
|
|
if ( m_pHierarchy == NULL )
|
|
{
|
|
return FALSE;
|
|
}
|
|
memcpy( m_pHierarchy, pH, m_cHierarchy * sizeof(IISMDB_HEntry) );
|
|
}
|
|
|
|
return ResetPrivate();
|
|
}
|
|
|
|
|
|
BOOL
|
|
CIisAcctMapper::Load(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Load mapper ( mappings, hierarchy, derived class private data )
|
|
from a file, checking registry entry for MD5 signature
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
--*/
|
|
{
|
|
UINT x;
|
|
MD5_CTX md5Check;
|
|
FILE * fIn;
|
|
BOOL fSt = TRUE;
|
|
DWORD dwType;
|
|
DWORD dwLen;
|
|
DWORD dwVal;
|
|
IIS_CRYPTO_STORAGE storage;
|
|
|
|
Reset();
|
|
|
|
MD5Init( &md5Check );
|
|
if ( FAILED( storage.Initialize( (PIIS_CRYPTO_BLOB)m_pSesKey) ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if ( (fIn = fopen( m_achFileName, "rb" )) == NULL )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
// magic value & version
|
|
|
|
if( fread( (LPVOID)&dwVal, sizeof(dwVal), 1, fIn ) != 1 )
|
|
{
|
|
fSt = FALSE;
|
|
goto cleanup;
|
|
}
|
|
if ( dwVal != IISMDB_FILE_MAGIC_VALUE )
|
|
{
|
|
SetLastError( ERROR_BAD_FORMAT );
|
|
fSt = FALSE;
|
|
goto cleanup;
|
|
}
|
|
MD5Update( &md5Check, (LPBYTE)&dwVal, sizeof(dwVal) );
|
|
|
|
if( fread( (LPVOID)&dwVal, sizeof(dwVal), 1, fIn ) != 1 )
|
|
{
|
|
fSt = FALSE;
|
|
goto cleanup;
|
|
}
|
|
MD5Update( &md5Check, (LPBYTE)&dwVal, sizeof(dwVal) );
|
|
|
|
// mappings
|
|
|
|
if( fread( (LPVOID)&m_cMapping, sizeof(m_cMapping), 1, fIn ) != 1 )
|
|
{
|
|
fSt = FALSE;
|
|
goto cleanup;
|
|
}
|
|
|
|
MD5Update( &md5Check, (LPBYTE)&m_cMapping, sizeof(m_cMapping) );
|
|
|
|
m_pMapping = (CIisMapping**)LocalAlloc( LMEM_FIXED, sizeof(CIisMapping*)*m_cMapping );
|
|
if ( m_pMapping == NULL )
|
|
{
|
|
fSt = FALSE;
|
|
goto cleanup;
|
|
}
|
|
|
|
for ( x = 0 ; x < m_cMapping ; ++x )
|
|
{
|
|
if ( !(m_pMapping[x] = CreateNewMapping()) )
|
|
{
|
|
m_cMapping = x;
|
|
fSt = FALSE;
|
|
goto cleanup;
|
|
}
|
|
if ( !m_pMapping[x]->Deserialize( fIn ,(VALID_CTX)&md5Check, (LPVOID)&storage ) )
|
|
{
|
|
m_cMapping = x;
|
|
fSt = FALSE;
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
// load hierarchy
|
|
|
|
if( fread( (LPVOID)&m_cHierarchy, sizeof(m_cHierarchy), 1, fIn ) != 1 )
|
|
{
|
|
fSt = FALSE;
|
|
goto cleanup;
|
|
}
|
|
|
|
MD5Update( &md5Check, (LPBYTE)&m_cHierarchy, sizeof(m_cHierarchy) );
|
|
|
|
m_pHierarchy = (IISMDB_HEntry*)LocalAlloc( LMEM_FIXED, sizeof(IISMDB_HEntry)*m_cHierarchy );
|
|
if ( m_pHierarchy == NULL )
|
|
{
|
|
fSt = FALSE;
|
|
goto cleanup;
|
|
}
|
|
|
|
if( fread( (LPVOID)m_pHierarchy, sizeof(IISMDB_HEntry), m_cHierarchy, fIn ) != m_cHierarchy )
|
|
{
|
|
fSt = FALSE;
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// insure hierarchy correct
|
|
//
|
|
|
|
for ( x = 0 ; x < m_cHierarchy; ++x )
|
|
{
|
|
if ( m_pHierarchy[x].m_dwIndex >= m_cFields )
|
|
{
|
|
fSt = FALSE;
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
MD5Update( &md5Check, (LPBYTE)m_pHierarchy, sizeof(IISMDB_HEntry)*m_cHierarchy );
|
|
|
|
// load private data
|
|
|
|
fSt = LoadPrivate( fIn, (VALID_CTX)&md5Check );
|
|
|
|
MD5Final( &md5Check );
|
|
|
|
#if 0
|
|
//
|
|
// Don't use signature for now - a metabase Restore operation
|
|
// may have restored another signature, so metabase and
|
|
// file won't match
|
|
//
|
|
|
|
if ( !(fSt = !memcmp( m_md5.digest,
|
|
md5Check.digest,
|
|
sizeof(md5Check.digest) )) )
|
|
{
|
|
SetLastError( ERROR_INVALID_ACCESS );
|
|
}
|
|
#endif
|
|
|
|
cleanup:
|
|
fclose( fIn );
|
|
|
|
if ( !fSt && GetLastError() != ERROR_INVALID_ACCESS )
|
|
{
|
|
Reset();
|
|
}
|
|
else
|
|
{
|
|
UpdateClasses();
|
|
}
|
|
|
|
if ( !fSt )
|
|
{
|
|
char achErr[32];
|
|
LPCTSTR pA[2];
|
|
pA[0] = m_achFileName;
|
|
pA[1] = achErr;
|
|
_itoa( GetLastError(), achErr, 10 );
|
|
ReportIisMapEvent( EVENTLOG_ERROR_TYPE,
|
|
IISMAP_EVENT_LOAD_ERROR,
|
|
2,
|
|
pA );
|
|
}
|
|
|
|
return fSt;
|
|
}
|
|
|
|
|
|
// CIisCertMapper
|
|
|
|
CIisCertMapper::CIisCertMapper(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Constructor for CIisCertMapper
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Returns:
|
|
|
|
Nothing
|
|
|
|
--*/
|
|
{
|
|
m_pIssuers = NULL;
|
|
m_cIssuers = 0;
|
|
|
|
m_pFields = IisCertMappingFields;
|
|
m_cFields = sizeof(IisCertMappingFields)/sizeof(IISMDB_Fields);
|
|
|
|
m_dwOptions = IISMDB_CERT_OPTIONS;
|
|
}
|
|
|
|
|
|
CIisCertMapper::~CIisCertMapper(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Destructor for CIisCertMapper
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Returns:
|
|
|
|
Nothing
|
|
|
|
--*/
|
|
{
|
|
}
|
|
|
|
|
|
IISMDB_HEntry*
|
|
CIisCertMapper::GetDefaultHierarchy(
|
|
LPDWORD pdwN
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
return ptr to default hierarchy for certificates mapping
|
|
|
|
Arguments:
|
|
|
|
pdwN -- updated with hierarchy entries count
|
|
|
|
Returns:
|
|
|
|
ptr to hierarchy entries or NULL if error
|
|
|
|
--*/
|
|
{
|
|
*pdwN = sizeof(IisCertMappingHierarchy) / sizeof(IISMDB_HEntry);
|
|
|
|
return IisCertMappingHierarchy;
|
|
}
|
|
|
|
|
|
#if defined(DECODE_ASN1)
|
|
CIisMapping*
|
|
CIisCertMapper::CreateNewMapping(
|
|
Cert_Map *pC
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create a new mapping from a certificate
|
|
|
|
Arguments:
|
|
|
|
pC -- ptr to certificate issuer & subject
|
|
|
|
Returns:
|
|
|
|
ptr to mapping. ownership of this object is transfered to caller.
|
|
NULL if error
|
|
|
|
--*/
|
|
{
|
|
CCertMapping *pCM = new CCertMapping( this );
|
|
if ( pCM == NULL )
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
if ( pCM->Init( pC, m_pHierarchy, m_cHierarchy ) )
|
|
{
|
|
return (CIisMapping*)pCM;
|
|
}
|
|
delete pCM;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
CIisMapping*
|
|
CIisCertMapper::CreateNewMapping(
|
|
const LPBYTE pC,
|
|
DWORD cC
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create a new mapping from a certificate
|
|
|
|
Arguments:
|
|
|
|
pC -- ptr to certificate issuer & subject
|
|
cC -- size of buffer pointed to by pC
|
|
|
|
Returns:
|
|
|
|
ptr to mapping. ownership of this object is transfered to caller.
|
|
NULL if error
|
|
|
|
--*/
|
|
{
|
|
CCertMapping *pCM = new CCertMapping( this );
|
|
if ( pCM == NULL )
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
if ( pCM->Init( pC, cC, m_pHierarchy, m_cHierarchy ) )
|
|
{
|
|
return (CIisMapping*)pCM;
|
|
}
|
|
delete pCM;
|
|
|
|
return NULL;
|
|
}
|
|
#endif
|
|
|
|
|
|
BOOL
|
|
CIisCertMapper::ResetPrivate(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Reset CIisCertMapper issuer list
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
--*/
|
|
{
|
|
// free issuer list
|
|
|
|
if ( m_pIssuers != NULL )
|
|
{
|
|
for ( UINT x = 0 ; x < m_cIssuers ; ++x )
|
|
{
|
|
LocalFree( m_pIssuers[x].pbIssuer );
|
|
}
|
|
LocalFree( m_pIssuers );
|
|
m_pIssuers = NULL;
|
|
}
|
|
m_cIssuers = 0;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CIisCertMapper::LoadPrivate(
|
|
FILE* fIn,
|
|
VALID_CTX pMD5
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Load issuer list
|
|
|
|
Arguments:
|
|
|
|
fIn -- file to read from
|
|
pMD5 -- MD5 to update with signature from input byte stream
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
--*/
|
|
{
|
|
BOOL fSt = TRUE;
|
|
UINT x;
|
|
|
|
if( fread( (LPVOID)&m_cIssuers, sizeof(m_cIssuers), 1, fIn ) != 1 )
|
|
{
|
|
fSt = FALSE;
|
|
goto cleanup;
|
|
}
|
|
|
|
MD5Update( (MD5_CTX*)pMD5, (LPBYTE)&m_cIssuers, sizeof(m_cIssuers) );
|
|
|
|
m_pIssuers = (IssuerAccepted*)LocalAlloc( LMEM_FIXED, sizeof(IssuerAccepted)*m_cIssuers );
|
|
if ( m_pIssuers == NULL )
|
|
{
|
|
fSt = FALSE;
|
|
goto cleanup;
|
|
}
|
|
|
|
for ( x = 0 ; x < m_cIssuers ; ++x )
|
|
{
|
|
if ( fread( (LPVOID)&m_pIssuers[x].cbIssuerLen, sizeof(m_pIssuers[x].cbIssuerLen), 1, fIn ) != 1 )
|
|
{
|
|
m_cIssuers = x;
|
|
fSt = FALSE;
|
|
goto cleanup;
|
|
}
|
|
|
|
MD5Update( (MD5_CTX*)pMD5, (LPBYTE)&m_pIssuers[x].cbIssuerLen, sizeof(m_pIssuers[x].cbIssuerLen) );
|
|
|
|
if ( (m_pIssuers[x].pbIssuer = (LPBYTE)LocalAlloc( LMEM_FIXED, m_pIssuers[x].cbIssuerLen )) == NULL )
|
|
{
|
|
m_cIssuers = x;
|
|
fSt = FALSE;
|
|
goto cleanup;
|
|
}
|
|
if ( fread( m_pIssuers[x].pbIssuer, m_pIssuers[x].cbIssuerLen, 1, fIn ) != 1 )
|
|
{
|
|
m_cIssuers = x;
|
|
fSt = FALSE;
|
|
goto cleanup;
|
|
}
|
|
|
|
MD5Update( (MD5_CTX*)pMD5, m_pIssuers[x].pbIssuer, m_pIssuers[x].cbIssuerLen );
|
|
}
|
|
|
|
cleanup:
|
|
return fSt;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CIisCertMapper::SavePrivate(
|
|
FILE* fOut,
|
|
VALID_CTX pMD5
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Save issuer list
|
|
|
|
Arguments:
|
|
|
|
fOut -- file to write to
|
|
pMD5 -- MD5 to update with signature of output byte stream
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
--*/
|
|
{
|
|
BOOL fSt = TRUE;
|
|
UINT x;
|
|
|
|
if( fwrite( (LPVOID)&m_cIssuers, sizeof(m_cIssuers), 1, fOut ) != 1 )
|
|
{
|
|
fSt = FALSE;
|
|
goto cleanup;
|
|
}
|
|
|
|
MD5Update( (MD5_CTX*)pMD5, (LPBYTE)&m_cIssuers, sizeof(m_cIssuers) );
|
|
|
|
for ( x = 0 ; x < m_cIssuers ; ++x )
|
|
{
|
|
if ( fwrite( (LPVOID)&m_pIssuers[x].cbIssuerLen, sizeof(m_pIssuers[x].cbIssuerLen), 1, fOut ) != 1 )
|
|
{
|
|
fSt = FALSE;
|
|
goto cleanup;
|
|
}
|
|
|
|
MD5Update( (MD5_CTX*)pMD5, (LPBYTE)&m_pIssuers[x].cbIssuerLen, sizeof(m_pIssuers[x].cbIssuerLen) );
|
|
|
|
if ( fwrite( m_pIssuers[x].pbIssuer, m_pIssuers[x].cbIssuerLen, 1, fOut ) != 1 )
|
|
{
|
|
fSt = FALSE;
|
|
goto cleanup;
|
|
}
|
|
|
|
MD5Update( (MD5_CTX*)pMD5, m_pIssuers[x].pbIssuer, m_pIssuers[x].cbIssuerLen );
|
|
}
|
|
|
|
cleanup:
|
|
return fSt;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CIisCertMapper::SetIssuerList(
|
|
IssuerAccepted*pI,
|
|
DWORD dwC
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Set the issuer list by copying supplied list
|
|
|
|
Arguments:
|
|
|
|
pI -- list of issuers
|
|
dwC -- count of issuers
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
--*/
|
|
{
|
|
UINT x;
|
|
|
|
if ( (m_pIssuers = (IssuerAccepted*)LocalAlloc( LMEM_FIXED, sizeof(IssuerAccepted)*dwC )) == NULL )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
for ( x = 0 ; x < dwC ; ++x )
|
|
{
|
|
m_pIssuers[x].cbIssuerLen = pI[x].cbIssuerLen;
|
|
if ( (m_pIssuers[x].pbIssuer = (LPBYTE)LocalAlloc( LMEM_FIXED, pI[x].cbIssuerLen )) == NULL )
|
|
{
|
|
m_cIssuers = x;
|
|
return FALSE;
|
|
}
|
|
memcpy( m_pIssuers[x].pbIssuer, pI[x].pbIssuer, pI[x].cbIssuerLen );
|
|
}
|
|
m_cIssuers = dwC;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CIisCertMapper::GetIssuerList(
|
|
IssuerAccepted**pIssuers,
|
|
DWORD*pdwI
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Retrieve the issuer list. Ownership of list transferred to caller
|
|
|
|
Arguments:
|
|
|
|
pI -- updated with ptr to array of issuers
|
|
pdwI -- updated with count of issuers
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
--*/
|
|
{
|
|
IssuerAccepted *pI;
|
|
|
|
Lock();
|
|
|
|
pI = (IssuerAccepted*)LocalAlloc( LMEM_FIXED, m_cIssuers * sizeof(IssuerAccepted*) );
|
|
if ( pI == NULL )
|
|
{
|
|
Unlock();
|
|
return FALSE;
|
|
}
|
|
|
|
for ( UINT x = 0 ; x < m_cIssuers ; ++x )
|
|
{
|
|
if ( (pI[x].pbIssuer = (LPBYTE)LocalAlloc( LMEM_FIXED,
|
|
m_pIssuers[x].cbIssuerLen ))
|
|
== NULL )
|
|
{
|
|
Unlock();
|
|
DeleteIssuerList( pI, x );
|
|
return FALSE;
|
|
}
|
|
memcpy( pI[x].pbIssuer,
|
|
m_pIssuers[x].pbIssuer,
|
|
m_pIssuers[x].cbIssuerLen );
|
|
}
|
|
|
|
*pIssuers = pI;
|
|
*pdwI = m_cIssuers;
|
|
|
|
Unlock();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
CIisCertMapper::DeleteIssuerList(
|
|
IssuerAccepted* pI,
|
|
DWORD dwI
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Delete an issuer list.
|
|
|
|
Arguments:
|
|
|
|
pI -- ptr to array of issuers
|
|
dwI -- count of issuers
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
--*/
|
|
{
|
|
for ( DWORD x = 0 ; x < dwI ; ++x )
|
|
{
|
|
LocalFree( pI[x].pbIssuer );
|
|
}
|
|
LocalFree( pI );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CIisCertMapper::GetIssuerBuffer(
|
|
LPBYTE pB,
|
|
DWORD* pdwI
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Retrieve the issuer list. Ownership of list transferred to caller
|
|
|
|
Arguments:
|
|
|
|
pB -- updated with ptr to issuers buffer
|
|
pdwI -- updated with size of buffer of issuers
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
--*/
|
|
{
|
|
LPBYTE pS;
|
|
DWORD dwC = 0;
|
|
|
|
Lock();
|
|
|
|
for ( UINT x = 0 ; x < m_cIssuers ; ++x )
|
|
{
|
|
dwC += m_pIssuers[x].cbIssuerLen + sizeof(USHORT);
|
|
}
|
|
|
|
*pdwI = dwC;
|
|
|
|
if ( pB != NULL )
|
|
{
|
|
for ( pS = pB, x = 0 ; x < m_cIssuers ; ++x )
|
|
{
|
|
pS[0] = (BYTE)(m_pIssuers[x].cbIssuerLen >> 8);
|
|
pS[1] = (BYTE)(m_pIssuers[x].cbIssuerLen);
|
|
memcpy( pS + sizeof(USHORT),
|
|
m_pIssuers[x].pbIssuer,
|
|
m_pIssuers[x].cbIssuerLen );
|
|
pS += m_pIssuers[x].cbIssuerLen + sizeof(USHORT);
|
|
}
|
|
}
|
|
|
|
Unlock();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
CIisCertMapper::FreeIssuerBuffer(
|
|
LPBYTE pI
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Delete an issuer list.
|
|
|
|
Arguments:
|
|
|
|
pI -- ptr to issuers
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
--*/
|
|
{
|
|
LocalFree( pI );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
// CIisCert11Mapper
|
|
|
|
CIisCert11Mapper::CIisCert11Mapper(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Constructor for CIisCert11Mapper
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Returns:
|
|
|
|
Nothing
|
|
|
|
--*/
|
|
{
|
|
m_pIssuers = NULL;
|
|
m_cIssuers = 0;
|
|
|
|
m_pFields = IisCert11MappingFields;
|
|
m_cFields = sizeof(IisCert11MappingFields)/sizeof(IISMDB_Fields);
|
|
|
|
m_dwOptions = IISMDB_CERT11_OPTIONS;
|
|
|
|
m_pSubjectSource = NULL;
|
|
m_pDefaultDomain = NULL;
|
|
}
|
|
|
|
|
|
CIisCert11Mapper::~CIisCert11Mapper(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Destructor for CIisCert11Mapper
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Returns:
|
|
|
|
Nothing
|
|
|
|
--*/
|
|
{
|
|
}
|
|
|
|
|
|
BOOL
|
|
CIisCert11Mapper::Add(
|
|
CIisMapping* pM
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Add a mapping entry to mapping array
|
|
Transfer ownership of mapping object to mapper
|
|
Check is mapping to same NT account does not already exist.
|
|
|
|
Arguments:
|
|
|
|
pM -- pointer to mapping to be added to mapper
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
--*/
|
|
{
|
|
UINT x;
|
|
LPSTR pA;
|
|
LPSTR pF;
|
|
DWORD dwA;
|
|
DWORD dwF;
|
|
|
|
// check if NT acct not already present.
|
|
// if so, return FALSE, SetLastError( ERROR_INVALID_PARAMETER );
|
|
|
|
if ( pM == NULL )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
#if 0
|
|
if ( !pM->MappingGetField( IISMDB_INDEX_CERT11_NT_ACCT, &pA, &dwA, FALSE )
|
|
|| pA == NULL )
|
|
{
|
|
pA = "";
|
|
}
|
|
|
|
for ( x = 0 ; x < m_cMapping ; ++x )
|
|
{
|
|
if ( !m_pMapping[x]->MappingGetField( IISMDB_INDEX_CERT11_NT_ACCT, &pF, &dwF, FALSE )
|
|
|| pF == NULL )
|
|
{
|
|
pF = "";
|
|
}
|
|
if ( dwA == dwF && !memcmp( pF, pA, dwF ) )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return FALSE;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if 1
|
|
#if defined(CERT11_FULL_CERT)
|
|
LPSTR pCe;
|
|
DWORD dwCe;
|
|
LPSTR pCeIter;
|
|
DWORD dwCeIter;
|
|
|
|
if ( !pM->MappingGetField( IISMDB_INDEX_CERT11_CERT, &pCe, &dwCe, FALSE )
|
|
|| pCe == NULL )
|
|
{
|
|
dwCe = 0;
|
|
}
|
|
|
|
for ( x = 0 ; x < m_cMapping ; ++x )
|
|
{
|
|
if ( !m_pMapping[x]->MappingGetField( IISMDB_INDEX_CERT11_CERT, &pCeIter, &dwCeIter, FALSE )
|
|
|| pCeIter == NULL )
|
|
{
|
|
dwCeIter = 0;
|
|
}
|
|
if ( dwCe == dwCeIter && !memcmp( pCe, pCeIter, dwCe ) )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return FALSE;
|
|
}
|
|
}
|
|
#else
|
|
LPSTR pSu;
|
|
LPSTR pIs;
|
|
DWORD dwSu;
|
|
DWORD dwIs;
|
|
LPSTR pSuIter;
|
|
LPSTR pIsIter;
|
|
DWORD dwSuIter;
|
|
DWORD dwIsIter;
|
|
|
|
if ( !pM->MappingGetField( IISMDB_INDEX_CERT11_SUBJECT, &pSu, &dwSu, FALSE )
|
|
|| pSu == NULL )
|
|
{
|
|
dwSu = 0;
|
|
}
|
|
|
|
if ( !pM->MappingGetField( IISMDB_INDEX_CERT11_ISSUER, &pIs, &dwIs, FALSE )
|
|
|| pIs == NULL )
|
|
{
|
|
dwIs = 0;
|
|
}
|
|
|
|
for ( x = 0 ; x < m_cMapping ; ++x )
|
|
{
|
|
if ( !m_pMapping[x]->MappingGetField( IISMDB_INDEX_CERT11_SUBJECT, &pSuIter, &dwSuIter, FALSE )
|
|
|| pSuIter == NULL )
|
|
{
|
|
dwSuIter = 0;
|
|
}
|
|
if ( !m_pMapping[x]->MappingGetField( IISMDB_INDEX_CERT11_ISSUER, &pIsIter, &dwIsIter, FALSE )
|
|
|| pIsIter == NULL )
|
|
{
|
|
dwIsIter = 0;
|
|
}
|
|
if ( dwSu == dwSuIter && !memcmp( pSu, pSuIter, dwSu ) &&
|
|
dwIs == dwIsIter && !memcmp( pIs, pIsIter, dwIs ) )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return FALSE;
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
return CIisAcctMapper::Add( pM );
|
|
}
|
|
|
|
|
|
IISMDB_HEntry*
|
|
CIisCert11Mapper::GetDefaultHierarchy(
|
|
LPDWORD pdwN
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
return ptr to default hierarchy for certificates mapping
|
|
|
|
Arguments:
|
|
|
|
pdwN -- updated with hierarchy entries count
|
|
|
|
Returns:
|
|
|
|
ptr to hierarchy entries or NULL if error
|
|
|
|
--*/
|
|
{
|
|
*pdwN = sizeof(IisCert11MappingHierarchy) / sizeof(IISMDB_HEntry);
|
|
|
|
return IisCert11MappingHierarchy;
|
|
}
|
|
|
|
|
|
#if defined(CERT11_FULL_CERT)
|
|
|
|
CIisMapping*
|
|
CIisCert11Mapper::CreateNewMapping(
|
|
LPBYTE pC,
|
|
DWORD dwC
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create a new mapping from a certificate
|
|
|
|
Arguments:
|
|
|
|
pC -- cert ( ASN.1 format )
|
|
dwC -- length of cert
|
|
|
|
Returns:
|
|
|
|
ptr to mapping. ownership of this object is transfered to caller.
|
|
NULL if error
|
|
|
|
--*/
|
|
{
|
|
CCert11Mapping *pCM = new CCert11Mapping( this );
|
|
if ( pCM == NULL )
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
if ( pCM->Init( pC, dwC, m_pHierarchy, m_cHierarchy ) )
|
|
{
|
|
return (CIisMapping*)pCM;
|
|
}
|
|
delete pCM;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
#else
|
|
|
|
CIisMapping*
|
|
CIisCert11Mapper::CreateNewMapping(
|
|
LPBYTE pI,
|
|
DWORD dwI,
|
|
LPBYTE pS,
|
|
DWORD dwS
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create a new mapping from a certificate
|
|
|
|
Arguments:
|
|
|
|
pI -- cert issuer ( ASN.1 format )
|
|
dwI -- length of issuer
|
|
pS -- cert subject ( ASN.1 format )
|
|
dwS -- length of subject
|
|
|
|
Returns:
|
|
|
|
ptr to mapping. ownership of this object is transfered to caller.
|
|
NULL if error
|
|
|
|
--*/
|
|
{
|
|
CCert11Mapping *pCM = new CCert11Mapping( this );
|
|
if ( pCM == NULL )
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
if ( pCM->Init( pI, dwI, pS, dwS, m_pHierarchy, m_cHierarchy ) )
|
|
{
|
|
return (CIisMapping*)pCM;
|
|
}
|
|
delete pCM;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
BOOL
|
|
CIisCert11Mapper::ResetPrivate(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Reset CIisCert11Mapper issuer list
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
--*/
|
|
{
|
|
// free issuer list
|
|
|
|
if ( m_pIssuers != NULL )
|
|
{
|
|
for ( UINT x = 0 ; x < m_cIssuers ; ++x )
|
|
{
|
|
LocalFree( m_pIssuers[x].pbIssuer );
|
|
}
|
|
LocalFree( m_pIssuers );
|
|
m_pIssuers = NULL;
|
|
}
|
|
m_cIssuers = 0;
|
|
|
|
if ( m_pSubjectSource != NULL )
|
|
{
|
|
LocalFree( m_pSubjectSource );
|
|
}
|
|
|
|
if ( m_pDefaultDomain != NULL )
|
|
{
|
|
LocalFree( m_pDefaultDomain );
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CIisCert11Mapper::LoadPrivate(
|
|
FILE* fIn,
|
|
VALID_CTX pMD5
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Load issuer list
|
|
|
|
Arguments:
|
|
|
|
fIn -- file to read from
|
|
pMD5 -- MD5 to update with signature from input byte stream
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
--*/
|
|
{
|
|
BOOL fSt = TRUE;
|
|
UINT x;
|
|
UINT cLen;
|
|
CHAR achBuf[64];
|
|
|
|
if( fread( (LPVOID)&m_cIssuers, sizeof(m_cIssuers), 1, fIn ) != 1 )
|
|
{
|
|
fSt = FALSE;
|
|
goto cleanup;
|
|
}
|
|
|
|
MD5Update( (MD5_CTX*)pMD5, (LPBYTE)&m_cIssuers, sizeof(m_cIssuers) );
|
|
|
|
m_pIssuers = (IssuerAccepted*)LocalAlloc( LMEM_FIXED, sizeof(IssuerAccepted)*m_cIssuers );
|
|
if ( m_pIssuers == NULL )
|
|
{
|
|
fSt = FALSE;
|
|
goto cleanup;
|
|
}
|
|
|
|
for ( x = 0 ; x < m_cIssuers ; ++x )
|
|
{
|
|
if ( fread( (LPVOID)&m_pIssuers[x].cbIssuerLen, sizeof(m_pIssuers[x].cbIssuerLen), 1, fIn ) != 1 )
|
|
{
|
|
m_cIssuers = x;
|
|
fSt = FALSE;
|
|
goto cleanup;
|
|
}
|
|
|
|
MD5Update( (MD5_CTX*)pMD5, (LPBYTE)&m_pIssuers[x].cbIssuerLen, sizeof(m_pIssuers[x].cbIssuerLen) );
|
|
|
|
if ( (m_pIssuers[x].pbIssuer = (LPBYTE)LocalAlloc( LMEM_FIXED, m_pIssuers[x].cbIssuerLen )) == NULL )
|
|
{
|
|
m_cIssuers = x;
|
|
fSt = FALSE;
|
|
goto cleanup;
|
|
}
|
|
if ( fread( m_pIssuers[x].pbIssuer, m_pIssuers[x].cbIssuerLen, 1, fIn ) != 1 )
|
|
{
|
|
m_cIssuers = x;
|
|
fSt = FALSE;
|
|
goto cleanup;
|
|
}
|
|
|
|
MD5Update( (MD5_CTX*)pMD5, m_pIssuers[x].pbIssuer, m_pIssuers[x].cbIssuerLen );
|
|
}
|
|
|
|
//
|
|
// Read subject source
|
|
//
|
|
|
|
if( Iisfgets( achBuf, sizeof(achBuf), fIn ) == NULL )
|
|
{
|
|
fSt = FALSE;
|
|
goto cleanup;
|
|
}
|
|
cLen = strlen(achBuf);
|
|
MD5Update( (MD5_CTX*)pMD5, (LPBYTE)achBuf, cLen );
|
|
if ( !(m_pSubjectSource = (LPSTR)LocalAlloc( LMEM_FIXED, cLen+1 )) )
|
|
{
|
|
fSt = FALSE;
|
|
goto cleanup;
|
|
}
|
|
memcpy( m_pSubjectSource, achBuf, cLen+1 );
|
|
|
|
//
|
|
// Read default domain
|
|
//
|
|
|
|
if( Iisfgets( achBuf, sizeof(achBuf), fIn ) == NULL )
|
|
{
|
|
fSt = FALSE;
|
|
goto cleanup;
|
|
}
|
|
cLen = strlen(achBuf);
|
|
MD5Update( (MD5_CTX*)pMD5, (LPBYTE)achBuf, cLen );
|
|
if ( !(m_pDefaultDomain = (LPSTR)LocalAlloc( LMEM_FIXED, cLen+1 )) )
|
|
{
|
|
fSt = FALSE;
|
|
goto cleanup;
|
|
}
|
|
memcpy( m_pDefaultDomain, achBuf, cLen+1 );
|
|
|
|
cleanup:
|
|
return fSt;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CIisCert11Mapper::SavePrivate(
|
|
FILE* fOut,
|
|
VALID_CTX pMD5
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Save issuer list
|
|
|
|
Arguments:
|
|
|
|
fOut -- file to write to
|
|
pMD5 -- MD5 to update with signature of output byte stream
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
--*/
|
|
{
|
|
BOOL fSt = TRUE;
|
|
UINT x;
|
|
|
|
if( fwrite( (LPVOID)&m_cIssuers, sizeof(m_cIssuers), 1, fOut ) != 1 )
|
|
{
|
|
fSt = FALSE;
|
|
goto cleanup;
|
|
}
|
|
|
|
MD5Update( (MD5_CTX*)pMD5, (LPBYTE)&m_cIssuers, sizeof(m_cIssuers) );
|
|
|
|
for ( x = 0 ; x < m_cIssuers ; ++x )
|
|
{
|
|
if ( fwrite( (LPVOID)&m_pIssuers[x].cbIssuerLen, sizeof(m_pIssuers[x].cbIssuerLen), 1, fOut ) != 1 )
|
|
{
|
|
fSt = FALSE;
|
|
goto cleanup;
|
|
}
|
|
|
|
MD5Update( (MD5_CTX*)pMD5, (LPBYTE)&m_pIssuers[x].cbIssuerLen, sizeof(m_pIssuers[x].cbIssuerLen) );
|
|
|
|
if ( fwrite( m_pIssuers[x].pbIssuer, m_pIssuers[x].cbIssuerLen, 1, fOut ) != 1 )
|
|
{
|
|
fSt = FALSE;
|
|
goto cleanup;
|
|
}
|
|
|
|
MD5Update( (MD5_CTX*)pMD5, m_pIssuers[x].pbIssuer, m_pIssuers[x].cbIssuerLen );
|
|
}
|
|
|
|
//
|
|
// Write subject source
|
|
//
|
|
|
|
if ( m_pSubjectSource )
|
|
{
|
|
if( Iisfputs( m_pSubjectSource, fOut ) == EOF )
|
|
{
|
|
fSt = FALSE;
|
|
goto cleanup;
|
|
}
|
|
MD5Update( (MD5_CTX*)pMD5, (LPBYTE)m_pSubjectSource, strlen( m_pSubjectSource ) );
|
|
}
|
|
else
|
|
{
|
|
Iisfputs( "", fOut );
|
|
}
|
|
|
|
//
|
|
// Write default domain
|
|
//
|
|
|
|
if ( m_pDefaultDomain )
|
|
{
|
|
if( Iisfputs( m_pDefaultDomain, fOut ) == EOF )
|
|
{
|
|
fSt = FALSE;
|
|
goto cleanup;
|
|
}
|
|
MD5Update( (MD5_CTX*)pMD5, (LPBYTE)m_pDefaultDomain, strlen( m_pDefaultDomain ) );
|
|
}
|
|
else
|
|
{
|
|
Iisfputs( "", fOut );
|
|
}
|
|
|
|
cleanup:
|
|
return fSt;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CIisCert11Mapper::SetSubjectSource(
|
|
LPSTR psz
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Set the subject field to use as source for NT acct
|
|
|
|
Arguments:
|
|
|
|
psz - ASN.1 name of field to use
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
--*/
|
|
{
|
|
if ( m_pSubjectSource != NULL )
|
|
{
|
|
LocalFree( m_pSubjectSource );
|
|
}
|
|
|
|
if ( m_pSubjectSource = (LPSTR)LocalAlloc( LMEM_FIXED, strlen(psz)+1) )
|
|
{
|
|
strcpy( m_pSubjectSource, psz );
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CIisCert11Mapper::SetDefaultDomain(
|
|
LPSTR psz
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Set the domain to use for NT acct
|
|
|
|
Arguments:
|
|
|
|
psz - domain name
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
--*/
|
|
{
|
|
if ( m_pDefaultDomain != NULL )
|
|
{
|
|
LocalFree( m_pDefaultDomain );
|
|
}
|
|
|
|
if ( m_pDefaultDomain = (LPSTR)LocalAlloc( LMEM_FIXED, strlen(psz)+1) )
|
|
{
|
|
strcpy( m_pDefaultDomain, psz );
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CIisCert11Mapper::SetIssuerList(
|
|
IssuerAccepted*pI,
|
|
DWORD dwC
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Set the issuer list by copying supplied list
|
|
|
|
Arguments:
|
|
|
|
pI -- list of issuers
|
|
dwC -- count of issuers
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
--*/
|
|
{
|
|
UINT x;
|
|
|
|
if ( (m_pIssuers = (IssuerAccepted*)LocalAlloc( LMEM_FIXED, sizeof(IssuerAccepted)*dwC )) == NULL )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
for ( x = 0 ; x < dwC ; ++x )
|
|
{
|
|
m_pIssuers[x].cbIssuerLen = pI[x].cbIssuerLen;
|
|
if ( (m_pIssuers[x].pbIssuer = (LPBYTE)LocalAlloc( LMEM_FIXED, pI[x].cbIssuerLen )) == NULL )
|
|
{
|
|
m_cIssuers = x;
|
|
return FALSE;
|
|
}
|
|
memcpy( m_pIssuers[x].pbIssuer, pI[x].pbIssuer, pI[x].cbIssuerLen );
|
|
}
|
|
m_cIssuers = dwC;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CIisCert11Mapper::GetIssuerList(
|
|
IssuerAccepted**pIssuers,
|
|
DWORD*pdwI
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Retrieve the issuer list. Ownership of list transferred to caller
|
|
|
|
Arguments:
|
|
|
|
pI -- updated with ptr to array of issuers
|
|
pdwI -- updated with count of issuers
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
--*/
|
|
{
|
|
IssuerAccepted *pI;
|
|
|
|
Lock();
|
|
|
|
pI = (IssuerAccepted*)LocalAlloc( LMEM_FIXED, m_cIssuers * sizeof(IssuerAccepted*) );
|
|
if ( pI == NULL )
|
|
{
|
|
Unlock();
|
|
return FALSE;
|
|
}
|
|
|
|
for ( UINT x = 0 ; x < m_cIssuers ; ++x )
|
|
{
|
|
if ( (pI[x].pbIssuer = (LPBYTE)LocalAlloc( LMEM_FIXED,
|
|
m_pIssuers[x].cbIssuerLen ))
|
|
== NULL )
|
|
{
|
|
Unlock();
|
|
DeleteIssuerList( pI, x );
|
|
return FALSE;
|
|
}
|
|
memcpy( pI[x].pbIssuer,
|
|
m_pIssuers[x].pbIssuer,
|
|
m_pIssuers[x].cbIssuerLen );
|
|
}
|
|
|
|
*pIssuers = pI;
|
|
*pdwI = m_cIssuers;
|
|
|
|
Unlock();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
CIisCert11Mapper::DeleteIssuerList(
|
|
IssuerAccepted* pI,
|
|
DWORD dwI
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Delete an issuer list.
|
|
|
|
Arguments:
|
|
|
|
pI -- ptr to array of issuers
|
|
dwI -- count of issuers
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
--*/
|
|
{
|
|
for ( DWORD x = 0 ; x < dwI ; ++x )
|
|
{
|
|
LocalFree( pI[x].pbIssuer );
|
|
}
|
|
LocalFree( pI );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CIisCert11Mapper::GetIssuerBuffer(
|
|
LPBYTE pB,
|
|
DWORD* pdwI
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Retrieve the issuer list. Ownership of list transferred to caller
|
|
|
|
Arguments:
|
|
|
|
pB -- updated with ptr to issuers buffer
|
|
pdwI -- updated with size of buffer of issuers
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
--*/
|
|
{
|
|
LPBYTE pS;
|
|
DWORD dwC = 0;
|
|
|
|
Lock();
|
|
|
|
for ( UINT x = 0 ; x < m_cIssuers ; ++x )
|
|
{
|
|
dwC += m_pIssuers[x].cbIssuerLen + sizeof(USHORT);
|
|
}
|
|
|
|
*pdwI = dwC;
|
|
|
|
if ( pB != NULL )
|
|
{
|
|
for ( pS = pB, x = 0 ; x < m_cIssuers ; ++x )
|
|
{
|
|
pS[0] = (BYTE)(m_pIssuers[x].cbIssuerLen >> 8);
|
|
pS[1] = (BYTE)(m_pIssuers[x].cbIssuerLen);
|
|
memcpy( pS + sizeof(USHORT),
|
|
m_pIssuers[x].pbIssuer,
|
|
m_pIssuers[x].cbIssuerLen );
|
|
pS += m_pIssuers[x].cbIssuerLen + sizeof(USHORT);
|
|
}
|
|
}
|
|
|
|
Unlock();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
CIisCert11Mapper::FreeIssuerBuffer(
|
|
LPBYTE pI
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Delete an issuer list.
|
|
|
|
Arguments:
|
|
|
|
pI -- ptr to issuers
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
--*/
|
|
{
|
|
LocalFree( pI );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
// CCertMapping
|
|
|
|
CCertMapping::CCertMapping(
|
|
CIisAcctMapper* pMap
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Constructor for CCertMapping
|
|
|
|
Arguments:
|
|
|
|
pMap -- ptr to mapper object linked to this mapping
|
|
|
|
Returns:
|
|
|
|
Nothing
|
|
|
|
--*/
|
|
{
|
|
m_pMapper = (CIisAcctMapper*)pMap;
|
|
|
|
for ( int x = 0 ; x < sizeof(m_pFields)/sizeof(LPSTR) ; ++x )
|
|
{
|
|
m_pFields[x] = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
CCertMapping::~CCertMapping(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Destructor for CCertMapping
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Returns:
|
|
|
|
Nothing
|
|
|
|
--*/
|
|
{
|
|
}
|
|
|
|
|
|
#if defined(DECODE_ASN1)
|
|
BOOL
|
|
DecodeNextField(
|
|
LPBYTE* ppAscii,
|
|
DWORD* pcAscii,
|
|
int* piF,
|
|
LPBYTE* ppN
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Decode next field certificate ASCII representation
|
|
field format as
|
|
name=content
|
|
where name is zero or more non comma chars
|
|
|
|
Arguments:
|
|
|
|
ppAscii - ptr to buffer where to scan for next field
|
|
updated with ptr to field content
|
|
pcAscii - ptr to count of char in ppAscii
|
|
updated with count of remaining char after ppAscii update
|
|
piF - updated with field type ( -1: unrecognized, 0:O, 1:OU, 2:C, 3:CN )
|
|
ppN - updated with ptr to field name
|
|
|
|
Returns:
|
|
|
|
TRUE if next field exists, otherwise FALSE
|
|
|
|
--*/
|
|
{
|
|
LPBYTE pAscii = *ppAscii;
|
|
LPBYTE pN;
|
|
int iF;
|
|
LPBYTE p = (LPBYTE)memchr( pAscii, '=', *pcAscii );
|
|
|
|
if ( p == NULL )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
for ( pN = p ; pN > pAscii && pN[-1] != ' ' ; --pN )
|
|
{
|
|
}
|
|
|
|
if ( pN[0] == 'O' && pN[1] == '=' )
|
|
{
|
|
iF = 0;
|
|
}
|
|
else if ( pN[0] == 'O' && pN[1] == 'U' && pN[2] == '=' )
|
|
{
|
|
iF = 1;
|
|
}
|
|
else if ( pN[0] == 'C' && pN[1] == '=' )
|
|
{
|
|
iF = 2;
|
|
}
|
|
else if ( pN[0] == 'C' && pN[1] == 'U' && pN[2] == '=' )
|
|
{
|
|
iF = 3;
|
|
}
|
|
else
|
|
{
|
|
iF = -1;
|
|
}
|
|
|
|
*piF = iF;
|
|
*pcAscii -= (p + 1 - pAscii);
|
|
*ppAscii = p + 1;
|
|
*ppN = pN;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
int
|
|
IisDecodeAsciiDN(
|
|
LPSTR *pF,
|
|
LPSTR pStore,
|
|
LPBYTE pAscii,
|
|
DWORD cAscii
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Decode certificate ASCII representation to an array of well-known fields
|
|
( 0:O, 1:OU, 2:C, 3:CN )
|
|
|
|
Arguments:
|
|
|
|
pF - ptr to array of fields to be updated with ptr to field content
|
|
pStore - buffer to be used to store fields content, assumed to be big enough
|
|
pAscii - ptr to buffer where to scan for fields
|
|
cAscii - ptr to count of char in pAscii
|
|
|
|
Returns:
|
|
|
|
# of chars stored in pStore
|
|
|
|
--*/
|
|
{
|
|
int iF;
|
|
int iNF;
|
|
LPBYTE pN;
|
|
BOOL f;
|
|
int l = 0;
|
|
|
|
//O, OU, C, CN
|
|
|
|
f = DecodeNextField( &pAscii, &cAscii, &iF, &pN );
|
|
|
|
for ( ; f ; )
|
|
{
|
|
LPBYTE pC = pAscii;
|
|
if ( !(f=DecodeNextField( &pAscii, &cAscii, &iNF, &pN )) )
|
|
{
|
|
pN = pAscii + cAscii;
|
|
}
|
|
else
|
|
{
|
|
while ( pN > pC && *pN != ',' )
|
|
{
|
|
--pN;
|
|
}
|
|
}
|
|
|
|
// field content is from pC to pN-1 inclusive
|
|
|
|
if ( iF >= 0 )
|
|
{
|
|
pF[iF] = pStore;
|
|
int cL = pN - pC;
|
|
memcpy( pStore, pC, cL );
|
|
pStore[cL++] = '\0';
|
|
l += cL;
|
|
pStore += cL;
|
|
}
|
|
|
|
iF = iNF;
|
|
}
|
|
|
|
return l;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CCertMapping::Init(
|
|
Cert_Map *pCert,
|
|
IISMDB_HEntry *pH,
|
|
DWORD dwH
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Constructor for CCertMapping
|
|
|
|
Arguments:
|
|
|
|
pCert -- ptr to certificate info to initialize from
|
|
pH -- ptr to hierarchy info
|
|
dwH -- number of hierarchy entries
|
|
|
|
Returns:
|
|
|
|
TRUE if success, otherwise FALSE
|
|
|
|
--*/
|
|
{
|
|
int l;
|
|
int l2;
|
|
|
|
if ( m_pBuff )
|
|
{
|
|
LocalFree( m_pBuff );
|
|
}
|
|
|
|
m_cUsedBuff = 0;
|
|
|
|
if ( !(m_pBuff = (LPBYTE)LocalAlloc( LMEM_FIXED, m_cAllocBuff = 2048 )) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
for ( int x = 0 ; x < sizeof(m_pFields)/sizeof(LPSTR) ; ++x )
|
|
{
|
|
m_pFields[x] = NULL;
|
|
}
|
|
|
|
//
|
|
// Check if content ASCII ( if so, 1st byte is a field name, so >= 'A' )
|
|
//
|
|
|
|
if ( pCert->cbIssuerLen && pCert->pIssuer[0] >= 'A' )
|
|
{
|
|
if ( (l = IisDecodeAsciiDN( m_pFields,
|
|
(LPSTR)m_pBuff,
|
|
pCert->pIssuer,
|
|
pCert->cbIssuerLen
|
|
)) == -1
|
|
|| (l2 = IisDecodeAsciiDN(
|
|
m_pFields+3,
|
|
(LPSTR)m_pBuff+l,
|
|
pCert->pSubject,
|
|
pCert->cbSubjectLen
|
|
)) == -1
|
|
)
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return FALSE;
|
|
}
|
|
}
|
|
//
|
|
// otherwise decode ASN.1 format
|
|
//
|
|
else if ( (l = IisDecodeDN( m_pFields,
|
|
(LPSTR)m_pBuff,
|
|
pCert->pIssuer,
|
|
pCert->cbIssuerLen
|
|
)) == -1
|
|
|| (l2 = IisDecodeDN(
|
|
m_pFields+3,
|
|
(LPSTR)m_pBuff+l,
|
|
pCert->pSubject,
|
|
pCert->cbSubjectLen
|
|
)) == -1
|
|
)
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return FALSE;
|
|
}
|
|
|
|
m_cUsedBuff = (UINT)(l + l2);
|
|
|
|
UpdateMask( pH, dwH );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CCertMapping::Init(
|
|
const LPBYTE pCert,
|
|
DWORD cCert,
|
|
IISMDB_HEntry *pH,
|
|
DWORD dwH
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Constructor for CCertMapping
|
|
|
|
Arguments:
|
|
|
|
pCert -- ptr to certificate info to initialize from
|
|
cCert -- size of buffer pointed to by pCert
|
|
pH -- ptr to hierarchy info
|
|
dwH -- number of hierarchy entries
|
|
|
|
Returns:
|
|
|
|
TRUE if success, otherwise FALSE
|
|
|
|
--*/
|
|
{
|
|
UINT l;
|
|
|
|
if ( m_pBuff )
|
|
{
|
|
LocalFree( m_pBuff );
|
|
}
|
|
|
|
m_cUsedBuff = 0;
|
|
|
|
if ( !(m_pBuff = (LPBYTE)LocalAlloc( LMEM_FIXED, m_cAllocBuff = 2048 )) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
for ( int x = 0 ; x < sizeof(m_pFields)/sizeof(LPSTR) ; ++x )
|
|
{
|
|
m_pFields[x] = NULL;
|
|
}
|
|
|
|
//
|
|
// decode ASN.1 format
|
|
//
|
|
// extract issuer, subject from pCert, cCert
|
|
// O, OU, C, CN ( issuer then subject )
|
|
//
|
|
|
|
if ( (l = DecodeCert(
|
|
pCert,
|
|
cCert,
|
|
m_pFields,
|
|
(LPSTR)m_pBuff
|
|
)) == 0
|
|
)
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return FALSE;
|
|
}
|
|
|
|
m_cUsedBuff = l;
|
|
|
|
UpdateMask( pH, dwH );
|
|
|
|
return TRUE;
|
|
}
|
|
#endif
|
|
|
|
|
|
// CCert11Mapping
|
|
|
|
CCert11Mapping::CCert11Mapping(
|
|
CIisAcctMapper* pMap
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Constructor for CCert11Mapping
|
|
|
|
Arguments:
|
|
|
|
pMap -- ptr to mapper object linked to this mapping
|
|
|
|
Returns:
|
|
|
|
Nothing
|
|
|
|
--*/
|
|
{
|
|
m_pMapper = (CIisAcctMapper*)pMap;
|
|
|
|
for ( int x = 0 ; x < sizeof(m_pFields)/sizeof(LPSTR) ; ++x )
|
|
{
|
|
m_pFields[x] = NULL;
|
|
}
|
|
for ( x = 0 ; x < sizeof(m_pFields)/sizeof(LPSTR) ; ++x )
|
|
{
|
|
m_cFields[x] = 0;
|
|
}
|
|
}
|
|
|
|
|
|
CCert11Mapping::~CCert11Mapping(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Destructor for CCert11Mapping
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Returns:
|
|
|
|
Nothing
|
|
|
|
--*/
|
|
{
|
|
}
|
|
|
|
|
|
#if defined(CERT11_FULL_CERT)
|
|
|
|
BOOL
|
|
CCert11Mapping::Init(
|
|
LPBYTE pC,
|
|
DWORD dwC,
|
|
IISMDB_HEntry *pH,
|
|
DWORD dwH
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Constructor for CCert11Mapping
|
|
|
|
Arguments:
|
|
|
|
pC -- cert ( ASN.1 format )
|
|
dwC -- length of cert
|
|
pH -- ptr to hierarchy info
|
|
dwH -- number of hierarchy entries
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
--*/
|
|
{
|
|
StoreFieldRef( IISMDB_INDEX_CERT11_CERT, (LPSTR)pC, dwC );
|
|
|
|
UpdateMask( pH, dwH );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
#else
|
|
|
|
BOOL
|
|
CCert11Mapping::Init(
|
|
LPBYTE pI,
|
|
DWORD dwI,
|
|
LPBYTE pS,
|
|
DWORD dwS,
|
|
IISMDB_HEntry *pH,
|
|
DWORD dwH
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Constructor for CCert11Mapping
|
|
|
|
Arguments:
|
|
|
|
pI -- cert issuer ( ASN.1 format )
|
|
dwI -- length of issuer
|
|
pS -- cert subject ( ASN.1 format )
|
|
dwS -- length of subject
|
|
pH -- ptr to hierarchy info
|
|
dwH -- number of hierarchy entries
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
--*/
|
|
{
|
|
StoreFieldRef( IISMDB_INDEX_CERT11_SUBJECT, (LPSTR)pS, dwS );
|
|
StoreFieldRef( IISMDB_INDEX_CERT11_ISSUER, (LPSTR)pI, dwI);
|
|
|
|
UpdateMask( pH, dwH );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
// CIisMapping
|
|
|
|
CIisMapping::CIisMapping(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Constructor for CIisMapping
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Returns:
|
|
|
|
Nothing
|
|
|
|
--*/
|
|
{
|
|
m_pBuff = NULL;
|
|
m_cUsedBuff = m_cAllocBuff = 0;
|
|
m_dwMask = 0;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CIisMapping::CloneEx(
|
|
CIisMapping** ppM,
|
|
LPSTR* ppTargetS,
|
|
LPSTR* ppS,
|
|
LPDWORD pTargetC,
|
|
LPDWORD pC,
|
|
UINT cF
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Clone a mapping entry
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
TRUE if success, otherwise FALSE
|
|
|
|
--*/
|
|
{
|
|
CIisMapping* pM = *ppM;
|
|
UINT i;
|
|
|
|
if ( ppTargetS && ppS )
|
|
{
|
|
memcpy( ppTargetS, ppS, sizeof(LPSTR*) * cF );
|
|
}
|
|
|
|
if ( pTargetC && pC )
|
|
{
|
|
memcpy( pTargetC, pC, sizeof(DWORD) * cF );
|
|
}
|
|
|
|
if ( !(pM->m_pBuff = (LPBYTE)LocalAlloc( LMEM_FIXED, m_cAllocBuff )) )
|
|
{
|
|
delete pM;
|
|
*ppM = NULL;
|
|
return FALSE;
|
|
}
|
|
|
|
memcpy( pM->m_pBuff, m_pBuff, m_cUsedBuff );
|
|
|
|
pM->m_cUsedBuff = m_cUsedBuff;
|
|
pM->m_cAllocBuff = m_cAllocBuff;
|
|
pM->m_pMapper = m_pMapper;
|
|
pM->m_dwMask = m_dwMask;
|
|
|
|
//
|
|
// Adjust ptr to point to new buffer
|
|
//
|
|
|
|
for ( i = 0 ; i < cF ; ++i )
|
|
{
|
|
if ( ppTargetS[i] )
|
|
{
|
|
ppTargetS[i] += pM->m_pBuff - m_pBuff;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CIisMapping::UpdateMask(
|
|
IISMDB_HEntry* pH,
|
|
DWORD dwI
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Update mask of significant fields for a mapping object
|
|
Field is significant if not containing "*"
|
|
mask if bitmask of n bits where n is # of hierarchy entries
|
|
bit of rank m == 0 means field pointed by hierarchy entry n - 1 - m
|
|
is significant. ( i.e. MSB is hierarchy entry 0, the most significant )
|
|
|
|
Arguments:
|
|
|
|
pH -- ptr to hierarchy info
|
|
dwI -- number of hierarchy entries
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
--*/
|
|
{
|
|
LPSTR *pFields;
|
|
LPDWORD pcFields;
|
|
LPSTR pF;
|
|
DWORD dwC;
|
|
int iMax;
|
|
m_dwMask = (1u << dwI)-1;
|
|
|
|
iMax = GetNbField( &pFields, &pcFields );
|
|
|
|
if ( pcFields )
|
|
{
|
|
for ( UINT x = 0 ; x < dwI ; ++x )
|
|
{
|
|
MappingGetField( pH[x].m_dwIndex, &pF, &dwC, FALSE );
|
|
if ( !pF || dwC != 1 || *pF != '*' )
|
|
{
|
|
m_dwMask &= ~(1u << (dwI - 1 - x) );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for ( UINT x = 0 ; x < dwI ; ++x )
|
|
{
|
|
MappingGetField( pH[x].m_dwIndex, &pF );
|
|
if ( !pF || strcmp( pF, "*" ) )
|
|
{
|
|
m_dwMask &= ~(1u << (dwI - 1 - x) );
|
|
}
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CIisMapping::Copy(
|
|
CIisMapping* pM
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Copy the specified mapping in this
|
|
|
|
Arguments:
|
|
|
|
pM - ptr to mapping to duplicate
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
--*/
|
|
{
|
|
LPSTR *pFields;
|
|
LPSTR pF;
|
|
UINT iMax = GetNbField( &pFields );
|
|
|
|
for ( UINT x = 0 ; x < iMax ; ++x )
|
|
{
|
|
if ( pM->MappingGetField( x, &pF ) && *pF )
|
|
{
|
|
if ( !MappingSetField( x, pF ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
int
|
|
CIisMapping::Cmp(
|
|
CIisMapping* pM,
|
|
BOOL fCmpForMatch
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Compare 2 mappings, return -1, 0 or 1 as suitable for qsort or bsearch
|
|
Can compare either for full sort order ( using mask & significant fields )
|
|
or for a match ( not using mask )
|
|
|
|
Arguments:
|
|
|
|
pM -- ptr to mapping to compare to. This is to be used as the 2nd
|
|
entry for purpose of lexicographical order.
|
|
fCmpForMatch -- TRUE if comparing for a match inside a given mask class
|
|
|
|
Returns:
|
|
|
|
-1 if *this < *pM, 0 if *this == *pM, 1 if *this > *pM
|
|
|
|
--*/
|
|
{
|
|
DWORD dwCmpMask = 0xffffffff;
|
|
|
|
// if not compare for match, consider mask
|
|
|
|
if ( !fCmpForMatch )
|
|
{
|
|
if ( m_dwMask < pM->GetMask() )
|
|
{
|
|
return -1;
|
|
}
|
|
else if ( m_dwMask > pM->GetMask() )
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
// mask are identical, have to consider fields
|
|
}
|
|
|
|
// compute common significant fields : bit is 1 if significant
|
|
|
|
dwCmpMask = (~m_dwMask) & (~pM->GetMask());
|
|
|
|
DWORD dwH;
|
|
IISMDB_HEntry* pH = m_pMapper->GetHierarchy( &dwH );
|
|
UINT x;
|
|
LPSTR *pFL;
|
|
LPDWORD pcFL;
|
|
GetNbField( &pFL, &pcFL );
|
|
|
|
for ( x = 0 ; x < dwH ; ++x )
|
|
{
|
|
if( ! (dwCmpMask & (1u << (dwH - 1 - x) )) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
LPSTR pA;
|
|
LPSTR pB;
|
|
DWORD dwA;
|
|
DWORD dwB;
|
|
int fC;
|
|
if ( pcFL ) // check if length available
|
|
{
|
|
MappingGetField( pH[x].m_dwIndex, &pA, &dwA, FALSE );
|
|
pM->MappingGetField( pH[x].m_dwIndex, &pB, &dwB, FALSE );
|
|
if ( pA == NULL )
|
|
{
|
|
dwA = 0;
|
|
}
|
|
if ( pB == NULL )
|
|
{
|
|
dwB = 0;
|
|
}
|
|
if ( dwA != dwB )
|
|
{
|
|
return dwA < dwB ? -1 : 1;
|
|
}
|
|
fC = memcmp( pA, pB, dwA );
|
|
}
|
|
else
|
|
{
|
|
MappingGetField( pH[x].m_dwIndex, &pA );
|
|
pM->MappingGetField( pH[x].m_dwIndex, &pB );
|
|
if ( pA == NULL )
|
|
{
|
|
pA = "";
|
|
}
|
|
if ( pB == NULL )
|
|
{
|
|
pB = "";
|
|
}
|
|
fC = strcmp( pA, pB );
|
|
}
|
|
if ( fC )
|
|
{
|
|
return fC;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CIisMapping::MappingGetField(
|
|
DWORD dwIndex,
|
|
LPSTR *pF
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get ptr to field in mapping entry
|
|
ownership of field remains with mapping entry
|
|
|
|
Arguments:
|
|
|
|
dwIndex -- index of field
|
|
pF -- updated with ptr to field entry. can be NULL if
|
|
field empty.
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
Lock:
|
|
mapper must be locked for ptr to remain valid
|
|
|
|
--*/
|
|
{
|
|
LPSTR *pFields;
|
|
DWORD iMax = GetNbField( &pFields );
|
|
if ( dwIndex >= iMax )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
*pF = pFields[dwIndex];
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CIisMapping::MappingGetField(
|
|
DWORD dwIndex,
|
|
LPSTR *pF,
|
|
LPDWORD pcF,
|
|
BOOL fUuEncode
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get ptr to field in mapping entry
|
|
ownership of field remains with mapping entry
|
|
|
|
Arguments:
|
|
|
|
dwIndex -- index of field
|
|
pF -- updated with ptr to field entry. can be NULL if
|
|
field empty.
|
|
pcF -- updated with length of fields, 0 if empty
|
|
fUuEncode -- TRUE if result is to be uuencoded.
|
|
if TRUE, caller must LocalFree( *pF )
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
Lock:
|
|
mapper must be locked for ptr to remain valid
|
|
|
|
--*/
|
|
{
|
|
LPSTR *pFields;
|
|
LPDWORD pcFields;
|
|
DWORD iMax = GetNbField( &pFields, &pcFields );
|
|
if ( dwIndex >= iMax )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if ( fUuEncode )
|
|
{
|
|
LPSTR pU = (LPSTR)LocalAlloc( LMEM_FIXED, ((pcFields[dwIndex]+3)*4)/3+1 );
|
|
if ( pU == NULL )
|
|
{
|
|
return FALSE;
|
|
}
|
|
DWORD cO;
|
|
IISuuencode( (LPBYTE)pFields[dwIndex], pcFields[dwIndex], (LPBYTE)pU, FALSE );
|
|
*pF = pU;
|
|
*pcF = strlen(pU);
|
|
}
|
|
else
|
|
{
|
|
*pF = pFields[dwIndex];
|
|
*pcF = pcFields[dwIndex];
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CIisMapping::MappingSetField(
|
|
DWORD dwIndex,
|
|
LPSTR pszNew
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Set field in mapping entry to specified content
|
|
data pointed by pszNew is copied inside mapping entry
|
|
|
|
Arguments:
|
|
|
|
dwIndex -- index of field
|
|
pszNew -- data to copy inside field
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
Lock:
|
|
mapper must be locked for ptr to remain valid
|
|
|
|
--*/
|
|
{
|
|
LPSTR *pFields;
|
|
DWORD iMax = GetNbField( &pFields );
|
|
if ( dwIndex >= iMax )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return StoreField( pFields, dwIndex, iMax, pszNew );
|
|
}
|
|
|
|
|
|
BOOL
|
|
CIisMapping::MappingSetField(
|
|
DWORD dwIndex,
|
|
LPSTR pszNew,
|
|
DWORD cNew,
|
|
BOOL fIsUuEncoded
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Set field in mapping entry to specified content
|
|
data pointed by pszNew is copied inside mapping entry
|
|
|
|
Arguments:
|
|
|
|
dwIndex -- index of field
|
|
pszNew -- data to copy inside field
|
|
cNew -- length of data
|
|
fIsUuEncoded -- TRUE if pszNew is UUEncoded
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
Lock:
|
|
mapper must be locked for ptr to remain valid
|
|
|
|
--*/
|
|
{
|
|
LPSTR *pFields;
|
|
LPDWORD pcFields;
|
|
DWORD iMax = GetNbField( &pFields, &pcFields );
|
|
if ( dwIndex >= iMax )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return StoreField( pFields, pcFields, dwIndex, iMax, pszNew, cNew, fIsUuEncoded );
|
|
}
|
|
|
|
|
|
BOOL
|
|
CIisMapping::StoreField(
|
|
LPSTR* ppszFields,
|
|
DWORD dwIndex,
|
|
DWORD dwNbIndex,
|
|
LPSTR pszNew
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Update field array in mapping entry with new field
|
|
data pointed by pszNew is copied inside mapping entry
|
|
|
|
Arguments:
|
|
|
|
ppszFields -- array of field pointers to be updated
|
|
dwIndex -- index of field
|
|
dwNbIndex -- number of fields in array
|
|
pszNew -- data to copy inside field
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
--*/
|
|
{
|
|
UINT x;
|
|
|
|
// pszOld is assumed to point inside m_pBuff if non NULL
|
|
// is has to be removed
|
|
|
|
LPSTR pszOld = ppszFields[dwIndex];
|
|
if ( pszOld && m_pBuff && (LPBYTE)pszOld > m_pBuff && (LPBYTE)pszOld < m_pBuff+m_cUsedBuff )
|
|
{
|
|
int lO = strlen( pszOld ) + 1;
|
|
int lM = DIFF((m_pBuff + m_cUsedBuff) - (LPBYTE)pszOld) - lO;
|
|
if ( lM )
|
|
{
|
|
memmove( pszOld, pszOld + lO, lM );
|
|
for ( x = 0 ; x < dwNbIndex ; ++x )
|
|
{
|
|
if ( x != dwIndex && ppszFields[x] > pszOld )
|
|
{
|
|
ppszFields[x] -= lO;
|
|
}
|
|
}
|
|
}
|
|
ppszFields[ dwIndex ] = NULL;
|
|
m_cUsedBuff -= lO;
|
|
}
|
|
|
|
// pszNew is to appended to m_pBuff
|
|
|
|
int lN = strlen( pszNew ) + 1;
|
|
|
|
if ( m_cUsedBuff + lN > m_cAllocBuff )
|
|
{
|
|
UINT cNewBuff = (( m_cUsedBuff + lN + IIS_MAP_BUFF_GRAN ) / IIS_MAP_BUFF_GRAN) * IIS_MAP_BUFF_GRAN;
|
|
LPSTR pNewBuff = (LPSTR)LocalAlloc( LMEM_FIXED, cNewBuff );
|
|
if ( pNewBuff == NULL )
|
|
{
|
|
return FALSE;
|
|
}
|
|
if ( m_pBuff )
|
|
{
|
|
memcpy( pNewBuff, m_pBuff, m_cUsedBuff );
|
|
LocalFree( m_pBuff );
|
|
}
|
|
m_cAllocBuff = cNewBuff;
|
|
// adjust pointers
|
|
for ( UINT x = 0 ; x < dwNbIndex ; ++x )
|
|
{
|
|
if ( x != dwIndex )
|
|
{
|
|
if ( ppszFields[x] != NULL )
|
|
{
|
|
ppszFields[x] += ((LPBYTE)pNewBuff - m_pBuff);
|
|
}
|
|
}
|
|
}
|
|
m_pBuff = (LPBYTE)pNewBuff;
|
|
}
|
|
|
|
memcpy( m_pBuff + m_cUsedBuff, pszNew, lN );
|
|
|
|
ppszFields[dwIndex] = (LPSTR)(m_pBuff + m_cUsedBuff);
|
|
|
|
m_cUsedBuff += lN;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CIisMapping::StoreField(
|
|
LPSTR* ppszFields,
|
|
LPDWORD ppdwFields,
|
|
DWORD dwIndex,
|
|
DWORD dwNbIndex,
|
|
LPSTR pbNew,
|
|
DWORD cNew,
|
|
BOOL fIsUuEncoded
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Update field array in mapping entry with new field
|
|
data pointed by pszNew is copied inside mapping entry
|
|
|
|
Arguments:
|
|
|
|
ppszFields -- array of field pointers to be updated
|
|
ppdwFields -- array of field length to be updated
|
|
dwIndex -- index of field
|
|
dwNbIndex -- number of fields in array
|
|
pbNew -- data to copy inside field
|
|
cNew -- length of data
|
|
fIsUuEncoded -- TRUE if pbNew is UUEncoded
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
--*/
|
|
{
|
|
UINT x;
|
|
|
|
// pszOld is assumed to point inside m_pBuff if non NULL
|
|
// it has to be removed
|
|
|
|
LPSTR pszOld = ppszFields[dwIndex];
|
|
if ( pszOld && m_pBuff && (LPBYTE)pszOld > m_pBuff && (LPBYTE)pszOld < m_pBuff+m_cUsedBuff )
|
|
{
|
|
int lO = ppdwFields[dwIndex];
|
|
int lM = DIFF((m_pBuff + m_cUsedBuff) - (LPBYTE)pszOld) - lO;
|
|
if ( lM )
|
|
{
|
|
memmove( pszOld, pszOld + lO, lM );
|
|
for ( x = 0 ; x < dwNbIndex ; ++x )
|
|
{
|
|
if ( x != dwIndex && ppszFields[x] > pszOld )
|
|
{
|
|
ppszFields[x] -= lO;
|
|
}
|
|
}
|
|
}
|
|
ppszFields[ dwIndex ] = NULL;
|
|
m_cUsedBuff -= lO;
|
|
}
|
|
|
|
// pszNew is to appended to m_pBuff
|
|
|
|
int lN = cNew;
|
|
if ( fIsUuEncoded )
|
|
{
|
|
LPSTR pU = (LPSTR)LocalAlloc( LMEM_FIXED, lN + 3);
|
|
if ( pU == NULL )
|
|
{
|
|
return FALSE;
|
|
}
|
|
DWORD cO;
|
|
IISuudecode( pbNew, (LPBYTE)pU, &cO, FALSE );
|
|
pbNew = pU;
|
|
cNew = lN = cO;
|
|
}
|
|
|
|
if ( m_cUsedBuff + lN > m_cAllocBuff )
|
|
{
|
|
UINT cNewBuff = (( m_cUsedBuff + lN + IIS_MAP_BUFF_GRAN ) / IIS_MAP_BUFF_GRAN) * IIS_MAP_BUFF_GRAN;
|
|
LPSTR pNewBuff = (LPSTR)LocalAlloc( LMEM_FIXED, cNewBuff );
|
|
if ( pNewBuff == NULL )
|
|
{
|
|
if ( fIsUuEncoded )
|
|
{
|
|
LocalFree( pbNew );
|
|
}
|
|
return FALSE;
|
|
}
|
|
if ( m_pBuff )
|
|
{
|
|
memcpy( pNewBuff, m_pBuff, m_cUsedBuff );
|
|
LocalFree( m_pBuff );
|
|
}
|
|
m_cAllocBuff = cNewBuff;
|
|
// adjust pointers
|
|
for ( UINT x = 0 ; x < dwNbIndex ; ++x )
|
|
{
|
|
if ( x != dwIndex )
|
|
{
|
|
if ( ppszFields[x] != NULL )
|
|
{
|
|
ppszFields[x] += ((LPBYTE)pNewBuff - m_pBuff);
|
|
}
|
|
}
|
|
}
|
|
m_pBuff = (LPBYTE)pNewBuff;
|
|
}
|
|
|
|
memcpy( m_pBuff + m_cUsedBuff, pbNew, lN );
|
|
|
|
ppszFields[dwIndex] = (LPSTR)(m_pBuff + m_cUsedBuff);
|
|
if ( ppdwFields )
|
|
{
|
|
ppdwFields[dwIndex] = cNew;
|
|
}
|
|
|
|
m_cUsedBuff += lN;
|
|
|
|
if ( fIsUuEncoded )
|
|
{
|
|
LocalFree( pbNew );
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CIisMapping::Serialize(
|
|
FILE* pFile,
|
|
VALID_CTX pMD5,
|
|
LPVOID pStorage
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Serialize a mapping entry
|
|
|
|
Arguments:
|
|
|
|
pFile -- file to write to
|
|
pMD5 -- MD5 to update with signature of written bytes
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
Lock:
|
|
mapper must be locked while serializing
|
|
|
|
--*/
|
|
{
|
|
LPSTR *pFields;
|
|
LPDWORD pcFields;
|
|
LPSTR pO = NULL;
|
|
DWORD dwO = 0;
|
|
UINT iMax = GetNbField( &pFields, &pcFields );
|
|
UINT x;
|
|
LPBYTE pB;
|
|
BOOL fMustFree;
|
|
|
|
for ( x = 0 ; x < iMax ; ++x )
|
|
{
|
|
LPSTR pF;
|
|
DWORD dwF;
|
|
|
|
fMustFree = FALSE;
|
|
|
|
if ( pcFields )
|
|
{
|
|
MappingGetField( x, &pF, &dwF, FALSE );
|
|
MD5Update( (MD5_CTX*)pMD5, (LPBYTE)pF, dwF );
|
|
store_as_binary:
|
|
if ( IsCrypt( x ) && dwF )
|
|
{
|
|
if ( FAILED(((IIS_CRYPTO_STORAGE*)pStorage)->EncryptData(
|
|
(PIIS_CRYPTO_BLOB*)&pB,
|
|
pF,
|
|
dwF,
|
|
REG_BINARY )) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
pF = (LPSTR)pB;
|
|
dwF = IISCryptoGetBlobLength( (PIIS_CRYPTO_BLOB)pB );
|
|
fMustFree = TRUE;
|
|
}
|
|
|
|
if ( dwF )
|
|
{
|
|
DWORD dwNeed = ((dwF+2)*4)/3 + 1;
|
|
if ( dwNeed > dwO )
|
|
{
|
|
if ( pO != NULL )
|
|
{
|
|
LocalFree( pO );
|
|
}
|
|
dwNeed += 100; // alloc more than needed
|
|
// to minimize # of allocation
|
|
if ( !(pO = (LPSTR)LocalAlloc( LMEM_FIXED, dwNeed )) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
dwO = dwNeed;
|
|
}
|
|
/* INTRINSA suppress = null */
|
|
IISuuencode( (LPBYTE)pF, dwF, (LPBYTE)pO, FALSE );
|
|
fputs( pO, pFile );
|
|
}
|
|
|
|
if ( fMustFree )
|
|
{
|
|
IISCryptoFreeBlob( (PIIS_CRYPTO_BLOB)pB );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MappingGetField( x, &pF );
|
|
if ( pF != NULL )
|
|
{
|
|
MD5Update( (MD5_CTX*)pMD5, (LPBYTE)pF, strlen(pF) );
|
|
if ( IsCrypt( x ) )
|
|
{
|
|
dwF = strlen( pF ) + 1;
|
|
goto store_as_binary;
|
|
}
|
|
fputs( pF, pFile );
|
|
}
|
|
}
|
|
fputs( "|", pFile );
|
|
}
|
|
|
|
fputs( "\r\n", pFile );
|
|
|
|
if ( pO != NULL )
|
|
{
|
|
LocalFree( pO );
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CIisMapping::Deserialize(
|
|
FILE* pFile,
|
|
VALID_CTX pMD5,
|
|
LPVOID pStorage
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Deserialize a mapping entry
|
|
|
|
Arguments:
|
|
|
|
pFile -- file to read from
|
|
pMD5 -- MD5 to update with signature of read bytes
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
Lock:
|
|
mapper must be locked while serializing
|
|
|
|
--*/
|
|
{
|
|
LPSTR *pFields;
|
|
LPDWORD pcFields;
|
|
UINT iMax;
|
|
UINT x;
|
|
int c;
|
|
CHAR achBuf[4096];
|
|
DWORD dwType;
|
|
LPBYTE pB;
|
|
|
|
iMax = GetNbField( &pFields, &pcFields );
|
|
|
|
for ( x = 0 ; x < iMax ; ++x )
|
|
{
|
|
StoreFieldRef( x, NULL );
|
|
}
|
|
|
|
for ( x = 0 ; x < sizeof(achBuf) && (c=fgetc(pFile))!= EOF ; )
|
|
{
|
|
achBuf[x++] = (CHAR)c;
|
|
|
|
if ( c == '\n' )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if ( x == sizeof(achBuf ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if ( x > 1 )
|
|
{
|
|
achBuf[x-2] = '\0';
|
|
|
|
m_cUsedBuff = m_cAllocBuff = x - 1;
|
|
if ( (m_pBuff = (LPBYTE)LocalAlloc( LMEM_FIXED, m_cAllocBuff )) == NULL )
|
|
{
|
|
m_cAllocBuff = m_cUsedBuff = 0;
|
|
return FALSE;
|
|
}
|
|
memcpy( m_pBuff, achBuf, m_cUsedBuff );
|
|
|
|
LPSTR pCur = (LPSTR)m_pBuff;
|
|
LPSTR pNext;
|
|
LPSTR pStore = (LPSTR)m_pBuff;
|
|
DWORD dwDec;
|
|
if ( pcFields )
|
|
{
|
|
for ( x = 0 ; x < iMax ; ++x )
|
|
{
|
|
pNext = strchr( pCur, '|' );
|
|
if ( pNext != NULL )
|
|
{
|
|
*pNext = '\0';
|
|
++pNext;
|
|
}
|
|
else
|
|
{
|
|
pNext = NULL;
|
|
}
|
|
IISuudecode( pCur, (PBYTE)pStore, &dwDec, FALSE );
|
|
if ( IsCrypt( x ) && dwDec )
|
|
{
|
|
if ( FAILED(((IIS_CRYPTO_STORAGE*)pStorage)->DecryptData(
|
|
(PVOID*)&pB,
|
|
&dwDec,
|
|
&dwType,
|
|
(PIIS_CRYPTO_BLOB)pStore )) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
memmove( pStore, pB, dwDec );
|
|
}
|
|
MD5Update( (MD5_CTX*)pMD5, (LPBYTE)pStore, dwDec );
|
|
StoreFieldRef( x, pStore, dwDec );
|
|
pCur = pNext;
|
|
pStore += dwDec;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for ( x = 0 ; x < iMax ; ++x )
|
|
{
|
|
pNext = strchr( pCur, '|' );
|
|
if ( pNext != NULL )
|
|
{
|
|
*pNext = '\0';
|
|
++pNext;
|
|
}
|
|
if ( *pCur && IsCrypt( x ) )
|
|
{
|
|
IISuudecode( pCur, (PBYTE)pCur, &dwDec, FALSE );
|
|
|
|
if ( FAILED(((IIS_CRYPTO_STORAGE*)pStorage)->DecryptData(
|
|
(PVOID*)&pB,
|
|
&dwDec,
|
|
&dwType,
|
|
(PIIS_CRYPTO_BLOB)pCur )) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
MD5Update( (MD5_CTX*)pMD5, (LPBYTE)pB, dwDec );
|
|
StoreFieldRef( x, (LPSTR)pB );
|
|
pCur = pNext;
|
|
}
|
|
else
|
|
{
|
|
MD5Update( (MD5_CTX*)pMD5, (LPBYTE)pCur, strlen(pCur) );
|
|
StoreFieldRef( x, pCur );
|
|
pCur = pNext;
|
|
}
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//
|
|
|
|
|
|
extern "C" BOOL WINAPI
|
|
DllMain(
|
|
HANDLE hModule,
|
|
DWORD dwReason,
|
|
LPVOID pV
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
DLL init/terminate notification function
|
|
|
|
Arguments:
|
|
|
|
hModule - DLL handle
|
|
dwReason - notification type
|
|
LPVOID - not used
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if failure
|
|
|
|
--*/
|
|
{
|
|
//BOOL f = Crypt32DllMain( (HINSTANCE)hModule, dwReason, pV );
|
|
|
|
switch ( dwReason )
|
|
{
|
|
case DLL_PROCESS_ATTACH:
|
|
#ifdef _NO_TRACING_
|
|
CREATE_DEBUG_PRINT_OBJECT( "IISMAP" );
|
|
#endif
|
|
// record the module handle to access module info later
|
|
g_hModule = (HINSTANCE)hModule;
|
|
INITIALIZE_CRITICAL_SECTION( &g_csIisMap );
|
|
InitializeWildcardMapping( hModule );
|
|
InitializeMapping( hModule );
|
|
if ( IISCryptoInitialize() != NO_ERROR )
|
|
{
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
|
|
case DLL_PROCESS_DETACH:
|
|
IISCryptoTerminate();
|
|
TerminateWildcardMapping();
|
|
TerminateMapping();
|
|
DeleteCriticalSection( &g_csIisMap );
|
|
#ifdef _NO_TRACING_
|
|
DELETE_DEBUG_PRINT_OBJECT( );
|
|
#endif
|
|
break;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
InitializeMapping(
|
|
HANDLE hModule
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Initialize mapping
|
|
|
|
Arguments:
|
|
|
|
hModule - module handle of this DLL
|
|
|
|
Return Value:
|
|
|
|
Nothing
|
|
|
|
--*/
|
|
{
|
|
// get install path
|
|
|
|
if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE,
|
|
W3_PARAMS,
|
|
0,
|
|
KEY_READ|KEY_SET_VALUE,
|
|
&g_hKey ) == ERROR_SUCCESS )
|
|
{
|
|
DWORD dwLen = 0;
|
|
DWORD dwType;
|
|
|
|
if ( RegQueryValueEx( g_hKey,
|
|
INSTALL_PATH,
|
|
NULL,
|
|
&dwType,
|
|
NULL,
|
|
&dwLen ) != ERROR_SUCCESS ||
|
|
dwType != REG_SZ ||
|
|
!( g_pszInstallPath = (LPSTR)LocalAlloc( LMEM_FIXED, dwLen ) ) ||
|
|
RegQueryValueEx( g_hKey,
|
|
INSTALL_PATH,
|
|
NULL,
|
|
&dwType,
|
|
(LPBYTE)g_pszInstallPath,
|
|
&dwLen ) != ERROR_SUCCESS )
|
|
{
|
|
if ( g_pszInstallPath )
|
|
{
|
|
LocalFree( g_pszInstallPath );
|
|
g_pszInstallPath = NULL;
|
|
}
|
|
}
|
|
|
|
dwLen = sizeof( g_dwGuid );
|
|
if ( RegQueryValueEx( g_hKey,
|
|
MAPPER_GUID,
|
|
NULL,
|
|
&dwType,
|
|
(LPBYTE)&g_dwGuid,
|
|
&dwLen ) != ERROR_SUCCESS ||
|
|
dwType != REG_DWORD )
|
|
{
|
|
g_dwGuid = 0;
|
|
}
|
|
|
|
return LoadFieldNames( IisItaMappingFields,
|
|
sizeof(IisItaMappingFields)/sizeof(IISMDB_Fields) ) &&
|
|
LoadFieldNames( IisCert11MappingFields,
|
|
sizeof(IisCert11MappingFields)/sizeof(IISMDB_Fields) ) &&
|
|
LoadFieldNames( IisMd5MappingFields,
|
|
sizeof(IisMd5MappingFields)/sizeof(IISMDB_Fields) );
|
|
}
|
|
else
|
|
{
|
|
g_hKey = NULL;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
LoadFieldNames(
|
|
IISMDB_Fields* pFields,
|
|
UINT cFields
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Load fields names from resource
|
|
|
|
Arguments:
|
|
|
|
pFields - ptr to array where to store reference to names
|
|
cFields - count of element in array
|
|
|
|
Return Value:
|
|
|
|
TRUE if success, otherwise FALSE
|
|
|
|
--*/
|
|
{
|
|
|
|
UINT x;
|
|
BOOL fSt = TRUE;
|
|
|
|
for ( x = 0 ;
|
|
x < cFields ;
|
|
++x )
|
|
{
|
|
char achTmp[128];
|
|
|
|
if ( LoadString( g_hModule,
|
|
pFields[x].m_dwResID,
|
|
achTmp,
|
|
sizeof( achTmp ) ) != 0 )
|
|
{
|
|
int lN = strlen( achTmp ) + sizeof(CHAR);
|
|
if ( (pFields[x].m_pszDisplayName = (LPSTR)LocalAlloc( LMEM_FIXED, lN )) == NULL )
|
|
{
|
|
fSt = FALSE;
|
|
break;
|
|
}
|
|
memcpy( pFields[x].m_pszDisplayName, achTmp, lN );
|
|
}
|
|
else
|
|
{
|
|
fSt = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return fSt;
|
|
}
|
|
|
|
|
|
VOID
|
|
FreeFieldNames(
|
|
IISMDB_Fields* pFields,
|
|
UINT cFields
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Free fields names loaded from resource
|
|
|
|
Arguments:
|
|
|
|
pFields - ptr to array where reference to names are stored
|
|
cFields - count of element in array
|
|
|
|
Return Value:
|
|
|
|
Nothing
|
|
|
|
--*/
|
|
{
|
|
|
|
UINT x;
|
|
BOOL fSt = TRUE;
|
|
|
|
for ( x = 0 ;
|
|
x < cFields ;
|
|
++x )
|
|
{
|
|
if ( pFields[x].m_pszDisplayName )
|
|
{
|
|
LocalFree( pFields[x].m_pszDisplayName );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
TerminateMapping(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Terminate mapping
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
Nothing
|
|
|
|
--*/
|
|
{
|
|
if ( g_hKey != NULL )
|
|
{
|
|
RegCloseKey( g_hKey );
|
|
}
|
|
|
|
if ( g_pszInstallPath )
|
|
{
|
|
LocalFree( g_pszInstallPath );
|
|
}
|
|
|
|
FreeFieldNames( IisItaMappingFields,
|
|
sizeof(IisItaMappingFields)/sizeof(IISMDB_Fields) );
|
|
FreeFieldNames( IisCert11MappingFields,
|
|
sizeof(IisCert11MappingFields)/sizeof(IISMDB_Fields) );
|
|
FreeFieldNames( IisMd5MappingFields,
|
|
sizeof(IisMd5MappingFields)/sizeof(IISMDB_Fields) );
|
|
}
|
|
|
|
//
|
|
|
|
|
|
dllexp
|
|
BOOL
|
|
ReportIisMapEvent(
|
|
WORD wType,
|
|
DWORD dwEventId,
|
|
WORD cNbStr,
|
|
LPCTSTR* pStr
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Log an event based on type, ID and insertion strings
|
|
|
|
Arguments:
|
|
|
|
wType -- event type ( error, warning, information )
|
|
dwEventId -- event ID ( as defined by the .mc file )
|
|
cNbStr -- nbr of LPSTR in the pStr array
|
|
pStr -- insertion strings
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if failure
|
|
|
|
--*/
|
|
{
|
|
BOOL fSt = TRUE;
|
|
HANDLE hEventLog = NULL;
|
|
|
|
hEventLog = RegisterEventSource(NULL,"IISMAP");
|
|
|
|
if ( hEventLog != NULL )
|
|
{
|
|
if (!ReportEvent(hEventLog, // event log handle
|
|
wType, // event type
|
|
0, // category zero
|
|
(DWORD) dwEventId, // event identifier
|
|
NULL, // no user security identifier
|
|
cNbStr, // count of substitution strings (may be no strings)
|
|
// less ProgName (argv[0]) and Event ID (argv[1])
|
|
0, // no data
|
|
(LPCTSTR *) pStr, // address of string array
|
|
NULL)) // address of data
|
|
{
|
|
fSt = FALSE;
|
|
}
|
|
|
|
DeregisterEventSource( hEventLog );
|
|
}
|
|
else
|
|
{
|
|
fSt = FALSE;
|
|
}
|
|
|
|
return fSt;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////
|
|
|
|
|
|
// CIisItaMapper
|
|
|
|
CIisItaMapper::CIisItaMapper(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Constructor for CIisItaMapper
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Returns:
|
|
|
|
Nothing
|
|
|
|
--*/
|
|
{
|
|
m_pFields = IisItaMappingFields;
|
|
m_cFields = sizeof(IisItaMappingFields)/sizeof(IISMDB_Fields);
|
|
|
|
m_dwOptions = IISMDB_ITA_OPTIONS;
|
|
}
|
|
|
|
|
|
CIisItaMapper::~CIisItaMapper(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Destructor for CIisItaMapper
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Returns:
|
|
|
|
Nothing
|
|
|
|
--*/
|
|
{
|
|
}
|
|
|
|
|
|
IISMDB_HEntry*
|
|
CIisItaMapper::GetDefaultHierarchy(
|
|
LPDWORD pdwN
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
return ptr to default hierarchy for ita mapping
|
|
|
|
Arguments:
|
|
|
|
pdwN -- updated with hierarchy entries count
|
|
|
|
Returns:
|
|
|
|
ptr to hierarchy entries or NULL if error
|
|
|
|
--*/
|
|
{
|
|
*pdwN = sizeof(IisItaMappingHierarchy) / sizeof(IISMDB_HEntry);
|
|
|
|
return IisItaMappingHierarchy;
|
|
}
|
|
|
|
|
|
CIisMapping*
|
|
CIisItaMapper::CreateNewMapping(
|
|
LPSTR pszType,
|
|
LPSTR pszUser,
|
|
LPSTR pszPwd
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create a new mapping from internet credentials
|
|
|
|
Arguments:
|
|
|
|
pszType -- login type : basic, user, MD5, SSL/PCT, ...
|
|
pszUser -- user name
|
|
pszPwd -- clear text password
|
|
|
|
Returns:
|
|
|
|
ptr to mapping. ownership of this object is transfered to caller.
|
|
NULL if error
|
|
|
|
--*/
|
|
{
|
|
CItaMapping *pCM = new CItaMapping( this );
|
|
if ( pCM == NULL )
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
if ( pCM->Init( pszType, pszUser, pszPwd, m_pHierarchy, m_cHierarchy ) )
|
|
{
|
|
return (CIisMapping*)pCM;
|
|
}
|
|
delete pCM;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
// CItaMapping
|
|
|
|
CItaMapping::CItaMapping(
|
|
CIisAcctMapper* pMap
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Constructor for CItaMapping
|
|
|
|
Arguments:
|
|
|
|
pMap -- ptr to mapper object linked to this mapping
|
|
|
|
Returns:
|
|
|
|
Nothing
|
|
|
|
--*/
|
|
{
|
|
m_pMapper = (CIisAcctMapper*)pMap;
|
|
|
|
for ( int x = 0 ; x < sizeof(m_pFields)/sizeof(LPSTR) ; ++x )
|
|
{
|
|
m_pFields[x] = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
CItaMapping::~CItaMapping(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Destructor for CItaMapping
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Returns:
|
|
|
|
Nothing
|
|
|
|
--*/
|
|
{
|
|
}
|
|
|
|
|
|
BOOL
|
|
CItaMapping::Init(
|
|
LPSTR pszType,
|
|
LPSTR pszUser,
|
|
LPSTR pszPwd,
|
|
IISMDB_HEntry *pH,
|
|
DWORD dwH
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Constructor for CItaMapping
|
|
|
|
Arguments:
|
|
|
|
pszType -- login type : basic, user, MD5, SSL/PCT, ...
|
|
pszUser -- user name
|
|
pszPwd -- clear text password
|
|
pH -- ptr to hierarchy info
|
|
dwH -- number of hierarchy entries
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
--*/
|
|
{
|
|
if ( !MappingSetField( IISIMDB_INDEX_IT_ACCT, pszUser ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if ( !MappingSetField( IISIMDB_INDEX_IT_PWD, pszPwd ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return UpdateMask( pH, dwH );
|
|
}
|
|
|
|
|
|
BOOL
|
|
CCert11Mapping::MappingSetField(
|
|
DWORD dwIndex,
|
|
LPSTR pszNew
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Set field in mapping entry to specified content
|
|
data pointed by pszNew is copied inside mapping entry
|
|
|
|
Arguments:
|
|
|
|
dwIndex -- index of field
|
|
pszNew -- data to copy inside field
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
Lock:
|
|
mapper must be locked for ptr to remain valid
|
|
|
|
--*/
|
|
{
|
|
LPSTR *pFields;
|
|
LPDWORD pcFields;
|
|
DWORD iMax = GetNbField( &pFields, &pcFields );
|
|
if ( dwIndex >= iMax )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return StoreField( pFields, pcFields, dwIndex, iMax, pszNew, strlen(pszNew)+1, FALSE );
|
|
}
|
|
|
|
|
|
BOOL
|
|
CItaMapping::MappingSetField(
|
|
DWORD dwIndex,
|
|
LPSTR pszNew
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Set field in mapping entry to specified content
|
|
data pointed by pszNew is copied inside mapping entry
|
|
|
|
Arguments:
|
|
|
|
dwIndex -- index of field
|
|
pszNew -- data to copy inside field
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
Lock:
|
|
mapper must be locked for ptr to remain valid
|
|
|
|
--*/
|
|
{
|
|
MD5_CTX md5;
|
|
CHAR achDigest[ sizeof(md5.digest)*2 + 1];
|
|
|
|
#define TOHEX(a) ((a)>=10 ? 'a'+(a)-10 : '0'+(a))
|
|
|
|
// convert clear text pwd to MD5 digest ( as ASCII string )
|
|
|
|
if ( dwIndex == IISIMDB_INDEX_IT_PWD )
|
|
{
|
|
MD5Init( &md5 );
|
|
MD5Update( &md5, (LPBYTE)pszNew, strlen(pszNew) );
|
|
MD5Final( &md5 );
|
|
for ( UINT x = 0, y = 0 ; x < sizeof(md5.digest) ; ++x )
|
|
{
|
|
UINT v;
|
|
v = md5.digest[x]>>4;
|
|
achDigest[y++] = TOHEX( v );
|
|
v = md5.digest[x]&0x0f;
|
|
achDigest[y++] = TOHEX( v );
|
|
}
|
|
achDigest[y] = '\0';
|
|
pszNew = achDigest;
|
|
}
|
|
|
|
return CIisMapping::MappingSetField( dwIndex, pszNew );
|
|
}
|
|
|
|
// CIisMd5Mapper
|
|
|
|
CIisMd5Mapper::CIisMd5Mapper(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Constructor for CIisMd5Mapper
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Returns:
|
|
|
|
Nothing
|
|
|
|
--*/
|
|
{
|
|
m_pFields = IisMd5MappingFields;
|
|
m_cFields = sizeof(IisMd5MappingFields)/sizeof(IISMDB_Fields);
|
|
|
|
m_dwOptions = IISMDB_MD5_OPTIONS;
|
|
}
|
|
|
|
|
|
CIisMd5Mapper::~CIisMd5Mapper(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Destructor for CIisMd5Mapper
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Returns:
|
|
|
|
Nothing
|
|
|
|
--*/
|
|
{
|
|
}
|
|
|
|
|
|
IISMDB_HEntry*
|
|
CIisMd5Mapper::GetDefaultHierarchy(
|
|
LPDWORD pdwN
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
return ptr to default hierarchy for ita mapping
|
|
|
|
Arguments:
|
|
|
|
pdwN -- updated with hierarchy entries count
|
|
|
|
Returns:
|
|
|
|
ptr to hierarchy entries or NULL if error
|
|
|
|
--*/
|
|
{
|
|
*pdwN = sizeof(IisMd5MappingHierarchy) / sizeof(IISMDB_HEntry);
|
|
|
|
return IisMd5MappingHierarchy;
|
|
}
|
|
|
|
|
|
CIisMapping*
|
|
CIisMd5Mapper::CreateNewMapping(
|
|
LPSTR pszRealm,
|
|
LPSTR pszUser
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create a new mapping from internet credentials
|
|
|
|
Arguments:
|
|
|
|
pszRealm -- Realm
|
|
pszUser -- user name
|
|
|
|
Returns:
|
|
|
|
ptr to mapping. ownership of this object is transfered to caller.
|
|
NULL if error
|
|
|
|
--*/
|
|
{
|
|
CMd5Mapping *pCM = new CMd5Mapping( this );
|
|
if ( pCM == NULL )
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
if ( pCM->Init( pszRealm, pszUser, m_pHierarchy, m_cHierarchy ) )
|
|
{
|
|
return (CIisMapping*)pCM;
|
|
}
|
|
delete pCM;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
// CMd5Mapping
|
|
|
|
CMd5Mapping::CMd5Mapping(
|
|
CIisAcctMapper* pMap
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Constructor for CMd5Mapping
|
|
|
|
Arguments:
|
|
|
|
pMap -- ptr to mapper object linked to this mapping
|
|
|
|
Returns:
|
|
|
|
Nothing
|
|
|
|
--*/
|
|
{
|
|
m_pMapper = (CIisAcctMapper*)pMap;
|
|
|
|
for ( int x = 0 ; x < sizeof(m_pFields)/sizeof(LPSTR) ; ++x )
|
|
{
|
|
m_pFields[x] = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
CMd5Mapping::~CMd5Mapping(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Destructor for CItaMapping
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Returns:
|
|
|
|
Nothing
|
|
|
|
--*/
|
|
{
|
|
}
|
|
|
|
|
|
BOOL
|
|
CMd5Mapping::Init(
|
|
LPSTR pszRealm,
|
|
LPSTR pszUser,
|
|
IISMDB_HEntry *pH,
|
|
DWORD dwH
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Constructor for CItaMapping
|
|
|
|
Arguments:
|
|
|
|
pszRealm -- Realm
|
|
pszUser -- user name
|
|
pH -- ptr to hierarchy info
|
|
dwH -- number of hierarchy entries
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
--*/
|
|
{
|
|
if ( !MappingSetField( IISMMDB_INDEX_IT_ACCT, pszUser ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if ( !MappingSetField( IISMMDB_INDEX_IT_REALM, pszRealm ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return UpdateMask( pH, dwH );
|
|
}
|
|
|
|
|
|
BOOL
|
|
CMd5Mapping::MappingSetField(
|
|
DWORD dwIndex,
|
|
LPSTR pszNew
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Set field in mapping entry to specified content
|
|
data pointed by pszNew is copied inside mapping entry
|
|
|
|
Arguments:
|
|
|
|
dwIndex -- index of field
|
|
pszNew -- data to copy inside field
|
|
|
|
Returns:
|
|
|
|
TRUE if success, FALSE if error
|
|
|
|
Lock:
|
|
mapper must be locked for ptr to remain valid
|
|
|
|
--*/
|
|
{
|
|
MD5_CTX md5;
|
|
CHAR achDigest[ sizeof(md5.digest)*2 + 1];
|
|
|
|
|
|
|
|
// convert clear text pwd to MD5 digest ( as ASCII string )
|
|
|
|
if ( dwIndex == IISMMDB_INDEX_IT_MD5PWD )
|
|
{
|
|
if ( !CIisMapping::MappingSetField( IISMMDB_INDEX_IT_CLRPWD, pszNew ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
gen_md5pwd:
|
|
|
|
LPSTR pszName = m_pFields[IISMMDB_INDEX_IT_ACCT];
|
|
LPSTR pszRealm = m_pFields[IISMMDB_INDEX_IT_REALM];
|
|
CHAR *pS;
|
|
|
|
if ( pszName == NULL )
|
|
{
|
|
pszName = "";
|
|
}
|
|
if ( pszRealm == NULL )
|
|
{
|
|
pszRealm = "";
|
|
}
|
|
|
|
pS = new CHAR[strlen(pszName)+1+strlen(pszRealm)+1+strlen(pszNew)+1];
|
|
if ( pS == NULL )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
strcpy( pS, pszName );
|
|
strcat( pS, ":" );
|
|
strcat( pS, pszRealm );
|
|
strcat( pS, ":" );
|
|
strcat( pS, pszNew );
|
|
|
|
MD5Init( &md5 );
|
|
MD5Update( &md5, (LPBYTE)pS, strlen(pS) );
|
|
MD5Final( &md5 );
|
|
for ( UINT x = 0, y = 0 ; x < sizeof(md5.digest) ; ++x )
|
|
{
|
|
UINT v;
|
|
v = md5.digest[x]>>4;
|
|
achDigest[y++] = TOHEX( v );
|
|
v = md5.digest[x]&0x0f;
|
|
achDigest[y++] = TOHEX( v );
|
|
}
|
|
achDigest[y] = '\0';
|
|
pszNew = achDigest;
|
|
|
|
delete [] pS;
|
|
}
|
|
else if ( (dwIndex == IISMMDB_INDEX_IT_REALM ||
|
|
dwIndex == IISMMDB_INDEX_IT_ACCT) &&
|
|
m_pFields[ IISMMDB_INDEX_IT_CLRPWD ] )
|
|
{
|
|
if ( !CIisMapping::MappingSetField( dwIndex, pszNew ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
dwIndex = IISMMDB_INDEX_IT_MD5PWD;
|
|
pszNew = m_pFields[ IISMMDB_INDEX_IT_CLRPWD ];
|
|
|
|
goto gen_md5pwd;
|
|
}
|
|
|
|
return CIisMapping::MappingSetField( dwIndex, pszNew );
|
|
}
|
|
|
|
#if 0
|
|
PRDN_VALUE_BLOB
|
|
CertGetNameField(
|
|
UINT iEncoding,
|
|
IN LPCTSTR pszObjId,
|
|
IN PNAME_INFO pInfo
|
|
)
|
|
{
|
|
DWORD cRDN, cAttr;
|
|
PRDN pRDN;
|
|
PRDN_ATTR pAttr;
|
|
|
|
// Array of RDNs
|
|
for ( cRDN = pInfo->cRDN, pRDN = pInfo->rgRDN ;
|
|
cRDN > 0 ;
|
|
cRDN--, pRDN++ )
|
|
{
|
|
for ( cAttr = pRDN->cRDNAttr, pAttr = pRDN->rgRDNAttr ;
|
|
cAttr > 0 ;
|
|
cAttr--, pAttr++ )
|
|
{
|
|
if ( !strcmp( pAttr->pszObjId, pszObjId ) )
|
|
{
|
|
return &pAttr->Value;
|
|
}
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
BOOL
|
|
StoreField(
|
|
LPSTR* pFields,
|
|
LPSTR* pStore,
|
|
UINT* pLen,
|
|
PRDN_VALUE_BLOB pValue
|
|
)
|
|
{
|
|
memcpy( *pStore, pValue->pbData, pValue->cbData );
|
|
(*pStore)[ pValue->cbData ] = '\0';
|
|
|
|
*pFields = *pStore;
|
|
|
|
*pStore += pValue->cbData + 1;
|
|
*pLen += pValue->cbData + 1;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
UINT DecodeNames(
|
|
IN PNAME_BLOB pNameBlob,
|
|
IN LPSTR* pFields,
|
|
IN LPSTR pStore
|
|
)
|
|
{
|
|
PNAME_INFO pNameInfo = NULL;
|
|
DWORD cbNameInfo;
|
|
PRDN_VALUE_BLOB pValue;
|
|
UINT l = 0;
|
|
|
|
if (!DecodeObject(X509_ASN_ENCODING,
|
|
(LPCSTR)X509_NAME,
|
|
pNameBlob->pbData,
|
|
pNameBlob->cbData,
|
|
NULL,
|
|
&cbNameInfo))
|
|
{
|
|
goto Ret;
|
|
}
|
|
|
|
if (NULL == (pNameInfo = (PNAME_INFO)malloc(cbNameInfo)))
|
|
{
|
|
goto Ret;
|
|
}
|
|
if (!CertDecodeName(X509_ASN_ENCODING,
|
|
//(LPCSTR)X509_NAME,
|
|
pNameBlob->pbData,
|
|
pNameBlob->cbData,
|
|
pNameInfo,
|
|
&cbNameInfo))
|
|
{
|
|
goto Ret;
|
|
}
|
|
|
|
if (NULL == (pValue = CertGetNameField(X509_ASN_ENCODING,
|
|
COUNTRY_NAME_OBJID,
|
|
pNameInfo)))
|
|
{
|
|
goto Ret;
|
|
}
|
|
StoreField( pFields+IISMDB_INDEX_ISSUER_C, &pStore, &l, pValue );
|
|
|
|
if (NULL == (pValue = CertGetNameField(X509_ASN_ENCODING,
|
|
ORGANIZATION_NAME_OBJID,
|
|
pNameInfo)))
|
|
{
|
|
goto Ret;
|
|
}
|
|
StoreField( pFields+IISMDB_INDEX_ISSUER_O, &pStore, &l, pValue );
|
|
|
|
if (NULL == (pValue = CertGetNameField(X509_ASN_ENCODING,
|
|
ORGANIZATIONAL_UNIT_NAME_OBJID,
|
|
pNameInfo)))
|
|
{
|
|
goto Ret;
|
|
}
|
|
StoreField( pFields+IISMDB_INDEX_ISSUER_OU, &pStore, &l, pValue );
|
|
|
|
if (NULL == (pValue = CertGetNameField(X509_ASN_ENCODING,
|
|
COMMON_NAME_OBJID,
|
|
pNameInfo)))
|
|
{
|
|
goto Ret;
|
|
}
|
|
StoreField( pFields+IISMDB_INDEX_ISSUER_C+1, &pStore, &l, pValue );
|
|
|
|
Ret:
|
|
free(pNameInfo);
|
|
return l;
|
|
}
|
|
|
|
|
|
UINT DecodeCert(
|
|
IN PBYTE pbEncodedCert,
|
|
IN DWORD cbEncodedCert,
|
|
LPSTR* pFields,
|
|
LPSTR pStore
|
|
)
|
|
{
|
|
PCCERT_CONTEXT pCert = NULL;
|
|
UINT l;
|
|
|
|
if (NULL == (pCert = CertCreateCertificateContext(X509_ASN_ENCODING,
|
|
pbEncodedCert,
|
|
cbEncodedCert)))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
l = DecodeNames(&pCert->pCertInfo->Issuer, pFields, pStore )
|
|
+
|
|
DecodeNames(&pCert->pCertInfo->Subject, pFields+3, pStore );
|
|
|
|
CertFreeCertificateContext( pCert );
|
|
|
|
return l;
|
|
}
|
|
#endif
|
|
|
|
///////////////////////
|
|
|
|
//
|
|
// Taken from NCSA HTTP and wwwlib.
|
|
//
|
|
// NOTE: These conform to RFC1113, which is slightly different then the Unix
|
|
// uuencode and uudecode!
|
|
//
|
|
|
|
const int _pr2six[256]={
|
|
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
|
|
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,62,64,64,64,63,
|
|
52,53,54,55,56,57,58,59,60,61,64,64,64,64,64,64,64,0,1,2,3,4,5,6,7,8,9,
|
|
10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,64,64,64,64,64,64,26,27,
|
|
28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,
|
|
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
|
|
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
|
|
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
|
|
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
|
|
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
|
|
64,64,64,64,64,64,64,64,64,64,64,64,64
|
|
};
|
|
|
|
char _six2pr[64] = {
|
|
'A','B','C','D','E','F','G','H','I','J','K','L','M',
|
|
'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
|
|
'a','b','c','d','e','f','g','h','i','j','k','l','m',
|
|
'n','o','p','q','r','s','t','u','v','w','x','y','z',
|
|
'0','1','2','3','4','5','6','7','8','9','+','/'
|
|
};
|
|
|
|
const int _pr2six64[256]={
|
|
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
|
|
64,64,64,64,64,64,64,64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,
|
|
16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,
|
|
40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,
|
|
0,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
|
|
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
|
|
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
|
|
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
|
|
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
|
|
64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
|
|
64,64,64,64,64,64,64,64,64,64,64,64,64
|
|
};
|
|
|
|
char _six2pr64[64] = {
|
|
'`','!','"','#','$','%','&','\'','(',')','*','+',',',
|
|
'-','.','/','0','1','2','3','4','5','6','7','8','9',
|
|
':',';','<','=','>','?','@','A','B','C','D','E','F',
|
|
'G','H','I','J','K','L','M','N','O','P','Q','R','S',
|
|
'T','U','V','W','X','Y','Z','[','\\',']','^','_'
|
|
};
|
|
|
|
BOOL IISuudecode(char * bufcoded,
|
|
BYTE * bufout,
|
|
DWORD * pcbDecoded,
|
|
BOOL fBase64
|
|
)
|
|
{
|
|
int nbytesdecoded;
|
|
char *bufin = bufcoded;
|
|
int nprbytes;
|
|
int *pr2six = (int*)(fBase64 ? _pr2six64 : _pr2six);
|
|
int chL;
|
|
|
|
/* Strip leading whitespace. */
|
|
|
|
while(*bufcoded==' ' || *bufcoded == '\t') bufcoded++;
|
|
|
|
/* Figure out how many characters are in the input buffer.
|
|
* If this would decode into more bytes than would fit into
|
|
* the output buffer, adjust the number of input bytes downwards.
|
|
*/
|
|
bufin = bufcoded;
|
|
while(pr2six[*(bufin++)] <= 63);
|
|
nprbytes = DIFF(bufin - bufcoded) - 1;
|
|
nbytesdecoded = ((nprbytes+3)/4) * 3;
|
|
|
|
bufin = bufcoded;
|
|
|
|
while (nprbytes > 0) {
|
|
chL = bufin[2];
|
|
*(bufout++) =
|
|
(unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
|
|
*(bufout++) =
|
|
(unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
|
|
*(bufout++) =
|
|
(unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
|
|
bufin += 4;
|
|
nprbytes -= 4;
|
|
}
|
|
|
|
if(nprbytes & 03) {
|
|
if(pr2six[chL] > 63)
|
|
nbytesdecoded -= 2;
|
|
else
|
|
nbytesdecoded -= 1;
|
|
}
|
|
|
|
if ( pcbDecoded )
|
|
*pcbDecoded = nbytesdecoded;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// NOTE NOTE NOTE
|
|
// If the buffer length isn't a multiple of 3, we encode one extra byte beyond the
|
|
// end of the buffer. This garbage byte is stripped off by the uudecode code, but
|
|
// -IT HAS TO BE THERE- for uudecode to work. This applies not only our uudecode, but
|
|
// to every uudecode() function that is based on the lib-www distribution [probably
|
|
// a fairly large percentage of the code that's floating around out there].
|
|
//
|
|
|
|
BOOL IISuuencode( BYTE * bufin,
|
|
DWORD nbytes,
|
|
BYTE * outptr,
|
|
BOOL fBase64 )
|
|
{
|
|
unsigned int i;
|
|
unsigned int iRemainder = 0;
|
|
unsigned int iClosestMultOfThree = 0;
|
|
char *six2pr = fBase64 ? _six2pr64 : _six2pr;
|
|
BOOL fOneByteDiff = FALSE;
|
|
BOOL fTwoByteDiff = FALSE;
|
|
|
|
|
|
iRemainder = nbytes % 3; //also works for nbytes == 1, 2
|
|
fOneByteDiff = (iRemainder == 1 ? TRUE : FALSE);
|
|
fTwoByteDiff = (iRemainder == 2 ? TRUE : FALSE);
|
|
iClosestMultOfThree = ((nbytes - iRemainder)/3) * 3 ;
|
|
|
|
//
|
|
// Encode bytes in buffer up to multiple of 3 that is closest to nbytes.
|
|
//
|
|
for (i=0; i< iClosestMultOfThree ; i += 3) {
|
|
*(outptr++) = six2pr[*bufin >> 2]; /* c1 */
|
|
*(outptr++) = six2pr[((*bufin << 4) & 060) | ((bufin[1] >> 4) & 017)]; /*c2*/
|
|
*(outptr++) = six2pr[((bufin[1] << 2) & 074) | ((bufin[2] >> 6) & 03)];/*c3*/
|
|
*(outptr++) = six2pr[bufin[2] & 077]; /* c4 */
|
|
|
|
bufin += 3;
|
|
}
|
|
|
|
//
|
|
// We deal with trailing bytes by pretending that the input buffer has been padded with
|
|
// zeros. Expressions are thus the same as above, but the second half drops off b'cos
|
|
// ( a | ( b & 0) ) = ( a | 0 ) = a
|
|
//
|
|
if (fOneByteDiff)
|
|
{
|
|
*(outptr++) = six2pr[*bufin >> 2]; /* c1 */
|
|
*(outptr++) = six2pr[((*bufin << 4) & 060)]; /* c2 */
|
|
|
|
//pad with '='
|
|
*(outptr++) = '='; /* c3 */
|
|
*(outptr++) = '='; /* c4 */
|
|
}
|
|
else if (fTwoByteDiff)
|
|
{
|
|
*(outptr++) = six2pr[*bufin >> 2]; /* c1 */
|
|
*(outptr++) = six2pr[((*bufin << 4) & 060) | ((bufin[1] >> 4) & 017)]; /*c2*/
|
|
*(outptr++) = six2pr[((bufin[1] << 2) & 074)];/*c3*/
|
|
|
|
//pad with '='
|
|
*(outptr++) = '='; /* c4 */
|
|
}
|
|
|
|
//encoded buffer must be zero-terminated
|
|
*outptr = '\0';
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
#if 0
|
|
|
|
//
|
|
// Functions to create 1:1 mapping using issuer, subject to NT acct
|
|
//
|
|
|
|
static CIisCert11Mapper g_ExpCert11Mapper;
|
|
LONG g_fCert11Init = FALSE;
|
|
|
|
DWORD
|
|
MappingInit(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Initialize cert 1:1 mapping entry points
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Returns:
|
|
|
|
0 if success, otherwise NT error code
|
|
|
|
--*/
|
|
{
|
|
DWORD st = 0;
|
|
BOOL fFirst;
|
|
|
|
EnterCriticalSection( &g_csIisMap );
|
|
if ( !g_fCert11Init )
|
|
{
|
|
st = g_ExpCert11Mapper.Init( &fFirst, FALSE ) ? 0 : ERROR_OPEN_FAILED;
|
|
if ( !st )
|
|
{
|
|
st = g_ExpCert11Mapper.Load() ? 0 : GetLastError();
|
|
}
|
|
g_fCert11Init = TRUE;
|
|
}
|
|
LeaveCriticalSection( &g_csIisMap );
|
|
|
|
return st;
|
|
}
|
|
|
|
|
|
BOOL
|
|
UnicodeToAnsi(
|
|
LPWSTR pwsz,
|
|
LPSTR* ppsz,
|
|
LPDWORD pc )
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create ANSI version of Unicode string
|
|
|
|
Arguments:
|
|
|
|
pwsz - ptr to Unicode string
|
|
ppsz - updated with ptr to ANSI string, or NULL if error
|
|
pc - updated with # of chars in converted string
|
|
|
|
Returns:
|
|
|
|
TRUE if success, otherwise FALSE
|
|
|
|
--*/
|
|
{
|
|
DWORD dwW = wcslen( pwsz );
|
|
#if 1 // DBCS worst case
|
|
DWORD dwS = dwW * 2;
|
|
#else
|
|
DWORD dwS = dwW;
|
|
#endif
|
|
LPSTR psz;
|
|
|
|
if ( *ppsz = psz = (LPSTR)LocalAlloc( LMEM_FIXED, dwS + 1 ) )
|
|
{
|
|
dwS = WideCharToMultiByte( CP_ACP, 0,
|
|
pwsz, dwW,
|
|
psz, dwS,
|
|
NULL, NULL );
|
|
psz[dwS] = '\0';
|
|
*pc = dwS;
|
|
}
|
|
|
|
if ( dwS == 0 && dwW != 0 )
|
|
{
|
|
if ( psz )
|
|
{
|
|
LocalFree( psz );
|
|
*ppsz = NULL;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
#define UnicodeToAnsiFree( a ) {if ( (a)!=NULL ) LocalFree(a);}
|
|
|
|
|
|
DWORD WINAPI
|
|
CreateMapping(
|
|
LPWSTR pwszUuIssuer,
|
|
LPWSTR pwszUuSubject,
|
|
LPWSTR pwszNtAcct
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create mapping for cert 1:1 mapper
|
|
|
|
Arguments:
|
|
|
|
pwszUuIssuer - uuencoded Issuer
|
|
pwszSubject - uuencoded Subject
|
|
pwszNtAcct - NT account to map to
|
|
|
|
Returns:
|
|
|
|
0 if success, otherwise NT error code
|
|
|
|
--*/
|
|
{
|
|
DWORD st = 0;
|
|
LPSTR pI;
|
|
LPSTR pS;
|
|
LPSTR pN;
|
|
DWORD cI;
|
|
DWORD cS;
|
|
DWORD cN;
|
|
|
|
if ( (st=MappingInit()) )
|
|
{
|
|
return st;
|
|
}
|
|
|
|
CIisMapping *pM = g_ExpCert11Mapper.CreateNewMapping();
|
|
if ( !pM )
|
|
{
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
UnicodeToAnsi( pwszUuIssuer, &pI, &cI );
|
|
UnicodeToAnsi( pwszUuSubject, &pS, &cS );
|
|
UnicodeToAnsi( pwszNtAcct, &pN, &cN );
|
|
|
|
if ( pI != NULL && pS != NULL && pN != NULL )
|
|
{
|
|
pM->MappingSetField( IISMDB_INDEX_CERT11_ISSUER, pI, cI, TRUE );
|
|
pM->MappingSetField( IISMDB_INDEX_CERT11_SUBJECT, pS, cS, TRUE );
|
|
pM->MappingSetField( IISMDB_INDEX_CERT11_NT_ACCT, pN, cN, FALSE );
|
|
|
|
if ( !g_ExpCert11Mapper.Add( pM ) )
|
|
{
|
|
st = GetLastError();;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
st = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
UnicodeToAnsiFree( pI );
|
|
UnicodeToAnsiFree( pS );
|
|
UnicodeToAnsiFree( pN );
|
|
|
|
return st;
|
|
}
|
|
|
|
|
|
DWORD WINAPI
|
|
CheckMapping(
|
|
LPWSTR pwszUuIssuer,
|
|
LPWSTR pwszUuSubject,
|
|
LPWSTR* ppwszNtAcct // Out
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Check if mapping exists for cert 1:1 mapper
|
|
|
|
Arguments:
|
|
|
|
pwszUuIssuer - uuencoded Issuer
|
|
pwszSubject - uuencoded Subject
|
|
ppwszNtAcct - receive ptr to mapped NT account if exist
|
|
or NULL if any error
|
|
Must be released by a call to LocalFree()
|
|
|
|
Returns:
|
|
|
|
0 if success, otherwise NT error code
|
|
ERROR_INVALID_PARAMETER if no such mapping
|
|
|
|
--*/
|
|
{
|
|
DWORD st = 0;
|
|
LPSTR pI;
|
|
LPSTR pS;
|
|
DWORD cI;
|
|
DWORD cS;
|
|
LPWSTR pwszNtAcct = NULL;
|
|
|
|
if ( (st=MappingInit()) )
|
|
{
|
|
return st;
|
|
}
|
|
|
|
CIisMapping *pM = g_ExpCert11Mapper.CreateNewMapping();
|
|
if ( !pM )
|
|
{
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
UnicodeToAnsi( pwszUuIssuer, &pI, &cI );
|
|
UnicodeToAnsi( pwszUuSubject, &pS, &cS );
|
|
|
|
if ( pI != NULL && pS != NULL )
|
|
{
|
|
pM->MappingSetField( IISMDB_INDEX_CERT11_ISSUER, pI, cI, TRUE );
|
|
pM->MappingSetField( IISMDB_INDEX_CERT11_SUBJECT, pS, cS, TRUE );
|
|
|
|
DWORD iCurrent = 0xffffffff;
|
|
CIisMapping* pMi;
|
|
LPSTR pAcct;
|
|
DWORD dwAcct;
|
|
|
|
if ( !g_ExpCert11Mapper.FindMatch( pM, &pMi ) ||
|
|
!pMi->MappingGetField( IISMDB_INDEX_CERT11_NT_ACCT, &pAcct, &dwAcct, FALSE )
|
|
|| pAcct == NULL )
|
|
{
|
|
st = ERROR_INVALID_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
DWORD dw;
|
|
if ( !(pwszNtAcct = (LPWSTR)LocalAlloc( LMEM_FIXED,
|
|
(dwAcct+1)*sizeof(WCHAR) )) )
|
|
{
|
|
st = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
else
|
|
{
|
|
dw = MultiByteToWideChar( CP_ACP, 0,
|
|
pAcct, dwAcct,
|
|
pwszNtAcct, dwAcct );
|
|
pwszNtAcct[dw] = L'\0';
|
|
*ppwszNtAcct = pwszNtAcct;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
st = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
g_ExpCert11Mapper.DeleteMappingObject( pM );
|
|
UnicodeToAnsiFree( pI );
|
|
UnicodeToAnsiFree( pS );
|
|
|
|
if ( st )
|
|
{
|
|
*ppwszNtAcct = NULL;
|
|
}
|
|
|
|
return st;
|
|
}
|
|
|
|
|
|
DWORD WINAPI
|
|
SaveMapping(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Save mappings for cert 1:1 mapper
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Returns:
|
|
|
|
0 if success, otherwise NT error code
|
|
ERROR_WRITE_FAULT if generic write error
|
|
|
|
--*/
|
|
{
|
|
DWORD st = 0;
|
|
|
|
if ( (st=MappingInit()) )
|
|
{
|
|
return st;
|
|
}
|
|
|
|
SetLastError( 0 );
|
|
if ( !g_ExpCert11Mapper.Save() )
|
|
{
|
|
st = GetLastError();
|
|
st = st ? st : ERROR_WRITE_FAULT;
|
|
}
|
|
|
|
return st;
|
|
}
|
|
|
|
#endif
|