|
|
/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
crconv.c
Abstract:
This module contains credential conversion routines shared between advapi32.dll and crtest.exe
Author:
Cliff Van Dyke (CliffV) February 25, 2000
Revision History:
--*/
DWORD CredpConvertStringSize ( IN WTOA_ENUM WtoA, IN LPWSTR String OPTIONAL )
/*++
Routine Description:
Determines the size of the converted string
Arguments:
WtoA - Specifies the direction of the string conversion.
String - The string to convert
Return Values:
Returns the size (in bytes) of the converted string.
--*/
{ ULONG Size = 0; UNICODE_STRING UnicodeString; ANSI_STRING AnsiString;
if ( String == NULL ) { return Size; }
switch ( WtoA ) { case DoWtoA: RtlInitUnicodeString( &UnicodeString, String ); Size = RtlUnicodeStringToAnsiSize( &UnicodeString ); break;
case DoAtoW: RtlInitAnsiString( &AnsiString, (LPSTR)String ); Size = RtlAnsiStringToUnicodeSize( &AnsiString ); break; case DoWtoW: Size = (wcslen( String ) + 1) * sizeof(WCHAR); break; }
return Size;
}
DWORD CredpConvertString ( IN WTOA_ENUM WtoA, IN LPWSTR String OPTIONAL, OUT LPWSTR *OutString, IN OUT LPBYTE *WherePtr )
/*++
Routine Description:
Determines the size of the converted string
Arguments:
WtoA - Specifies the direction of the string conversion.
String - The string to convert
OutString - Returns the pointer to the marshaled string
WherePtr - Specifies the address of the first byte to write the string to. Returns a pointer to the first byte after the marshaled string
Return Values:
Returns the status of the conversion
--*/
{ NTSTATUS Status;
ULONG Size;
UNICODE_STRING UnicodeString; ANSI_STRING AnsiString; LPBYTE Where = *WherePtr;
if ( String == NULL ) { *OutString = NULL; return NO_ERROR; }
*OutString = (LPWSTR)Where;
switch ( WtoA ) { case DoWtoA: RtlInitUnicodeString( &UnicodeString, String ); AnsiString.Buffer = (PCHAR)Where; AnsiString.MaximumLength = 0xFFFF; Status = RtlUnicodeStringToAnsiString( &AnsiString, &UnicodeString, FALSE );
if ( !NT_SUCCESS(Status) ) { return RtlNtStatusToDosError( Status ); }
Where += AnsiString.Length + sizeof(CHAR); break;
case DoAtoW: RtlInitAnsiString( &AnsiString, (LPSTR)String ); UnicodeString.Buffer = (LPWSTR)Where; UnicodeString.MaximumLength = 0xFFFF;
Status = RtlAnsiStringToUnicodeString( &UnicodeString, &AnsiString, FALSE );
if ( !NT_SUCCESS(Status) ) { return RtlNtStatusToDosError( Status ); }
Where += UnicodeString.Length + sizeof(WCHAR);
break; case DoWtoW: Size = (wcslen( String ) + 1) * sizeof(WCHAR);
RtlCopyMemory( Where, String, Size ); Where += Size; break; }
*WherePtr = Where; return NO_ERROR;
}
DWORD CredpConvertOneCredentialSize ( IN WTOA_ENUM WtoA, IN PCREDENTIALW InCredential )
/*++
Routine Description:
Computes the size of a converted credential
Arguments:
WtoA - Specifies the direction of the string conversion.
InCredential - Input credential
Return Values:
Returns the size (in bytes) the CredpConvertOneCredential will need to copy this credential into a buffer.
--*/
{ DWORD WinStatus; ULONG Size;
ULONG i;
//
// Compute the initial size
//
Size = ROUND_UP_COUNT( sizeof(ENCRYPTED_CREDENTIALW), ALIGN_WORST ) + ROUND_UP_COUNT( InCredential->AttributeCount * sizeof(CREDENTIAL_ATTRIBUTEW), ALIGN_WORST );
if ( InCredential->CredentialBlobSize != 0 ) { ULONG CredBlobSize;
// Leave room for the encoding over the wire
CredBlobSize = AllocatedCredBlobSize( InCredential->CredentialBlobSize );
// Align the data following the credential blob
Size += ROUND_UP_COUNT( CredBlobSize, ALIGN_WORST ); }
//
// Compute the size of the strings in the right character set.
//
Size += CredpConvertStringSize( WtoA, InCredential->TargetName ); Size += CredpConvertStringSize( WtoA, InCredential->Comment ); Size += CredpConvertStringSize( WtoA, InCredential->TargetAlias ); Size += CredpConvertStringSize( WtoA, InCredential->UserName );
//
// Compute the size of the attributes
//
if ( InCredential->AttributeCount != 0 ) {
for ( i=0; i<InCredential->AttributeCount; i++ ) {
Size += CredpConvertStringSize( WtoA, InCredential->Attributes[i].Keyword );
Size += ROUND_UP_COUNT(InCredential->Attributes[i].ValueSize, ALIGN_WORST);
} }
Size = ROUND_UP_COUNT( Size, ALIGN_WORST );
return Size;
}
DWORD CredpConvertOneCredential ( IN WTOA_ENUM WtoA, IN ENCODE_BLOB_ENUM DoDecode, IN PCREDENTIALW InCredential, IN OUT LPBYTE *WherePtr )
/*++
Routine Description:
Converts one credential from Ansi to Unicode or vice-versa.
Arguments:
WtoA - Specifies the direction of the string conversion.
DoDecode - Specifies whether CredentialBlob should be encoded, decoded, or neither. If DoBlobDecode, then InCredential really points to a PENCRYPTED_CREDENTIALW.
InCredential - Input credentials
WherePtr - Specifies the address of the first byte to write the credential to. On input, the strucure should be aligned ALIGN_WORST. Returns a pointer to the first byte after the marshaled credential. The output credential is actually a ENCRYPTED_CREDENTIALW. The caller can use it as a CREDENTIALW depending on the DoDecode value.
Return Values:
Window status code
--*/
{ DWORD WinStatus;
ULONG i; LPBYTE Where = *WherePtr; LPBYTE OldWhere; PENCRYPTED_CREDENTIALW OutCredential;
//
// Initialize the base structure
//
OutCredential = (PENCRYPTED_CREDENTIALW) Where;
RtlZeroMemory( OutCredential, sizeof(*OutCredential) ); Where += sizeof(*OutCredential);
// Align the running pointer again
OldWhere = Where; Where = (PUCHAR) ROUND_UP_POINTER( OldWhere, ALIGN_WORST ); RtlZeroMemory( OldWhere, Where-OldWhere );
//
// Copy the fixed size data
//
OutCredential->Cred.Flags = InCredential->Flags; OutCredential->Cred.Type = InCredential->Type; OutCredential->Cred.LastWritten = InCredential->LastWritten; OutCredential->Cred.CredentialBlobSize = InCredential->CredentialBlobSize; OutCredential->Cred.Persist = InCredential->Persist; OutCredential->Cred.AttributeCount = InCredential->AttributeCount;
//
// Copy the data we don't know the alignment for.
// (ALIGN_WORST so our caller can't blame us.)
//
if ( InCredential->CredentialBlobSize != 0 ) { ULONG CredBlobSize;
OutCredential->Cred.CredentialBlob = Where; RtlCopyMemory( Where, InCredential->CredentialBlob, InCredential->CredentialBlobSize ); Where += InCredential->CredentialBlobSize;
// Leave room for the encoding over the wire
CredBlobSize = AllocatedCredBlobSize( InCredential->CredentialBlobSize );
// Align the running pointer again
OldWhere = Where; // Align the data following the credential blob
Where = (LPBYTE) ROUND_UP_POINTER( OldWhere+(CredBlobSize-InCredential->CredentialBlobSize), ALIGN_WORST ); RtlZeroMemory( OldWhere, Where-OldWhere );
//
// Encode or decode the Credential blob as requested
//
switch (DoDecode) { case DoBlobDecode: OutCredential->ClearCredentialBlobSize = ((PENCRYPTED_CREDENTIALW)InCredential)->ClearCredentialBlobSize; #ifndef _CRTEST_EXE_
CredpDecodeCredential( OutCredential ); #endif // _CRTEST_EXE_
break; case DoBlobEncode: OutCredential->ClearCredentialBlobSize = InCredential->CredentialBlobSize; #ifndef _CRTEST_EXE_
if (!CredpEncodeCredential( OutCredential ) ) { return ERROR_INVALID_PARAMETER; } #endif // _CRTEST_EXE_
break; case DoBlobNeither: OutCredential->ClearCredentialBlobSize = InCredential->CredentialBlobSize; break; default: return ERROR_INVALID_PARAMETER; } }
if ( InCredential->AttributeCount != 0 ) {
//
// Push an array of attribute structs
//
OutCredential->Cred.Attributes = (PCREDENTIAL_ATTRIBUTEW) Where; Where += InCredential->AttributeCount * sizeof(CREDENTIAL_ATTRIBUTEW);
// Align the running pointer again
OldWhere = Where; Where = (PUCHAR) ROUND_UP_POINTER( OldWhere, ALIGN_WORST ); RtlZeroMemory( OldWhere, Where-OldWhere );
//
// Fill it in.
//
for ( i=0; i<InCredential->AttributeCount; i++ ) {
OutCredential->Cred.Attributes[i].Flags = InCredential->Attributes[i].Flags; OutCredential->Cred.Attributes[i].ValueSize = InCredential->Attributes[i].ValueSize;
if ( InCredential->Attributes[i].ValueSize != 0 ) { OutCredential->Cred.Attributes[i].Value = Where; RtlCopyMemory( Where, InCredential->Attributes[i].Value, InCredential->Attributes[i].ValueSize ); Where += InCredential->Attributes[i].ValueSize;
// Align the running pointer again
OldWhere = Where; Where = (PUCHAR) ROUND_UP_POINTER( OldWhere, ALIGN_WORST ); RtlZeroMemory( OldWhere, Where-OldWhere ); } else { OutCredential->Cred.Attributes[i].Value = NULL; }
} }
//
// Convert the strings to the right character set.
//
WinStatus = CredpConvertString( WtoA, InCredential->TargetName, &OutCredential->Cred.TargetName, &Where );
if ( WinStatus != NO_ERROR ) { goto Cleanup; }
WinStatus = CredpConvertString( WtoA, InCredential->Comment, &OutCredential->Cred.Comment, &Where );
if ( WinStatus != NO_ERROR ) { goto Cleanup; }
WinStatus = CredpConvertString( WtoA, InCredential->TargetAlias, &OutCredential->Cred.TargetAlias, &Where );
if ( WinStatus != NO_ERROR ) { goto Cleanup; }
WinStatus = CredpConvertString( WtoA, InCredential->UserName, &OutCredential->Cred.UserName, &Where );
if ( WinStatus != NO_ERROR ) { goto Cleanup; }
if ( InCredential->AttributeCount != 0 ) {
for ( i=0; i<InCredential->AttributeCount; i++ ) {
WinStatus = CredpConvertString( WtoA, InCredential->Attributes[i].Keyword, &OutCredential->Cred.Attributes[i].Keyword, &Where );
if ( WinStatus != NO_ERROR ) { goto Cleanup; }
} }
// Align the running pointer again
OldWhere = Where; Where = (PUCHAR) ROUND_UP_POINTER( OldWhere, ALIGN_WORST ); RtlZeroMemory( OldWhere, Where-OldWhere );
*WherePtr = Where; WinStatus = NO_ERROR;
//
// Be tidy
//
Cleanup:
return WinStatus;
}
#ifndef _CRTEST_EXE_
DWORD APIENTRY CredpConvertCredential ( IN WTOA_ENUM WtoA, IN ENCODE_BLOB_ENUM DoDecode, IN PCREDENTIALW InCredential, OUT PCREDENTIALW *OutCredential )
/*++
Routine Description:
Converts a credential from Ansi to Unicode or vice-versa.
Arguments:
WtoA - Specifies the direction of the string conversion.
DoDecode - Specifies whether CredentialBlob should be encoded, decoded, or neither.
InCredential - Input credentials
OutCredential - Output credential This credential should be freed using MIDL_user_free.
Return Values:
Window status code
--*/
{ DWORD WinStatus; ULONG Size = 0;
LPBYTE Where;
//
// BVTs pass NULL explicitly. We could let the AV be caught in the try/except, but
// that would prevent them from being able to run under a debugger. So, handle NULL
// explicitly.
//
if ( InCredential == NULL ) { return ERROR_INVALID_PARAMETER; }
//
// Use an exception handle to prevent bad user parameter from AVing in our code.
//
#ifndef _CRTEST_EXE_
try { #endif // _CRTEST_EXE_
//
// Compute the size needed for the output credential
//
Size = CredpConvertOneCredentialSize( WtoA, InCredential );
//
// Allocate a buffer for the resultant credential
//
*OutCredential = (PCREDENTIALW) MIDL_user_allocate( Size );
if ( *OutCredential == NULL ) { WinStatus = ERROR_NOT_ENOUGH_MEMORY; goto Cleanup; }
//
// Convert the credential into the allocated buffer
//
Where = (LPBYTE) *OutCredential;
WinStatus = CredpConvertOneCredential( WtoA, DoDecode, InCredential, &Where );
if ( WinStatus != NO_ERROR ) { MIDL_user_free( *OutCredential ); *OutCredential = NULL; } else { ASSERT( (ULONG)(Where - ((LPBYTE)*OutCredential)) == Size ); } Cleanup: NOTHING; #ifndef _CRTEST_EXE_
} except( EXCEPTION_EXECUTE_HANDLER ) { WinStatus = ERROR_INVALID_PARAMETER; } #endif // _CRTEST_EXE_
return WinStatus;
}
DWORD APIENTRY CredpConvertTargetInfo ( IN WTOA_ENUM WtoA, IN PCREDENTIAL_TARGET_INFORMATIONW InTargetInfo, OUT PCREDENTIAL_TARGET_INFORMATIONW *OutTargetInfo, OUT PULONG OutTargetInfoSize OPTIONAL )
/*++
Routine Description:
Converts a target info from Ansi to Unicode or vice-versa.
Arguments:
WtoA - Specifies the direction of the string conversion.
InTargetInfo - Input TargetInfo
OutTargetInfo - Output TargetInfo This TargetInfo should be freed using CredFree.
OutTargetInfoSize - Size (in bytes) of the buffer returned in OutTargetInfo
Return Values:
Window status code
--*/
{ DWORD WinStatus; ULONG Size;
LPBYTE Where;
*OutTargetInfo = NULL;
//
// BVTs pass NULL explicitly. We could let the AV be caught in the try/except, but
// that would prevent them from being able to run under a debugger. So, handle NULL
// explicitly.
//
if ( InTargetInfo == NULL ) { return ERROR_INVALID_PARAMETER; }
//
// Use an exception handle to prevent bad user parameter from AVing in our code.
//
#ifndef _CRTEST_EXE_
try { #endif // _CRTEST_EXE_
//
// Compute the size needed for the output target info
//
Size = sizeof(CREDENTIAL_TARGET_INFORMATIONW);
//
// Compute the size of the strings in the right character set.
//
Size += CredpConvertStringSize( WtoA, InTargetInfo->TargetName ); Size += CredpConvertStringSize( WtoA, InTargetInfo->NetbiosServerName ); Size += CredpConvertStringSize( WtoA, InTargetInfo->DnsServerName ); Size += CredpConvertStringSize( WtoA, InTargetInfo->NetbiosDomainName ); Size += CredpConvertStringSize( WtoA, InTargetInfo->DnsDomainName ); Size += CredpConvertStringSize( WtoA, InTargetInfo->DnsTreeName ); Size += CredpConvertStringSize( WtoA, InTargetInfo->PackageName ); Size += InTargetInfo->CredTypeCount * sizeof(DWORD);
//
// Allocate a buffer for the resultant credential
//
*OutTargetInfo = (PCREDENTIAL_TARGET_INFORMATIONW) MIDL_user_allocate( Size );
if ( *OutTargetInfo == NULL ) { WinStatus = ERROR_NOT_ENOUGH_MEMORY; goto Cleanup; }
if ( ARGUMENT_PRESENT(OutTargetInfoSize) ) { *OutTargetInfoSize = Size; } Where = (LPBYTE)((*OutTargetInfo) + 1);
//
// Copy the fixed size data
//
(*OutTargetInfo)->Flags = InTargetInfo->Flags;
//
// Copy the DWORD aligned data
//
(*OutTargetInfo)->CredTypeCount = InTargetInfo->CredTypeCount; if ( InTargetInfo->CredTypeCount != 0 ) { (*OutTargetInfo)->CredTypes = (LPDWORD) Where; RtlCopyMemory( Where, InTargetInfo->CredTypes, InTargetInfo->CredTypeCount * sizeof(DWORD) ); Where += InTargetInfo->CredTypeCount * sizeof(DWORD); } else { (*OutTargetInfo)->CredTypes = NULL; }
//
// Convert the strings to the right character set.
//
WinStatus = CredpConvertString( WtoA, InTargetInfo->TargetName, &(*OutTargetInfo)->TargetName, &Where );
if ( WinStatus != NO_ERROR ) { goto Cleanup; }
WinStatus = CredpConvertString( WtoA, InTargetInfo->NetbiosServerName, &(*OutTargetInfo)->NetbiosServerName, &Where );
if ( WinStatus != NO_ERROR ) { goto Cleanup; }
WinStatus = CredpConvertString( WtoA, InTargetInfo->DnsServerName, &(*OutTargetInfo)->DnsServerName, &Where );
if ( WinStatus != NO_ERROR ) { goto Cleanup; }
WinStatus = CredpConvertString( WtoA, InTargetInfo->NetbiosDomainName, &(*OutTargetInfo)->NetbiosDomainName, &Where );
if ( WinStatus != NO_ERROR ) { goto Cleanup; }
WinStatus = CredpConvertString( WtoA, InTargetInfo->DnsDomainName, &(*OutTargetInfo)->DnsDomainName, &Where );
if ( WinStatus != NO_ERROR ) { goto Cleanup; }
WinStatus = CredpConvertString( WtoA, InTargetInfo->DnsTreeName, &(*OutTargetInfo)->DnsTreeName, &Where );
if ( WinStatus != NO_ERROR ) { goto Cleanup; }
WinStatus = CredpConvertString( WtoA, InTargetInfo->PackageName, &(*OutTargetInfo)->PackageName, &Where );
if ( WinStatus != NO_ERROR ) { goto Cleanup; }
ASSERT( (ULONG)(Where - ((LPBYTE)*OutTargetInfo)) == Size ); Cleanup: NOTHING; #ifndef _CRTEST_EXE_
} except( EXCEPTION_EXECUTE_HANDLER ) { WinStatus = ERROR_INVALID_PARAMETER; } #endif // _CRTEST_EXE_
//
// Be tidy
//
if ( WinStatus != NO_ERROR ) { if ( *OutTargetInfo != NULL ) { MIDL_user_free( *OutTargetInfo ); *OutTargetInfo = NULL; } }
return WinStatus;
} #endif // _CRTEST_EXE_
DWORD CredpConvertCredentials ( IN WTOA_ENUM WtoA, IN ENCODE_BLOB_ENUM DoDecode, IN PCREDENTIALW *InCredential, IN ULONG InCredentialCount, OUT PCREDENTIALW **OutCredential )
/*++
Routine Description:
Converts a set of credentials from Ansi to Unicode or vice-versa.
Arguments:
WtoA - Specifies the direction of the string conversion.
DoDecode - Specifies whether CredentialBlob should be encoded, decoded, or neither.
InCredential - Input credentials
OutCredential - Output credential This credential should be freed using MIDL_user_free.
Return Values:
Window status code
--*/
{ DWORD WinStatus; ULONG Size = 0; ULONG i;
LPBYTE Where; LPBYTE OldWhere;
*OutCredential = NULL;
//
// Use an exception handle to prevent bad user parameter from AVing in our code.
//
#ifndef _CRTEST_EXE_
try { #endif // _CRTEST_EXE_
//
// Compute the size needed for the output credentials
//
for ( i=0; i<InCredentialCount; i++ ) { Size += CredpConvertOneCredentialSize( WtoA, InCredential[i] ); }
//
// Allocate a buffer for the resultant credential array
//
Size += ROUND_UP_COUNT( InCredentialCount * sizeof(PCREDENTIALW), ALIGN_WORST );
*OutCredential = (PCREDENTIALW *)MIDL_user_allocate( Size );
if ( *OutCredential == NULL ) { WinStatus = ERROR_NOT_ENOUGH_MEMORY; goto Cleanup; }
//
// Convert the credential into the allocated buffer
//
Where = (LPBYTE) *OutCredential; Where += InCredentialCount * sizeof(PCREDENTIALW);
// Align the running pointer again
OldWhere = Where; Where = (PUCHAR) ROUND_UP_POINTER( OldWhere, ALIGN_WORST ); RtlZeroMemory( OldWhere, Where-OldWhere );
for ( i=0; i<InCredentialCount; i++ ) {
//
// Save a pointer to this credential
//
(*OutCredential)[i] = (PCREDENTIALW) Where;
//
// Marshal the credential
//
WinStatus = CredpConvertOneCredential( WtoA, DoDecode, InCredential[i], &Where );
if ( WinStatus != NO_ERROR ) { goto Cleanup; } }
ASSERT( (ULONG)(Where - ((LPBYTE)*OutCredential)) == Size ); WinStatus = NO_ERROR;
Cleanup: NOTHING; #ifndef _CRTEST_EXE_
} except( EXCEPTION_EXECUTE_HANDLER ) { WinStatus = ERROR_INVALID_PARAMETER; } #endif // _CRTEST_EXE_
if ( WinStatus != NO_ERROR ) { if ( *OutCredential != NULL ) { MIDL_user_free( *OutCredential ); *OutCredential = NULL; } }
return WinStatus;
}
|