Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/windows/native/sun/security/krb5/NativeCreds.c
32288 views
1
/*
2
* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
/*
27
* ===========================================================================
28
* (C) Copyright IBM Corp. 2000 All Rights Reserved.
29
* ===========================================================================
30
*/
31
32
#define UNICODE
33
#define _UNICODE
34
35
#include <windows.h>
36
#include <stdio.h>
37
#include <string.h>
38
#define SECURITY_WIN32
39
#include <security.h>
40
#include <ntsecapi.h>
41
#include <dsgetdc.h>
42
#include <lmcons.h>
43
#include <lmapibuf.h>
44
#include <jni.h>
45
#include <winsock.h>
46
47
#undef LSA_SUCCESS
48
#define LSA_SUCCESS(Status) ((Status) >= 0)
49
#define EXIT_FAILURE -1 // mdu
50
51
/*
52
* Library-wide static references
53
*/
54
55
jclass derValueClass = NULL;
56
jclass ticketClass = NULL;
57
jclass principalNameClass = NULL;
58
jclass encryptionKeyClass = NULL;
59
jclass ticketFlagsClass = NULL;
60
jclass kerberosTimeClass = NULL;
61
jclass javaLangStringClass = NULL;
62
63
jmethodID derValueConstructor = 0;
64
jmethodID ticketConstructor = 0;
65
jmethodID principalNameConstructor = 0;
66
jmethodID encryptionKeyConstructor = 0;
67
jmethodID ticketFlagsConstructor = 0;
68
jmethodID kerberosTimeConstructor = 0;
69
jmethodID krbcredsConstructor = 0;
70
71
/*
72
* Function prototypes for internal routines
73
*
74
*/
75
BOOL native_debug = 0;
76
77
BOOL PackageConnectLookup(PHANDLE,PULONG);
78
79
NTSTATUS ConstructTicketRequest(JNIEnv *env,
80
UNICODE_STRING DomainName,
81
PKERB_RETRIEVE_TKT_REQUEST *outRequest,
82
ULONG *outSize);
83
84
DWORD ConcatenateUnicodeStrings(UNICODE_STRING *pTarget,
85
UNICODE_STRING Source1,
86
UNICODE_STRING Source2);
87
88
VOID ShowNTError(LPSTR,NTSTATUS);
89
90
VOID
91
InitUnicodeString(
92
PUNICODE_STRING DestinationString,
93
PCWSTR SourceString OPTIONAL
94
);
95
96
jobject BuildTicket(JNIEnv *env, PUCHAR encodedTicket, ULONG encodedTicketSize);
97
98
//mdu
99
jobject BuildPrincipal(JNIEnv *env, PKERB_EXTERNAL_NAME principalName,
100
UNICODE_STRING domainName);
101
102
jobject BuildEncryptionKey(JNIEnv *env, PKERB_CRYPTO_KEY cryptoKey);
103
jobject BuildTicketFlags(JNIEnv *env, PULONG flags);
104
jobject BuildKerberosTime(JNIEnv *env, PLARGE_INTEGER kerbtime);
105
106
void ThrowOOME(JNIEnv *env, const char *szMessage);
107
108
/*
109
* Class: sun_security_krb5_KrbCreds
110
* Method: JNI_OnLoad
111
*/
112
113
JNIEXPORT jint JNICALL JNI_OnLoad(
114
JavaVM *jvm,
115
void *reserved) {
116
117
jclass cls;
118
JNIEnv *env;
119
jfieldID fldDEBUG;
120
121
if ((*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_2)) {
122
return JNI_EVERSION; /* JNI version not supported */
123
}
124
125
cls = (*env)->FindClass(env,"sun/security/krb5/internal/Krb5");
126
if (cls == NULL) {
127
printf("LSA: Couldn't find Krb5\n");
128
return JNI_ERR;
129
}
130
fldDEBUG = (*env)->GetStaticFieldID(env, cls, "DEBUG", "Z");
131
if (fldDEBUG == NULL) {
132
printf("LSA: Krb5 has no DEBUG field\n");
133
return JNI_ERR;
134
}
135
native_debug = (*env)->GetStaticBooleanField(env, cls, fldDEBUG);
136
137
cls = (*env)->FindClass(env,"sun/security/krb5/internal/Ticket");
138
139
if (cls == NULL) {
140
printf("LSA: Couldn't find Ticket\n");
141
return JNI_ERR;
142
}
143
if (native_debug) {
144
printf("LSA: Found Ticket\n");
145
}
146
147
ticketClass = (*env)->NewWeakGlobalRef(env,cls);
148
if (ticketClass == NULL) {
149
return JNI_ERR;
150
}
151
if (native_debug) {
152
printf("LSA: Made NewWeakGlobalRef\n");
153
}
154
155
cls = (*env)->FindClass(env, "sun/security/krb5/PrincipalName");
156
157
if (cls == NULL) {
158
printf("LSA: Couldn't find PrincipalName\n");
159
return JNI_ERR;
160
}
161
if (native_debug) {
162
printf("LSA: Found PrincipalName\n");
163
}
164
165
principalNameClass = (*env)->NewWeakGlobalRef(env,cls);
166
if (principalNameClass == NULL) {
167
return JNI_ERR;
168
}
169
if (native_debug) {
170
printf("LSA: Made NewWeakGlobalRef\n");
171
}
172
173
cls = (*env)->FindClass(env,"sun/security/util/DerValue");
174
175
if (cls == NULL) {
176
printf("LSA: Couldn't find DerValue\n");
177
return JNI_ERR;
178
}
179
if (native_debug) {
180
printf("LSA: Found DerValue\n");
181
}
182
183
derValueClass = (*env)->NewWeakGlobalRef(env,cls);
184
if (derValueClass == NULL) {
185
return JNI_ERR;
186
}
187
if (native_debug) {
188
printf("LSA: Made NewWeakGlobalRef\n");
189
}
190
191
cls = (*env)->FindClass(env,"sun/security/krb5/EncryptionKey");
192
193
if (cls == NULL) {
194
printf("LSA: Couldn't find EncryptionKey\n");
195
return JNI_ERR;
196
}
197
if (native_debug) {
198
printf("LSA: Found EncryptionKey\n");
199
}
200
201
encryptionKeyClass = (*env)->NewWeakGlobalRef(env,cls);
202
if (encryptionKeyClass == NULL) {
203
return JNI_ERR;
204
}
205
if (native_debug) {
206
printf("LSA: Made NewWeakGlobalRef\n");
207
}
208
209
cls = (*env)->FindClass(env,"sun/security/krb5/internal/TicketFlags");
210
211
if (cls == NULL) {
212
printf("LSA: Couldn't find TicketFlags\n");
213
return JNI_ERR;
214
}
215
if (native_debug) {
216
printf("LSA: Found TicketFlags\n");
217
}
218
219
ticketFlagsClass = (*env)->NewWeakGlobalRef(env,cls);
220
if (ticketFlagsClass == NULL) {
221
return JNI_ERR;
222
}
223
if (native_debug) {
224
printf("LSA: Made NewWeakGlobalRef\n");
225
}
226
227
cls = (*env)->FindClass(env,"sun/security/krb5/internal/KerberosTime");
228
229
if (cls == NULL) {
230
printf("LSA: Couldn't find KerberosTime\n");
231
return JNI_ERR;
232
}
233
if (native_debug) {
234
printf("LSA: Found KerberosTime\n");
235
}
236
237
kerberosTimeClass = (*env)->NewWeakGlobalRef(env,cls);
238
if (kerberosTimeClass == NULL) {
239
return JNI_ERR;
240
}
241
if (native_debug) {
242
printf("LSA: Made NewWeakGlobalRef\n");
243
}
244
245
cls = (*env)->FindClass(env,"java/lang/String");
246
247
if (cls == NULL) {
248
printf("LSA: Couldn't find String\n");
249
return JNI_ERR;
250
}
251
if (native_debug) {
252
printf("LSA: Found String\n");
253
}
254
255
javaLangStringClass = (*env)->NewWeakGlobalRef(env,cls);
256
if (javaLangStringClass == NULL) {
257
return JNI_ERR;
258
}
259
if (native_debug) {
260
printf("LSA: Made NewWeakGlobalRef\n");
261
}
262
263
derValueConstructor = (*env)->GetMethodID(env, derValueClass,
264
"<init>", "([B)V");
265
if (derValueConstructor == 0) {
266
printf("LSA: Couldn't find DerValue constructor\n");
267
return JNI_ERR;
268
}
269
if (native_debug) {
270
printf("LSA: Found DerValue constructor\n");
271
}
272
273
ticketConstructor = (*env)->GetMethodID(env, ticketClass,
274
"<init>", "(Lsun/security/util/DerValue;)V");
275
if (ticketConstructor == 0) {
276
printf("LSA: Couldn't find Ticket constructor\n");
277
return JNI_ERR;
278
}
279
if (native_debug) {
280
printf("LSA: Found Ticket constructor\n");
281
}
282
283
principalNameConstructor = (*env)->GetMethodID(env, principalNameClass,
284
"<init>", "([Ljava/lang/String;Ljava/lang/String;)V");
285
if (principalNameConstructor == 0) {
286
printf("LSA: Couldn't find PrincipalName constructor\n");
287
return JNI_ERR;
288
}
289
if (native_debug) {
290
printf("LSA: Found PrincipalName constructor\n");
291
}
292
293
encryptionKeyConstructor = (*env)->GetMethodID(env, encryptionKeyClass,
294
"<init>", "(I[B)V");
295
if (encryptionKeyConstructor == 0) {
296
printf("LSA: Couldn't find EncryptionKey constructor\n");
297
return JNI_ERR;
298
}
299
if (native_debug) {
300
printf("LSA: Found EncryptionKey constructor\n");
301
}
302
303
ticketFlagsConstructor = (*env)->GetMethodID(env, ticketFlagsClass,
304
"<init>", "(I[B)V");
305
if (ticketFlagsConstructor == 0) {
306
printf("LSA: Couldn't find TicketFlags constructor\n");
307
return JNI_ERR;
308
}
309
if (native_debug) {
310
printf("LSA: Found TicketFlags constructor\n");
311
}
312
313
kerberosTimeConstructor = (*env)->GetMethodID(env, kerberosTimeClass,
314
"<init>", "(Ljava/lang/String;)V");
315
if (kerberosTimeConstructor == 0) {
316
printf("LSA: Couldn't find KerberosTime constructor\n");
317
return JNI_ERR;
318
}
319
if (native_debug) {
320
printf("LSA: Found KerberosTime constructor\n");
321
}
322
323
if (native_debug) {
324
printf("LSA: Finished OnLoad processing\n");
325
}
326
327
return JNI_VERSION_1_2;
328
}
329
330
/*
331
* Class: sun_security_jgss_KrbCreds
332
* Method: JNI_OnUnload
333
*/
334
335
JNIEXPORT void JNICALL JNI_OnUnload(
336
JavaVM *jvm,
337
void *reserved) {
338
339
JNIEnv *env;
340
341
if ((*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_2)) {
342
return; /* Nothing else we can do */
343
}
344
345
if (ticketClass != NULL) {
346
(*env)->DeleteWeakGlobalRef(env,ticketClass);
347
}
348
if (derValueClass != NULL) {
349
(*env)->DeleteWeakGlobalRef(env,derValueClass);
350
}
351
if (principalNameClass != NULL) {
352
(*env)->DeleteWeakGlobalRef(env,principalNameClass);
353
}
354
if (encryptionKeyClass != NULL) {
355
(*env)->DeleteWeakGlobalRef(env,encryptionKeyClass);
356
}
357
if (ticketFlagsClass != NULL) {
358
(*env)->DeleteWeakGlobalRef(env,ticketFlagsClass);
359
}
360
if (kerberosTimeClass != NULL) {
361
(*env)->DeleteWeakGlobalRef(env,kerberosTimeClass);
362
}
363
if (javaLangStringClass != NULL) {
364
(*env)->DeleteWeakGlobalRef(env,javaLangStringClass);
365
}
366
367
return;
368
}
369
370
/*
371
* Class: sun_security_krb5_Credentials
372
* Method: acquireDefaultNativeCreds
373
* Signature: ([I])Lsun/security/krb5/Credentials;
374
*/
375
JNIEXPORT jobject JNICALL Java_sun_security_krb5_Credentials_acquireDefaultNativeCreds(
376
JNIEnv *env,
377
jclass krbcredsClass,
378
jintArray jetypes) {
379
380
KERB_QUERY_TKT_CACHE_REQUEST CacheRequest;
381
PKERB_RETRIEVE_TKT_RESPONSE TktCacheResponse = NULL;
382
PKERB_RETRIEVE_TKT_REQUEST pTicketRequest = NULL;
383
PKERB_RETRIEVE_TKT_RESPONSE pTicketResponse = NULL;
384
NTSTATUS Status, SubStatus;
385
ULONG requestSize = 0;
386
ULONG responseSize = 0;
387
ULONG rspSize = 0;
388
HANDLE LogonHandle = NULL;
389
ULONG PackageId;
390
jobject ticket, clientPrincipal, targetPrincipal, encryptionKey;
391
jobject ticketFlags, startTime, endTime, krbCreds = NULL;
392
jobject authTime, renewTillTime, hostAddresses = NULL;
393
KERB_EXTERNAL_TICKET *msticket;
394
int found = 0;
395
FILETIME Now, EndTime;
396
397
int i, netypes;
398
jint *etypes = NULL;
399
400
while (TRUE) {
401
402
if (krbcredsConstructor == 0) {
403
krbcredsConstructor = (*env)->GetMethodID(env, krbcredsClass, "<init>",
404
"(Lsun/security/krb5/internal/Ticket;"
405
"Lsun/security/krb5/PrincipalName;"
406
"Lsun/security/krb5/PrincipalName;"
407
"Lsun/security/krb5/PrincipalName;"
408
"Lsun/security/krb5/PrincipalName;"
409
"Lsun/security/krb5/EncryptionKey;"
410
"Lsun/security/krb5/internal/TicketFlags;"
411
"Lsun/security/krb5/internal/KerberosTime;"
412
"Lsun/security/krb5/internal/KerberosTime;"
413
"Lsun/security/krb5/internal/KerberosTime;"
414
"Lsun/security/krb5/internal/KerberosTime;"
415
"Lsun/security/krb5/internal/HostAddresses;)V");
416
if (krbcredsConstructor == 0) {
417
printf("LSA: Couldn't find sun.security.krb5.Credentials constructor\n");
418
break;
419
}
420
}
421
422
if (native_debug) {
423
printf("LSA: Found KrbCreds constructor\n");
424
}
425
426
//
427
// Get the logon handle and package ID from the
428
// Kerberos package
429
//
430
if (!PackageConnectLookup(&LogonHandle, &PackageId))
431
break;
432
433
if (native_debug) {
434
printf("LSA: Got handle to Kerberos package\n");
435
}
436
437
// Get the MS TGT from cache
438
CacheRequest.MessageType = KerbRetrieveTicketMessage;
439
CacheRequest.LogonId.LowPart = 0;
440
CacheRequest.LogonId.HighPart = 0;
441
442
Status = LsaCallAuthenticationPackage(
443
LogonHandle,
444
PackageId,
445
&CacheRequest,
446
sizeof(CacheRequest),
447
&TktCacheResponse,
448
&rspSize,
449
&SubStatus
450
);
451
452
if (native_debug) {
453
printf("LSA: Response size is %d\n", rspSize);
454
}
455
456
if (!LSA_SUCCESS(Status) || !LSA_SUCCESS(SubStatus)) {
457
if (!LSA_SUCCESS(Status)) {
458
ShowNTError("LsaCallAuthenticationPackage", Status);
459
} else {
460
ShowNTError("Protocol status", SubStatus);
461
}
462
break;
463
}
464
465
// got the native MS TGT
466
msticket = &(TktCacheResponse->Ticket);
467
468
netypes = (*env)->GetArrayLength(env, jetypes);
469
etypes = (jint *) (*env)->GetIntArrayElements(env, jetypes, NULL);
470
471
if (etypes == NULL) {
472
break;
473
}
474
475
// check TGT validity
476
if (native_debug) {
477
printf("LSA: TICKET SessionKey KeyType is %d\n", msticket->SessionKey.KeyType);
478
}
479
480
if ((msticket->TicketFlags & KERB_TICKET_FLAGS_invalid) == 0) {
481
GetSystemTimeAsFileTime(&Now);
482
EndTime.dwLowDateTime = msticket->EndTime.LowPart;
483
EndTime.dwHighDateTime = msticket->EndTime.HighPart;
484
if (CompareFileTime(&Now, &EndTime) < 0) {
485
for (i=0; i<netypes; i++) {
486
if (etypes[i] == msticket->SessionKey.KeyType) {
487
found = 1;
488
if (native_debug) {
489
printf("LSA: Valid etype found: %d\n", etypes[i]);
490
}
491
break;
492
}
493
}
494
}
495
}
496
497
if (!found) {
498
if (native_debug) {
499
printf("LSA: MS TGT in cache is invalid/not supported; request new ticket\n");
500
}
501
502
// use domain to request Ticket
503
Status = ConstructTicketRequest(env, msticket->TargetDomainName,
504
&pTicketRequest, &requestSize);
505
if (!LSA_SUCCESS(Status)) {
506
ShowNTError("ConstructTicketRequest status", Status);
507
break;
508
}
509
510
pTicketRequest->MessageType = KerbRetrieveEncodedTicketMessage;
511
pTicketRequest->CacheOptions = KERB_RETRIEVE_TICKET_DONT_USE_CACHE;
512
513
for (i=0; i<netypes; i++) {
514
pTicketRequest->EncryptionType = etypes[i];
515
Status = LsaCallAuthenticationPackage(
516
LogonHandle,
517
PackageId,
518
pTicketRequest,
519
requestSize,
520
&pTicketResponse,
521
&responseSize,
522
&SubStatus
523
);
524
525
if (native_debug) {
526
printf("LSA: Response size is %d for %d\n", responseSize, etypes[i]);
527
}
528
529
if (!LSA_SUCCESS(Status) || !LSA_SUCCESS(SubStatus)) {
530
if (!LSA_SUCCESS(Status)) {
531
ShowNTError("LsaCallAuthenticationPackage", Status);
532
} else {
533
ShowNTError("Protocol status", SubStatus);
534
}
535
continue;
536
}
537
538
// got the native MS Kerberos TGT
539
msticket = &(pTicketResponse->Ticket);
540
541
if (msticket->SessionKey.KeyType != etypes[i]) {
542
if (native_debug) {
543
printf("LSA: Response etype is %d for %d. Retry.\n", msticket->SessionKey.KeyType, etypes[i]);
544
}
545
continue;
546
}
547
found = 1;
548
break;
549
}
550
}
551
552
if (etypes != NULL) {
553
(*env)->ReleaseIntArrayElements(env, jetypes, etypes, 0);
554
}
555
556
/*
557
558
typedef struct _KERB_RETRIEVE_TKT_RESPONSE {
559
KERB_EXTERNAL_TICKET Ticket;
560
} KERB_RETRIEVE_TKT_RESPONSE, *PKERB_RETRIEVE_TKT_RESPONSE;
561
562
typedef struct _KERB_EXTERNAL_TICKET {
563
PKERB_EXTERNAL_NAME ServiceName;
564
PKERB_EXTERNAL_NAME TargetName;
565
PKERB_EXTERNAL_NAME ClientName;
566
UNICODE_STRING DomainName;
567
UNICODE_STRING TargetDomainName;
568
UNICODE_STRING AltTargetDomainName;
569
KERB_CRYPTO_KEY SessionKey;
570
ULONG TicketFlags;
571
ULONG Flags;
572
LARGE_INTEGER KeyExpirationTime;
573
LARGE_INTEGER StartTime;
574
LARGE_INTEGER EndTime;
575
LARGE_INTEGER RenewUntil;
576
LARGE_INTEGER TimeSkew;
577
ULONG EncodedTicketSize;
578
PUCHAR EncodedTicket; <========== Here's the good stuff
579
} KERB_EXTERNAL_TICKET, *PKERB_EXTERNAL_TICKET;
580
581
typedef struct _KERB_EXTERNAL_NAME {
582
SHORT NameType;
583
USHORT NameCount;
584
UNICODE_STRING Names[ANYSIZE_ARRAY];
585
} KERB_EXTERNAL_NAME, *PKERB_EXTERNAL_NAME;
586
587
typedef struct _LSA_UNICODE_STRING {
588
USHORT Length;
589
USHORT MaximumLength;
590
PWSTR Buffer;
591
} LSA_UNICODE_STRING, *PLSA_UNICODE_STRING;
592
593
typedef LSA_UNICODE_STRING UNICODE_STRING, *PUNICODE_STRING;
594
595
typedef struct KERB_CRYPTO_KEY {
596
LONG KeyType;
597
ULONG Length;
598
PUCHAR Value;
599
} KERB_CRYPTO_KEY, *PKERB_CRYPTO_KEY;
600
601
*/
602
if (!found) {
603
break;
604
}
605
606
// Build a com.sun.security.krb5.Ticket
607
ticket = BuildTicket(env, msticket->EncodedTicket,
608
msticket->EncodedTicketSize);
609
if (ticket == NULL) {
610
break;
611
}
612
// OK, have a Ticket, now need to get the client name
613
clientPrincipal = BuildPrincipal(env, msticket->ClientName,
614
msticket->TargetDomainName); // mdu
615
if (clientPrincipal == NULL) {
616
break;
617
}
618
619
// and the "name" of tgt
620
targetPrincipal = BuildPrincipal(env, msticket->ServiceName,
621
msticket->DomainName);
622
if (targetPrincipal == NULL) {
623
break;
624
}
625
626
// Get the encryption key
627
encryptionKey = BuildEncryptionKey(env, &(msticket->SessionKey));
628
if (encryptionKey == NULL) {
629
break;
630
}
631
632
// and the ticket flags
633
ticketFlags = BuildTicketFlags(env, &(msticket->TicketFlags));
634
if (ticketFlags == NULL) {
635
break;
636
}
637
638
// Get the start time
639
startTime = BuildKerberosTime(env, &(msticket->StartTime));
640
if (startTime == NULL) {
641
break;
642
}
643
644
/*
645
* mdu: No point storing the eky expiration time in the auth
646
* time field. Set it to be same as startTime. Looks like
647
* windows does not have post-dated tickets.
648
*/
649
authTime = startTime;
650
651
// and the end time
652
endTime = BuildKerberosTime(env, &(msticket->EndTime));
653
if (endTime == NULL) {
654
break;
655
}
656
657
// Get the renew till time
658
renewTillTime = BuildKerberosTime(env, &(msticket->RenewUntil));
659
if (renewTillTime == NULL) {
660
break;
661
}
662
663
// and now go build a KrbCreds object
664
krbCreds = (*env)->NewObject(
665
env,
666
krbcredsClass,
667
krbcredsConstructor,
668
ticket,
669
clientPrincipal,
670
NULL,
671
targetPrincipal,
672
NULL,
673
encryptionKey,
674
ticketFlags,
675
authTime, // mdu
676
startTime,
677
endTime,
678
renewTillTime, //mdu
679
hostAddresses);
680
681
break;
682
} // end of WHILE. This WHILE will never loop.
683
684
// clean up resources
685
if (TktCacheResponse != NULL) {
686
LsaFreeReturnBuffer(TktCacheResponse);
687
}
688
if (pTicketRequest) {
689
LocalFree(pTicketRequest);
690
}
691
if (pTicketResponse != NULL) {
692
LsaFreeReturnBuffer(pTicketResponse);
693
}
694
695
return krbCreds;
696
}
697
698
static NTSTATUS
699
ConstructTicketRequest(JNIEnv *env, UNICODE_STRING DomainName,
700
PKERB_RETRIEVE_TKT_REQUEST *outRequest, ULONG *outSize)
701
{
702
NTSTATUS Status;
703
UNICODE_STRING TargetPrefix;
704
USHORT TargetSize;
705
ULONG RequestSize;
706
ULONG Length;
707
PKERB_RETRIEVE_TKT_REQUEST pTicketRequest = NULL;
708
709
*outRequest = NULL;
710
*outSize = 0;
711
712
//
713
// Set up the "krbtgt/" target prefix into a UNICODE_STRING so we
714
// can easily concatenate it later.
715
//
716
717
TargetPrefix.Buffer = L"krbtgt/";
718
Length = (ULONG)wcslen(TargetPrefix.Buffer) * sizeof(WCHAR);
719
TargetPrefix.Length = (USHORT)Length;
720
TargetPrefix.MaximumLength = TargetPrefix.Length;
721
722
//
723
// We will need to concatenate the "krbtgt/" prefix and the
724
// Logon Session's DnsDomainName into our request's target name.
725
//
726
// Therefore, first compute the necessary buffer size for that.
727
//
728
// Note that we might theoretically have integer overflow.
729
//
730
731
TargetSize = TargetPrefix.Length + DomainName.Length;
732
733
//
734
// The ticket request buffer needs to be a single buffer. That buffer
735
// needs to include the buffer for the target name.
736
//
737
738
RequestSize = sizeof (*pTicketRequest) + TargetSize;
739
740
//
741
// Allocate the request buffer and make sure it's zero-filled.
742
//
743
744
pTicketRequest = (PKERB_RETRIEVE_TKT_REQUEST)
745
LocalAlloc(LMEM_ZEROINIT, RequestSize);
746
if (!pTicketRequest) {
747
ThrowOOME(env, "Can't allocate memory for ticket");
748
return GetLastError();
749
}
750
751
//
752
// Concatenate the target prefix with the previous response's
753
// target domain.
754
//
755
756
pTicketRequest->TargetName.Length = 0;
757
pTicketRequest->TargetName.MaximumLength = TargetSize;
758
pTicketRequest->TargetName.Buffer = (PWSTR) (pTicketRequest + 1);
759
Status = ConcatenateUnicodeStrings(&(pTicketRequest->TargetName),
760
TargetPrefix,
761
DomainName);
762
*outRequest = pTicketRequest;
763
*outSize = RequestSize;
764
return Status;
765
}
766
767
DWORD
768
ConcatenateUnicodeStrings(
769
UNICODE_STRING *pTarget,
770
UNICODE_STRING Source1,
771
UNICODE_STRING Source2
772
)
773
{
774
//
775
// The buffers for Source1 and Source2 cannot overlap pTarget's
776
// buffer. Source1.Length + Source2.Length must be <= 0xFFFF,
777
// otherwise we overflow...
778
//
779
780
USHORT TotalSize = Source1.Length + Source2.Length;
781
PBYTE buffer = (PBYTE) pTarget->Buffer;
782
783
if (TotalSize > pTarget->MaximumLength)
784
return ERROR_INSUFFICIENT_BUFFER;
785
786
pTarget->Length = TotalSize;
787
memcpy(buffer, Source1.Buffer, Source1.Length);
788
memcpy(buffer + Source1.Length, Source2.Buffer, Source2.Length);
789
return ERROR_SUCCESS;
790
}
791
792
BOOL
793
PackageConnectLookup(
794
HANDLE *pLogonHandle,
795
ULONG *pPackageId
796
)
797
{
798
LSA_STRING Name;
799
NTSTATUS Status;
800
801
Status = LsaConnectUntrusted(
802
pLogonHandle
803
);
804
805
if (!LSA_SUCCESS(Status))
806
{
807
ShowNTError("LsaConnectUntrusted", Status);
808
return FALSE;
809
}
810
811
Name.Buffer = MICROSOFT_KERBEROS_NAME_A;
812
Name.Length = (USHORT)strlen(Name.Buffer);
813
Name.MaximumLength = Name.Length + 1;
814
815
Status = LsaLookupAuthenticationPackage(
816
*pLogonHandle,
817
&Name,
818
pPackageId
819
);
820
821
if (!LSA_SUCCESS(Status))
822
{
823
ShowNTError("LsaLookupAuthenticationPackage", Status);
824
return FALSE;
825
}
826
827
return TRUE;
828
829
}
830
831
VOID
832
ShowLastError(
833
LPSTR szAPI,
834
DWORD dwError
835
)
836
{
837
#define MAX_MSG_SIZE 256
838
839
static WCHAR szMsgBuf[MAX_MSG_SIZE];
840
DWORD dwRes;
841
842
if (native_debug) {
843
printf("LSA: Error calling function %s: %lu\n", szAPI, dwError);
844
}
845
846
dwRes = FormatMessage (
847
FORMAT_MESSAGE_FROM_SYSTEM,
848
NULL,
849
dwError,
850
0,
851
szMsgBuf,
852
MAX_MSG_SIZE,
853
NULL);
854
if (native_debug) {
855
if (0 == dwRes) {
856
printf("LSA: FormatMessage failed with %d\n", GetLastError());
857
// ExitProcess(EXIT_FAILURE);
858
} else {
859
printf("LSA: %S",szMsgBuf);
860
}
861
}
862
}
863
864
VOID
865
ShowNTError(
866
LPSTR szAPI,
867
NTSTATUS Status
868
)
869
{
870
//
871
// Convert the NTSTATUS to Winerror. Then call ShowLastError().
872
//
873
ShowLastError(szAPI, LsaNtStatusToWinError(Status));
874
}
875
876
VOID
877
InitUnicodeString(
878
PUNICODE_STRING DestinationString,
879
PCWSTR SourceString OPTIONAL
880
)
881
{
882
ULONG Length;
883
884
DestinationString->Buffer = (PWSTR)SourceString;
885
if (SourceString != NULL) {
886
Length = (ULONG)wcslen( SourceString ) * sizeof( WCHAR );
887
DestinationString->Length = (USHORT)Length;
888
DestinationString->MaximumLength = (USHORT)(Length + sizeof(UNICODE_NULL));
889
}
890
else {
891
DestinationString->MaximumLength = 0;
892
DestinationString->Length = 0;
893
}
894
}
895
896
jobject BuildTicket(JNIEnv *env, PUCHAR encodedTicket, ULONG encodedTicketSize) {
897
898
/* To build a Ticket, we first need to build a DerValue out of the EncodedTicket.
899
* But before we can do that, we need to make a byte array out of the ET.
900
*/
901
902
jobject derValue, ticket;
903
jbyteArray ary;
904
905
ary = (*env)->NewByteArray(env,encodedTicketSize);
906
if (ary == NULL) {
907
return (jobject) NULL;
908
}
909
910
(*env)->SetByteArrayRegion(env, ary, (jsize) 0, encodedTicketSize,
911
(jbyte *)encodedTicket);
912
if ((*env)->ExceptionOccurred(env)) {
913
(*env)->DeleteLocalRef(env, ary);
914
return (jobject) NULL;
915
}
916
917
derValue = (*env)->NewObject(env, derValueClass, derValueConstructor, ary);
918
if ((*env)->ExceptionOccurred(env)) {
919
(*env)->DeleteLocalRef(env, ary);
920
return (jobject) NULL;
921
}
922
923
(*env)->DeleteLocalRef(env, ary);
924
ticket = (*env)->NewObject(env, ticketClass, ticketConstructor, derValue);
925
if ((*env)->ExceptionOccurred(env)) {
926
(*env)->DeleteLocalRef(env, derValue);
927
return (jobject) NULL;
928
}
929
(*env)->DeleteLocalRef(env, derValue);
930
return ticket;
931
}
932
933
// mdu
934
jobject BuildPrincipal(JNIEnv *env, PKERB_EXTERNAL_NAME principalName,
935
UNICODE_STRING domainName) {
936
937
/*
938
* To build the Principal, we need to get the names out of
939
* this goofy MS structure
940
*/
941
jobject principal = NULL;
942
jobject realmStr = NULL;
943
jobjectArray stringArray;
944
jstring tempString;
945
int nameCount,i;
946
PUNICODE_STRING scanner;
947
WCHAR *realm;
948
ULONG realmLen;
949
950
realm = (WCHAR *) LocalAlloc(LMEM_ZEROINIT,
951
((domainName.Length)*sizeof(WCHAR) + sizeof(UNICODE_NULL)));
952
if (realm == NULL) {
953
ThrowOOME(env, "Can't allocate memory for realm");
954
return NULL;
955
}
956
wcsncpy(realm, domainName.Buffer, domainName.Length/sizeof(WCHAR));
957
958
if (native_debug) {
959
printf("LSA: Principal domain is %S\n", realm);
960
printf("LSA: Name type is %x\n", principalName->NameType);
961
printf("LSA: Name count is %x\n", principalName->NameCount);
962
}
963
964
nameCount = principalName->NameCount;
965
stringArray = (*env)->NewObjectArray(env, nameCount,
966
javaLangStringClass, NULL);
967
if (stringArray == NULL) {
968
if (native_debug) {
969
printf("LSA: Can't allocate String array for Principal\n");
970
}
971
goto cleanup;
972
}
973
974
for (i=0; i<nameCount; i++) {
975
// get the principal name
976
scanner = &(principalName->Names[i]);
977
978
// OK, got a Char array, so construct a String
979
tempString = (*env)->NewString(env, (const jchar*)scanner->Buffer,
980
scanner->Length/sizeof(WCHAR));
981
982
if (tempString == NULL) {
983
goto cleanup;
984
}
985
986
// Set the String into the StringArray
987
(*env)->SetObjectArrayElement(env, stringArray, i, tempString);
988
989
if ((*env)->ExceptionCheck(env)) {
990
goto cleanup;
991
}
992
993
// Do I have to worry about storage reclamation here?
994
}
995
// now set the realm in the principal
996
realmLen = (ULONG)wcslen((PWCHAR)realm);
997
realmStr = (*env)->NewString(env, (PWCHAR)realm, (USHORT)realmLen);
998
999
if (realmStr == NULL) {
1000
goto cleanup;
1001
}
1002
1003
principal = (*env)->NewObject(env, principalNameClass,
1004
principalNameConstructor, stringArray, realmStr);
1005
1006
cleanup:
1007
// free local resources
1008
LocalFree(realm);
1009
1010
return principal;
1011
}
1012
1013
jobject BuildEncryptionKey(JNIEnv *env, PKERB_CRYPTO_KEY cryptoKey) {
1014
// First, need to build a byte array
1015
jbyteArray ary;
1016
jobject encryptionKey = NULL;
1017
unsigned int i;
1018
1019
for (i=0; i<cryptoKey->Length; i++) {
1020
if (cryptoKey->Value[i]) break;
1021
}
1022
if (i == cryptoKey->Length) {
1023
if (native_debug) {
1024
printf("LSA: Session key all zero. Stop.\n");
1025
}
1026
return NULL;
1027
}
1028
1029
ary = (*env)->NewByteArray(env,cryptoKey->Length);
1030
if (ary == NULL) {
1031
return (jobject) NULL;
1032
}
1033
(*env)->SetByteArrayRegion(env, ary, (jsize) 0, cryptoKey->Length,
1034
(jbyte *)cryptoKey->Value);
1035
if ((*env)->ExceptionOccurred(env)) {
1036
(*env)->DeleteLocalRef(env, ary);
1037
} else {
1038
encryptionKey = (*env)->NewObject(env, encryptionKeyClass,
1039
encryptionKeyConstructor, cryptoKey->KeyType, ary);
1040
}
1041
1042
return encryptionKey;
1043
}
1044
1045
jobject BuildTicketFlags(JNIEnv *env, PULONG flags) {
1046
jobject ticketFlags = NULL;
1047
jbyteArray ary;
1048
/*
1049
* mdu: Convert the bytes to nework byte order before copying
1050
* them to a Java byte array.
1051
*/
1052
ULONG nlflags = htonl(*flags);
1053
1054
ary = (*env)->NewByteArray(env, sizeof(*flags));
1055
if (ary == NULL) {
1056
return (jobject) NULL;
1057
}
1058
(*env)->SetByteArrayRegion(env, ary, (jsize) 0, sizeof(*flags),
1059
(jbyte *)&nlflags);
1060
if ((*env)->ExceptionOccurred(env)) {
1061
(*env)->DeleteLocalRef(env, ary);
1062
} else {
1063
ticketFlags = (*env)->NewObject(env, ticketFlagsClass,
1064
ticketFlagsConstructor, sizeof(*flags)*8, ary);
1065
}
1066
1067
return ticketFlags;
1068
}
1069
1070
jobject BuildKerberosTime(JNIEnv *env, PLARGE_INTEGER kerbtime) {
1071
jobject kerberosTime = NULL;
1072
jstring stringTime = NULL;
1073
SYSTEMTIME systemTime;
1074
WCHAR timeString[16];
1075
WCHAR month[3];
1076
WCHAR day[3];
1077
WCHAR hour[3];
1078
WCHAR minute[3];
1079
WCHAR second[3];
1080
1081
if (FileTimeToSystemTime((FILETIME *)kerbtime, &systemTime)) {
1082
// XXX Cannot use %02.2ld, because the leading 0 is ignored for integers.
1083
// So, print them to strings, and then print them to the master string with a
1084
// format pattern that makes it two digits and prefix with a 0 if necessary.
1085
swprintf( (wchar_t *)month, 3, L"%2.2d", systemTime.wMonth);
1086
swprintf( (wchar_t *)day, 3, L"%2.2d", systemTime.wDay);
1087
swprintf( (wchar_t *)hour, 3, L"%2.2d", systemTime.wHour);
1088
swprintf( (wchar_t *)minute, 3, L"%2.2d", systemTime.wMinute);
1089
swprintf( (wchar_t *)second, 3, L"%2.2d", systemTime.wSecond);
1090
swprintf( (wchar_t *)timeString, 16,
1091
L"%ld%02.2s%02.2s%02.2s%02.2s%02.2sZ",
1092
systemTime.wYear,
1093
month,
1094
day,
1095
hour,
1096
minute,
1097
second );
1098
if (native_debug) {
1099
printf("LSA: %S\n", (wchar_t *)timeString);
1100
}
1101
stringTime = (*env)->NewString(env, timeString,
1102
(sizeof(timeString)/sizeof(WCHAR))-1);
1103
if (stringTime != NULL) { // everything's OK so far
1104
kerberosTime = (*env)->NewObject(env, kerberosTimeClass,
1105
kerberosTimeConstructor, stringTime);
1106
}
1107
}
1108
return kerberosTime;
1109
}
1110
1111
void ThrowOOME(JNIEnv *env, const char *szMessage) {
1112
jclass exceptionClazz = (*env)->FindClass(env, "java/lang/OutOfMemoryError");
1113
if (exceptionClazz != NULL) {
1114
(*env)->ThrowNew(env, exceptionClazz, szMessage);
1115
}
1116
}
1117
1118