Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/windows/native/sun/security/krb5/NativeCreds.c
32288 views
/*1* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425/*26* ===========================================================================27* (C) Copyright IBM Corp. 2000 All Rights Reserved.28* ===========================================================================29*/3031#define UNICODE32#define _UNICODE3334#include <windows.h>35#include <stdio.h>36#include <string.h>37#define SECURITY_WIN3238#include <security.h>39#include <ntsecapi.h>40#include <dsgetdc.h>41#include <lmcons.h>42#include <lmapibuf.h>43#include <jni.h>44#include <winsock.h>4546#undef LSA_SUCCESS47#define LSA_SUCCESS(Status) ((Status) >= 0)48#define EXIT_FAILURE -1 // mdu4950/*51* Library-wide static references52*/5354jclass derValueClass = NULL;55jclass ticketClass = NULL;56jclass principalNameClass = NULL;57jclass encryptionKeyClass = NULL;58jclass ticketFlagsClass = NULL;59jclass kerberosTimeClass = NULL;60jclass javaLangStringClass = NULL;6162jmethodID derValueConstructor = 0;63jmethodID ticketConstructor = 0;64jmethodID principalNameConstructor = 0;65jmethodID encryptionKeyConstructor = 0;66jmethodID ticketFlagsConstructor = 0;67jmethodID kerberosTimeConstructor = 0;68jmethodID krbcredsConstructor = 0;6970/*71* Function prototypes for internal routines72*73*/74BOOL native_debug = 0;7576BOOL PackageConnectLookup(PHANDLE,PULONG);7778NTSTATUS ConstructTicketRequest(JNIEnv *env,79UNICODE_STRING DomainName,80PKERB_RETRIEVE_TKT_REQUEST *outRequest,81ULONG *outSize);8283DWORD ConcatenateUnicodeStrings(UNICODE_STRING *pTarget,84UNICODE_STRING Source1,85UNICODE_STRING Source2);8687VOID ShowNTError(LPSTR,NTSTATUS);8889VOID90InitUnicodeString(91PUNICODE_STRING DestinationString,92PCWSTR SourceString OPTIONAL93);9495jobject BuildTicket(JNIEnv *env, PUCHAR encodedTicket, ULONG encodedTicketSize);9697//mdu98jobject BuildPrincipal(JNIEnv *env, PKERB_EXTERNAL_NAME principalName,99UNICODE_STRING domainName);100101jobject BuildEncryptionKey(JNIEnv *env, PKERB_CRYPTO_KEY cryptoKey);102jobject BuildTicketFlags(JNIEnv *env, PULONG flags);103jobject BuildKerberosTime(JNIEnv *env, PLARGE_INTEGER kerbtime);104105void ThrowOOME(JNIEnv *env, const char *szMessage);106107/*108* Class: sun_security_krb5_KrbCreds109* Method: JNI_OnLoad110*/111112JNIEXPORT jint JNICALL JNI_OnLoad(113JavaVM *jvm,114void *reserved) {115116jclass cls;117JNIEnv *env;118jfieldID fldDEBUG;119120if ((*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_2)) {121return JNI_EVERSION; /* JNI version not supported */122}123124cls = (*env)->FindClass(env,"sun/security/krb5/internal/Krb5");125if (cls == NULL) {126printf("LSA: Couldn't find Krb5\n");127return JNI_ERR;128}129fldDEBUG = (*env)->GetStaticFieldID(env, cls, "DEBUG", "Z");130if (fldDEBUG == NULL) {131printf("LSA: Krb5 has no DEBUG field\n");132return JNI_ERR;133}134native_debug = (*env)->GetStaticBooleanField(env, cls, fldDEBUG);135136cls = (*env)->FindClass(env,"sun/security/krb5/internal/Ticket");137138if (cls == NULL) {139printf("LSA: Couldn't find Ticket\n");140return JNI_ERR;141}142if (native_debug) {143printf("LSA: Found Ticket\n");144}145146ticketClass = (*env)->NewWeakGlobalRef(env,cls);147if (ticketClass == NULL) {148return JNI_ERR;149}150if (native_debug) {151printf("LSA: Made NewWeakGlobalRef\n");152}153154cls = (*env)->FindClass(env, "sun/security/krb5/PrincipalName");155156if (cls == NULL) {157printf("LSA: Couldn't find PrincipalName\n");158return JNI_ERR;159}160if (native_debug) {161printf("LSA: Found PrincipalName\n");162}163164principalNameClass = (*env)->NewWeakGlobalRef(env,cls);165if (principalNameClass == NULL) {166return JNI_ERR;167}168if (native_debug) {169printf("LSA: Made NewWeakGlobalRef\n");170}171172cls = (*env)->FindClass(env,"sun/security/util/DerValue");173174if (cls == NULL) {175printf("LSA: Couldn't find DerValue\n");176return JNI_ERR;177}178if (native_debug) {179printf("LSA: Found DerValue\n");180}181182derValueClass = (*env)->NewWeakGlobalRef(env,cls);183if (derValueClass == NULL) {184return JNI_ERR;185}186if (native_debug) {187printf("LSA: Made NewWeakGlobalRef\n");188}189190cls = (*env)->FindClass(env,"sun/security/krb5/EncryptionKey");191192if (cls == NULL) {193printf("LSA: Couldn't find EncryptionKey\n");194return JNI_ERR;195}196if (native_debug) {197printf("LSA: Found EncryptionKey\n");198}199200encryptionKeyClass = (*env)->NewWeakGlobalRef(env,cls);201if (encryptionKeyClass == NULL) {202return JNI_ERR;203}204if (native_debug) {205printf("LSA: Made NewWeakGlobalRef\n");206}207208cls = (*env)->FindClass(env,"sun/security/krb5/internal/TicketFlags");209210if (cls == NULL) {211printf("LSA: Couldn't find TicketFlags\n");212return JNI_ERR;213}214if (native_debug) {215printf("LSA: Found TicketFlags\n");216}217218ticketFlagsClass = (*env)->NewWeakGlobalRef(env,cls);219if (ticketFlagsClass == NULL) {220return JNI_ERR;221}222if (native_debug) {223printf("LSA: Made NewWeakGlobalRef\n");224}225226cls = (*env)->FindClass(env,"sun/security/krb5/internal/KerberosTime");227228if (cls == NULL) {229printf("LSA: Couldn't find KerberosTime\n");230return JNI_ERR;231}232if (native_debug) {233printf("LSA: Found KerberosTime\n");234}235236kerberosTimeClass = (*env)->NewWeakGlobalRef(env,cls);237if (kerberosTimeClass == NULL) {238return JNI_ERR;239}240if (native_debug) {241printf("LSA: Made NewWeakGlobalRef\n");242}243244cls = (*env)->FindClass(env,"java/lang/String");245246if (cls == NULL) {247printf("LSA: Couldn't find String\n");248return JNI_ERR;249}250if (native_debug) {251printf("LSA: Found String\n");252}253254javaLangStringClass = (*env)->NewWeakGlobalRef(env,cls);255if (javaLangStringClass == NULL) {256return JNI_ERR;257}258if (native_debug) {259printf("LSA: Made NewWeakGlobalRef\n");260}261262derValueConstructor = (*env)->GetMethodID(env, derValueClass,263"<init>", "([B)V");264if (derValueConstructor == 0) {265printf("LSA: Couldn't find DerValue constructor\n");266return JNI_ERR;267}268if (native_debug) {269printf("LSA: Found DerValue constructor\n");270}271272ticketConstructor = (*env)->GetMethodID(env, ticketClass,273"<init>", "(Lsun/security/util/DerValue;)V");274if (ticketConstructor == 0) {275printf("LSA: Couldn't find Ticket constructor\n");276return JNI_ERR;277}278if (native_debug) {279printf("LSA: Found Ticket constructor\n");280}281282principalNameConstructor = (*env)->GetMethodID(env, principalNameClass,283"<init>", "([Ljava/lang/String;Ljava/lang/String;)V");284if (principalNameConstructor == 0) {285printf("LSA: Couldn't find PrincipalName constructor\n");286return JNI_ERR;287}288if (native_debug) {289printf("LSA: Found PrincipalName constructor\n");290}291292encryptionKeyConstructor = (*env)->GetMethodID(env, encryptionKeyClass,293"<init>", "(I[B)V");294if (encryptionKeyConstructor == 0) {295printf("LSA: Couldn't find EncryptionKey constructor\n");296return JNI_ERR;297}298if (native_debug) {299printf("LSA: Found EncryptionKey constructor\n");300}301302ticketFlagsConstructor = (*env)->GetMethodID(env, ticketFlagsClass,303"<init>", "(I[B)V");304if (ticketFlagsConstructor == 0) {305printf("LSA: Couldn't find TicketFlags constructor\n");306return JNI_ERR;307}308if (native_debug) {309printf("LSA: Found TicketFlags constructor\n");310}311312kerberosTimeConstructor = (*env)->GetMethodID(env, kerberosTimeClass,313"<init>", "(Ljava/lang/String;)V");314if (kerberosTimeConstructor == 0) {315printf("LSA: Couldn't find KerberosTime constructor\n");316return JNI_ERR;317}318if (native_debug) {319printf("LSA: Found KerberosTime constructor\n");320}321322if (native_debug) {323printf("LSA: Finished OnLoad processing\n");324}325326return JNI_VERSION_1_2;327}328329/*330* Class: sun_security_jgss_KrbCreds331* Method: JNI_OnUnload332*/333334JNIEXPORT void JNICALL JNI_OnUnload(335JavaVM *jvm,336void *reserved) {337338JNIEnv *env;339340if ((*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_2)) {341return; /* Nothing else we can do */342}343344if (ticketClass != NULL) {345(*env)->DeleteWeakGlobalRef(env,ticketClass);346}347if (derValueClass != NULL) {348(*env)->DeleteWeakGlobalRef(env,derValueClass);349}350if (principalNameClass != NULL) {351(*env)->DeleteWeakGlobalRef(env,principalNameClass);352}353if (encryptionKeyClass != NULL) {354(*env)->DeleteWeakGlobalRef(env,encryptionKeyClass);355}356if (ticketFlagsClass != NULL) {357(*env)->DeleteWeakGlobalRef(env,ticketFlagsClass);358}359if (kerberosTimeClass != NULL) {360(*env)->DeleteWeakGlobalRef(env,kerberosTimeClass);361}362if (javaLangStringClass != NULL) {363(*env)->DeleteWeakGlobalRef(env,javaLangStringClass);364}365366return;367}368369/*370* Class: sun_security_krb5_Credentials371* Method: acquireDefaultNativeCreds372* Signature: ([I])Lsun/security/krb5/Credentials;373*/374JNIEXPORT jobject JNICALL Java_sun_security_krb5_Credentials_acquireDefaultNativeCreds(375JNIEnv *env,376jclass krbcredsClass,377jintArray jetypes) {378379KERB_QUERY_TKT_CACHE_REQUEST CacheRequest;380PKERB_RETRIEVE_TKT_RESPONSE TktCacheResponse = NULL;381PKERB_RETRIEVE_TKT_REQUEST pTicketRequest = NULL;382PKERB_RETRIEVE_TKT_RESPONSE pTicketResponse = NULL;383NTSTATUS Status, SubStatus;384ULONG requestSize = 0;385ULONG responseSize = 0;386ULONG rspSize = 0;387HANDLE LogonHandle = NULL;388ULONG PackageId;389jobject ticket, clientPrincipal, targetPrincipal, encryptionKey;390jobject ticketFlags, startTime, endTime, krbCreds = NULL;391jobject authTime, renewTillTime, hostAddresses = NULL;392KERB_EXTERNAL_TICKET *msticket;393int found = 0;394FILETIME Now, EndTime;395396int i, netypes;397jint *etypes = NULL;398399while (TRUE) {400401if (krbcredsConstructor == 0) {402krbcredsConstructor = (*env)->GetMethodID(env, krbcredsClass, "<init>",403"(Lsun/security/krb5/internal/Ticket;"404"Lsun/security/krb5/PrincipalName;"405"Lsun/security/krb5/PrincipalName;"406"Lsun/security/krb5/PrincipalName;"407"Lsun/security/krb5/PrincipalName;"408"Lsun/security/krb5/EncryptionKey;"409"Lsun/security/krb5/internal/TicketFlags;"410"Lsun/security/krb5/internal/KerberosTime;"411"Lsun/security/krb5/internal/KerberosTime;"412"Lsun/security/krb5/internal/KerberosTime;"413"Lsun/security/krb5/internal/KerberosTime;"414"Lsun/security/krb5/internal/HostAddresses;)V");415if (krbcredsConstructor == 0) {416printf("LSA: Couldn't find sun.security.krb5.Credentials constructor\n");417break;418}419}420421if (native_debug) {422printf("LSA: Found KrbCreds constructor\n");423}424425//426// Get the logon handle and package ID from the427// Kerberos package428//429if (!PackageConnectLookup(&LogonHandle, &PackageId))430break;431432if (native_debug) {433printf("LSA: Got handle to Kerberos package\n");434}435436// Get the MS TGT from cache437CacheRequest.MessageType = KerbRetrieveTicketMessage;438CacheRequest.LogonId.LowPart = 0;439CacheRequest.LogonId.HighPart = 0;440441Status = LsaCallAuthenticationPackage(442LogonHandle,443PackageId,444&CacheRequest,445sizeof(CacheRequest),446&TktCacheResponse,447&rspSize,448&SubStatus449);450451if (native_debug) {452printf("LSA: Response size is %d\n", rspSize);453}454455if (!LSA_SUCCESS(Status) || !LSA_SUCCESS(SubStatus)) {456if (!LSA_SUCCESS(Status)) {457ShowNTError("LsaCallAuthenticationPackage", Status);458} else {459ShowNTError("Protocol status", SubStatus);460}461break;462}463464// got the native MS TGT465msticket = &(TktCacheResponse->Ticket);466467netypes = (*env)->GetArrayLength(env, jetypes);468etypes = (jint *) (*env)->GetIntArrayElements(env, jetypes, NULL);469470if (etypes == NULL) {471break;472}473474// check TGT validity475if (native_debug) {476printf("LSA: TICKET SessionKey KeyType is %d\n", msticket->SessionKey.KeyType);477}478479if ((msticket->TicketFlags & KERB_TICKET_FLAGS_invalid) == 0) {480GetSystemTimeAsFileTime(&Now);481EndTime.dwLowDateTime = msticket->EndTime.LowPart;482EndTime.dwHighDateTime = msticket->EndTime.HighPart;483if (CompareFileTime(&Now, &EndTime) < 0) {484for (i=0; i<netypes; i++) {485if (etypes[i] == msticket->SessionKey.KeyType) {486found = 1;487if (native_debug) {488printf("LSA: Valid etype found: %d\n", etypes[i]);489}490break;491}492}493}494}495496if (!found) {497if (native_debug) {498printf("LSA: MS TGT in cache is invalid/not supported; request new ticket\n");499}500501// use domain to request Ticket502Status = ConstructTicketRequest(env, msticket->TargetDomainName,503&pTicketRequest, &requestSize);504if (!LSA_SUCCESS(Status)) {505ShowNTError("ConstructTicketRequest status", Status);506break;507}508509pTicketRequest->MessageType = KerbRetrieveEncodedTicketMessage;510pTicketRequest->CacheOptions = KERB_RETRIEVE_TICKET_DONT_USE_CACHE;511512for (i=0; i<netypes; i++) {513pTicketRequest->EncryptionType = etypes[i];514Status = LsaCallAuthenticationPackage(515LogonHandle,516PackageId,517pTicketRequest,518requestSize,519&pTicketResponse,520&responseSize,521&SubStatus522);523524if (native_debug) {525printf("LSA: Response size is %d for %d\n", responseSize, etypes[i]);526}527528if (!LSA_SUCCESS(Status) || !LSA_SUCCESS(SubStatus)) {529if (!LSA_SUCCESS(Status)) {530ShowNTError("LsaCallAuthenticationPackage", Status);531} else {532ShowNTError("Protocol status", SubStatus);533}534continue;535}536537// got the native MS Kerberos TGT538msticket = &(pTicketResponse->Ticket);539540if (msticket->SessionKey.KeyType != etypes[i]) {541if (native_debug) {542printf("LSA: Response etype is %d for %d. Retry.\n", msticket->SessionKey.KeyType, etypes[i]);543}544continue;545}546found = 1;547break;548}549}550551if (etypes != NULL) {552(*env)->ReleaseIntArrayElements(env, jetypes, etypes, 0);553}554555/*556557typedef struct _KERB_RETRIEVE_TKT_RESPONSE {558KERB_EXTERNAL_TICKET Ticket;559} KERB_RETRIEVE_TKT_RESPONSE, *PKERB_RETRIEVE_TKT_RESPONSE;560561typedef struct _KERB_EXTERNAL_TICKET {562PKERB_EXTERNAL_NAME ServiceName;563PKERB_EXTERNAL_NAME TargetName;564PKERB_EXTERNAL_NAME ClientName;565UNICODE_STRING DomainName;566UNICODE_STRING TargetDomainName;567UNICODE_STRING AltTargetDomainName;568KERB_CRYPTO_KEY SessionKey;569ULONG TicketFlags;570ULONG Flags;571LARGE_INTEGER KeyExpirationTime;572LARGE_INTEGER StartTime;573LARGE_INTEGER EndTime;574LARGE_INTEGER RenewUntil;575LARGE_INTEGER TimeSkew;576ULONG EncodedTicketSize;577PUCHAR EncodedTicket; <========== Here's the good stuff578} KERB_EXTERNAL_TICKET, *PKERB_EXTERNAL_TICKET;579580typedef struct _KERB_EXTERNAL_NAME {581SHORT NameType;582USHORT NameCount;583UNICODE_STRING Names[ANYSIZE_ARRAY];584} KERB_EXTERNAL_NAME, *PKERB_EXTERNAL_NAME;585586typedef struct _LSA_UNICODE_STRING {587USHORT Length;588USHORT MaximumLength;589PWSTR Buffer;590} LSA_UNICODE_STRING, *PLSA_UNICODE_STRING;591592typedef LSA_UNICODE_STRING UNICODE_STRING, *PUNICODE_STRING;593594typedef struct KERB_CRYPTO_KEY {595LONG KeyType;596ULONG Length;597PUCHAR Value;598} KERB_CRYPTO_KEY, *PKERB_CRYPTO_KEY;599600*/601if (!found) {602break;603}604605// Build a com.sun.security.krb5.Ticket606ticket = BuildTicket(env, msticket->EncodedTicket,607msticket->EncodedTicketSize);608if (ticket == NULL) {609break;610}611// OK, have a Ticket, now need to get the client name612clientPrincipal = BuildPrincipal(env, msticket->ClientName,613msticket->TargetDomainName); // mdu614if (clientPrincipal == NULL) {615break;616}617618// and the "name" of tgt619targetPrincipal = BuildPrincipal(env, msticket->ServiceName,620msticket->DomainName);621if (targetPrincipal == NULL) {622break;623}624625// Get the encryption key626encryptionKey = BuildEncryptionKey(env, &(msticket->SessionKey));627if (encryptionKey == NULL) {628break;629}630631// and the ticket flags632ticketFlags = BuildTicketFlags(env, &(msticket->TicketFlags));633if (ticketFlags == NULL) {634break;635}636637// Get the start time638startTime = BuildKerberosTime(env, &(msticket->StartTime));639if (startTime == NULL) {640break;641}642643/*644* mdu: No point storing the eky expiration time in the auth645* time field. Set it to be same as startTime. Looks like646* windows does not have post-dated tickets.647*/648authTime = startTime;649650// and the end time651endTime = BuildKerberosTime(env, &(msticket->EndTime));652if (endTime == NULL) {653break;654}655656// Get the renew till time657renewTillTime = BuildKerberosTime(env, &(msticket->RenewUntil));658if (renewTillTime == NULL) {659break;660}661662// and now go build a KrbCreds object663krbCreds = (*env)->NewObject(664env,665krbcredsClass,666krbcredsConstructor,667ticket,668clientPrincipal,669NULL,670targetPrincipal,671NULL,672encryptionKey,673ticketFlags,674authTime, // mdu675startTime,676endTime,677renewTillTime, //mdu678hostAddresses);679680break;681} // end of WHILE. This WHILE will never loop.682683// clean up resources684if (TktCacheResponse != NULL) {685LsaFreeReturnBuffer(TktCacheResponse);686}687if (pTicketRequest) {688LocalFree(pTicketRequest);689}690if (pTicketResponse != NULL) {691LsaFreeReturnBuffer(pTicketResponse);692}693694return krbCreds;695}696697static NTSTATUS698ConstructTicketRequest(JNIEnv *env, UNICODE_STRING DomainName,699PKERB_RETRIEVE_TKT_REQUEST *outRequest, ULONG *outSize)700{701NTSTATUS Status;702UNICODE_STRING TargetPrefix;703USHORT TargetSize;704ULONG RequestSize;705ULONG Length;706PKERB_RETRIEVE_TKT_REQUEST pTicketRequest = NULL;707708*outRequest = NULL;709*outSize = 0;710711//712// Set up the "krbtgt/" target prefix into a UNICODE_STRING so we713// can easily concatenate it later.714//715716TargetPrefix.Buffer = L"krbtgt/";717Length = (ULONG)wcslen(TargetPrefix.Buffer) * sizeof(WCHAR);718TargetPrefix.Length = (USHORT)Length;719TargetPrefix.MaximumLength = TargetPrefix.Length;720721//722// We will need to concatenate the "krbtgt/" prefix and the723// Logon Session's DnsDomainName into our request's target name.724//725// Therefore, first compute the necessary buffer size for that.726//727// Note that we might theoretically have integer overflow.728//729730TargetSize = TargetPrefix.Length + DomainName.Length;731732//733// The ticket request buffer needs to be a single buffer. That buffer734// needs to include the buffer for the target name.735//736737RequestSize = sizeof (*pTicketRequest) + TargetSize;738739//740// Allocate the request buffer and make sure it's zero-filled.741//742743pTicketRequest = (PKERB_RETRIEVE_TKT_REQUEST)744LocalAlloc(LMEM_ZEROINIT, RequestSize);745if (!pTicketRequest) {746ThrowOOME(env, "Can't allocate memory for ticket");747return GetLastError();748}749750//751// Concatenate the target prefix with the previous response's752// target domain.753//754755pTicketRequest->TargetName.Length = 0;756pTicketRequest->TargetName.MaximumLength = TargetSize;757pTicketRequest->TargetName.Buffer = (PWSTR) (pTicketRequest + 1);758Status = ConcatenateUnicodeStrings(&(pTicketRequest->TargetName),759TargetPrefix,760DomainName);761*outRequest = pTicketRequest;762*outSize = RequestSize;763return Status;764}765766DWORD767ConcatenateUnicodeStrings(768UNICODE_STRING *pTarget,769UNICODE_STRING Source1,770UNICODE_STRING Source2771)772{773//774// The buffers for Source1 and Source2 cannot overlap pTarget's775// buffer. Source1.Length + Source2.Length must be <= 0xFFFF,776// otherwise we overflow...777//778779USHORT TotalSize = Source1.Length + Source2.Length;780PBYTE buffer = (PBYTE) pTarget->Buffer;781782if (TotalSize > pTarget->MaximumLength)783return ERROR_INSUFFICIENT_BUFFER;784785pTarget->Length = TotalSize;786memcpy(buffer, Source1.Buffer, Source1.Length);787memcpy(buffer + Source1.Length, Source2.Buffer, Source2.Length);788return ERROR_SUCCESS;789}790791BOOL792PackageConnectLookup(793HANDLE *pLogonHandle,794ULONG *pPackageId795)796{797LSA_STRING Name;798NTSTATUS Status;799800Status = LsaConnectUntrusted(801pLogonHandle802);803804if (!LSA_SUCCESS(Status))805{806ShowNTError("LsaConnectUntrusted", Status);807return FALSE;808}809810Name.Buffer = MICROSOFT_KERBEROS_NAME_A;811Name.Length = (USHORT)strlen(Name.Buffer);812Name.MaximumLength = Name.Length + 1;813814Status = LsaLookupAuthenticationPackage(815*pLogonHandle,816&Name,817pPackageId818);819820if (!LSA_SUCCESS(Status))821{822ShowNTError("LsaLookupAuthenticationPackage", Status);823return FALSE;824}825826return TRUE;827828}829830VOID831ShowLastError(832LPSTR szAPI,833DWORD dwError834)835{836#define MAX_MSG_SIZE 256837838static WCHAR szMsgBuf[MAX_MSG_SIZE];839DWORD dwRes;840841if (native_debug) {842printf("LSA: Error calling function %s: %lu\n", szAPI, dwError);843}844845dwRes = FormatMessage (846FORMAT_MESSAGE_FROM_SYSTEM,847NULL,848dwError,8490,850szMsgBuf,851MAX_MSG_SIZE,852NULL);853if (native_debug) {854if (0 == dwRes) {855printf("LSA: FormatMessage failed with %d\n", GetLastError());856// ExitProcess(EXIT_FAILURE);857} else {858printf("LSA: %S",szMsgBuf);859}860}861}862863VOID864ShowNTError(865LPSTR szAPI,866NTSTATUS Status867)868{869//870// Convert the NTSTATUS to Winerror. Then call ShowLastError().871//872ShowLastError(szAPI, LsaNtStatusToWinError(Status));873}874875VOID876InitUnicodeString(877PUNICODE_STRING DestinationString,878PCWSTR SourceString OPTIONAL879)880{881ULONG Length;882883DestinationString->Buffer = (PWSTR)SourceString;884if (SourceString != NULL) {885Length = (ULONG)wcslen( SourceString ) * sizeof( WCHAR );886DestinationString->Length = (USHORT)Length;887DestinationString->MaximumLength = (USHORT)(Length + sizeof(UNICODE_NULL));888}889else {890DestinationString->MaximumLength = 0;891DestinationString->Length = 0;892}893}894895jobject BuildTicket(JNIEnv *env, PUCHAR encodedTicket, ULONG encodedTicketSize) {896897/* To build a Ticket, we first need to build a DerValue out of the EncodedTicket.898* But before we can do that, we need to make a byte array out of the ET.899*/900901jobject derValue, ticket;902jbyteArray ary;903904ary = (*env)->NewByteArray(env,encodedTicketSize);905if (ary == NULL) {906return (jobject) NULL;907}908909(*env)->SetByteArrayRegion(env, ary, (jsize) 0, encodedTicketSize,910(jbyte *)encodedTicket);911if ((*env)->ExceptionOccurred(env)) {912(*env)->DeleteLocalRef(env, ary);913return (jobject) NULL;914}915916derValue = (*env)->NewObject(env, derValueClass, derValueConstructor, ary);917if ((*env)->ExceptionOccurred(env)) {918(*env)->DeleteLocalRef(env, ary);919return (jobject) NULL;920}921922(*env)->DeleteLocalRef(env, ary);923ticket = (*env)->NewObject(env, ticketClass, ticketConstructor, derValue);924if ((*env)->ExceptionOccurred(env)) {925(*env)->DeleteLocalRef(env, derValue);926return (jobject) NULL;927}928(*env)->DeleteLocalRef(env, derValue);929return ticket;930}931932// mdu933jobject BuildPrincipal(JNIEnv *env, PKERB_EXTERNAL_NAME principalName,934UNICODE_STRING domainName) {935936/*937* To build the Principal, we need to get the names out of938* this goofy MS structure939*/940jobject principal = NULL;941jobject realmStr = NULL;942jobjectArray stringArray;943jstring tempString;944int nameCount,i;945PUNICODE_STRING scanner;946WCHAR *realm;947ULONG realmLen;948949realm = (WCHAR *) LocalAlloc(LMEM_ZEROINIT,950((domainName.Length)*sizeof(WCHAR) + sizeof(UNICODE_NULL)));951if (realm == NULL) {952ThrowOOME(env, "Can't allocate memory for realm");953return NULL;954}955wcsncpy(realm, domainName.Buffer, domainName.Length/sizeof(WCHAR));956957if (native_debug) {958printf("LSA: Principal domain is %S\n", realm);959printf("LSA: Name type is %x\n", principalName->NameType);960printf("LSA: Name count is %x\n", principalName->NameCount);961}962963nameCount = principalName->NameCount;964stringArray = (*env)->NewObjectArray(env, nameCount,965javaLangStringClass, NULL);966if (stringArray == NULL) {967if (native_debug) {968printf("LSA: Can't allocate String array for Principal\n");969}970goto cleanup;971}972973for (i=0; i<nameCount; i++) {974// get the principal name975scanner = &(principalName->Names[i]);976977// OK, got a Char array, so construct a String978tempString = (*env)->NewString(env, (const jchar*)scanner->Buffer,979scanner->Length/sizeof(WCHAR));980981if (tempString == NULL) {982goto cleanup;983}984985// Set the String into the StringArray986(*env)->SetObjectArrayElement(env, stringArray, i, tempString);987988if ((*env)->ExceptionCheck(env)) {989goto cleanup;990}991992// Do I have to worry about storage reclamation here?993}994// now set the realm in the principal995realmLen = (ULONG)wcslen((PWCHAR)realm);996realmStr = (*env)->NewString(env, (PWCHAR)realm, (USHORT)realmLen);997998if (realmStr == NULL) {999goto cleanup;1000}10011002principal = (*env)->NewObject(env, principalNameClass,1003principalNameConstructor, stringArray, realmStr);10041005cleanup:1006// free local resources1007LocalFree(realm);10081009return principal;1010}10111012jobject BuildEncryptionKey(JNIEnv *env, PKERB_CRYPTO_KEY cryptoKey) {1013// First, need to build a byte array1014jbyteArray ary;1015jobject encryptionKey = NULL;1016unsigned int i;10171018for (i=0; i<cryptoKey->Length; i++) {1019if (cryptoKey->Value[i]) break;1020}1021if (i == cryptoKey->Length) {1022if (native_debug) {1023printf("LSA: Session key all zero. Stop.\n");1024}1025return NULL;1026}10271028ary = (*env)->NewByteArray(env,cryptoKey->Length);1029if (ary == NULL) {1030return (jobject) NULL;1031}1032(*env)->SetByteArrayRegion(env, ary, (jsize) 0, cryptoKey->Length,1033(jbyte *)cryptoKey->Value);1034if ((*env)->ExceptionOccurred(env)) {1035(*env)->DeleteLocalRef(env, ary);1036} else {1037encryptionKey = (*env)->NewObject(env, encryptionKeyClass,1038encryptionKeyConstructor, cryptoKey->KeyType, ary);1039}10401041return encryptionKey;1042}10431044jobject BuildTicketFlags(JNIEnv *env, PULONG flags) {1045jobject ticketFlags = NULL;1046jbyteArray ary;1047/*1048* mdu: Convert the bytes to nework byte order before copying1049* them to a Java byte array.1050*/1051ULONG nlflags = htonl(*flags);10521053ary = (*env)->NewByteArray(env, sizeof(*flags));1054if (ary == NULL) {1055return (jobject) NULL;1056}1057(*env)->SetByteArrayRegion(env, ary, (jsize) 0, sizeof(*flags),1058(jbyte *)&nlflags);1059if ((*env)->ExceptionOccurred(env)) {1060(*env)->DeleteLocalRef(env, ary);1061} else {1062ticketFlags = (*env)->NewObject(env, ticketFlagsClass,1063ticketFlagsConstructor, sizeof(*flags)*8, ary);1064}10651066return ticketFlags;1067}10681069jobject BuildKerberosTime(JNIEnv *env, PLARGE_INTEGER kerbtime) {1070jobject kerberosTime = NULL;1071jstring stringTime = NULL;1072SYSTEMTIME systemTime;1073WCHAR timeString[16];1074WCHAR month[3];1075WCHAR day[3];1076WCHAR hour[3];1077WCHAR minute[3];1078WCHAR second[3];10791080if (FileTimeToSystemTime((FILETIME *)kerbtime, &systemTime)) {1081// XXX Cannot use %02.2ld, because the leading 0 is ignored for integers.1082// So, print them to strings, and then print them to the master string with a1083// format pattern that makes it two digits and prefix with a 0 if necessary.1084swprintf( (wchar_t *)month, 3, L"%2.2d", systemTime.wMonth);1085swprintf( (wchar_t *)day, 3, L"%2.2d", systemTime.wDay);1086swprintf( (wchar_t *)hour, 3, L"%2.2d", systemTime.wHour);1087swprintf( (wchar_t *)minute, 3, L"%2.2d", systemTime.wMinute);1088swprintf( (wchar_t *)second, 3, L"%2.2d", systemTime.wSecond);1089swprintf( (wchar_t *)timeString, 16,1090L"%ld%02.2s%02.2s%02.2s%02.2s%02.2sZ",1091systemTime.wYear,1092month,1093day,1094hour,1095minute,1096second );1097if (native_debug) {1098printf("LSA: %S\n", (wchar_t *)timeString);1099}1100stringTime = (*env)->NewString(env, timeString,1101(sizeof(timeString)/sizeof(WCHAR))-1);1102if (stringTime != NULL) { // everything's OK so far1103kerberosTime = (*env)->NewObject(env, kerberosTimeClass,1104kerberosTimeConstructor, stringTime);1105}1106}1107return kerberosTime;1108}11091110void ThrowOOME(JNIEnv *env, const char *szMessage) {1111jclass exceptionClazz = (*env)->FindClass(env, "java/lang/OutOfMemoryError");1112if (exceptionClazz != NULL) {1113(*env)->ThrowNew(env, exceptionClazz, szMessage);1114}1115}111611171118