Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1450 lines
38 KiB

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1993.
//
// File: ticktest.cxx
//
// Contents: KDC Ticket granting service test code.
//
// Classes:
//
// Functions:
//
// History: 19-Aug-93 WadeR Created
//
//----------------------------------------------------------------------------
#include <secpch2.hxx>
#pragma hdrstop
#include <stdio.h>
#include <authdata.hxx>
#include <kerbcomm.h>
#include <tostring.hxx>
extern "C" {
#include <winsock.h>
#include <kdc.h>
}
#include <kdcsvr.hxx>
#include <tktutil.hxx>
extern PWCHAR pwzKdcPasswd;
extern PWCHAR pwzPSPasswd;
extern PWCHAR pwzRealm;
extern PWCHAR pwzUserName;
extern PWCHAR pwzUserPasswd;
extern PWCHAR pwzTransport;
extern PWCHAR pwzEndPoint;
extern PWCHAR pwzAddress;
extern PWCHAR pwzClientAddress;
extern PWCHAR pwzKDC;
extern PWCHAR pwzPrivSvr;
extern PWCHAR pwzServiceName;
extern DWORD dwUserRID;
extern DWORD dwServiceRID;
extern DWORD dwKdcRID;
extern DWORD dwPrivSvrRID;
extern BOOL fGetAS;
extern BOOL fGetTGS;
extern BOOL fGetPAC;
extern BOOL fGetCTGT;
extern BOOL fGetServiceTkt;
extern BOOL fRenewSvc;
extern BOOL fTestTransitComp;
extern BOOL fTestReferal;
extern BOOL fPrintPACs;
extern BOOL fPrintTickets;
extern BOOL fVerbose;
enum BindTarget {KDC, KDCDBG};
enum CallType {GETTGS, GETAS};
handle_t
BindTo( BindTarget target,
LPTSTR pszTransport,
LPTSTR pszEndpoint,
LPTSTR pszServer );
NTSTATUS
CheckPAData( const KERB_ENCRYPTION_KEY& kSessionKey, PKERB_PA_DATA pkdReply, enum CallType type );
//////////////////////////////////////////////////////////////////////////
//
// Socket client functions
//
//////////////////////////////////////////////////////////////////////////
//+-------------------------------------------------------------------------
//
// Function: KerbInitializeSockets
//
// Synopsis:
//
// Effects:
//
// Arguments:
//
// Requires:
//
// Returns:
//
// Notes:
//
//
//--------------------------------------------------------------------------
#define KERB_KDC_CALL_TIMEOUT 10
void
PrintFlags( const KERB_TICKET_FLAGS fFlags )
{
#define KerbFlagDef(x) {#x, KERB_TICKET_FLAGS_ ## x}
const static struct {
char * FlagName;
KERB_TICKET_FLAGS Flag;
} Flags[] = {
KerbFlagDef( forwardable ),
KerbFlagDef( forwarded ),
KerbFlagDef( proxiable ),
KerbFlagDef( proxy ),
KerbFlagDef( may_postdate ),
KerbFlagDef( postdated ),
KerbFlagDef( invalid ),
KerbFlagDef( renewable ),
KerbFlagDef( initial ),
KerbFlagDef( pre_authent ),
KerbFlagDef( hw_authent ),
KerbFlagDef( reserved )
};
const int cFlags = sizeof( Flags ) / sizeof( Flags[0] );
for (int i=0; i<cFlags; i++)
{
if (fFlags & Flags[i].Flag)
{
printf("%s,", Flags[i].FlagName );
}
}
printf("\b \n");
#undef KerbFlagDef
}
inline void
Print( const UNICODE_STRING& ssFoo )
{
printf("%wZ", &ssFoo );
}
void
Print( const LARGE_INTEGER& tsFoo )
{
UNICODE_STRING ssTime = TimeStampToString( tsFoo );
printf("%wZ", &ssTime );
KerbFreeString(&ssTime);
}
void
Print( const KERB_ENCRYPTION_KEY& kKey )
{
printf("%d,%d,{",kKey.keytype, kKey.keyvalue.length);
for (ULONG i=0; i<kKey.keyvalue.length; i++ )
{
printf("%02x ", kKey.keyvalue.value[i] );
}
printf("\b}");
}
void
Print( const PISID psid )
{
WCHAR Buffer[512];
UNICODE_STRING usFoo = {0, sizeof(Buffer), Buffer};
RtlConvertSidToUnicodeString( &usFoo, psid, FALSE );
printf("%wZ", &usFoo );
}
void
PrintTicket( PKERB_TICKET pktTicket,
PWCHAR pwzPasswd )
{
#ifdef notdef
NTSTATUS sc;
PKERB_ENCRYPTED_TICKET pkitTicket;
PKERB_TICKET pktTicketCopy;
KERB_ENCRYPTION_KEY kKey;
UNICODE_STRING ssFoo;
RtlInitUnicodeString( &ssFoo, pwzPasswd );
KerbHashPassword(
&ssFoo,
KERB_ETYPE_RC4_MD4,
&kKey
);
pktTicketCopy = (PKerbTicket) new BYTE [sizeof(SizeOfTicket( pktTicket )];
RtlCopyMemory( pktTicketCopy, pktTicket, SizeOfTicket( pktTicket ) );
sc = KerbUnpackTicket( pktTicketCopy, &kKey, &kitTicket );
if (FAILED(sc))
{
printf("Couldn't decrypt ticket with password '%ws' (0x%X)\n",
pwzPasswd, sc );
return;
}
if (kitTicket.dwVersion != 5) {
printf("\t*** dwVersion: 0x%lX\t\t*** not 5\n", kitTicket.dwVersion );
} else {
printf("\tdwVersion:\t%d",kitTicket.dwVersion );
}
printf("\n\tFlags: (0x%x):\t",kitTicket.kitEncryptPart.fTicketFlags );
PrintFlags( kitTicket.kitEncryptPart.fTicketFlags );
printf("\tInitialTicket:\t" );
::Print( kitTicket.gInitialTicket );
printf("\n\tThisTicket:\t" );
::Print( kitTicket.gThisTicket );
printf("\n\tIssuingRealm: \t" );
::Print( kitTicket.dsIssuingRealm );
printf("\n\tServerName: \t" );
::Print( kitTicket.ServerName.accsid );
printf("\n\tSessionKey: \t" );
::Print(kitTicket.kitEncryptPart.kSessionKey);
printf("\n\tInitialRealm: \t" );
::Print( kitTicket.kitEncryptPart.dsInitialRealm );
printf("\n\tPrincipal: \t" );
::Print( kitTicket.kitEncryptPart.Principal.accsid );
printf("\n\ttsAuthentication:" );
::Print( kitTicket.kitEncryptPart.tsAuthentication );
printf("\n\ttsStartTime:\t" );
::Print( kitTicket.kitEncryptPart.tsStartTime );
printf("\n\ttsEndTime:\t" );
::Print( kitTicket.kitEncryptPart.tsEndTime );
printf("\n\ttsRenewUntil:\t" );
::Print( kitTicket.kitEncryptPart.tsRenewUntil );
printf("\n\tTransited: \t%ws", kitTicket.kitEncryptPart.tdTransited.pwzTransited );
// printf("\n\tHostAddresses:\t%ws", kitTicket.kitEncryptPart.pkdHostAddresses );
printf("\n");
if (kitTicket.kitEncryptPart.pkdAuthorizationData)
{
ULONG j;
BOOL fFoundSomething = FALSE;
CAuthDataList* padlList = (CAuthDataList*)kitTicket.kitEncryptPart.pkdAuthorizationData->bPAData;
CAuthData* padData;
for (padData = padlList->FindFirst(Any);
padData != NULL;
padData = padlList->FindNext(padData, Any))
{
switch (padData->adtDataType)
{
#if 0
case Pac:
{
printf("\tAuthorizationData (PAC):\n");
CPAC Pac;
ULONG cb = Pac.UnMarshal( (PBYTE) padData->abData );
if (cb <= padData->cbData )
{
if (fPrintPACs)
::Print( Pac );
fFoundSomething = TRUE;
break;
}
else
{
printf("PAC didn't unmarshal correctly");
}
}
#endif
default:
printf("\tAuthorizationData (Unknown: %d bytes):",
padData->cbData );
for (j=0; j < padData->cbData; j++ ) {
printf("%x ", padData->abData[j] );
}
printf("\n" );
}
}
if (!fFoundSomething)
{
printf("\tAuthorizationData (%d) : 0x", kitTicket.kitEncryptPart.pkdAuthorizationData->cbPAData );
for (j=0; j < kitTicket.kitEncryptPart.pkdAuthorizationData->cbPAData; j++ ) {
printf("%x ", ((PBYTE)kitTicket.kitEncryptPart.pkdAuthorizationData->bPAData)[j] );
}
printf("\n" );
}
}
#endif
}
int
PrintPAC( PEncryptedData pedPAC,
PWCHAR pwzKdcPasswd )
{
#ifdef notdef
// Decrypt it again to print it out.
PEncryptedData pedPacCopy =
(PEncryptedData) new BYTE [ SizeOfEncryptedData( pedPAC ) ];
memcpy( pedPacCopy, pedPAC, SizeOfEncryptedData( pedPAC ) );
//
// Find the PAC in the mess of credentials
//
CAuthData * pad = ((CAuthDataList*)pedPacCopy->ctCipher.bMessage)->FindFirst(Pac_2);
if (pad == NULL)
{
printf("GetPAC's return didn't have a PAC in it.");
return 1;
}
PEncryptedData pedRealPac = (PEncryptedData) pad->abData;
//
// Get the KDC's key, use it to decrypt pedNewPac
//
// Print out the resulting new pac.
//
// delete pedNewPac
//
NTSTATUS sc;
UNICODE_STRING ssFoo;
KERB_ENCRYPTION_KEY kKey;
SRtlInitString( &ssFoo, pwzKdcPasswd );
KerbHashPassword(
&ssFoo,
KERB_ETYPE_RC4_MD4,
&kKey
);
sc = KIDecryptData(pedRealPac, &kKey );
if (!NT_SUCCESS(sc))
{
printf("Couldn't decrypt PAC second time 0x%X\n", sc );
return(1);
}
#endif
return(0);
}
NTSTATUS
CheckPAData( const KERB_ENCRYPTION_KEY& kSessionKey, PKERB_PA_DATA pkdReply, enum CallType type )
{
#ifdef notdef
NTSTATUS err = 0;
TimeStamp tsKdcTime, tsLocalTime, tsDiff;
CAuthData * pad;
CAuthDataList * padlList;
if (pkdReply == 0)
{
printf("Nothing in the padata returned.\n");
return(1);
}
//
// This PAData should contain: Time
// May contain: address info
// May contain: old passwords
//
padlList = (CAuthDataList*) &pkdReply->bPAData[0];
if (padlList->GetMaxSize() != pkdReply->cbPAData )
{
printf("Sizes are wrong for padata.\n");
err = -1;
}
pad = padlList->FindFirst( Time );
if (pad == NULL)
{
printf("Time not included in padata.");
err = -1;
}
//sc = KIDecryptData( (PEncryptedData) pad->bData, &(KERB_ENCRYPTION_KEY&)kSessionKey );
//if (FAILED(sc))
//{
// printf("error 0x%X decrypting time.\n", sc );
// err = -1;
//}
//tsKdcTime = * (PTimeStamp) ((PEncryptedData) pad->abData)->ctCipherText.bMessage;
tsKdcTime = * (PTimeStamp) pad->abData;
GetCurrentTimeStamp( &tsLocalTime );
if (tsKdcTime > tsLocalTime)
tsDiff = tsKdcTime - tsLocalTime;
else
tsDiff = tsLocalTime - tsKdcTime;
if (tsDiff.QuadPart > UInt32x32To64( 10000000ul, 15 ) ) // 15 seconds.
{
printf("Warning: the time at the KDC is " );
Print( tsDiff );
printf(" different.\n" );
}
//
// Address info
//
//
// Passwords
//
#endif
return(S_OK);
}
KERBERR
FooGetASTicket( IN PVOID hBinding,
IN PWCHAR pwzUserName,
IN PWCHAR pwzUserRealm,
IN PWCHAR pwzServiceName,
IN PWCHAR pwzUserPassword,
IN PWCHAR pwzThisWorkstation,
OUT PKERB_TICKET pktTicket,
OUT PKERB_ENCRYPTED_KDC_REPLY * ReplyBody )
{
NTSTATUS Status;
KERBERR KerbErr;
KERB_ENCRYPTION_KEY kUserKey;
KERB_KDC_REQUEST Request;
PKERB_KDC_REQUEST_BODY RequestBody = &Request.request_body;
PKERB_ENCRYPTED_DATA pedReply = 0;
PULONG CryptArray = NULL;
ULONG CryptArraySize = 0;
LARGE_INTEGER TempTime;
KERB_MESSAGE_BUFFER InputMessage;
KERB_MESSAGE_BUFFER OutputMessage;
UNICODE_STRING ssPass;
UNICODE_STRING ssService;
UNICODE_STRING ssRealm;
UNICODE_STRING ssName;
PKERB_KDC_REPLY Reply = NULL;
RtlInitUnicodeString( &ssPass, pwzUserPasswd );
KerbHashPassword(
&ssPass,
KERB_ETYPE_RC4_MD4,
&kUserKey
);
RtlZeroMemory(
&OutputMessage,
sizeof(KERB_MESSAGE_BUFFER)
);
RtlZeroMemory(
&InputMessage,
sizeof(KERB_MESSAGE_BUFFER)
);
RtlInitUnicodeString(
&ssService,
pwzServiceName
);
RtlInitUnicodeString(
&ssRealm,
pwzUserRealm
);
RtlInitUnicodeString(
&ssName,
pwzUserName
);
//
// Build the request
//
RtlZeroMemory( &Request, sizeof( KERB_KDC_REQUEST ) );
RequestBody->kdc_options =
KERB_KDC_OPTIONS_forwardable |
KERB_KDC_OPTIONS_proxiable |
KERB_KDC_OPTIONS_renewable |
KERB_KDC_OPTIONS_renewable_ok;
RequestBody->nonce = 3;
TempTime.QuadPart = 0;
KerbConvertLargeIntToGeneralizedTime(
&RequestBody->KERB_KDC_REQUEST_BODY_starttime,
NULL,
&TempTime
);
TempTime.LowPart = 0xffffffff;
TempTime.HighPart = 0x7fffffff;
KerbConvertLargeIntToGeneralizedTime(
&RequestBody->KERB_KDC_REQUEST_BODY_renew_until,
NULL,
&TempTime
);
RequestBody->bit_mask |= KERB_KDC_REQUEST_BODY_renew_until_present;
TempTime.QuadPart = 0;
KerbConvertLargeIntToGeneralizedTime(
&RequestBody->endtime,
NULL,
&TempTime
);
//
// Build crypt vector.
//
CDBuildVect( &CryptArraySize, NULL );
CryptArray = new ULONG [ CryptArraySize ];
CDBuildVect( &CryptArraySize, CryptArray );
KerbErr = KerbConvertArrayToCryptList(
&RequestBody->encryption_type,
CryptArray,
CryptArraySize
);
if (!KERB_SUCCESS(KerbErr))
{
printf("Faield to convert array to crypt list: 0x%x\n",KerbErr);
goto Cleanup;
}
//
// BUGBUG: don't build pre-auth data
//
KerbErr = KerbConvertStringToPrincipalName(
&RequestBody->server_name,
&ssService
);
if (!KERB_SUCCESS(KerbErr))
{
printf("Failed to convert string to principal name: 0x%x\n",KerbErr);
goto Cleanup;
}
KerbErr = KerbConvertStringToPrincipalName(
&RequestBody->KERB_KDC_REQUEST_BODY_client_name,
&ssName
);
if (!KERB_SUCCESS(KerbErr))
{
printf("Failed to convert string to principal name: 0x%x\n",KerbErr);
goto Cleanup;
}
RequestBody->bit_mask |= KERB_KDC_REQUEST_BODY_client_name_present;
KerbErr = KerbConvertUnicodeStringToRealm(
&RequestBody->realm,
&ssRealm
);
if (!KERB_SUCCESS(KerbErr))
{
printf("Failed to convert unicde string to realm: 0x%x\n",KerbErr);
goto Cleanup;
}
Request.version = KERBEROS_VERSION;
Request.message_type = KRB_AS_REQ;
KerbErr = KerbPackKdcRequest(
&Request,
&InputMessage.BufferSize,
&InputMessage.Buffer
);
if (!KERB_SUCCESS(KerbErr))
{
printf("Failed to pack KDC request: 0x%x\n",KerbErr);
goto Cleanup;
}
Status = KerbCallKdc(
hBinding,
&InputMessage,
&OutputMessage
);
KerbErr = (KERBERR) Status;
if (!KERB_SUCCESS(KerbErr))
{
printf("KerbCallKdc failed: 0x%x\n",Status);
goto Cleanup;
}
KerbErr = KerbUnpackKdcReply(
OutputMessage.Buffer,
OutputMessage.BufferSize,
&Reply
);
if (!KERB_SUCCESS(KerbErr))
{
printf("Failed to unpack KDC reply: 0x%x\n",KerbErr);
goto Cleanup;
}
KerbErr = KerbUnpackKdcReplyBody(
&Reply->encrypted_part,
&kUserKey,
ReplyBody
);
if (!KERB_SUCCESS(KerbErr))
{
printf("Failed to unpack KDC reply body: 0x%x\n",KerbErr);
goto Cleanup;
}
#ifdef notdef
sc = CheckPAData( pkrReply->kSessionKey, pkdReply, GETAS );
if (FAILED(sc))
{
printf("Problem with PAData returned: 0x%X\n", sc );
return(1);
}
#endif
*pktTicket = Reply->ticket;
Cleanup:
//
// BUGBUG: memory leak here
//
return(KerbErr);
}
KERBERR
FooGetTGSTicket(
IN PVOID hBinding,
IN PWCHAR pwzUserName,
IN PWCHAR pwzUserRealm,
IN PWCHAR pwzServiceName,
IN PKERB_TICKET pktTGTicket,
IN PKERB_ENCRYPTED_KDC_REPLY pkrTGTReply,
IN ULONG AuthDataSize,
IN PUCHAR AuthData,
IN BOOLEAN Renew,
OUT PKERB_TICKET pktTicket,
OUT PKERB_ENCRYPTED_KDC_REPLY * ReplyBody
)
{
KERB_KDC_REQUEST Request;
PKERB_KDC_REQUEST_BODY RequestBody = &Request.request_body;
UNICODE_STRING ssService;
UNICODE_STRING UserName;
UNICODE_STRING UserRealm;
KERBERR KerbErr;
KERB_PA_DATA_LIST PaData;
PULONG CryptArray = NULL;
ULONG CryptArraySize = 0;
LARGE_INTEGER TempTime;
KERB_MESSAGE_BUFFER InputMessage;
KERB_MESSAGE_BUFFER OutputMessage;
PKERB_KDC_REPLY Reply = NULL;
KERB_ENCRYPTED_DATA EncAuthData;
RtlZeroMemory(
&EncAuthData,
sizeof(KERB_ENCRYPTED_DATA)
);
RtlInitUnicodeString(
&ssService,
pwzServiceName
);
RtlInitUnicodeString(
&UserName,
pwzUserName
);
RtlInitUnicodeString(
&UserRealm,
pwzUserRealm
);
//
// Build the request
//
RtlZeroMemory( &Request, sizeof( KERB_KDC_REQUEST ) );
RequestBody->kdc_options = KERB_KDC_OPTIONS_forwardable |
KERB_KDC_OPTIONS_proxiable |
KERB_KDC_OPTIONS_renewable |
KERB_KDC_OPTIONS_renewable_ok;
if (Renew)
{
RequestBody->kdc_options |= KERB_KDC_OPTIONS_renew;
}
RequestBody->nonce = 4;
//
// Build an AP request inside an encrypted data structure.
//
PaData.next = NULL;
PaData.value.preauth_data_type = PA_TGS_REQ;
KerbErr = KerbCreateApRequest(
&UserName,
&UserRealm,
&pkrTGTReply->session_key,
5, // nonce
pktTGTicket,
0, // AP options
NULL, // gss checksum
(PULONG) &PaData.value.preauth_data.length,
&PaData.value.preauth_data.value
);
if (!KERB_SUCCESS(KerbErr))
{
printf("Failed to create AP request: 0x%x\n",KerbErr);
goto Cleanup;
}
Request.KERB_KDC_REQUEST_preauth_data = &PaData;
Request.bit_mask |= KERB_KDC_REQUEST_preauth_data_present;
//
// Build crypt vector.
//
CDBuildVect( &CryptArraySize, NULL );
CryptArray = new ULONG [ CryptArraySize ];
CDBuildVect( &CryptArraySize, CryptArray );
KerbErr = KerbConvertArrayToCryptList(
&RequestBody->encryption_type,
CryptArray,
CryptArraySize
);
if (!KERB_SUCCESS(KerbErr))
{
printf("Faield to convert array to crypt list: 0x%x\n",KerbErr);
goto Cleanup;
}
KerbErr = KerbConvertStringToPrincipalName(
&RequestBody->KERB_KDC_REQUEST_BODY_client_name,
&UserName
);
if (!KERB_SUCCESS(KerbErr))
{
goto Cleanup;
}
RequestBody->bit_mask |= KERB_KDC_REQUEST_BODY_client_name_present;
KerbErr = KerbConvertUnicodeStringToRealm(
&RequestBody->realm,
&UserRealm
);
if (!KERB_SUCCESS(KerbErr))
{
goto Cleanup;
}
KerbErr = KerbConvertStringToPrincipalName(
&RequestBody->server_name,
&ssService
);
if (!KERB_SUCCESS(KerbErr))
{
goto Cleanup;
}
TempTime.QuadPart = 0;
KerbConvertLargeIntToGeneralizedTime(
&RequestBody->KERB_KDC_REQUEST_BODY_starttime,
NULL,
&TempTime
);
TempTime.LowPart = 0xffffffff;
TempTime.HighPart = 0x7fffffff;
KerbConvertLargeIntToGeneralizedTime(
&RequestBody->KERB_KDC_REQUEST_BODY_renew_until,
NULL,
&TempTime
);
RequestBody->bit_mask |= KERB_KDC_REQUEST_BODY_renew_until_present;
TempTime.LowPart = 0xffffffff;
TempTime.HighPart = 0x7fffffff;
KerbConvertLargeIntToGeneralizedTime(
&RequestBody->endtime,
NULL,
&TempTime
);
if (ARGUMENT_PRESENT(AuthData))
{
ULONG EncryptionOverhead;
KerbErr = KerbGetEncryptionOverhead(
pktTGTicket->encrypted_part.encryption_type,
&EncryptionOverhead,
NULL // BUGBUG
);
if (!KERB_SUCCESS(KerbErr))
{
printf("Failed to get encryption overhead: 0x%x\n",KerbErr);
goto Cleanup;
}
EncAuthData.cipher_text.length = AuthDataSize + EncryptionOverhead;
EncAuthData.cipher_text.value = (PUCHAR) MIDL_user_allocate(EncAuthData.cipher_text.length);
if (EncAuthData.cipher_text.value == NULL)
{
KerbErr = KRB_ERR_GENERIC;
goto Cleanup;
}
KerbErr = KerbEncryptData(
&EncAuthData,
AuthDataSize,
AuthData,
pktTGTicket->encrypted_part.encryption_type,
&pkrTGTReply->session_key
);
if (!KERB_SUCCESS(KerbErr))
{
printf("Failed to encrypt pac auth data: 0x%x\n",KerbErr);
goto Cleanup;
}
RequestBody->enc_authorization_data = EncAuthData;
RequestBody->bit_mask |= enc_authorization_data_present;
}
Request.version = KERBEROS_VERSION;
Request.message_type = KRB_TGS_REQ;
KerbErr = KerbPackKdcRequest(
&Request,
&InputMessage.BufferSize,
&InputMessage.Buffer
);
if (!KERB_SUCCESS(KerbErr))
{
printf("Failed to pack KDC request: 0x%x\n",KerbErr);
goto Cleanup;
}
//
// Get the ticket.
//
OutputMessage.Buffer = NULL;
OutputMessage.BufferSize = 0;
KerbErr = (KERBERR) KerbCallKdc(
hBinding,
&InputMessage,
&OutputMessage
);
if (!KERB_SUCCESS(KerbErr))
{
printf("KerbCallKdc failed: 0x%x\n",KerbErr);
goto Cleanup;
}
KerbErr = KerbUnpackKdcReply(
OutputMessage.Buffer,
OutputMessage.BufferSize,
&Reply
);
if (!KERB_SUCCESS(KerbErr))
{
printf("Failed to unpack KDC reply: 0x%x\n",KerbErr);
goto Cleanup;
}
KerbErr = KerbUnpackKdcReplyBody(
&Reply->encrypted_part,
&pkrTGTReply->session_key,
ReplyBody
);
if (!KERB_SUCCESS(KerbErr))
{
printf("Failed to unpack KDC reply body: 0x%x\n",KerbErr);
goto Cleanup;
}
#ifdef notdef
sc = CheckPAData( pkrReply->kSessionKey, pkdReply, GETAS );
if (FAILED(sc))
{
printf("Problem with PAData returned: 0x%X\n", sc );
return(1);
}
#endif
*pktTicket = Reply->ticket;
Cleanup:
if (EncAuthData.cipher_text.value != NULL)
{
MIDL_user_free(EncAuthData.cipher_text.value);
}
return(KerbErr);
}
KERBERR
FooGetPAC(
PVOID hBinding,
LPWSTR pwzUserName,
LPWSTR pwzUserRealm,
PKERB_TICKET PrivSvrTicket,
PKERB_ENCRYPTED_KDC_REPLY PrivSvrReply,
PULONG AuthDataSize,
PUCHAR * PackedAuthData
)
{
KERBERR KerbErr = KDC_ERR_NONE;
UNICODE_STRING UserName;
UNICODE_STRING UserRealm;
KERB_MESSAGE_BUFFER RequestMessage;
KERB_MESSAGE_BUFFER ReplyMessage;
PKERB_ENCRYPTED_DATA EncryptedPacMessage = NULL;
ReplyMessage.Buffer = NULL;
ReplyMessage.BufferSize = 0;
RtlInitUnicodeString(
&UserName,
pwzUserName
);
RtlInitUnicodeString(
&UserRealm,
pwzUserRealm
);
KerbErr = KerbCreateApRequest(
&UserName,
&UserRealm,
&PrivSvrReply->session_key,
6, // nonce
PrivSvrTicket,
0, // AP options
NULL, // gss checksum
&RequestMessage.BufferSize,
&RequestMessage.Buffer
);
if (!KERB_SUCCESS(KerbErr))
{
printf("Failed to create AP request for PAC: 0x%x\n",KerbErr);
goto Cleanup;
}
#ifdef notdef
KerbErr = (KERBERR) GetPAC(
hBinding,
&RequestMessage,
&ReplyMessage
);
if (!KERB_SUCCESS(KerbErr))
{
printf("Failed to get pac : 0x%x\n",KerbErr);
goto Cleanup;
}
#endif
//
// Now decode pac
//
//
// First unpack message into an encrypted data structure
//
KerbErr = KerbUnpackEncryptedData(
ReplyMessage.Buffer,
ReplyMessage.BufferSize,
&EncryptedPacMessage
);
if (!KERB_SUCCESS(KerbErr))
{
printf("Failed to unpack enc pac data: 0x%x\n",KerbErr);
goto Cleanup;
}
//
// Now decrypt into a packed authorization data
//
*PackedAuthData = (PUCHAR) MIDL_user_allocate(EncryptedPacMessage->cipher_text.length);
if (*PackedAuthData == NULL)
{
KerbErr = KRB_ERR_GENERIC;
goto Cleanup;
}
KerbErr = KerbDecryptData(
EncryptedPacMessage,
&PrivSvrReply->session_key,
AuthDataSize,
*PackedAuthData
);
if (!KERB_SUCCESS(KerbErr))
{
printf("Failed to decrypt pac auth data: 0x%x\n",KerbErr);
goto Cleanup;
}
Cleanup:
if (RequestMessage.Buffer != NULL)
{
MIDL_user_free(RequestMessage.Buffer);
}
if (EncryptedPacMessage != NULL)
{
MIDL_user_free(EncryptedPacMessage);
}
if (ReplyMessage.Buffer != NULL)
{
MIDL_user_free(ReplyMessage.Buffer);
}
return(KerbErr);
}
KERBERR
FooCheckTicket(
LPWSTR pwzUserName,
LPWSTR pwzUserRealm,
LPWSTR pwzServiceName,
LPWSTR pwzServicePassword,
PKERB_TICKET ServiceTicket,
PKERB_ENCRYPTED_KDC_REPLY ServiceReply
)
{
KERBERR KerbErr = KDC_ERR_NONE;
UNICODE_STRING UserName;
UNICODE_STRING UserRealm;
UNICODE_STRING ServiceName;
UNICODE_STRING ServicePassword;
ULONG AuthDataSize;
ULONG ApRequestSize;
PUCHAR ApRequestMessage = NULL;
PKERB_AP_REQUEST ApRequest = NULL;
KERB_ENCRYPTION_KEY ServiceKey;
LARGE_INTEGER tsFudgeFactor;
PKERB_ENCRYPTED_TICKET EncryptPart = NULL;
PKERB_AUTHENTICATOR Authenticator = NULL;
KERB_ENCRYPTION_KEY SessionKey;
BOOLEAN UseSubKey;
tsFudgeFactor.QuadPart = 300 * (LONGLONG) 10000000;
CAuthenticatorList Authenticators( tsFudgeFactor );
if (!NT_SUCCESS(Authenticators->Init())
{
return KERB_ERR_GENERIC;
}
RtlInitUnicodeString(
&UserName,
pwzUserName
);
RtlInitUnicodeString(
&UserRealm,
pwzUserRealm
);
RtlInitUnicodeString(
&ServiceName,
pwzServiceName
);
RtlInitUnicodeString(
&ServicePassword,
pwzServicePassword
);
KerbErr = KerbHashPassword(
&ServicePassword,
KERB_ETYPE_RC4_MD4,
&ServiceKey
);
if (!KERB_SUCCESS(KerbErr))
{
goto Cleanup;
}
KerbErr = KerbCreateApRequest(
&UserName,
&UserRealm,
&ServiceReply->session_key,
7, // nonce
ServiceTicket,
0, // AP options
NULL, // gss checksum
&ApRequestSize,
&ApRequestMessage
);
if (!KERB_SUCCESS(KerbErr))
{
printf("Failed to create AP request for PAC: 0x%x\n",KerbErr);
goto Cleanup;
}
KerbErr = KerbUnpackApRequest(
ApRequestMessage,
ApRequestSize,
&ApRequest
);
if (!KERB_SUCCESS(KerbErr))
{
printf("Failed to unpack ap request: 0x%x\n",KerbErr);
goto Cleanup;
}
KerbErr = KerbCheckTicket(
&ApRequest->ticket,
&ApRequest->authenticator,
&ServiceKey,
Authenticators,
&tsFudgeFactor,
&ServiceName,
&EncryptPart,
&Authenticator,
&SessionKey,
&UseSubKey
);
if (!KERB_SUCCESS(KerbErr))
{
printf("Failed to check ticket: 0x%x\n",KerbErr);
goto Cleanup;
}
Cleanup:
if (ApRequest != NULL)
{
MIDL_user_free(ApRequest);
}
KerbFreeTicket(EncryptPart);
KerbFreeAuthenticator(Authenticator);
if (ApRequestMessage != NULL)
{
MIDL_user_free(ApRequestMessage);
}
return(KerbErr);
}
int
TicketTests()
{
int ret = 0;
ULONG cbAuthen = 0;
NTSTATUS sc;
WCHAR ServiceName[100];
UNICODE_STRING KdcName;
PVOID SocketHandle = NULL;
wcscpy(
ServiceName,
pwzRealm
);
wcscat(ServiceName,L"\\");
wcscat(ServiceName,pwzUserName);
sc = KerbInitializeSockets(
0x0101,
5
);
if (!NT_SUCCESS(sc))
{
printf("Failed to initialize sockets: 0x%x\n",sc);
return((int) sc);
}
RtlInitUnicodeString(
&KdcName,
pwzAddress
);
sc = KerbBindSocket(
&KdcName,
&SocketHandle
);
if (!NT_SUCCESS(sc))
{
printf("KerbSocketBind failed: %0x%x\n",sc);
return((int) sc);
}
__try
{
KERB_TICKET ktASTicket;
KERB_TICKET ktPSTicket;
KERB_TICKET ktCTGTicket;
KERB_TICKET ktServTicket;
KERB_TICKET ktRenewServTicket;
PKERB_ENCRYPTED_KDC_REPLY pkrASReply = NULL;
PKERB_ENCRYPTED_KDC_REPLY pkrPSReply = NULL;
PKERB_ENCRYPTED_KDC_REPLY pkrCTGTReply = NULL;
PKERB_ENCRYPTED_KDC_REPLY pkrServReply = NULL;
PKERB_ENCRYPTED_KDC_REPLY pkrRenewServReply = NULL;
ULONG AuthDataSize = 0;
PUCHAR AuthData = NULL;
LARGE_INTEGER tsPing;
KERBERR KerbErr;
ULONG PingFlags = 0;
handle_t hKDC = BindTo( KDC, pwzTransport, pwzEndPoint, pwzAddress );
if (hKDC == 0 || hKDC == (handle_t)-1 )
{
printf("Error binding, quitting.\n" );
ret = (1);
goto Done;
}
sc = KDCPing( hKDC, &PingFlags, &tsPing );
if (sc != 0)
{
printf("Error %d (0x%X) from KdcPing()\n", sc );
ret = (1);
goto Done;
}
if (fGetAS)
{
KerbErr = FooGetASTicket(
SocketHandle,
pwzUserName,
pwzRealm,
pwzKDC,
pwzUserPasswd,
pwzClientAddress,
&ktASTicket,
&pkrASReply );
if (!KERB_SUCCESS(KerbErr))
{
goto Done;
}
if (fPrintTickets)
{
printf("Initial TGT:\n" );
PrintTicket( &ktASTicket, pwzKdcPasswd );
}
}
if (fGetTGS)
{
KerbErr = FooGetTGSTicket( SocketHandle, // hBinding
pwzUserName, // pwzUserName
pwzRealm, // pwzUserRealm
pwzPrivSvr, // pwzServiceName
&ktASTicket, // ktTGTicket
pkrASReply, // krTGTReply
0,
NULL, // no authorization
FALSE, // don't renew
&ktPSTicket, // ppktTicket
&pkrPSReply ); // pkrReply
if (!KERB_SUCCESS(KerbErr))
{
goto Done;
}
if (fPrintTickets)
{
printf("Ticket to PS:\n" );
PrintTicket( &ktPSTicket, pwzPSPasswd );
}
}
#ifdef notdef
if (fGetPAC)
{
//
// Get the PAC.
//
KerbErr = FooGetPAC(
SocketHandle,
pwzUserName,
pwzRealm,
&ktPSTicket,
pkrPSReply,
&AuthDataSize,
&AuthData
);
if (!KERB_SUCCESS(KerbErr))
{
printf("FooGetPAC() == 0x%X\n", KerbErr );
goto Done;
}
}
if (fGetCTGT)
{
KerbErr = FooGetTGSTicket( SocketHandle, // hBinding
pwzUserName, // pwzUserName
pwzRealm, // pwzUserRealm
pwzKDC, // pwzServiceName
&ktASTicket, // ktTGTicket
pkrASReply, // krTGTReply
AuthDataSize,
AuthData,
FALSE, // don't renew
&ktCTGTicket, // ppktTicket
&pkrCTGTReply ); // pkrReply
if (!KERB_SUCCESS(KerbErr))
{
printf("Failed to get TGT: 0x%x\n",KerbErr);
goto Done;
}
}
#endif // notdef
if (fGetServiceTkt) {
KerbErr = FooGetTGSTicket( SocketHandle, // hBinding
pwzUserName, // pwzUserName
pwzRealm, // pwzUserRealm
ServiceName, // pwzServiceName
&ktASTicket, // ktTGTicket
pkrASReply, // krTGTReply
0,
NULL, // no auth data
FALSE, // don't renew
&ktServTicket, // ppktTicket
&pkrServReply ); // pkrReply
if (!KERB_SUCCESS(KerbErr))
{
printf("Faield to get ticket to service: 0x%x\n",KerbErr);
goto Done;
}
//
// Now check the ticket.
//
KerbErr = FooCheckTicket(
pwzUserName,
pwzRealm,
ServiceName, // service name
pwzUserPasswd, /// service password
&ktServTicket,
pkrServReply
);
if (!KERB_SUCCESS(KerbErr))
{
printf("Failed tocheck service ticket: 0x%x\n",KerbErr);
goto Done;
}
}
if (fRenewSvc)
{
KerbErr = FooGetTGSTicket( SocketHandle, // hBinding
pwzUserName, // pwzUserName
pwzRealm, // pwzUserRealm
ServiceName, // pwzServiceName
&ktServTicket, // ktTGTicket
pkrServReply, // krTGTReply
0,
NULL, // no auth data
TRUE,
&ktRenewServTicket, // ppktTicket
&pkrRenewServReply ); // pkrReply
if (!KERB_SUCCESS(KerbErr))
{
printf("Faield to get ticket to service: 0x%x\n",KerbErr);
goto Done;
}
//
// Now check the ticket.
//
KerbErr = FooCheckTicket(
pwzUserName,
pwzRealm,
ServiceName, // service name
pwzUserPasswd, /// service password
&ktServTicket,
pkrServReply
);
if (!KERB_SUCCESS(KerbErr))
{
printf("Failed tocheck service ticket: 0x%x\n",KerbErr);
goto Done;
}
}
Done:
;
}
__except ( EXCEPTION_EXECUTE_HANDLER )
{
printf("Exception 0x%x (%d) in ticktest.\n", GetExceptionCode(), GetExceptionCode() );
ret = 5;
}
if (SocketHandle != NULL)
{
closesocket((SOCKET) SocketHandle);
}
return(ret);
}