You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
811 lines
18 KiB
811 lines
18 KiB
/*++
|
|
|
|
Copyright (c) 2001 Microsoft Corporation
|
|
All rights reserved
|
|
|
|
Module Name:
|
|
|
|
krbutils.cxx
|
|
|
|
Abstract:
|
|
|
|
utils
|
|
|
|
Author:
|
|
|
|
Larry Zhu (LZhu) December 1, 2001 Created
|
|
|
|
Environment:
|
|
|
|
User Mode -Win32
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "precomp.hxx"
|
|
#pragma hdrstop
|
|
|
|
#include "krbutils.hxx"
|
|
#include "kerberr.hxx"
|
|
|
|
VOID
|
|
KerbFreeRealm(
|
|
IN PKERB_REALM pRealm
|
|
)
|
|
{
|
|
if (*pRealm != NULL)
|
|
{
|
|
MIDL_user_free(*pRealm);
|
|
*pRealm = NULL;
|
|
}
|
|
}
|
|
|
|
VOID
|
|
KerbFreePrincipalName(
|
|
IN PKERB_PRINCIPAL_NAME pName
|
|
)
|
|
{
|
|
PKERB_PRINCIPAL_NAME_ELEM pElem, pNextElem;
|
|
|
|
pElem = pName->name_string;
|
|
while (pElem != NULL)
|
|
{
|
|
if (pElem->value != NULL)
|
|
{
|
|
MIDL_user_free(pElem->value);
|
|
}
|
|
pNextElem = pElem->next;
|
|
MIDL_user_free(pElem);
|
|
pElem = pNextElem;
|
|
}
|
|
pName->name_string = NULL;
|
|
}
|
|
|
|
VOID
|
|
KerbFreeData(
|
|
IN ULONG PduValue,
|
|
IN PVOID pData
|
|
)
|
|
{
|
|
ASN1decoding_t pDec = NULL;
|
|
|
|
if (pData)
|
|
{
|
|
TKerbErr KerbErr;
|
|
KerbErr DBGCHK = KerbInitAsn(
|
|
NULL,
|
|
&pDec // this is a decoded structure
|
|
);
|
|
|
|
if (KERB_SUCCESS(KerbErr))
|
|
{
|
|
ASN1_FreeDecoded(pDec, pData, PduValue);
|
|
}
|
|
|
|
KerbTermAsn(NULL, pDec);
|
|
}
|
|
}
|
|
|
|
BOOL fKRB5ModuleStarted = FALSE;
|
|
|
|
KERBERR
|
|
KerbInitAsn(
|
|
IN OUT ASN1encoding_t * pEnc,
|
|
IN OUT ASN1decoding_t * pDec
|
|
)
|
|
{
|
|
TKerbErr KerbErr = KRB_ERR_GENERIC;
|
|
ASN1error_e Asn1Err;
|
|
|
|
if (!fKRB5ModuleStarted)
|
|
{
|
|
fKRB5ModuleStarted = TRUE;
|
|
KRB5_Module_Startup();
|
|
}
|
|
|
|
if (pEnc != NULL)
|
|
{
|
|
Asn1Err = ASN1_CreateEncoder(
|
|
KRB5_Module,
|
|
pEnc,
|
|
NULL, // pbBuf
|
|
0, // cbBufSize
|
|
NULL // pParent
|
|
);
|
|
}
|
|
else
|
|
{
|
|
Asn1Err = ASN1_CreateDecoder(
|
|
KRB5_Module,
|
|
pDec,
|
|
NULL, // pbBuf
|
|
0, // cbBufSize
|
|
NULL // pParent
|
|
);
|
|
}
|
|
|
|
KerbErr DBGCHK = ASN1_SUCCESS == Asn1Err ? KDC_ERR_NONE : KRB_ERR_GENERIC;
|
|
|
|
return KerbErr;
|
|
}
|
|
|
|
VOID
|
|
KerbTermAsn(
|
|
IN ASN1encoding_t pEnc,
|
|
IN ASN1decoding_t pDec
|
|
)
|
|
{
|
|
if (pEnc != NULL)
|
|
{
|
|
ASN1_CloseEncoder(pEnc);
|
|
}
|
|
else if (pDec != NULL)
|
|
{
|
|
ASN1_CloseDecoder(pDec);
|
|
}
|
|
}
|
|
|
|
KERBERR
|
|
KerbEncryptDataEx(
|
|
OUT PKERB_ENCRYPTED_DATA pEncryptedData,
|
|
IN ULONG cbDataSize,
|
|
IN PUCHAR Data,
|
|
IN ULONG KeyVersion,
|
|
IN ULONG UsageFlags,
|
|
IN PKERB_ENCRYPTION_KEY pKey
|
|
)
|
|
{
|
|
PCRYPTO_SYSTEM pcsCrypt = NULL;
|
|
PCRYPT_STATE_BUFFER psbCryptBuffer = NULL;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
Status = CDLocateCSystem(pKey->keytype, &pcsCrypt);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
return(KDC_ERR_ETYPE_NOTSUPP);
|
|
}
|
|
|
|
//
|
|
// Initialize header
|
|
//
|
|
|
|
pEncryptedData->encryption_type = pKey->keytype;
|
|
|
|
Status = pcsCrypt->Initialize(
|
|
(PUCHAR) pKey->keyvalue.value,
|
|
pKey->keyvalue.length,
|
|
UsageFlags,
|
|
&psbCryptBuffer
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
return(KRB_ERR_GENERIC);
|
|
}
|
|
|
|
Status = pcsCrypt->Encrypt(
|
|
psbCryptBuffer,
|
|
Data,
|
|
cbDataSize,
|
|
pEncryptedData->cipher_text.value,
|
|
&pEncryptedData->cipher_text.length
|
|
);
|
|
|
|
(void) pcsCrypt->Discard(&psbCryptBuffer);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
return(KRB_ERR_GENERIC);
|
|
}
|
|
|
|
if (KeyVersion != KERB_NO_KEY_VERSION)
|
|
{
|
|
pEncryptedData->version = KeyVersion;
|
|
pEncryptedData->bit_mask |= version_present;
|
|
}
|
|
return KDC_ERR_NONE;
|
|
}
|
|
|
|
KERBERR
|
|
KerbAllocateEncryptionBuffer(
|
|
IN ULONG EncryptionType,
|
|
IN ULONG cbBufferSize,
|
|
OUT PUINT pcbEncryptionBufferSize,
|
|
OUT PBYTE* pEncryptionBuffer
|
|
)
|
|
{
|
|
TKerbErr KerbErr = KDC_ERR_NONE;
|
|
ULONG cbEncryptionOverhead = 0;
|
|
ULONG cbBlockSize = 0;
|
|
|
|
KerbErr DBGCHK = KerbGetEncryptionOverhead(
|
|
EncryptionType,
|
|
&cbEncryptionOverhead,
|
|
&cbBlockSize
|
|
);
|
|
if (KERB_SUCCESS(KerbErr))
|
|
{
|
|
*pcbEncryptionBufferSize = (UINT) ROUND_UP_COUNT(cbEncryptionOverhead + cbBufferSize, cbBlockSize);
|
|
|
|
*pEncryptionBuffer = (PBYTE) MIDL_user_allocate(*pcbEncryptionBufferSize);
|
|
if (*pEncryptionBuffer == NULL)
|
|
{
|
|
KerbErr DBGCHK = KRB_ERR_GENERIC;
|
|
}
|
|
}
|
|
|
|
return KerbErr;
|
|
}
|
|
|
|
KERBERR
|
|
KerbAllocateEncryptionBufferWrapper(
|
|
IN ULONG EncryptionType,
|
|
IN ULONG cbBufferSize,
|
|
OUT ULONG* pcbEncryptionBufferSize,
|
|
OUT PBYTE* pEncryptionBuffer
|
|
)
|
|
{
|
|
TKerbErr KerbErr = KDC_ERR_NONE;
|
|
UINT tempInt = 0;
|
|
|
|
KerbErr DBGCHK = KerbAllocateEncryptionBuffer(
|
|
EncryptionType,
|
|
cbBufferSize,
|
|
&tempInt,
|
|
pEncryptionBuffer
|
|
);
|
|
|
|
if (KERB_SUCCESS(KerbErr))
|
|
{
|
|
*pcbEncryptionBufferSize = tempInt;
|
|
}
|
|
|
|
return KerbErr;
|
|
}
|
|
|
|
KERBERR
|
|
KerbGetEncryptionOverhead(
|
|
IN ULONG Algorithm,
|
|
OUT PULONG pcbOverhead,
|
|
OUT OPTIONAL PULONG pcbBlockSize
|
|
)
|
|
{
|
|
PCRYPTO_SYSTEM pcsCrypt;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
Status = CDLocateCSystem(Algorithm, &pcsCrypt);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
return (KDC_ERR_ETYPE_NOTSUPP);
|
|
}
|
|
|
|
*pcbOverhead = pcsCrypt->HeaderSize;
|
|
if (pcbBlockSize)
|
|
{
|
|
*pcbBlockSize = pcsCrypt->BlockSize;
|
|
}
|
|
return (KDC_ERR_NONE);
|
|
}
|
|
|
|
KERBERR NTAPI
|
|
KerbPackData(
|
|
IN PVOID Data,
|
|
IN ULONG PduValue,
|
|
OUT PULONG pcbDataSize,
|
|
OUT PUCHAR * MarshalledData
|
|
)
|
|
{
|
|
TKerbErr KerbErr = KDC_ERR_NONE;
|
|
ASN1encoding_t pEnc = NULL;
|
|
ASN1error_e Asn1Err;
|
|
|
|
KerbErr DBGCHK = KerbInitAsn(
|
|
&pEnc, // we are encoding
|
|
NULL
|
|
);
|
|
if (KERB_SUCCESS(KerbErr))
|
|
{
|
|
//
|
|
// Encode the data type.
|
|
//
|
|
|
|
Asn1Err = ASN1_Encode(
|
|
pEnc,
|
|
Data,
|
|
PduValue,
|
|
ASN1ENCODE_ALLOCATEBUFFER,
|
|
NULL, // pbBuf
|
|
0 // cbBufSize
|
|
);
|
|
|
|
if (!ASN1_SUCCEEDED(Asn1Err))
|
|
{
|
|
DebugPrintf(SSPI_ERROR, "KerbPackData failed to encode data: %d\n", Asn1Err);
|
|
KerbErr DBGCHK = KRB_ERR_GENERIC;
|
|
}
|
|
else
|
|
{
|
|
*MarshalledData = (PUCHAR) MIDL_user_allocate(pEnc->len);
|
|
if (*MarshalledData == NULL)
|
|
{
|
|
KerbErr DBGCHK = KRB_ERR_GENERIC;
|
|
*pcbDataSize = 0;
|
|
}
|
|
else
|
|
{
|
|
RtlCopyMemory(*MarshalledData, pEnc->buf, pEnc->len);
|
|
*pcbDataSize = pEnc->len;
|
|
|
|
}
|
|
ASN1_FreeEncoded(pEnc, pEnc->buf);
|
|
}
|
|
}
|
|
|
|
KerbTermAsn(pEnc, NULL);
|
|
|
|
return KerbErr;
|
|
}
|
|
|
|
KERBERR
|
|
KerbConvertUnicodeStringToRealm(
|
|
OUT PKERB_REALM pRealm,
|
|
IN PUNICODE_STRING pString
|
|
)
|
|
{
|
|
TKerbErr KerbErr;
|
|
STRING TempString;
|
|
|
|
RtlInitString(
|
|
&TempString,
|
|
NULL
|
|
);
|
|
|
|
*pRealm = NULL;
|
|
KerbErr DBGCHK = KerbUnicodeStringToKerbString(
|
|
&TempString,
|
|
pString
|
|
);
|
|
|
|
if (KERB_SUCCESS(KerbErr))
|
|
{
|
|
*pRealm = TempString.Buffer;
|
|
}
|
|
|
|
return KerbErr;
|
|
}
|
|
|
|
KERBERR
|
|
KerbUnicodeStringToKerbString(
|
|
OUT PSTRING pKerbString,
|
|
IN PUNICODE_STRING pString
|
|
)
|
|
{
|
|
STRING TempString;
|
|
|
|
if (!pKerbString)
|
|
{
|
|
return KRB_ERR_GENERIC;
|
|
}
|
|
|
|
TempString.Buffer = KerbAllocUtf8StrFromUnicodeString(pString);
|
|
if (TempString.Buffer == NULL)
|
|
{
|
|
return KRB_ERR_GENERIC;
|
|
}
|
|
|
|
RtlInitString(
|
|
&TempString,
|
|
TempString.Buffer
|
|
);
|
|
*pKerbString = TempString;
|
|
return KDC_ERR_NONE;
|
|
}
|
|
|
|
KERBERR
|
|
KerbConvertKdcNameToPrincipalName(
|
|
OUT PKERB_PRINCIPAL_NAME pPrincipalName,
|
|
IN PKERB_INTERNAL_NAME pKdcName
|
|
)
|
|
{
|
|
TKerbErr KerbErr = KDC_ERR_NONE;
|
|
|
|
PKERB_PRINCIPAL_NAME_ELEM pElem;
|
|
PKERB_PRINCIPAL_NAME_ELEM* pLast;
|
|
STRING TempKerbString;
|
|
ULONG Index;
|
|
|
|
pPrincipalName->name_type = (int) pKdcName->NameType;
|
|
pPrincipalName->name_string = NULL;
|
|
pLast = &pPrincipalName->name_string;
|
|
|
|
//
|
|
// Index through the KDC name and add each element to the list
|
|
//
|
|
|
|
for (Index = 0; KERB_SUCCESS(KerbErr) && (Index < pKdcName->NameCount); Index++)
|
|
{
|
|
KerbErr DBGCHK = KerbUnicodeStringToKerbString(
|
|
&TempKerbString,
|
|
&pKdcName->Names[Index]
|
|
);
|
|
if (KERB_SUCCESS(KerbErr))
|
|
{
|
|
pElem = (PKERB_PRINCIPAL_NAME_ELEM) MIDL_user_allocate(sizeof(KERB_PRINCIPAL_NAME_ELEM));
|
|
if (pElem == NULL)
|
|
{
|
|
KerbErr DBGCHK = KRB_ERR_GENERIC;
|
|
}
|
|
pElem->value = TempKerbString.Buffer;
|
|
pElem->next = NULL;
|
|
*pLast = pElem;
|
|
pLast = &pElem->next;
|
|
}
|
|
}
|
|
|
|
if (!KERB_SUCCESS(KerbErr))
|
|
{
|
|
KerbFreePrincipalName(pPrincipalName);
|
|
}
|
|
return KerbErr;
|
|
}
|
|
|
|
ULONG
|
|
KerbConvertUlongToFlagUlong(
|
|
IN ULONG Flag
|
|
)
|
|
{
|
|
ULONG ReturnFlag;
|
|
|
|
((PUCHAR) &ReturnFlag)[0] = ((PUCHAR) &Flag)[3];
|
|
((PUCHAR) &ReturnFlag)[1] = ((PUCHAR) &Flag)[2];
|
|
((PUCHAR) &ReturnFlag)[2] = ((PUCHAR) &Flag)[1];
|
|
((PUCHAR) &ReturnFlag)[3] = ((PUCHAR) &Flag)[0];
|
|
|
|
return ReturnFlag;
|
|
}
|
|
|
|
VOID
|
|
KerbConvertLargeIntToGeneralizedTime(
|
|
OUT PKERB_TIME pClientTime,
|
|
OUT OPTIONAL INT* pClientUsec,
|
|
IN PTimeStamp pTimeStamp
|
|
)
|
|
{
|
|
TIME_FIELDS TimeFields;
|
|
|
|
//
|
|
// Special case zero time
|
|
//
|
|
|
|
#ifndef WIN32_CHICAGO
|
|
if (pTimeStamp->QuadPart == 0)
|
|
#else // WIN32_CHICAGO
|
|
if (*pTimeStamp == 0)
|
|
#endif // WIN32_CHICAGO
|
|
{
|
|
RtlZeroMemory(
|
|
pClientTime,
|
|
sizeof(KERB_TIME)
|
|
);
|
|
//
|
|
// For MIT compatibility, time zero is 1/1/70
|
|
//
|
|
|
|
pClientTime->year = 1970;
|
|
pClientTime->month = 1;
|
|
pClientTime->day = 1;
|
|
|
|
if (pClientUsec)
|
|
|
|
{
|
|
*pClientUsec = 0;
|
|
}
|
|
pClientTime->universal = TRUE;
|
|
}
|
|
else
|
|
{
|
|
|
|
#ifndef WIN32_CHICAGO
|
|
RtlTimeToTimeFields(
|
|
pTimeStamp,
|
|
&TimeFields
|
|
);
|
|
#else // WIN32_CHICAGO
|
|
RtlTimeToTimeFields(
|
|
(LARGE_INTEGER*) pTimeStamp,
|
|
&TimeFields
|
|
);
|
|
#endif // WIN32_CHICAGO
|
|
|
|
//
|
|
// Generalized times can only contains years up to four digits.
|
|
//
|
|
|
|
if (TimeFields.Year > 2037)
|
|
{
|
|
pClientTime->year = 2037;
|
|
}
|
|
else
|
|
{
|
|
pClientTime->year = TimeFields.Year;
|
|
}
|
|
pClientTime->month = (ASN1uint8_t) TimeFields.Month;
|
|
pClientTime->day = (ASN1uint8_t) TimeFields.Day;
|
|
pClientTime->hour = (ASN1uint8_t) TimeFields.Hour;
|
|
pClientTime->minute = (ASN1uint8_t) TimeFields.Minute;
|
|
pClientTime->second = (ASN1uint8_t) TimeFields.Second;
|
|
|
|
// MIT kerberos does not support millseconds
|
|
//
|
|
|
|
pClientTime->millisecond = 0;
|
|
|
|
if (pClientUsec)
|
|
{
|
|
//
|
|
// Since we don't include milliseconds above, use the whole
|
|
// thing here.
|
|
//
|
|
|
|
#ifndef WIN32_CHICAGO
|
|
*pClientUsec = (pTimeStamp->LowPart / 10) % 1000000;
|
|
#else // WIN32_CHICAGO
|
|
*pClientUsec = (int) ((*pTimeStamp / 10) % 1000000);
|
|
#endif // WIN32_CHICAGO
|
|
}
|
|
|
|
pClientTime->diff = 0;
|
|
pClientTime->universal = TRUE;
|
|
}
|
|
}
|
|
|
|
NTSTATUS
|
|
KerbMapKerbError(
|
|
IN KERBERR KerbError
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
switch(KerbError)
|
|
{
|
|
case KDC_ERR_NONE:
|
|
Status = STATUS_SUCCESS;
|
|
break;
|
|
case KDC_ERR_CLIENT_REVOKED:
|
|
Status = STATUS_ACCOUNT_DISABLED;
|
|
break;
|
|
case KDC_ERR_KEY_EXPIRED:
|
|
Status = STATUS_PASSWORD_EXPIRED;
|
|
break;
|
|
case KRB_ERR_GENERIC:
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
break;
|
|
case KRB_AP_ERR_SKEW:
|
|
case KRB_AP_ERR_TKT_NYV:
|
|
// Note this was added because of the following scenario:
|
|
// Let's say the dc and the client have the correct time. And the
|
|
// server's time is off. We aren't going to get rid of the ticket for the
|
|
// server on the client because it hasn't expired yet. But, the server
|
|
// thinks it has. If event logging was turned on, then admins could look
|
|
// at the server's event log and potentially deduce that the server's
|
|
// time is off relative to the dc.
|
|
case KRB_AP_ERR_TKT_EXPIRED:
|
|
Status = STATUS_TIME_DIFFERENCE_AT_DC;
|
|
break;
|
|
case KDC_ERR_POLICY:
|
|
Status = STATUS_ACCOUNT_RESTRICTION;
|
|
break;
|
|
case KDC_ERR_C_PRINCIPAL_UNKNOWN:
|
|
Status = STATUS_NO_SUCH_USER;
|
|
break;
|
|
case KDC_ERR_S_PRINCIPAL_UNKNOWN:
|
|
Status = STATUS_NO_TRUST_SAM_ACCOUNT;
|
|
break;
|
|
case KRB_AP_ERR_MODIFIED:
|
|
case KDC_ERR_PREAUTH_FAILED:
|
|
Status = STATUS_WRONG_PASSWORD;
|
|
break;
|
|
case KRB_ERR_RESPONSE_TOO_BIG:
|
|
Status = STATUS_INVALID_BUFFER_SIZE;
|
|
break;
|
|
case KDC_ERR_PADATA_TYPE_NOSUPP:
|
|
Status = STATUS_NOT_SUPPORTED;
|
|
break;
|
|
case KRB_AP_ERR_NOT_US:
|
|
Status = SEC_E_WRONG_PRINCIPAL;
|
|
break;
|
|
|
|
case KDC_ERR_SVC_UNAVAILABLE:
|
|
Status = STATUS_NO_LOGON_SERVERS;
|
|
break;
|
|
case KDC_ERR_WRONG_REALM:
|
|
Status = STATUS_NO_LOGON_SERVERS;
|
|
break;
|
|
case KDC_ERR_CANT_VERIFY_CERTIFICATE:
|
|
Status = TRUST_E_SYSTEM_ERROR;
|
|
break;
|
|
case KDC_ERR_INVALID_CERTIFICATE:
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
break;
|
|
case KDC_ERR_REVOKED_CERTIFICATE:
|
|
Status = CRYPT_E_REVOKED;
|
|
break;
|
|
case KDC_ERR_REVOCATION_STATUS_UNKNOWN:
|
|
Status = CRYPT_E_NO_REVOCATION_CHECK;
|
|
break;
|
|
case KDC_ERR_REVOCATION_STATUS_UNAVAILABLE:
|
|
Status = CRYPT_E_REVOCATION_OFFLINE;
|
|
break;
|
|
case KDC_ERR_CLIENT_NAME_MISMATCH:
|
|
case KERB_PKINIT_CLIENT_NAME_MISMATCH:
|
|
case KDC_ERR_KDC_NAME_MISMATCH:
|
|
Status = STATUS_PKINIT_NAME_MISMATCH;
|
|
break;
|
|
case KDC_ERR_PATH_NOT_ACCEPTED:
|
|
Status = STATUS_TRUST_FAILURE;
|
|
break;
|
|
case KDC_ERR_ETYPE_NOTSUPP:
|
|
Status = STATUS_KDC_UNKNOWN_ETYPE;
|
|
break;
|
|
case KDC_ERR_MUST_USE_USER2USER:
|
|
case KRB_AP_ERR_USER_TO_USER_REQUIRED:
|
|
Status = STATUS_USER2USER_REQUIRED;
|
|
break;
|
|
case KRB_AP_ERR_NOKEY:
|
|
Status = STATUS_NO_KERB_KEY;
|
|
break;
|
|
case KRB_ERR_NAME_TOO_LONG:
|
|
Status = STATUS_NAME_TOO_LONG;
|
|
break;
|
|
default:
|
|
Status = STATUS_LOGON_FAILURE;
|
|
}
|
|
return (Status);
|
|
}
|
|
|
|
KERBERR NTAPI
|
|
KerbUnpackData(
|
|
IN PUCHAR pData,
|
|
IN ULONG cbDataSize,
|
|
IN ULONG PduValue,
|
|
OUT PVOID * pDecodedData
|
|
)
|
|
{
|
|
TKerbErr KerbErr = KDC_ERR_NONE;
|
|
ASN1decoding_t pDec = NULL;
|
|
ASN1error_e Asn1Err;
|
|
|
|
if ((cbDataSize == 0) || (pData == NULL))
|
|
{
|
|
KerbErr DBGCHK = KRB_ERR_GENERIC;
|
|
}
|
|
|
|
if (KERB_SUCCESS(KerbErr))
|
|
{
|
|
KerbErr DBGCHK = KerbInitAsn(
|
|
NULL,
|
|
&pDec // we are decoding
|
|
);
|
|
}
|
|
|
|
if (KERB_SUCCESS(KerbErr))
|
|
{
|
|
*pDecodedData = NULL;
|
|
Asn1Err = ASN1_Decode(
|
|
pDec,
|
|
pDecodedData,
|
|
PduValue,
|
|
ASN1DECODE_SETBUFFER,
|
|
(BYTE *) pData,
|
|
cbDataSize
|
|
);
|
|
|
|
if (!ASN1_SUCCEEDED(Asn1Err))
|
|
{
|
|
if ((ASN1_ERR_BADARGS == Asn1Err) ||
|
|
(ASN1_ERR_EOD == Asn1Err))
|
|
{
|
|
KerbErr DBGCHK = KDC_ERR_MORE_DATA;
|
|
}
|
|
else
|
|
{
|
|
KerbErr DBGCHK = KRB_ERR_GENERIC;
|
|
}
|
|
*pDecodedData = NULL;
|
|
}
|
|
}
|
|
|
|
KerbTermAsn(NULL, pDec);
|
|
|
|
return KerbErr;
|
|
}
|
|
|
|
PSTR
|
|
KerbAllocUtf8StrFromUnicodeString(
|
|
IN PUNICODE_STRING pUnicodeString
|
|
)
|
|
{
|
|
PSTR pUtf8String = NULL;
|
|
UINT cbUtf8StringLen;
|
|
|
|
//
|
|
// If the length is zero, return a null string.
|
|
//
|
|
|
|
if (pUnicodeString->Length == 0)
|
|
{
|
|
pUtf8String = (PSTR) MIDL_user_allocate(sizeof(CHAR));
|
|
if (pUtf8String != NULL)
|
|
{
|
|
*pUtf8String = '\0';
|
|
}
|
|
return pUtf8String;
|
|
}
|
|
|
|
//
|
|
// Determine the length of the Unicode string.
|
|
//
|
|
|
|
cbUtf8StringLen = WideCharToMultiByte(
|
|
#ifndef WIN32_CHICAGO
|
|
CP_UTF8,
|
|
#else // WIN32_CHICAGO
|
|
CP_OEMCP,
|
|
#endif // WIN32_CHICAGO
|
|
0, // All characters can be mapped.
|
|
pUnicodeString->Buffer,
|
|
pUnicodeString->Length / sizeof(WCHAR),
|
|
pUtf8String,
|
|
0,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
if ( cbUtf8StringLen == 0 )
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// Allocate a buffer for the Unicode string.
|
|
//
|
|
|
|
pUtf8String = (PSTR) MIDL_user_allocate( cbUtf8StringLen + 1 );
|
|
|
|
if (pUtf8String == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// Translate the string to Unicode.
|
|
//
|
|
|
|
cbUtf8StringLen = WideCharToMultiByte(
|
|
#ifndef WIN32_CHICAGO
|
|
CP_UTF8,
|
|
#else // WIN32_CHICAGO
|
|
CP_OEMCP,
|
|
#endif // WIN32_CHICAGO
|
|
0, // All characters can be mapped.
|
|
pUnicodeString->Buffer,
|
|
pUnicodeString->Length / sizeof(WCHAR),
|
|
pUtf8String,
|
|
cbUtf8StringLen,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
if ( cbUtf8StringLen == 0 )
|
|
{
|
|
MIDL_user_free( pUtf8String );
|
|
return NULL;
|
|
}
|
|
|
|
pUtf8String[cbUtf8StringLen] = '\0';
|
|
|
|
return pUtf8String;
|
|
}
|
|
|
|
|
|
|