/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* ===========================================================================
* (C) Copyright IBM Corp. 2000 All Rights Reserved.
* ===========================================================================
*/
#define UNICODE
#define _UNICODE
#include <windows.h>
#include <stdio.h>
#include <string.h>
#define SECURITY_WIN32
#include <security.h>
#include <ntsecapi.h>
#include <dsgetdc.h>
#include <lmcons.h>
#include <lmapibuf.h>
#include <jni.h>
#include <winsock.h>
/*
* Library-wide static references
*/
/*
* Function prototypes for internal routines
*
*/
);
//mdu
/*
* Class: sun_security_krb5_KrbCreds
* Method: JNI_OnLoad
*/
void *reserved) {
return JNI_EVERSION; /* JNI version not supported */
}
printf("LSA: Couldn't find Krb5\n");
return JNI_ERR;
}
printf("LSA: Krb5 has no DEBUG field\n");
return JNI_ERR;
}
printf("LSA: Couldn't find Ticket\n");
return JNI_ERR;
}
if (native_debug) {
printf("LSA: Found Ticket\n");
}
if (ticketClass == NULL) {
return JNI_ERR;
}
if (native_debug) {
printf("LSA: Made NewWeakGlobalRef\n");
}
printf("LSA: Couldn't find PrincipalName\n");
return JNI_ERR;
}
if (native_debug) {
printf("LSA: Found PrincipalName\n");
}
if (principalNameClass == NULL) {
return JNI_ERR;
}
if (native_debug) {
printf("LSA: Made NewWeakGlobalRef\n");
}
printf("LSA: Couldn't find DerValue\n");
return JNI_ERR;
}
if (native_debug) {
printf("LSA: Found DerValue\n");
}
if (derValueClass == NULL) {
return JNI_ERR;
}
if (native_debug) {
printf("LSA: Made NewWeakGlobalRef\n");
}
printf("LSA: Couldn't find EncryptionKey\n");
return JNI_ERR;
}
if (native_debug) {
printf("LSA: Found EncryptionKey\n");
}
if (encryptionKeyClass == NULL) {
return JNI_ERR;
}
if (native_debug) {
printf("LSA: Made NewWeakGlobalRef\n");
}
printf("LSA: Couldn't find TicketFlags\n");
return JNI_ERR;
}
if (native_debug) {
printf("LSA: Found TicketFlags\n");
}
if (ticketFlagsClass == NULL) {
return JNI_ERR;
}
if (native_debug) {
printf("LSA: Made NewWeakGlobalRef\n");
}
printf("LSA: Couldn't find KerberosTime\n");
return JNI_ERR;
}
if (native_debug) {
printf("LSA: Found KerberosTime\n");
}
if (kerberosTimeClass == NULL) {
return JNI_ERR;
}
if (native_debug) {
printf("LSA: Made NewWeakGlobalRef\n");
}
printf("LSA: Couldn't find String\n");
return JNI_ERR;
}
if (native_debug) {
printf("LSA: Found String\n");
}
if (javaLangStringClass == NULL) {
return JNI_ERR;
}
if (native_debug) {
printf("LSA: Made NewWeakGlobalRef\n");
}
"<init>", "([B)V");
if (derValueConstructor == 0) {
printf("LSA: Couldn't find DerValue constructor\n");
return JNI_ERR;
}
if (native_debug) {
printf("LSA: Found DerValue constructor\n");
}
if (ticketConstructor == 0) {
printf("LSA: Couldn't find Ticket constructor\n");
return JNI_ERR;
}
if (native_debug) {
printf("LSA: Found Ticket constructor\n");
}
if (principalNameConstructor == 0) {
printf("LSA: Couldn't find PrincipalName constructor\n");
return JNI_ERR;
}
if (native_debug) {
printf("LSA: Found PrincipalName constructor\n");
}
"<init>", "(I[B)V");
if (encryptionKeyConstructor == 0) {
printf("LSA: Couldn't find EncryptionKey constructor\n");
return JNI_ERR;
}
if (native_debug) {
printf("LSA: Found EncryptionKey constructor\n");
}
"<init>", "(I[B)V");
if (ticketFlagsConstructor == 0) {
printf("LSA: Couldn't find TicketFlags constructor\n");
return JNI_ERR;
}
if (native_debug) {
printf("LSA: Found TicketFlags constructor\n");
}
if (kerberosTimeConstructor == 0) {
printf("LSA: Couldn't find KerberosTime constructor\n");
return JNI_ERR;
}
if (native_debug) {
printf("LSA: Found KerberosTime constructor\n");
}
// load the setRealm method in PrincipalName
if (setRealmMethod == 0) {
printf("LSA: Couldn't find setRealm in PrincipalName\n");
return JNI_ERR;
}
if (native_debug) {
printf("LSA: Finished OnLoad processing\n");
}
return JNI_VERSION_1_2;
}
/*
* Class: sun_security_jgss_KrbCreds
* Method: JNI_OnUnload
*/
void *reserved) {
return; /* Nothing else we can do */
}
if (ticketClass != NULL) {
}
if (derValueClass != NULL) {
}
if (principalNameClass != NULL) {
}
if (encryptionKeyClass != NULL) {
}
if (ticketFlagsClass != NULL) {
}
if (kerberosTimeClass != NULL) {
}
if (javaLangStringClass != NULL) {
}
return;
}
/*
* Class: sun_security_krb5_Credentials
* Method: acquireDefaultNativeCreds
* Signature: ()Lsun/security/krb5/Credentials;
*/
int ignore_cache = 0;
while (TRUE) {
if (krbcredsConstructor == 0) {
"Lsun/security/krb5/internal/HostAddresses;)V");
if (krbcredsConstructor == 0) {
break;
}
}
if (native_debug) {
printf("LSA: Found KrbCreds constructor\n");
}
//
// Get the logon handle and package ID from the
// Kerberos package
//
break;
if (native_debug) {
printf("LSA: Got handle to Kerberos package\n");
}
// Get the MS TGT from cache
sizeof(CacheRequest),
&rspSize,
);
if (native_debug) {
}
if (!LSA_SUCCESS(Status)) {
} else {
}
break;
}
// got the native MS TGT
// check TGT validity
case KERB_ETYPE_DES_CBC_CRC:
case KERB_ETYPE_DES_CBC_MD5:
case KERB_ETYPE_NULL:
case KERB_ETYPE_RC4_HMAC_NT:
ignore_cache = 1;
}
ignore_cache = 1;
}
break;
case KERB_ETYPE_RC4_MD4:
default:
// not supported
ignore_cache = 1;
break;
}
if (ignore_cache) {
if (native_debug) {
}
// use domain to request Ticket
if (!LSA_SUCCESS(Status)) {
break;
}
);
if (native_debug) {
}
if (!LSA_SUCCESS(Status)) {
} else {
}
break;
}
// got the native MS Kerberos TGT
}
/*
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
break;
}
// OK, have a Ticket, now need to get the client name
if (clientPrincipal == NULL) {
break;
}
// and the "name" of tgt
if (targetPrincipal == NULL) {
break;
}
// Get the encryption key
if (encryptionKey == NULL) {
break;
}
// and the ticket flags
if (ticketFlags == NULL) {
break;
}
// Get the start time
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.
*/
// and the end time
break;
}
// Get the renew till time
if (renewTillTime == NULL) {
break;
}
// and now go build a KrbCreds object
env,
authTime, // mdu
renewTillTime, //mdu
break;
} // end of WHILE
// clean up resources
if (TktCacheResponse != NULL) {
}
if (pTicketRequest) {
}
if (pTicketResponse != NULL) {
}
return krbCreds;
}
static NTSTATUS
{
*outRequest = NULL;
*outSize = 0;
//
// Set up the "krbtgt/" target prefix into a UNICODE_STRING so we
// can easily concatenate it later.
//
//
// We will need to concatenate the "krbtgt/" prefix and the
// Logon Session's DnsDomainName into our request's target name.
//
// Therefore, first compute the necessary buffer size for that.
//
// Note that we might theoretically have integer overflow.
//
//
// The ticket request buffer needs to be a single buffer. That buffer
// needs to include the buffer for the target name.
//
//
// Allocate the request buffer and make sure it's zero-filled.
//
if (!pTicketRequest)
return GetLastError();
//
// Concatenate the target prefix with the previous reponse's
// target domain.
//
*outSize = RequestSize;
return Status;
}
)
{
//
// The buffers for Source1 and Source2 cannot overlap pTarget's
// buffer. Source1.Length + Source2.Length must be <= 0xFFFF,
// otherwise we overflow...
//
return ERROR_INSUFFICIENT_BUFFER;
return ERROR_SUCCESS;
}
)
{
);
if (!LSA_SUCCESS(Status))
{
return FALSE;
}
&Name,
);
if (!LSA_SUCCESS(Status))
{
return FALSE;
}
return TRUE;
}
)
{
if (native_debug) {
}
dwRes = FormatMessage (
NULL,
0,
NULL);
if (native_debug) {
if (0 == dwRes) {
// ExitProcess(EXIT_FAILURE);
} else {
}
}
}
)
{
//
// Convert the NTSTATUS to Winerror. Then call ShowLastError().
//
}
)
{
if (SourceString != NULL) {
}
else {
DestinationString->Length = 0;
}
}
/* To build a Ticket, we first need to build a DerValue out of the EncodedTicket.
* But before we can do that, we need to make a byte array out of the ET.
*/
}
(jbyte *)encodedTicket);
}
}
}
return ticket;
}
// mdu
/*
* To build the Principal, we need to get the names out of
* this goofy MS structure
*/
int nameCount,i;
if (native_debug) {
}
if (stringArray == NULL) {
if (native_debug) {
printf("LSA: Can't allocate String array for Principal\n");
}
return principal;
}
for (i=0; i<nameCount; i++) {
// get the principal name
// OK, got a Char array, so construct a String
// Set the String into the StringArray
// Do I have to worry about storage reclamation here?
}
// now set the realm in the principal
// free local resources
return principal;
}
// First, need to build a byte array
unsigned int i;
}
if (native_debug) {
printf("LSA: Session key all zero. Stop.\n");
}
return NULL;
}
} else {
}
return encryptionKey;
}
/*
* mdu: Convert the bytes to nework byte order before copying
* them to a Java byte array.
*/
} else {
}
return ticketFlags;
}
// XXX Cannot use %02.2ld, because the leading 0 is ignored for integers.
// So, print them to strings, and then print them to the master string with a
// format pattern that makes it two digits and prefix with a 0 if necessary.
L"%ld%02.2s%02.2s%02.2s%02.2s%02.2sZ",
day,
hour,
second );
if (native_debug) {
}
}
}
return kerberosTime;
}