1007 lines
23 KiB
C
1007 lines
23 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1995 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
httpfilt.cxx
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module contains the code to create or set the HTTP PCT/SSL keys and
|
|||
|
password
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
John Ludeman (johnl) 19-Oct-1995
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include <nt.h>
|
|||
|
#include <ntrtl.h>
|
|||
|
#include <nturtl.h>
|
|||
|
#include <ntsecapi.h>
|
|||
|
|
|||
|
#include <windows.h>
|
|||
|
|
|||
|
#define SECURITY_WIN32
|
|||
|
#include <sspi.h>
|
|||
|
#include <spseal.h>
|
|||
|
#include <issperr.h>
|
|||
|
#include <sslsp.h>
|
|||
|
#include <w3svc.h>
|
|||
|
|
|||
|
#include <stdio.h>
|
|||
|
#include <stdlib.h>
|
|||
|
#include <string.h>
|
|||
|
#include <fcntl.h>
|
|||
|
#include <io.h>
|
|||
|
#include <strings.h>
|
|||
|
|
|||
|
//
|
|||
|
// macros
|
|||
|
//
|
|||
|
|
|||
|
#define IS_ARG(c) ((c) == L'-' || (c) == L'/')
|
|||
|
|
|||
|
#define TO_UNICODE( pch, ach ) \
|
|||
|
MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, (pch), -1, (ach), sizeof((ach))/sizeof(WCHAR))
|
|||
|
|
|||
|
#define TO_ANSI( pch, ach ) \
|
|||
|
WideCharToMultiByte( CP_ACP, WC_COMPOSITECHECK, pch, -1, ach, sizeof(ach), 0, 0 )
|
|||
|
|
|||
|
//
|
|||
|
// Private constants.
|
|||
|
//
|
|||
|
|
|||
|
//
|
|||
|
// Private types.
|
|||
|
//
|
|||
|
|
|||
|
BOOL fUUDecode = TRUE;
|
|||
|
|
|||
|
//
|
|||
|
// Private prototypes.
|
|||
|
//
|
|||
|
|
|||
|
DWORD
|
|||
|
SetRegKeys(
|
|||
|
IN LPWSTR pszServer,
|
|||
|
IN LPWSTR pszPrivateKeyFile,
|
|||
|
IN LPWSTR pszCertificateFile,
|
|||
|
IN LPWSTR pszPassword,
|
|||
|
IN LPWSTR pszAddress
|
|||
|
);
|
|||
|
|
|||
|
BOOL
|
|||
|
SetKeySecret(
|
|||
|
WCHAR * pszServer,
|
|||
|
WCHAR * pszFormat,
|
|||
|
WCHAR * pszAddress,
|
|||
|
VOID * pvData,
|
|||
|
DWORD cbData
|
|||
|
);
|
|||
|
|
|||
|
void usage();
|
|||
|
|
|||
|
VOID
|
|||
|
uudecode_cert(
|
|||
|
char * bufcoded,
|
|||
|
DWORD * pcbDecoded
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
printfids(
|
|||
|
DWORD ids,
|
|||
|
...
|
|||
|
);
|
|||
|
|
|||
|
DWORD
|
|||
|
DeleteAll(
|
|||
|
WCHAR * pszServer
|
|||
|
);
|
|||
|
|
|||
|
BOOL
|
|||
|
TsGetSecretW(
|
|||
|
WCHAR * pszSecretName,
|
|||
|
WCHAR * * ppchValue
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// Public functions.
|
|||
|
//
|
|||
|
|
|||
|
|
|||
|
int
|
|||
|
__cdecl
|
|||
|
main(
|
|||
|
int argc,
|
|||
|
char * argv[]
|
|||
|
)
|
|||
|
{
|
|||
|
DWORD err;
|
|||
|
CHAR buff[MAX_PATH+1];
|
|||
|
BOOL fDeleteAll = FALSE;
|
|||
|
|
|||
|
LPWSTR password = NULL;
|
|||
|
LPWSTR privatekey = NULL;
|
|||
|
LPWSTR cert = NULL;
|
|||
|
LPWSTR address = NULL;
|
|||
|
LPWSTR server = NULL;
|
|||
|
|
|||
|
WCHAR achpassword[MAX_PATH+1];
|
|||
|
WCHAR achprivatekey[MAX_PATH+1];
|
|||
|
WCHAR achcert[MAX_PATH+1];
|
|||
|
WCHAR achaddress[MAX_PATH+1];
|
|||
|
WCHAR achserver[MAX_PATH+1];
|
|||
|
|
|||
|
|
|||
|
printfids( IDS_BANNER1 );
|
|||
|
printfids( IDS_BANNER2 );
|
|||
|
|
|||
|
for (--argc, ++argv; argc; --argc, ++argv) {
|
|||
|
if (IS_ARG(**argv)) {
|
|||
|
switch (*++*argv) {
|
|||
|
|
|||
|
case 'u':
|
|||
|
case 'U':
|
|||
|
fUUDecode = FALSE;
|
|||
|
break;
|
|||
|
|
|||
|
case 'd':
|
|||
|
case 'D':
|
|||
|
fDeleteAll = TRUE;
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
printfids( IDS_BAD_FLAG, **argv );
|
|||
|
usage();
|
|||
|
|
|||
|
}
|
|||
|
} else if ( !server && (*argv)[0] == L'\\' && (*argv)[1] == L'\\'
|
|||
|
&& !password ) {
|
|||
|
TO_UNICODE( (*argv) + 2, achserver );
|
|||
|
server = achserver;
|
|||
|
} else if (!password) {
|
|||
|
TO_UNICODE( *argv, achpassword );
|
|||
|
password = achpassword;
|
|||
|
} else if (!privatekey) {
|
|||
|
TO_UNICODE( *argv, achprivatekey );
|
|||
|
privatekey = achprivatekey;
|
|||
|
} else if (!cert) {
|
|||
|
TO_UNICODE( *argv, achcert );
|
|||
|
cert = achcert;
|
|||
|
} else if (!address) {
|
|||
|
TO_UNICODE( *argv, achaddress );
|
|||
|
address = achaddress;
|
|||
|
} else {
|
|||
|
printfids( IDS_BAD_ARG, *argv);
|
|||
|
usage();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if ( fDeleteAll )
|
|||
|
{
|
|||
|
return DeleteAll( server );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Address and server are optional
|
|||
|
//
|
|||
|
|
|||
|
if (!(password && privatekey && cert)) {
|
|||
|
printfids( IDS_MISSING_ARG );
|
|||
|
usage();
|
|||
|
}
|
|||
|
|
|||
|
if ( err = SetRegKeys( server, privatekey, cert, password, address ) )
|
|||
|
{
|
|||
|
printfids( IDS_FAILED_TO_SET );
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if ( address )
|
|||
|
{
|
|||
|
TO_ANSI( address, buff );
|
|||
|
printfids( IDS_SUCCESSFUL_SET,
|
|||
|
buff );
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
printfids( IDS_SUCCESSFUL_SET_DEF );
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
return err;
|
|||
|
|
|||
|
} // main
|
|||
|
|
|||
|
void usage()
|
|||
|
{
|
|||
|
printfids( IDS_USAGE1 );
|
|||
|
printfids( IDS_USAGE2 );
|
|||
|
//printfids( IDS_USAGE3 ); // -p help
|
|||
|
printfids( IDS_USAGE4 );
|
|||
|
printfids( IDS_USAGE5 );
|
|||
|
printfids( IDS_USAGE6 );
|
|||
|
printfids( IDS_USAGE7 );
|
|||
|
printfids( IDS_USAGE8 );
|
|||
|
printfids( IDS_USAGE9 );
|
|||
|
printfids( IDS_USAGE10 );
|
|||
|
printfids( IDS_USAGE11 );
|
|||
|
printfids( IDS_USAGE12 );
|
|||
|
printfids( IDS_USAGE13 );
|
|||
|
//printfids( IDS_USAGE14 ); // -p help
|
|||
|
printfids( IDS_USAGE15 );
|
|||
|
printfids( IDS_USAGE16 );
|
|||
|
printfids( IDS_USAGE17 );
|
|||
|
printfids( IDS_USAGE18 );
|
|||
|
printfids( IDS_USAGE19 );
|
|||
|
printfids( IDS_USAGE20 );
|
|||
|
|
|||
|
exit(1);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//+---------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Function: SetRegKeys
|
|||
|
//
|
|||
|
// Synopsis: This loads the data contained in two files, a private key
|
|||
|
// file, which contains the key, and a certificate file,
|
|||
|
// which contains the certificate of the public portion of the key.
|
|||
|
// These are loaded, then turned into a credential handle, then
|
|||
|
// set in the registry as secrets
|
|||
|
//
|
|||
|
// Arguments: [pszServer] -- Server to create secrets, NULL for local
|
|||
|
// [pszPrivateKeyFile] -- Unicode file name
|
|||
|
// [pszCertificateFile] -- Unicode file name
|
|||
|
// [pszPassword] -- Unicode password
|
|||
|
// [pszAddress] -- Unicode IP address for name or NULL
|
|||
|
//
|
|||
|
// History: 9-27-95 RichardW Created
|
|||
|
//
|
|||
|
// Notes:
|
|||
|
//
|
|||
|
//----------------------------------------------------------------------------
|
|||
|
DWORD
|
|||
|
SetRegKeys(
|
|||
|
IN LPWSTR pszServer,
|
|||
|
IN LPWSTR pszPrivateKeyFile,
|
|||
|
IN LPWSTR pszCertificateFile,
|
|||
|
IN LPWSTR pszPassword,
|
|||
|
IN LPWSTR pszAddress
|
|||
|
)
|
|||
|
{
|
|||
|
HANDLE hFile;
|
|||
|
SSL_CREDENTIAL_CERTIFICATE creds;
|
|||
|
DWORD cbRead;
|
|||
|
SECURITY_STATUS scRet = 0;
|
|||
|
TimeStamp tsExpiry;
|
|||
|
CHAR achPassword[MAX_PATH + 1];
|
|||
|
CredHandle hCreds;
|
|||
|
DWORD cch;
|
|||
|
CHAR buff[MAX_PATH+1];
|
|||
|
|
|||
|
//
|
|||
|
// Fetch data from files:
|
|||
|
//
|
|||
|
|
|||
|
hFile = CreateFileW( pszPrivateKeyFile,
|
|||
|
GENERIC_READ,
|
|||
|
FILE_SHARE_READ,
|
|||
|
NULL,
|
|||
|
OPEN_EXISTING,
|
|||
|
0,
|
|||
|
NULL
|
|||
|
);
|
|||
|
|
|||
|
if (hFile == INVALID_HANDLE_VALUE)
|
|||
|
{
|
|||
|
TO_ANSI( pszPrivateKeyFile, buff );
|
|||
|
|
|||
|
printfids( IDS_FILE_NOT_FOUND,
|
|||
|
GetLastError(),
|
|||
|
buff );
|
|||
|
|
|||
|
return GetLastError();
|
|||
|
}
|
|||
|
|
|||
|
creds.cbPrivateKey = GetFileSize( hFile, NULL );
|
|||
|
|
|||
|
if (creds.cbPrivateKey == (DWORD) -1 )
|
|||
|
{
|
|||
|
CloseHandle( hFile );
|
|||
|
return GetLastError();
|
|||
|
}
|
|||
|
|
|||
|
creds.pPrivateKey = LocalAlloc( LMEM_FIXED, creds.cbPrivateKey );
|
|||
|
|
|||
|
if ( !creds.pPrivateKey )
|
|||
|
{
|
|||
|
CloseHandle( hFile );
|
|||
|
return GetLastError();
|
|||
|
}
|
|||
|
|
|||
|
if (! ReadFile( hFile,
|
|||
|
creds.pPrivateKey,
|
|||
|
creds.cbPrivateKey,
|
|||
|
&cbRead,
|
|||
|
NULL ) )
|
|||
|
{
|
|||
|
CloseHandle( hFile );
|
|||
|
|
|||
|
LocalFree( creds.pPrivateKey );
|
|||
|
|
|||
|
return GetLastError();
|
|||
|
}
|
|||
|
|
|||
|
CloseHandle( hFile );
|
|||
|
|
|||
|
//
|
|||
|
// Only the certificate is UUencoded
|
|||
|
//
|
|||
|
|
|||
|
hFile = CreateFileW( pszCertificateFile,
|
|||
|
GENERIC_READ,
|
|||
|
FILE_SHARE_READ,
|
|||
|
NULL,
|
|||
|
OPEN_EXISTING,
|
|||
|
0,
|
|||
|
NULL );
|
|||
|
|
|||
|
if (hFile == INVALID_HANDLE_VALUE)
|
|||
|
{
|
|||
|
TO_ANSI( pszCertificateFile, buff );
|
|||
|
printfids( IDS_FILE_NOT_FOUND,
|
|||
|
GetLastError(),
|
|||
|
buff );
|
|||
|
|
|||
|
LocalFree( creds.pPrivateKey );
|
|||
|
return GetLastError();
|
|||
|
}
|
|||
|
|
|||
|
creds.cbCertificate = GetFileSize( hFile, NULL );
|
|||
|
|
|||
|
if (creds.cbCertificate == (DWORD) -1 )
|
|||
|
{
|
|||
|
CloseHandle( hFile );
|
|||
|
|
|||
|
LocalFree( creds.pPrivateKey );
|
|||
|
|
|||
|
return GetLastError();
|
|||
|
}
|
|||
|
|
|||
|
creds.pCertificate = LocalAlloc( LMEM_FIXED, creds.cbCertificate + 1);
|
|||
|
|
|||
|
if ( !creds.pCertificate )
|
|||
|
{
|
|||
|
CloseHandle( hFile );
|
|||
|
|
|||
|
LocalFree( creds.pPrivateKey );
|
|||
|
|
|||
|
return GetLastError();
|
|||
|
}
|
|||
|
|
|||
|
if (! ReadFile( hFile,
|
|||
|
creds.pCertificate,
|
|||
|
creds.cbCertificate,
|
|||
|
&cbRead,
|
|||
|
NULL ) )
|
|||
|
{
|
|||
|
CloseHandle( hFile );
|
|||
|
|
|||
|
LocalFree( creds.pPrivateKey );
|
|||
|
|
|||
|
LocalFree( creds.pCertificate );
|
|||
|
|
|||
|
return GetLastError();
|
|||
|
}
|
|||
|
|
|||
|
CloseHandle( hFile );
|
|||
|
|
|||
|
//
|
|||
|
// Zero terminate so we can uudecode
|
|||
|
//
|
|||
|
|
|||
|
((BYTE *)creds.pCertificate)[cbRead] = '\0';
|
|||
|
|
|||
|
if ( fUUDecode )
|
|||
|
{
|
|||
|
uudecode_cert( creds.pCertificate,
|
|||
|
&creds.cbCertificate );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Whew! Now that we have safely loaded the keys from disk, get a cred
|
|||
|
// handle based on the certificate/prv key combo
|
|||
|
//
|
|||
|
|
|||
|
//
|
|||
|
// BUGBUG - password field should be Unicode, do a quick conversion
|
|||
|
// until structure is fixed
|
|||
|
//
|
|||
|
|
|||
|
cch = TO_ANSI( pszPassword, achPassword );
|
|||
|
|
|||
|
if ( !cch )
|
|||
|
{
|
|||
|
return GetLastError();
|
|||
|
}
|
|||
|
|
|||
|
creds.pszPassword = achPassword;
|
|||
|
|
|||
|
//
|
|||
|
// Note we always do the credential check locally even if the server is
|
|||
|
// remote. This means the local machine must have the correct security
|
|||
|
// provider package installed.
|
|||
|
//
|
|||
|
|
|||
|
#if 0
|
|||
|
if ( !pszServer )
|
|||
|
{
|
|||
|
#endif
|
|||
|
scRet = AcquireCredentialsHandleW( NULL, // My name (ignored)
|
|||
|
SSLSP_NAME_W, // Package
|
|||
|
SECPKG_CRED_INBOUND,// Use
|
|||
|
NULL, // Logon Id (ign.)
|
|||
|
&creds, // auth data
|
|||
|
NULL, // dce-stuff
|
|||
|
NULL, // dce-stuff
|
|||
|
&hCreds, // Handle
|
|||
|
&tsExpiry );
|
|||
|
|
|||
|
if ( FAILED(scRet) )
|
|||
|
{
|
|||
|
if ( scRet == SEC_E_NOT_OWNER )
|
|||
|
{
|
|||
|
printfids( IDS_BAD_PASSWORD );
|
|||
|
}
|
|||
|
else if ( scRet == SEC_E_SECPKG_NOT_FOUND )
|
|||
|
{
|
|||
|
printfids( IDS_SECPKG_NOT_FOUND );
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
printfids( IDS_KEYCHECK_FAILED,
|
|||
|
scRet );
|
|||
|
}
|
|||
|
}
|
|||
|
#if 0
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
printf("\nWarning! Bypassing credential check because target is remote\n");
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
//
|
|||
|
// If we successfully acquired a credential handle, set the secrets
|
|||
|
//
|
|||
|
|
|||
|
if ( !FAILED( scRet ))
|
|||
|
{
|
|||
|
if ( !pszServer )
|
|||
|
{
|
|||
|
FreeCredentialsHandle( &hCreds );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Supply the default name if none was supplied
|
|||
|
//
|
|||
|
|
|||
|
if ( !pszAddress )
|
|||
|
pszAddress = L"Default";
|
|||
|
|
|||
|
//
|
|||
|
// Set the secrets
|
|||
|
//
|
|||
|
|
|||
|
if ( !SetKeySecret( pszServer,
|
|||
|
L"W3_PUBLIC_KEY_%s",
|
|||
|
pszAddress,
|
|||
|
creds.pCertificate,
|
|||
|
creds.cbCertificate ) ||
|
|||
|
!SetKeySecret( pszServer,
|
|||
|
L"W3_PRIVATE_KEY_%s",
|
|||
|
pszAddress,
|
|||
|
creds.pPrivateKey,
|
|||
|
creds.cbPrivateKey ) ||
|
|||
|
!SetKeySecret( pszServer,
|
|||
|
L"W3_KEY_PASSWORD_%s",
|
|||
|
pszAddress,
|
|||
|
achPassword,
|
|||
|
strlen( achPassword ) + 1) )
|
|||
|
{
|
|||
|
printfids( IDS_SETSECRET_FAILED,
|
|||
|
GetLastError());
|
|||
|
|
|||
|
scRet = (SECURITY_STATUS) GetLastError();
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
WCHAR InstalledKeys[16384];
|
|||
|
WCHAR * pchKeys;
|
|||
|
|
|||
|
*InstalledKeys = L'\0';
|
|||
|
|
|||
|
//
|
|||
|
// Ok if this fails, it may not exist yet
|
|||
|
//
|
|||
|
|
|||
|
if ( TsGetSecretW( W3_SSL_KEY_LIST_SECRET,
|
|||
|
&pchKeys ))
|
|||
|
{
|
|||
|
wcscpy( InstalledKeys, pchKeys );
|
|||
|
}
|
|||
|
|
|||
|
wcscat( InstalledKeys, pszAddress );
|
|||
|
wcscat( InstalledKeys, L"," );
|
|||
|
|
|||
|
#if DBG
|
|||
|
printf("New list: %S\n", InstalledKeys);
|
|||
|
#endif
|
|||
|
|
|||
|
if ( !SetKeySecret( pszServer,
|
|||
|
L"W3_KEY_LIST",
|
|||
|
pszAddress,
|
|||
|
InstalledKeys,
|
|||
|
(wcslen( InstalledKeys ) + 1) * sizeof(WCHAR)))
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
printf("Warning: failed to set key list data, error %d\n");
|
|||
|
#endif
|
|||
|
scRet = (SECURITY_STATUS) GetLastError();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Zero out and free the key data memory, on success or fail
|
|||
|
//
|
|||
|
|
|||
|
ZeroMemory( creds.pPrivateKey, creds.cbPrivateKey );
|
|||
|
ZeroMemory( creds.pCertificate, creds.cbCertificate );
|
|||
|
ZeroMemory( achPassword, cch );
|
|||
|
ZeroMemory( pszPassword, cch );
|
|||
|
|
|||
|
LocalFree( creds.pPrivateKey );
|
|||
|
LocalFree( creds.pCertificate );
|
|||
|
|
|||
|
//
|
|||
|
// Tell the caller about it.
|
|||
|
//
|
|||
|
|
|||
|
return( scRet );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
BOOL
|
|||
|
SetKeySecret(
|
|||
|
WCHAR * pszServer,
|
|||
|
WCHAR * pszFormat,
|
|||
|
WCHAR * pszAddress,
|
|||
|
VOID * pvData,
|
|||
|
DWORD cbData
|
|||
|
)
|
|||
|
{
|
|||
|
BOOL fResult;
|
|||
|
NTSTATUS ntStatus;
|
|||
|
LSA_UNICODE_STRING unicodeName;
|
|||
|
LSA_UNICODE_STRING unicodeSecret;
|
|||
|
LSA_UNICODE_STRING unicodeServer;
|
|||
|
LSA_HANDLE hPolicy;
|
|||
|
LSA_OBJECT_ATTRIBUTES ObjectAttributes;
|
|||
|
WCHAR achSecretName[MAX_PATH+1];
|
|||
|
CHAR buff[MAX_PATH+1];
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Open a policy to the remote LSA
|
|||
|
//
|
|||
|
|
|||
|
InitializeObjectAttributes( &ObjectAttributes,
|
|||
|
NULL,
|
|||
|
0L,
|
|||
|
NULL,
|
|||
|
NULL );
|
|||
|
|
|||
|
if ( pszServer )
|
|||
|
{
|
|||
|
unicodeServer.Buffer = pszServer;
|
|||
|
unicodeServer.Length = wcslen( pszServer ) * sizeof(WCHAR);
|
|||
|
unicodeServer.MaximumLength = unicodeServer.Length + sizeof(WCHAR);
|
|||
|
}
|
|||
|
|
|||
|
ntStatus = LsaOpenPolicy( pszServer ? &unicodeServer : NULL,
|
|||
|
&ObjectAttributes,
|
|||
|
POLICY_ALL_ACCESS,
|
|||
|
&hPolicy );
|
|||
|
|
|||
|
if ( !NT_SUCCESS( ntStatus ) )
|
|||
|
{
|
|||
|
SetLastError( LsaNtStatusToWinError( ntStatus ) );
|
|||
|
|
|||
|
TO_ANSI( pszServer, buff );
|
|||
|
|
|||
|
printfids(IDS_FAILED_OPENING_SERVER,
|
|||
|
buff,
|
|||
|
GetLastError() );
|
|||
|
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Build the secret name
|
|||
|
//
|
|||
|
|
|||
|
wsprintfW( achSecretName,
|
|||
|
pszFormat,
|
|||
|
pszAddress );
|
|||
|
|
|||
|
unicodeSecret.Buffer = pvData;
|
|||
|
unicodeSecret.Length = (USHORT) cbData;
|
|||
|
unicodeSecret.MaximumLength = (USHORT) cbData;
|
|||
|
|
|||
|
unicodeName.Buffer = achSecretName;
|
|||
|
unicodeName.Length = wcslen( achSecretName ) * sizeof(WCHAR);
|
|||
|
unicodeName.MaximumLength = unicodeName.Length + sizeof(WCHAR);
|
|||
|
|
|||
|
//
|
|||
|
// Query the secret value.
|
|||
|
//
|
|||
|
|
|||
|
ntStatus = LsaStorePrivateData( hPolicy,
|
|||
|
&unicodeName,
|
|||
|
pvData ? &unicodeSecret : NULL );
|
|||
|
|
|||
|
fResult = NT_SUCCESS(ntStatus);
|
|||
|
|
|||
|
//
|
|||
|
// Cleanup & exit.
|
|||
|
//
|
|||
|
|
|||
|
LsaClose( hPolicy );
|
|||
|
|
|||
|
if ( !fResult )
|
|||
|
SetLastError( LsaNtStatusToWinError( ntStatus ));
|
|||
|
|
|||
|
return fResult;
|
|||
|
|
|||
|
} // SetKeySecret
|
|||
|
|
|||
|
VOID
|
|||
|
printfids(
|
|||
|
DWORD ids,
|
|||
|
...
|
|||
|
)
|
|||
|
{
|
|||
|
CHAR szBuff[2048];
|
|||
|
CHAR szString[2048];
|
|||
|
va_list argList;
|
|||
|
|
|||
|
//
|
|||
|
// Try and load the string
|
|||
|
//
|
|||
|
|
|||
|
if ( !LoadString( GetModuleHandle( NULL ),
|
|||
|
ids,
|
|||
|
szString,
|
|||
|
sizeof( szString ) ))
|
|||
|
{
|
|||
|
printf( "Error loading string ID %d\n",
|
|||
|
ids );
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
va_start( argList, ids );
|
|||
|
vsprintf( szBuff, szString, argList );
|
|||
|
va_end( argList );
|
|||
|
|
|||
|
printf( szBuff );
|
|||
|
}
|
|||
|
|
|||
|
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
|
|||
|
};
|
|||
|
|
|||
|
//
|
|||
|
// We have to squirt a record into the decoded stream
|
|||
|
//
|
|||
|
|
|||
|
#define CERT_RECORD 13
|
|||
|
#define CERT_SIZE_HIBYTE 2 // Index into record of record size
|
|||
|
#define CERT_SIZE_LOBYTE 3
|
|||
|
|
|||
|
unsigned char abCertHeader[] = {0x30, 0x82, // Record
|
|||
|
0x00, 0x00, // Size of cert + buff
|
|||
|
0x04, 0x0b, 0x63, 0x65,// Cert record data
|
|||
|
0x72, 0x74, 0x69, 0x66,
|
|||
|
0x69, 0x63, 0x61, 0x74,
|
|||
|
0x65 };
|
|||
|
|
|||
|
VOID uudecode_cert(char * bufcoded,
|
|||
|
DWORD * pcbDecoded )
|
|||
|
{
|
|||
|
int nbytesdecoded;
|
|||
|
char *bufin = bufcoded;
|
|||
|
unsigned char *bufout = bufcoded;
|
|||
|
unsigned char *pbuf;
|
|||
|
int nprbytes;
|
|||
|
char * beginbuf = bufcoded;
|
|||
|
|
|||
|
/* Strip leading whitespace. */
|
|||
|
|
|||
|
while(*bufcoded==' ' ||
|
|||
|
*bufcoded == '\t' ||
|
|||
|
*bufcoded == '\r' ||
|
|||
|
*bufcoded == '\n' )
|
|||
|
{
|
|||
|
bufcoded++;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If there is a beginning '---- ....' then skip the first line
|
|||
|
//
|
|||
|
|
|||
|
if ( bufcoded[0] == '-' && bufcoded[1] == '-' )
|
|||
|
{
|
|||
|
bufin = strchr( bufcoded, '\n' );
|
|||
|
|
|||
|
if ( bufin )
|
|||
|
{
|
|||
|
bufin++;
|
|||
|
bufcoded = bufin;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
bufin = bufcoded;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
bufin = bufcoded;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Strip all cr/lf from the block
|
|||
|
//
|
|||
|
|
|||
|
pbuf = bufin;
|
|||
|
while ( *pbuf )
|
|||
|
{
|
|||
|
if ( *pbuf == '\r' || *pbuf == '\n' )
|
|||
|
{
|
|||
|
memmove( pbuf, pbuf+1, strlen( pbuf + 1) + 1 );
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
pbuf++;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/* 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.
|
|||
|
*/
|
|||
|
|
|||
|
while(pr2six[*(bufin++)] <= 63);
|
|||
|
nprbytes = bufin - bufcoded - 1;
|
|||
|
nbytesdecoded = ((nprbytes+3)/4) * 3;
|
|||
|
|
|||
|
bufin = bufcoded;
|
|||
|
|
|||
|
while (nprbytes > 0) {
|
|||
|
*(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[bufin[-2]] > 63)
|
|||
|
nbytesdecoded -= 2;
|
|||
|
else
|
|||
|
nbytesdecoded -= 1;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Now we need to add a new wrapper sequence around the certificate
|
|||
|
// indicating this is a certificate
|
|||
|
//
|
|||
|
|
|||
|
memmove( beginbuf + sizeof(abCertHeader),
|
|||
|
beginbuf,
|
|||
|
nbytesdecoded );
|
|||
|
|
|||
|
memcpy( beginbuf,
|
|||
|
abCertHeader,
|
|||
|
sizeof(abCertHeader) );
|
|||
|
|
|||
|
//
|
|||
|
// The beginning record size is the total number of bytes decoded plus
|
|||
|
// the number of bytes in the certificate header
|
|||
|
//
|
|||
|
|
|||
|
beginbuf[CERT_SIZE_HIBYTE] = (BYTE) (((USHORT)nbytesdecoded+CERT_RECORD) >> 8);
|
|||
|
beginbuf[CERT_SIZE_LOBYTE] = (BYTE) ((USHORT)nbytesdecoded+CERT_RECORD);
|
|||
|
|
|||
|
nbytesdecoded += sizeof(abCertHeader);
|
|||
|
|
|||
|
if ( pcbDecoded )
|
|||
|
*pcbDecoded = nbytesdecoded;
|
|||
|
}
|
|||
|
|
|||
|
BOOL
|
|||
|
TsGetSecretW(
|
|||
|
WCHAR * pszSecretName,
|
|||
|
WCHAR * * ppchValue
|
|||
|
)
|
|||
|
/*++
|
|||
|
Description:
|
|||
|
|
|||
|
Retrieves the specified unicode secret
|
|||
|
|
|||
|
Note we're loose with the allocated buffer since we're a simple
|
|||
|
command line app.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pszSecretName - LSA Secret to retrieve
|
|||
|
ppchValue - Receives pointer to allocated buffer
|
|||
|
|
|||
|
Returns:
|
|||
|
TRUE on success and FALSE if any failure.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
NTSTATUS ntStatus;
|
|||
|
LSA_UNICODE_STRING * punicodePassword = NULL;
|
|||
|
LSA_UNICODE_STRING unicodeSecret;
|
|||
|
LSA_HANDLE hPolicy;
|
|||
|
LSA_OBJECT_ATTRIBUTES ObjectAttributes;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Open a policy to the remote LSA
|
|||
|
//
|
|||
|
|
|||
|
InitializeObjectAttributes( &ObjectAttributes,
|
|||
|
NULL,
|
|||
|
0L,
|
|||
|
NULL,
|
|||
|
NULL );
|
|||
|
|
|||
|
ntStatus = LsaOpenPolicy( NULL,
|
|||
|
&ObjectAttributes,
|
|||
|
POLICY_ALL_ACCESS,
|
|||
|
&hPolicy );
|
|||
|
|
|||
|
if ( !NT_SUCCESS( ntStatus ) )
|
|||
|
{
|
|||
|
SetLastError( LsaNtStatusToWinError( ntStatus ) );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
unicodeSecret.Buffer = pszSecretName;
|
|||
|
unicodeSecret.Length = wcslen( pszSecretName ) * sizeof(WCHAR);
|
|||
|
unicodeSecret.MaximumLength = unicodeSecret.Length + sizeof(WCHAR);
|
|||
|
|
|||
|
//
|
|||
|
// Query the secret value.
|
|||
|
//
|
|||
|
|
|||
|
ntStatus = LsaRetrievePrivateData( hPolicy,
|
|||
|
&unicodeSecret,
|
|||
|
&punicodePassword );
|
|||
|
|
|||
|
if( NT_SUCCESS(ntStatus) )
|
|||
|
{
|
|||
|
*ppchValue = (WCHAR *) punicodePassword->Buffer;
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
return FALSE;
|
|||
|
|
|||
|
} // TsGetSecretW
|
|||
|
|
|||
|
DWORD
|
|||
|
DeleteAll(
|
|||
|
WCHAR * pszServer
|
|||
|
)
|
|||
|
{
|
|||
|
WCHAR * pchKeys;
|
|||
|
WCHAR * pszAddress;
|
|||
|
|
|||
|
if ( !TsGetSecretW( L"W3_KEY_LIST",
|
|||
|
&pchKeys ))
|
|||
|
{
|
|||
|
printfids( IDS_NO_KEYS_INSTALLED );
|
|||
|
return NO_ERROR;
|
|||
|
}
|
|||
|
|
|||
|
#if DBG
|
|||
|
printf("Installed keys: %S\n", pchKeys);
|
|||
|
#endif
|
|||
|
|
|||
|
pszAddress = pchKeys;
|
|||
|
while ( pchKeys = wcschr( pchKeys, L',' ))
|
|||
|
{
|
|||
|
//
|
|||
|
// Ignore empty segments
|
|||
|
//
|
|||
|
|
|||
|
if ( *pszAddress != L',' )
|
|||
|
{
|
|||
|
*pchKeys = L'\0';
|
|||
|
|
|||
|
#if DBG
|
|||
|
printf("deleting %S\n", pszAddress );
|
|||
|
#endif
|
|||
|
|
|||
|
//
|
|||
|
// Nuke the secrets
|
|||
|
//
|
|||
|
|
|||
|
SetKeySecret( pszServer,
|
|||
|
L"W3_PUBLIC_KEY_%s",
|
|||
|
pszAddress,
|
|||
|
NULL,
|
|||
|
0 );
|
|||
|
SetKeySecret( pszServer,
|
|||
|
L"W3_PRIVATE_KEY_%s",
|
|||
|
pszAddress,
|
|||
|
NULL,
|
|||
|
0 );
|
|||
|
SetKeySecret( pszServer,
|
|||
|
L"W3_KEY_PASSWORD_%s",
|
|||
|
pszAddress,
|
|||
|
NULL,
|
|||
|
0 );
|
|||
|
}
|
|||
|
|
|||
|
pchKeys++;
|
|||
|
pszAddress = pchKeys;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Now delete the list key
|
|||
|
//
|
|||
|
|
|||
|
|
|||
|
if ( !SetKeySecret( pszServer,
|
|||
|
L"W3_KEY_LIST",
|
|||
|
L"",
|
|||
|
NULL,
|
|||
|
0 ))
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
printf("Warning: failed to set key list data, error %d\n");
|
|||
|
#endif
|
|||
|
return GetLastError();
|
|||
|
}
|
|||
|
|
|||
|
printfids( IDS_DELETE_SUCCESSFUL );
|
|||
|
|
|||
|
return NO_ERROR;
|
|||
|
}
|