NTSTATUS LsaCallKerberosPackage(PVOID ProtocolSubmitBuffer, ULONG SubmitBufferLength, PVOID *ProtocolReturnBuffer, PULONG ReturnBufferLength, PNTSTATUS ProtocolStatus) { NTSTATUS status = STATUS_HANDLE_NO_LONGER_VALID; if(g_hLSA && g_isAuthPackageKerberos) status = LsaCallAuthenticationPackage(g_hLSA, g_AuthenticationPackageId_Kerberos, ProtocolSubmitBuffer, SubmitBufferLength, ProtocolReturnBuffer, ReturnBufferLength, ProtocolStatus); return status; }
static BOOL GetLSAPrincipalName(char * pszUser, DWORD dwUserSize) { KERB_QUERY_TKT_CACHE_REQUEST CacheRequest; PKERB_RETRIEVE_TKT_RESPONSE pTicketResponse = NULL; ULONG ResponseSize; PKERB_EXTERNAL_NAME pClientName = NULL; PUNICODE_STRING pDomainName = NULL; LSA_STRING Name; HANDLE hLogon = INVALID_HANDLE_VALUE; ULONG PackageId; NTSTATUS ntStatus; NTSTATUS ntSubStatus = 0; WCHAR * wchUser = NULL; DWORD dwSize; SHORT sCount; BOOL bRet = FALSE; ntStatus = LsaConnectUntrusted( &hLogon); if (FAILED(ntStatus)) goto cleanup; Name.Buffer = MICROSOFT_KERBEROS_NAME_A; Name.Length = (USHORT)(sizeof(MICROSOFT_KERBEROS_NAME_A) - sizeof(char)); Name.MaximumLength = Name.Length; ntStatus = LsaLookupAuthenticationPackage( hLogon, &Name, &PackageId); if (FAILED(ntStatus)) goto cleanup; memset(&CacheRequest, 0, sizeof(KERB_QUERY_TKT_CACHE_REQUEST)); CacheRequest.MessageType = KerbRetrieveTicketMessage; CacheRequest.LogonId.LowPart = 0; CacheRequest.LogonId.HighPart = 0; ntStatus = LsaCallAuthenticationPackage( hLogon, PackageId, &CacheRequest, sizeof(CacheRequest), &pTicketResponse, &ResponseSize, &ntSubStatus); if (FAILED(ntStatus) || FAILED(ntSubStatus)) goto cleanup; /* We have a ticket in the response */ pClientName = pTicketResponse->Ticket.ClientName; pDomainName = &pTicketResponse->Ticket.DomainName; /* We want to return ClientName @ DomainName */ dwSize = 0; for ( sCount = 0; sCount < pClientName->NameCount; sCount++) { dwSize += pClientName->Names[sCount].Length; } dwSize += pDomainName->Length + sizeof(WCHAR); if ( dwSize / sizeof(WCHAR) > dwUserSize ) goto cleanup; wchUser = malloc(dwSize); if (wchUser == NULL) goto cleanup; for ( sCount = 0, wchUser[0] = L'\0'; sCount < pClientName->NameCount; sCount++) { StringCbCatNW( wchUser, dwSize, pClientName->Names[sCount].Buffer, pClientName->Names[sCount].Length); } StringCbCatNW( wchUser, dwSize, pDomainName->Buffer, pDomainName->Length); if ( !UnicodeToANSI( wchUser, pszUser, dwUserSize) ) goto cleanup; bRet = TRUE; cleanup: if (wchUser) free(wchUser); if ( hLogon != INVALID_HANDLE_VALUE) LsaDeregisterLogonProcess(hLogon); if ( pTicketResponse ) { SecureZeroMemory(pTicketResponse,ResponseSize); LsaFreeReturnBuffer(pTicketResponse); } return bRet; }
SECURITY_STATUS SEC_ENTRY InitializeSecurityContextW( PCredHandle phCredential, // Cred to base context PCtxtHandle phContext, // Existing context (OPT) PSECURITY_STRING pssTargetName, // Name of target unsigned long fContextReq, // Context Requirements unsigned long Reserved1, // Reserved, MBZ unsigned long TargetDataRep, // Data rep of target PSecBufferDesc pInput, // Input Buffers unsigned long Reserved2, // Reserved, MBZ PCtxtHandle phNewContext, // (out) New Context handle PSecBufferDesc pOutput, // (inout) Output Buffers unsigned long SEC_FAR * pfContextAttr, // (out) Context attrs PTimeStamp ptsExpiry // (out) Life span (OPT) ) { SECURITY_STATUS scRet; PMSV1_0_GETCHALLENRESP_REQUEST ChallengeRequest = NULL; ULONG ChallengeRequestSize; PMSV1_0_GETCHALLENRESP_RESPONSE ChallengeResponse = NULL; ULONG ChallengeResponseSize; PCHALLENGE_MESSAGE ChallengeMessage = NULL; ULONG ChallengeMessageSize; PNTLM_CHALLENGE_MESSAGE NtlmChallengeMessage = NULL; ULONG NtlmChallengeMessageSize; PAUTHENTICATE_MESSAGE AuthenticateMessage = NULL; ULONG AuthenticateMessageSize; PNTLM_INITIALIZE_RESPONSE NtlmInitializeResponse = NULL; PClient Client = NULL; UNICODE_STRING PasswordToUse; UNICODE_STRING UserNameToUse; UNICODE_STRING DomainNameToUse; ULONG ParameterControl = USE_PRIMARY_PASSWORD | RETURN_PRIMARY_USERNAME | RETURN_PRIMARY_LOGON_DOMAINNAME; NTSTATUS FinalStatus = STATUS_SUCCESS; PUCHAR Where; PSecBuffer AuthenticationToken = NULL; PSecBuffer InitializeResponseToken = NULL; BOOLEAN UseSuppliedCreds = FALSE; PAGED_CODE(); RtlInitUnicodeString( &PasswordToUse, NULL ); RtlInitUnicodeString( &UserNameToUse, NULL ); RtlInitUnicodeString( &DomainNameToUse, NULL ); // // Check for valid sizes, pointers, etc.: // if (!phCredential) { return(SEC_E_INVALID_HANDLE); } // // Check that we can indeed call the LSA and get the client // handle to it. // scRet = IsOkayToExec(&Client); if (!NT_SUCCESS(scRet)) { return(scRet); } // // Locate the buffers with the input data // if (!GetTokenBuffer( pInput, 0, // get the first security token (PVOID *) &ChallengeMessage, &ChallengeMessageSize, TRUE // may be readonly )) { scRet = SEC_E_INVALID_TOKEN; goto Cleanup; } // // If we are using supplied creds, get them now too. // if (fContextReq & ISC_REQ_USE_SUPPLIED_CREDS) { if (!GetTokenBuffer( pInput, 1, // get the second security token (PVOID *) &NtlmChallengeMessage, &NtlmChallengeMessageSize, TRUE // may be readonly )) { scRet = SEC_E_INVALID_TOKEN; goto Cleanup; } else { UseSuppliedCreds = TRUE; } } // // Get the output tokens // if (!GetSecurityToken( pOutput, 0, &AuthenticationToken) || !GetSecurityToken( pOutput, 1, &InitializeResponseToken ) ) { scRet = SEC_E_INVALID_TOKEN; goto Cleanup; } // // Make sure the sizes are o.k. // if ((ChallengeMessageSize < sizeof(CHALLENGE_MESSAGE)) || (UseSuppliedCreds && !(NtlmChallengeMessageSize < sizeof(NTLM_CHALLENGE_MESSAGE)))) { scRet = SEC_E_INVALID_TOKEN; } // // Make sure the caller wants us to allocate memory: // if (!(fContextReq & ISC_REQ_ALLOCATE_MEMORY)) { scRet = SEC_E_UNSUPPORTED_FUNCTION; goto Cleanup; } // // BUGBUG: allow calls requesting PROMPT_FOR_CREDS to go through. // We won't prompt, but we will setup a context properly. // // if ((fContextReq & ISC_REQ_PROMPT_FOR_CREDS) != 0) // { // scRet = SEC_E_UNSUPPORTED_FUNCTION; // goto Cleanup; // } // // Verify the validity of the challenge message. // if (strncmp( ChallengeMessage->Signature, NTLMSSP_SIGNATURE, sizeof(NTLMSSP_SIGNATURE))) { scRet = SEC_E_INVALID_TOKEN; goto Cleanup; } if (ChallengeMessage->MessageType != NtLmChallenge) { scRet = SEC_E_INVALID_TOKEN; goto Cleanup; } if (ChallengeMessage->NegotiateFlags & NTLMSSP_REQUIRED_NEGOTIATE_FLAGS != NTLMSSP_REQUIRED_NEGOTIATE_FLAGS) { scRet = SEC_E_UNSUPPORTED_FUNCTION; goto Cleanup; } if ((ChallengeMessage->NegotiateFlags & NTLMSSP_REQUEST_NON_NT_SESSION_KEY) != 0) { ParameterControl |= RETURN_NON_NT_USER_SESSION_KEY; } if ((fContextReq & ISC_REQ_USE_SUPPLIED_CREDS) != 0) { if ( NtlmChallengeMessage->Password.Buffer != NULL) { ParameterControl &= ~USE_PRIMARY_PASSWORD; PasswordToUse = NtlmChallengeMessage->Password; PasswordToUse.Buffer = (LPWSTR) ((PCHAR) PasswordToUse.Buffer + (ULONG) NtlmChallengeMessage); } if (NtlmChallengeMessage->UserName.Length != 0) { UserNameToUse = NtlmChallengeMessage->UserName; UserNameToUse.Buffer = (LPWSTR) ((PCHAR) UserNameToUse.Buffer + (ULONG) NtlmChallengeMessage); ParameterControl &= ~RETURN_PRIMARY_USERNAME; } if (NtlmChallengeMessage->DomainName.Length != 0) { DomainNameToUse = NtlmChallengeMessage->DomainName; DomainNameToUse.Buffer = (LPWSTR) ((PCHAR) DomainNameToUse.Buffer + (ULONG) NtlmChallengeMessage); ParameterControl &= ~RETURN_PRIMARY_LOGON_DOMAINNAME; } } // // Package up the parameter for a call to the LSA. // ChallengeRequestSize = sizeof(MSV1_0_GETCHALLENRESP_REQUEST) + PasswordToUse.Length; scRet = ZwAllocateVirtualMemory( NtCurrentProcess(), &ChallengeRequest, 0L, &ChallengeRequestSize, MEM_COMMIT, PAGE_READWRITE ); if (!NT_SUCCESS(scRet)) { goto Cleanup; } // // Build the challenge request message. // ChallengeRequest->MessageType = MsV1_0Lm20GetChallengeResponse; ChallengeRequest->ParameterControl = ParameterControl; ChallengeRequest->LogonId = * (PLUID) phCredential; RtlCopyMemory( ChallengeRequest->ChallengeToClient, ChallengeMessage->Challenge, MSV1_0_CHALLENGE_LENGTH ); if ((ParameterControl & USE_PRIMARY_PASSWORD) == 0) { ChallengeRequest->Password.Buffer = (LPWSTR) (ChallengeRequest+1); RtlCopyMemory( ChallengeRequest->Password.Buffer, PasswordToUse.Buffer, PasswordToUse.Length ); ChallengeRequest->Password.Length = PasswordToUse.Length; ChallengeRequest->Password.MaximumLength = PasswordToUse.Length; } // // Call the LSA to get the challenge response. // scRet = LsaCallAuthenticationPackage( Client->hPort, PackageId, ChallengeRequest, ChallengeRequestSize, &ChallengeResponse, &ChallengeResponseSize, &FinalStatus ); if (!NT_SUCCESS(scRet)) { goto Cleanup; } if (!NT_SUCCESS(FinalStatus)) { scRet = FinalStatus; goto Cleanup; } ASSERT(ChallengeResponse->MessageType == MsV1_0Lm20GetChallengeResponse); // // Now prepare the output message. // if (UserNameToUse.Buffer == NULL) { UserNameToUse = ChallengeResponse->UserName; } if (DomainNameToUse.Buffer == NULL) { DomainNameToUse = ChallengeResponse->LogonDomainName; } AuthenticateMessageSize = sizeof(AUTHENTICATE_MESSAGE) + UserNameToUse.Length + DomainNameToUse.Length + ChallengeResponse->CaseSensitiveChallengeResponse.Length + ChallengeResponse->CaseInsensitiveChallengeResponse.Length; // // BUGBUG: where do I get the workstation name from? // AuthenticateMessage = (PAUTHENTICATE_MESSAGE) SecAllocate(AuthenticateMessageSize); if (AuthenticateMessage == NULL) { scRet = SEC_E_INSUFFICIENT_MEMORY; goto Cleanup; } Where = (PUCHAR) (AuthenticateMessage + 1); RtlCopyMemory( AuthenticateMessage->Signature, NTLMSSP_SIGNATURE, sizeof(NTLMSSP_SIGNATURE) ); AuthenticateMessage->MessageType = NtLmAuthenticate; PutString( &AuthenticateMessage->LmChallengeResponse, &ChallengeResponse->CaseInsensitiveChallengeResponse, AuthenticateMessage, &Where ); PutString( &AuthenticateMessage->NtChallengeResponse, &ChallengeResponse->CaseSensitiveChallengeResponse, AuthenticateMessage, &Where ); PutString( &AuthenticateMessage->DomainName, (PSTRING) &DomainNameToUse, AuthenticateMessage, &Where ); PutString( &AuthenticateMessage->UserName, (PSTRING) &UserNameToUse, AuthenticateMessage, &Where ); // // BUGBUG: no workstation name to fill in. // AuthenticateMessage->Workstation.Length = 0; AuthenticateMessage->Workstation.MaximumLength = 0; AuthenticateMessage->Workstation.Buffer = NULL; // // Build the initialize response. // NtlmInitializeResponse = (PNTLM_INITIALIZE_RESPONSE) SecAllocate(sizeof(NTLM_INITIALIZE_RESPONSE)); if (NtlmInitializeResponse == NULL) { scRet = SEC_E_INSUFFICIENT_MEMORY; goto Cleanup; } RtlCopyMemory( NtlmInitializeResponse->UserSessionKey, ChallengeResponse->UserSessionKey, MSV1_0_USER_SESSION_KEY_LENGTH ); RtlCopyMemory( NtlmInitializeResponse->LanmanSessionKey, ChallengeResponse->LanmanSessionKey, MSV1_0_LANMAN_SESSION_KEY_LENGTH ); // // Fill in the output buffers now. // AuthenticationToken->pvBuffer = AuthenticateMessage; AuthenticationToken->cbBuffer = AuthenticateMessageSize; InitializeResponseToken->pvBuffer = NtlmInitializeResponse; InitializeResponseToken->cbBuffer = sizeof(NTLM_INITIALIZE_RESPONSE); // // Make a local context for this // scRet = NtlmInitKernelContext( NtlmInitializeResponse->UserSessionKey, NtlmInitializeResponse->LanmanSessionKey, NULL, // no token, phNewContext ); if (!NT_SUCCESS(scRet)) { goto Cleanup; } scRet = SEC_E_OK; Cleanup: if (ChallengeRequest != NULL) { ZwFreeVirtualMemory( NtCurrentProcess(), &ChallengeRequest, &ChallengeRequestSize, MEM_RELEASE ); } if (ChallengeResponse != NULL) { LsaFreeReturnBuffer( ChallengeResponse ); } if (!NT_SUCCESS(scRet)) { if (AuthenticateMessage != NULL) { SecFree(AuthenticateMessage); } if (NtlmInitializeResponse != NULL) { SecFree(NtlmInitializeResponse); } } return(scRet); }
SECURITY_STATUS SEC_ENTRY GetSecurityUserInfo( IN PLUID pLogonId, IN ULONG fFlags, OUT PSecurityUserData * ppUserInfo) { NTSTATUS Status, FinalStatus; PVOID GetInfoBuffer = NULL; PVOID GetInfoResponseBuffer = NULL; PMSV1_0_GETUSERINFO_REQUEST GetInfoRequest; PMSV1_0_GETUSERINFO_RESPONSE GetInfoResponse; ULONG ResponseSize; ULONG RegionSize = sizeof(MSV1_0_GETUSERINFO_REQUEST); PSecurityUserData UserInfo = NULL; ULONG UserInfoSize; PUCHAR Where; SECURITY_STATUS scRet; PClient Client = NULL; scRet = IsOkayToExec(&Client); if (!NT_SUCCESS(scRet)) { return(scRet); } // // Allocate virtual memory for the response buffer. // Status = ZwAllocateVirtualMemory( NtCurrentProcess(), &GetInfoBuffer, 0L, &RegionSize, MEM_COMMIT, PAGE_READWRITE ); GetInfoRequest = GetInfoBuffer; if (!NT_SUCCESS(Status)) { scRet = Status; goto Cleanup; } GetInfoRequest->MessageType = MsV1_0GetUserInfo; RtlCopyLuid(&GetInfoRequest->LogonId, pLogonId); Status = LsaCallAuthenticationPackage( Client->hPort, PackageId, GetInfoRequest, RegionSize, &GetInfoResponseBuffer, &ResponseSize, &FinalStatus); GetInfoResponse = GetInfoResponseBuffer; if (!NT_SUCCESS(Status)) { GetInfoResponseBuffer = NULL; scRet = Status; goto Cleanup; } if (!NT_SUCCESS(FinalStatus)) { scRet = FinalStatus; goto Cleanup; } ASSERT(GetInfoResponse->MessageType == MsV1_0GetUserInfo); // // Build a SecurityUserData // UserInfoSize = sizeof(SecurityUserData) + GetInfoResponse->UserName.MaximumLength + GetInfoResponse->LogonDomainName.MaximumLength + GetInfoResponse->LogonServer.MaximumLength + RtlLengthSid(GetInfoResponse->UserSid); scRet = ZwAllocateVirtualMemory( NtCurrentProcess(), &UserInfo, 0L, &UserInfoSize, MEM_COMMIT, PAGE_READWRITE ); if (!NT_SUCCESS(scRet)) { goto Cleanup; } // // Pack in the SID first, to respectalignment boundaries. // Where = (PUCHAR) (UserInfo + 1); UserInfo->pSid = (PSID) (Where); RtlCopySid( UserInfoSize, Where, GetInfoResponse->UserSid ); Where += RtlLengthSid(Where); // // Pack in the strings // PutString( (PSTRING) &UserInfo->UserName, (PSTRING) &GetInfoResponse->UserName, 0, &Where ); PutString( (PSTRING) &UserInfo->LogonDomainName, (PSTRING) &GetInfoResponse->LogonDomainName, 0, &Where ); PutString( (PSTRING) &UserInfo->LogonServer, (PSTRING) &GetInfoResponse->LogonServer, 0, &Where ); *ppUserInfo = UserInfo; UserInfo = NULL; scRet = STATUS_SUCCESS; Cleanup: if (GetInfoRequest != NULL) { ZwFreeVirtualMemory( NtCurrentProcess(), &GetInfoRequest, &RegionSize, MEM_RELEASE ); } if (UserInfo != NULL) { FreeContextBuffer(UserInfo); } if (GetInfoResponseBuffer != NULL) { LsaFreeReturnBuffer(GetInfoResponseBuffer); } return(scRet); }
BOOL ShowTgt( HANDLE LogonHandle, ULONG PackageId ) { NTSTATUS Status; KERB_QUERY_TKT_CACHE_REQUEST CacheRequest; PKERB_RETRIEVE_TKT_RESPONSE TicketEntry = NULL; PKERB_EXTERNAL_TICKET Ticket; ULONG ResponseSize; NTSTATUS SubStatus; BOOLEAN Trusted = TRUE; CacheRequest.MessageType = KerbRetrieveTicketMessage; CacheRequest.LogonId.LowPart = 0; CacheRequest.LogonId.HighPart = 0; Status = LsaCallAuthenticationPackage( LogonHandle, PackageId, &CacheRequest, sizeof(CacheRequest), (PVOID *) &TicketEntry, &ResponseSize, &SubStatus ); if (!SEC_SUCCESS(Status) || !SEC_SUCCESS(SubStatus)) { ShowNTError("LsaCallAuthenticationPackage", Status); printf("Substatus: 0x%x\n",SubStatus); return FALSE; } Ticket = &(TicketEntry->Ticket); printf("\nCached TGT:\n\n"); printf("ServiceName: "); PrintKerbName(Ticket->ServiceName); printf("TargetName: "); PrintKerbName(Ticket->TargetName); printf("FullServiceName: "); PrintKerbName(Ticket->ClientName); printf("DomainName: %.*S\n", Ticket->DomainName.Length/sizeof(WCHAR),Ticket->DomainName.Buffer); printf("TargetDomainName: %.*S\n", Ticket->TargetDomainName.Length/sizeof(WCHAR),Ticket->TargetDomainName.Buffer); printf("AltTargetDomainName: %.*S\n", Ticket->AltTargetDomainName.Length/sizeof(WCHAR),Ticket->AltTargetDomainName.Buffer); printf("TicketFlags: (0x%x) ",Ticket->TicketFlags); PrintTktFlags(Ticket->TicketFlags); PrintTime("KeyExpirationTime: ",Ticket->KeyExpirationTime); PrintTime("StartTime: ",Ticket->StartTime); PrintTime("EndTime: ",Ticket->EndTime); PrintTime("RenewUntil: ",Ticket->RenewUntil); PrintTime("TimeSkew: ",Ticket->TimeSkew); PrintEType(Ticket->SessionKey.KeyType); if (TicketEntry != NULL) { LsaFreeReturnBuffer(TicketEntry); } return TRUE; }
DWORD GetEncodedTicket( HANDLE LogonHandle, ULONG PackageId, wchar_t *Server ) { NTSTATUS Status; PKERB_RETRIEVE_TKT_REQUEST CacheRequest = NULL; PKERB_RETRIEVE_TKT_RESPONSE CacheResponse = NULL; PKERB_EXTERNAL_TICKET Ticket; ULONG ResponseSize; NTSTATUS SubStatus; BOOLEAN Trusted = TRUE; BOOLEAN Success = FALSE; UNICODE_STRING Target = {0}; UNICODE_STRING Target2 = {0}; InitUnicodeString( &Target2, Server); CacheRequest = (PKERB_RETRIEVE_TKT_REQUEST) LocalAlloc(LMEM_ZEROINIT, Target2.Length + sizeof(KERB_RETRIEVE_TKT_REQUEST)); CacheRequest->MessageType = KerbRetrieveEncodedTicketMessage ; CacheRequest->LogonId.LowPart = 0; CacheRequest->LogonId.HighPart = 0; Target.Buffer = (LPWSTR) (CacheRequest + 1); Target.Length = Target2.Length; Target.MaximumLength = Target2.MaximumLength; CopyMemory( Target.Buffer, Target2.Buffer, Target2.Length ); CacheRequest->TargetName = Target; Status = LsaCallAuthenticationPackage( LogonHandle, PackageId, CacheRequest, Target2.Length + sizeof(KERB_RETRIEVE_TKT_REQUEST), (PVOID *) &CacheResponse, &ResponseSize, &SubStatus ); if (!SEC_SUCCESS(Status) || !SEC_SUCCESS(SubStatus)) { ShowNTError("LsaCallAuthenticationPackage", Status); printf("Substatus: 0x%x\n",SubStatus); ShowNTError("Substatus:", SubStatus); } else { Ticket = &(CacheResponse->Ticket); printf("\nEncoded Ticket:\n\n"); printf("ServiceName: "); PrintKerbName(Ticket->ServiceName); printf("TargetName: "); PrintKerbName(Ticket->TargetName); printf("ClientName: "); PrintKerbName(Ticket->ClientName); printf("DomainName: %.*S\n", Ticket->DomainName.Length/sizeof(WCHAR),Ticket->DomainName.Buffer); printf("TargetDomainName: %.*S\n", Ticket->TargetDomainName.Length/sizeof(WCHAR),Ticket->TargetDomainName.Buffer); printf("AltTargetDomainName: %.*S\n", Ticket->AltTargetDomainName.Length/sizeof(WCHAR),Ticket->AltTargetDomainName.Buffer); printf("TicketFlags: (0x%x) ",Ticket->TicketFlags); PrintTktFlags(Ticket->TicketFlags); PrintTime("KeyExpirationTime: ",Ticket->KeyExpirationTime); PrintTime("StartTime: ",Ticket->StartTime); PrintTime("EndTime: ",Ticket->EndTime); PrintTime("RenewUntil: ",Ticket->RenewUntil); PrintTime("TimeSkew: ",Ticket->TimeSkew); PrintEType(Ticket->SessionKey.KeyType); Success = TRUE; } if (CacheResponse) { LsaFreeReturnBuffer(CacheResponse); } if (CacheRequest) { LocalFree(CacheRequest); } return Success; }
BOOL ShowTickets( HANDLE LogonHandle, ULONG PackageId, DWORD dwMode ) { NTSTATUS Status; KERB_QUERY_TKT_CACHE_REQUEST CacheRequest; PKERB_QUERY_TKT_CACHE_RESPONSE CacheResponse = NULL; ULONG ResponseSize; NTSTATUS SubStatus; ULONG Index; int ch; CacheRequest.MessageType = KerbQueryTicketCacheMessage; CacheRequest.LogonId.LowPart = 0; CacheRequest.LogonId.HighPart = 0; Status = LsaCallAuthenticationPackage( LogonHandle, PackageId, &CacheRequest, sizeof(CacheRequest), (PVOID *) &CacheResponse, &ResponseSize, &SubStatus ); if (!SEC_SUCCESS(Status) || !SEC_SUCCESS(SubStatus)) { ShowNTError("LsaCallAuthenticationPackage", Status); printf("Substatus: 0x%x\n",SubStatus); return FALSE; } printf("\nCached Tickets: (%lu)\n", CacheResponse->CountOfTickets); for (Index = 0; Index < CacheResponse->CountOfTickets ; Index++ ) { printf("\n Server: %wZ@%wZ\n", &CacheResponse->Tickets[Index].ServerName, &CacheResponse->Tickets[Index].RealmName); printf(" "); PrintEType(CacheResponse->Tickets[Index].EncryptionType); PrintTime(" End Time: ",CacheResponse->Tickets[Index].EndTime); PrintTime(" Renew Time: ",CacheResponse->Tickets[Index].RenewTime); printf(" TicketFlags: (0x%x) ", CacheResponse->Tickets[Index].TicketFlags); PrintTktFlags(CacheResponse->Tickets[Index].TicketFlags); printf("\n"); if(dwMode == INTERACTIVE_PURGE) { printf("Purge? (y/n/q) : "); ch = _getche(); if(ch == 'y' || ch == 'Y') { printf("\n"); PurgeTicket( LogonHandle, PackageId, CacheResponse->Tickets[Index].ServerName.Buffer, CacheResponse->Tickets[Index].ServerName.Length, CacheResponse->Tickets[Index].RealmName.Buffer, CacheResponse->Tickets[Index].RealmName.Length ); } else if(ch == 'q' || ch == 'Q') goto cleanup; else printf("\n\n"); } } cleanup: if (CacheResponse != NULL) { LsaFreeReturnBuffer(CacheResponse); } return TRUE; }
BOOL PurgeTicket( HANDLE LogonHandle, ULONG PackageId, LPWSTR Server, DWORD cbServer, LPWSTR Realm, DWORD cbRealm ) { NTSTATUS Status; PVOID Response; ULONG ResponseSize; NTSTATUS SubStatus=0; PKERB_PURGE_TKT_CACHE_REQUEST pCacheRequest = NULL; pCacheRequest = (PKERB_PURGE_TKT_CACHE_REQUEST) LocalAlloc(LMEM_ZEROINIT, cbServer + cbRealm + sizeof(KERB_PURGE_TKT_CACHE_REQUEST)); pCacheRequest->MessageType = KerbPurgeTicketCacheMessage; pCacheRequest->LogonId.LowPart = 0; pCacheRequest->LogonId.HighPart = 0; CopyMemory((LPBYTE)pCacheRequest+sizeof(KERB_PURGE_TKT_CACHE_REQUEST), Server,cbServer); CopyMemory((LPBYTE)pCacheRequest+sizeof(KERB_PURGE_TKT_CACHE_REQUEST)+cbServer, Realm,cbRealm); pCacheRequest->ServerName.Buffer = (LPWSTR)((LPBYTE)pCacheRequest+sizeof(KERB_PURGE_TKT_CACHE_REQUEST)); pCacheRequest->ServerName.Length = (unsigned short)cbServer; pCacheRequest->ServerName.MaximumLength = (unsigned short)cbServer; pCacheRequest->RealmName.Buffer = (LPWSTR)((LPBYTE)pCacheRequest+sizeof(KERB_PURGE_TKT_CACHE_REQUEST)+cbServer); pCacheRequest->RealmName.Length = (unsigned short)cbRealm; pCacheRequest->RealmName.MaximumLength = (unsigned short)cbRealm; printf("\tDeleting ticket: \n"); printf("\t ServerName = %wZ (cb=%lu)\n",&pCacheRequest->ServerName,cbServer); printf("\t RealmName = %wZ (cb=%lu)\n",&pCacheRequest->RealmName,cbRealm); Status = LsaCallAuthenticationPackage( LogonHandle, PackageId, pCacheRequest, sizeof(KERB_PURGE_TKT_CACHE_REQUEST)+cbServer+cbRealm, &Response, &ResponseSize, &SubStatus ); if (!SEC_SUCCESS(Status) || !SEC_SUCCESS(Status)) { ShowNTError("LsaCallAuthenticationPackage(purge)", Status); printf("Substatus: 0x%x\n",SubStatus); ShowNTError("LsaCallAuthenticationPackage(purge SubStatus)", SubStatus); return FALSE; } else { printf("\tTicket purged!\n"); return TRUE; } }
/* * Class: sun_security_krb5_Credentials * Method: acquireDefaultNativeCreds * Signature: ()Lsun/security/krb5/Credentials; */ JNIEXPORT jobject JNICALL Java_sun_security_krb5_Credentials_acquireDefaultNativeCreds( JNIEnv *env, jclass krbcredsClass) { KERB_QUERY_TKT_CACHE_REQUEST CacheRequest; PKERB_RETRIEVE_TKT_RESPONSE TktCacheResponse = NULL; PKERB_RETRIEVE_TKT_REQUEST pTicketRequest = NULL; PKERB_RETRIEVE_TKT_RESPONSE pTicketResponse = NULL; NTSTATUS Status, SubStatus; ULONG requestSize = 0; ULONG responseSize = 0; ULONG rspSize = 0; HANDLE LogonHandle = NULL; ULONG PackageId; jobject ticket, clientPrincipal, targetPrincipal, encryptionKey; jobject ticketFlags, startTime, endTime, krbCreds = NULL; jobject authTime, renewTillTime, hostAddresses = NULL; KERB_EXTERNAL_TICKET *msticket; int ignore_cache = 0; FILETIME Now, EndTime, LocalEndTime; while (TRUE) { if (krbcredsConstructor == 0) { krbcredsConstructor = (*env)->GetMethodID(env, krbcredsClass, "<init>", "(Lsun/security/krb5/internal/Ticket;Lsun/security/krb5/PrincipalName;Lsun/security/krb5/PrincipalName;Lsun/security/krb5/EncryptionKey;Lsun/security/krb5/internal/TicketFlags;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/HostAddresses;)V"); if (krbcredsConstructor == 0) { printf("Couldn't find sun.security.krb5.Credentials constructor\n"); break; } } #ifdef DEBUG printf("Found KrbCreds constructor\n"); #endif // // Get the logon handle and package ID from the // Kerberos package // if (!PackageConnectLookup(&LogonHandle, &PackageId)) break; #ifdef DEBUG printf("Got handle to Kerberos package\n"); #endif /* DEBUG */ // Get the MS TGT from cache CacheRequest.MessageType = KerbRetrieveTicketMessage; CacheRequest.LogonId.LowPart = 0; CacheRequest.LogonId.HighPart = 0; Status = LsaCallAuthenticationPackage( LogonHandle, PackageId, &CacheRequest, sizeof(CacheRequest), &TktCacheResponse, &rspSize, &SubStatus ); #ifdef DEBUG printf("Response size is %d\n", rspSize); #endif if (!LSA_SUCCESS(Status) || !LSA_SUCCESS(SubStatus)) { if (!LSA_SUCCESS(Status)) { ShowNTError("LsaCallAuthenticationPackage", Status); } else { ShowNTError("Protocol status", SubStatus); } break; } // got the native MS TGT msticket = &(TktCacheResponse->Ticket); // check TGT validity switch (msticket->SessionKey.KeyType) { case KERB_ETYPE_DES_CBC_CRC: case KERB_ETYPE_DES_CBC_MD5: case KERB_ETYPE_NULL: case KERB_ETYPE_RC4_HMAC_NT: GetSystemTimeAsFileTime(&Now); EndTime.dwLowDateTime = msticket->EndTime.LowPart; EndTime.dwHighDateTime = msticket->EndTime.HighPart; FileTimeToLocalFileTime(&EndTime, &LocalEndTime); if (CompareFileTime(&Now, &LocalEndTime) >= 0) { ignore_cache = 1; } if (msticket->TicketFlags & KERB_TICKET_FLAGS_invalid) { ignore_cache = 1; } break; case KERB_ETYPE_RC4_MD4: default: // not supported ignore_cache = 1; break; } if (ignore_cache) { #ifdef DEBUG printf("MS TGT in cache is invalid/not supported; request new ticket\n"); #endif /* DEBUG */ // use domain to request Ticket Status = ConstructTicketRequest(msticket->TargetDomainName, &pTicketRequest, &requestSize); if (!LSA_SUCCESS(Status)) { ShowNTError("ConstructTicketRequest status", Status); break; } pTicketRequest->MessageType = KerbRetrieveEncodedTicketMessage; pTicketRequest->EncryptionType = KERB_ETYPE_DES_CBC_MD5; pTicketRequest->CacheOptions = KERB_RETRIEVE_TICKET_DONT_USE_CACHE; Status = LsaCallAuthenticationPackage( LogonHandle, PackageId, pTicketRequest, requestSize, &pTicketResponse, &responseSize, &SubStatus ); #ifdef DEBUG printf("Response size is %d\n", responseSize); #endif /* DEBUG */ if (!LSA_SUCCESS(Status) || !LSA_SUCCESS(SubStatus)) { if (!LSA_SUCCESS(Status)) { ShowNTError("LsaCallAuthenticationPackage", Status); } else { ShowNTError("Protocol status", SubStatus); } break; } // got the native MS Kerberos TGT msticket = &(pTicketResponse->Ticket); } /* typedef struct _KERB_RETRIEVE_TKT_RESPONSE { KERB_EXTERNAL_TICKET Ticket; } KERB_RETRIEVE_TKT_RESPONSE, *PKERB_RETRIEVE_TKT_RESPONSE; typedef struct _KERB_EXTERNAL_TICKET { PKERB_EXTERNAL_NAME ServiceName; PKERB_EXTERNAL_NAME TargetName; PKERB_EXTERNAL_NAME ClientName; UNICODE_STRING DomainName; UNICODE_STRING TargetDomainName; UNICODE_STRING AltTargetDomainName; KERB_CRYPTO_KEY SessionKey; ULONG TicketFlags; ULONG Flags; LARGE_INTEGER KeyExpirationTime; LARGE_INTEGER StartTime; LARGE_INTEGER EndTime; LARGE_INTEGER RenewUntil; LARGE_INTEGER TimeSkew; ULONG EncodedTicketSize; PUCHAR EncodedTicket; <========== Here's the good stuff } KERB_EXTERNAL_TICKET, *PKERB_EXTERNAL_TICKET; typedef struct _KERB_EXTERNAL_NAME { SHORT NameType; USHORT NameCount; UNICODE_STRING Names[ANYSIZE_ARRAY]; } KERB_EXTERNAL_NAME, *PKERB_EXTERNAL_NAME; typedef struct _LSA_UNICODE_STRING { USHORT Length; USHORT MaximumLength; PWSTR Buffer; } LSA_UNICODE_STRING, *PLSA_UNICODE_STRING; typedef LSA_UNICODE_STRING UNICODE_STRING, *PUNICODE_STRING; typedef struct KERB_CRYPTO_KEY { LONG KeyType; ULONG Length; PUCHAR Value; } KERB_CRYPTO_KEY, *PKERB_CRYPTO_KEY; */ // Build a com.sun.security.krb5.Ticket ticket = BuildTicket(env, msticket->EncodedTicket, msticket->EncodedTicketSize); if (ticket == NULL) { break; } // OK, have a Ticket, now need to get the client name clientPrincipal = BuildPrincipal(env, msticket->ClientName, msticket->TargetDomainName); // mdu if (clientPrincipal == NULL) { break; } // and the "name" of tgt targetPrincipal = BuildPrincipal(env, msticket->ServiceName, msticket->DomainName); if (targetPrincipal == NULL) { break; } // Get the encryption key encryptionKey = BuildEncryptionKey(env, &(msticket->SessionKey)); if (encryptionKey == NULL) { break; } // and the ticket flags ticketFlags = BuildTicketFlags(env, &(msticket->TicketFlags)); if (ticketFlags == NULL) { break; } // Get the start time startTime = BuildKerberosTime(env, &(msticket->StartTime)); if (startTime == NULL) { break; } /* * mdu: No point storing the eky expiration time in the auth * time field. Set it to be same as startTime. Looks like * windows does not have post-dated tickets. */ authTime = startTime; // and the end time endTime = BuildKerberosTime(env, &(msticket->EndTime)); if (endTime == NULL) { break; } // Get the renew till time renewTillTime = BuildKerberosTime(env, &(msticket->RenewUntil)); if (renewTillTime == NULL) { break; } // and now go build a KrbCreds object krbCreds = (*env)->NewObject( env, krbcredsClass, krbcredsConstructor, ticket, clientPrincipal, targetPrincipal, encryptionKey, ticketFlags, authTime, // mdu startTime, endTime, renewTillTime, //mdu hostAddresses); break; } // end of WHILE // clean up resources if (TktCacheResponse != NULL) { LsaFreeReturnBuffer(TktCacheResponse); } if (pTicketRequest) { LocalFree(pTicketRequest); } if (pTicketResponse != NULL) { LsaFreeReturnBuffer(pTicketResponse); } return krbCreds; }
static BOOL DoChangePassword( IN PGINA_CONTEXT pgContext, IN HWND hwndDlg) { WCHAR UserName[256]; WCHAR Domain[256]; WCHAR OldPassword[256]; WCHAR NewPassword1[256]; WCHAR NewPassword2[256]; PMSV1_0_CHANGEPASSWORD_REQUEST RequestBuffer = NULL; PMSV1_0_CHANGEPASSWORD_RESPONSE ResponseBuffer = NULL; ULONG RequestBufferSize; ULONG ResponseBufferSize = 0; LPWSTR Ptr; BOOL res = FALSE; NTSTATUS ProtocolStatus; NTSTATUS Status; GetDlgItemTextW(hwndDlg, IDC_CHANGEPWD_USERNAME, UserName, 256); GetDlgItemTextW(hwndDlg, IDC_CHANGEPWD_DOMAIN, Domain, 256); GetDlgItemTextW(hwndDlg, IDC_CHANGEPWD_OLDPWD, OldPassword, 256); GetDlgItemTextW(hwndDlg, IDC_CHANGEPWD_NEWPWD1, NewPassword1, 256); GetDlgItemTextW(hwndDlg, IDC_CHANGEPWD_NEWPWD2, NewPassword2, 256); /* Compare the two passwords and fail if they do not match */ if (wcscmp(NewPassword1, NewPassword2) != 0) { ResourceMessageBox(pgContext, hwndDlg, MB_OK | MB_ICONEXCLAMATION, IDS_CHANGEPWDTITLE, IDS_NONMATCHINGPASSWORDS); return FALSE; } /* Calculate the request buffer size */ RequestBufferSize = sizeof(MSV1_0_CHANGEPASSWORD_REQUEST) + ((wcslen(Domain) + 1) * sizeof(WCHAR)) + ((wcslen(UserName) + 1) * sizeof(WCHAR)) + ((wcslen(OldPassword) + 1) * sizeof(WCHAR)) + ((wcslen(NewPassword1) + 1) * sizeof(WCHAR)); /* Allocate the request buffer */ RequestBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, RequestBufferSize); if (RequestBuffer == NULL) { ERR("HeapAlloc failed\n"); return FALSE; } /* Initialize the request buffer */ RequestBuffer->MessageType = MsV1_0ChangePassword; RequestBuffer->Impersonating = TRUE; Ptr = (LPWSTR)((ULONG_PTR)RequestBuffer + sizeof(MSV1_0_CHANGEPASSWORD_REQUEST)); /* Pack the domain name */ RequestBuffer->DomainName.Length = wcslen(Domain) * sizeof(WCHAR); RequestBuffer->DomainName.MaximumLength = RequestBuffer->DomainName.Length + sizeof(WCHAR); RequestBuffer->DomainName.Buffer = Ptr; RtlCopyMemory(RequestBuffer->DomainName.Buffer, Domain, RequestBuffer->DomainName.MaximumLength); Ptr = (LPWSTR)((ULONG_PTR)Ptr + RequestBuffer->DomainName.MaximumLength); /* Pack the user name */ RequestBuffer->AccountName.Length = wcslen(UserName) * sizeof(WCHAR); RequestBuffer->AccountName.MaximumLength = RequestBuffer->AccountName.Length + sizeof(WCHAR); RequestBuffer->AccountName.Buffer = Ptr; RtlCopyMemory(RequestBuffer->AccountName.Buffer, UserName, RequestBuffer->AccountName.MaximumLength); Ptr = (LPWSTR)((ULONG_PTR)Ptr + RequestBuffer->AccountName.MaximumLength); /* Pack the old password */ RequestBuffer->OldPassword.Length = wcslen(OldPassword) * sizeof(WCHAR); RequestBuffer->OldPassword.MaximumLength = RequestBuffer->OldPassword.Length + sizeof(WCHAR); RequestBuffer->OldPassword.Buffer = Ptr; RtlCopyMemory(RequestBuffer->OldPassword.Buffer, OldPassword, RequestBuffer->OldPassword.MaximumLength); Ptr = (LPWSTR)((ULONG_PTR)Ptr + RequestBuffer->OldPassword.MaximumLength); /* Pack the new password */ RequestBuffer->NewPassword.Length = wcslen(NewPassword1) * sizeof(WCHAR); RequestBuffer->NewPassword.MaximumLength = RequestBuffer->NewPassword.Length + sizeof(WCHAR); RequestBuffer->NewPassword.Buffer = Ptr; RtlCopyMemory(RequestBuffer->NewPassword.Buffer, NewPassword1, RequestBuffer->NewPassword.MaximumLength); /* Connect to the LSA server */ if (!ConnectToLsa(pgContext)) { ERR("ConnectToLsa() failed\n"); goto done; } /* Call the authentication package */ Status = LsaCallAuthenticationPackage(pgContext->LsaHandle, pgContext->AuthenticationPackage, RequestBuffer, RequestBufferSize, (PVOID*)&ResponseBuffer, &ResponseBufferSize, &ProtocolStatus); if (!NT_SUCCESS(Status)) { ERR("LsaCallAuthenticationPackage failed (Status 0x%08lx)\n", Status); goto done; } if (!NT_SUCCESS(ProtocolStatus)) { TRACE("LsaCallAuthenticationPackage failed (ProtocolStatus 0x%08lx)\n", ProtocolStatus); goto done; } res = TRUE; ResourceMessageBox(pgContext, hwndDlg, MB_OK | MB_ICONINFORMATION, IDS_CHANGEPWDTITLE, IDS_PASSWORDCHANGED); if ((wcscmp(UserName, pgContext->UserName) == 0) && (wcscmp(Domain, pgContext->Domain) == 0) && (wcscmp(OldPassword, pgContext->Password) == 0)) { ZeroMemory(pgContext->Password, 256 * sizeof(WCHAR)); wcscpy(pgContext->Password, NewPassword1); } done: if (RequestBuffer != NULL) HeapFree(GetProcessHeap(), 0, RequestBuffer); if (ResponseBuffer != NULL) LsaFreeReturnBuffer(ResponseBuffer); return res; }
/* * Class: sun_security_krb5_Credentials * Method: acquireDefaultNativeCreds * Signature: ()Lsun/security/krb5/Credentials; */ JNIEXPORT jobject JNICALL Java_sun_security_krb5_Credentials_acquireDefaultNativeCreds( JNIEnv *env, jclass krbcredsClass) { HANDLE LogonHandle = NULL; ULONG PackageId; PKERB_RETRIEVE_TKT_REQUEST CacheRequest = NULL; PKERB_RETRIEVE_TKT_RESPONSE CacheResponse = NULL; ULONG rspSize = 0; DWORD errorCode; NTSTATUS Status,SubStatus; PUCHAR pEncodedTicket = NULL; jobject ticket, clientPrincipal, targetPrincipal, encryptionKey; jobject ticketFlags, startTime, endTime, krbCreds = NULL; jobject authTime, renewTillTime, hostAddresses = NULL; UNICODE_STRING Target = {0}; UNICODE_STRING Target2 = {0}; PDOMAIN_CONTROLLER_INFO DomainControllerInfo = NULL; WCHAR *tgtName = L"krbtgt"; WCHAR *fullName; while (TRUE) { if (krbcredsConstructor == 0) { krbcredsConstructor = (*env)->GetMethodID(env, krbcredsClass, "<init>", "(Lsun/security/krb5/internal/Ticket;Lsun/security/krb5/PrincipalName;Lsun/security/krb5/PrincipalName;Lsun/security/krb5/EncryptionKey;Lsun/security/krb5/internal/TicketFlags;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/HostAddresses;)V"); if (krbcredsConstructor == 0) { printf("Couldn't find com.ibm.security.krb5.Credentials constructor\n"); break; } } //printf("Found KrbCreds constructor\n"); // // Get the logon handle and package ID from the // Kerberos package // if(!PackageConnectLookup(&LogonHandle, &PackageId)) break; #ifdef DEBUG printf("Got handle to Kerberos package\n"); #endif /* DEBUG */ //InitUnicodeString(&Target2, L"krbtgt"); // this doesn't work 'cause I need the domain name too // OK, I don't give up that easily // Go get the current domain name errorCode = DsGetDcName( (LPCTSTR) NULL, // machine name (LPCTSTR) NULL, // DomainName, if NULL, I'm asking what it is (GUID *) NULL, // DomainGuid, (LPCTSTR) NULL, // SiteName, DS_GC_SERVER_REQUIRED, //Flags &DomainControllerInfo); if (errorCode != NO_ERROR) { printf("DsGetDcName returned %d\n", errorCode); break; } #ifdef DEBUG printf("The domain name is %S\n", DomainControllerInfo->DomainName); #endif /* DEBUG */ // Build a fully-qualified name fullName = (WCHAR *) LocalAlloc(LMEM_ZEROINIT,((wcslen(tgtName)+wcslen(L"/")+wcslen(DomainControllerInfo->DomainName)) * sizeof(WCHAR) + sizeof(UNICODE_NULL))); wcscat(fullName, tgtName); wcscat(fullName, L"/"); wcscat(fullName, DomainControllerInfo->DomainName); #ifdef DEBUG printf("The fully-qualified name is %S\n", fullName); #endif /* DEBUG */ InitUnicodeString(&Target2, fullName); CacheRequest = (PKERB_RETRIEVE_TKT_REQUEST) LocalAlloc(LMEM_ZEROINIT, Target2.Length + sizeof(KERB_RETRIEVE_TKT_REQUEST)); CacheRequest->MessageType = KerbRetrieveEncodedTicketMessage ; Target.Buffer = (LPWSTR) (CacheRequest + 1); Target.Length = Target2.Length; Target.MaximumLength = Target2.MaximumLength; CopyMemory( Target.Buffer, Target2.Buffer, Target2.Length ); CacheRequest->TargetName = Target; CacheRequest->EncryptionType = KERB_ETYPE_DES_CBC_MD5; // mdu Status = LsaCallAuthenticationPackage( LogonHandle, PackageId, CacheRequest, Target2.Length + sizeof(KERB_RETRIEVE_TKT_REQUEST), (PVOID *) &CacheResponse, &rspSize, &SubStatus ); #ifdef DEBUG printf("Response size is %d\n", rspSize); #endif /* DEBUG */ LocalFree(fullName); if (!LSA_SUCCESS(Status) || !LSA_SUCCESS(SubStatus)) { if (!LSA_SUCCESS(Status)) { ShowNTError("LsaCallAuthenticationPackage", Status); } else { ShowNTError("Protocol status", SubStatus); } break; } // Now we need to skip over most of the junk in the buffer to get to the ticket // Here's what we're looking at... /* typedef struct _KERB_RETRIEVE_TKT_RESPONSE { KERB_EXTERNAL_TICKET Ticket; } KERB_RETRIEVE_TKT_RESPONSE, *PKERB_RETRIEVE_TKT_RESPONSE; typedef struct _KERB_EXTERNAL_TICKET { PKERB_EXTERNAL_NAME ServiceName; PKERB_EXTERNAL_NAME TargetName; PKERB_EXTERNAL_NAME ClientName; UNICODE_STRING DomainName; UNICODE_STRING TargetDomainName; UNICODE_STRING AltTargetDomainName; KERB_CRYPTO_KEY SessionKey; ULONG TicketFlags; ULONG Flags; LARGE_INTEGER KeyExpirationTime; LARGE_INTEGER StartTime; LARGE_INTEGER EndTime; LARGE_INTEGER RenewUntil; LARGE_INTEGER TimeSkew; ULONG EncodedTicketSize; PUCHAR EncodedTicket; <========== Here's the good stuff } KERB_EXTERNAL_TICKET, *PKERB_EXTERNAL_TICKET; typedef struct _KERB_EXTERNAL_NAME { SHORT NameType; USHORT NameCount; UNICODE_STRING Names[ANYSIZE_ARRAY]; } KERB_EXTERNAL_NAME, *PKERB_EXTERNAL_NAME; typedef struct _LSA_UNICODE_STRING { USHORT Length; USHORT MaximumLength; PWSTR Buffer; } LSA_UNICODE_STRING, *PLSA_UNICODE_STRING; typedef LSA_UNICODE_STRING UNICODE_STRING, *PUNICODE_STRING; typedef struct KERB_CRYPTO_KEY { LONG KeyType; ULONG Length; PUCHAR Value; } KERB_CRYPTO_KEY, *PKERB_CRYPTO_KEY; */ // Build a com.ibm.security.krb5.Ticket ticket = BuildTicket(env, CacheResponse->Ticket.EncodedTicket, CacheResponse->Ticket.EncodedTicketSize); if (ticket == NULL) { break; } // OK, have a Ticket, now need to get the client name clientPrincipal = BuildClientPrincipal(env, CacheResponse->Ticket.ClientName); // mdu if (clientPrincipal == NULL) break; // and the "name" of tgt targetPrincipal = BuildTGSPrincipal(env, CacheResponse->Ticket.TargetDomainName); // mdu if (targetPrincipal == NULL) break; // Get the encryption key encryptionKey = BuildEncryptionKey(env, &(CacheResponse->Ticket.SessionKey)); if (encryptionKey == NULL) break; // and the ticket flags ticketFlags = BuildTicketFlags(env, &(CacheResponse->Ticket.TicketFlags)); if (ticketFlags == NULL) break; // Get the start time startTime = BuildKerberosTime(env, &(CacheResponse->Ticket.StartTime)); if (startTime == NULL) break; /* * mdu: No point storing the eky expiration time in the auth * time field. Set it to be same as startTime. Looks like * windows does not have post-dated tickets. */ authTime = startTime; // and the end time endTime = BuildKerberosTime(env, &(CacheResponse->Ticket.EndTime)); if (endTime == NULL) break; // Get the renew till time renewTillTime = BuildKerberosTime(env, &(CacheResponse->Ticket.RenewUntil)); if (renewTillTime == NULL) break; // and now go build a KrbCreds object krbCreds = (*env)->NewObject( env, krbcredsClass, krbcredsConstructor, ticket, clientPrincipal, targetPrincipal, encryptionKey, ticketFlags, authTime, // mdu startTime, endTime, renewTillTime, //mdu hostAddresses); break; } // end of WHILE if (DomainControllerInfo != NULL) { NetApiBufferFree(DomainControllerInfo); } if (CacheResponse != NULL) { LsaFreeReturnBuffer(CacheResponse); } if (CacheRequest) { LocalFree(CacheRequest); } return krbCreds; }