0N/A/*
2362N/A * Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/A#include <jni.h>
0N/A#include <windows.h>
0N/A#include <rpc.h>
0N/A#include <winsock.h>
0N/A#include <lm.h>
0N/A
0N/A#include <stdio.h>
0N/A#include <stdarg.h>
0N/A#include <stdlib.h>
0N/A#include <string.h>
0N/A#include <tchar.h>
0N/A#include <fcntl.h>
0N/A
63N/A#include "jni_util.h"
63N/A
0N/A#define SECURITY_WIN32
0N/A#include "sspi.h"
0N/A
5542N/Astatic void endSequence (PCredHandle credHand, PCtxtHandle ctxHandle, JNIEnv *env, jobject status);
0N/A
0N/Astatic jfieldID ntlm_ctxHandleID;
0N/Astatic jfieldID ntlm_crdHandleID;
5542N/Astatic jfieldID status_seqCompleteID;
0N/A
0N/Astatic HINSTANCE lib = NULL;
0N/A
1791N/AJNIEXPORT void JNICALL Java_sun_net_www_protocol_http_ntlm_NTLMAuthSequence_initFirst
5542N/A(JNIEnv *env, jclass authseq_clazz, jclass status_clazz)
0N/A{
5542N/A ntlm_ctxHandleID = (*env)->GetFieldID(env, authseq_clazz, "ctxHandle", "J");
5542N/A ntlm_crdHandleID = (*env)->GetFieldID(env, authseq_clazz, "crdHandle", "J");
5542N/A status_seqCompleteID = (*env)->GetFieldID(env, status_clazz, "sequenceComplete", "Z");
0N/A}
0N/A
0N/A/*
0N/A * Class: sun_net_www_protocol_http_NTLMAuthSequence
0N/A * Method: getCredentialsHandle
0N/A * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)J
0N/A */
0N/A
1791N/AJNIEXPORT jlong JNICALL Java_sun_net_www_protocol_http_ntlm_NTLMAuthSequence_getCredentialsHandle
0N/A(JNIEnv *env, jobject this, jstring user, jstring domain, jstring password)
0N/A{
0N/A SEC_WINNT_AUTH_IDENTITY AuthId;
0N/A SEC_WINNT_AUTH_IDENTITY * pAuthId;
63N/A const CHAR *pUser = 0;
63N/A const CHAR *pDomain = 0;
63N/A const CHAR *pPassword = 0;
0N/A CredHandle *pCred;
0N/A TimeStamp ltime;
0N/A jboolean isCopy;
0N/A SECURITY_STATUS ss;
0N/A
0N/A if (user != 0) {
63N/A pUser = JNU_GetStringPlatformChars(env, user, &isCopy);
63N/A if (pUser == NULL)
63N/A return 0; // pending Exception
0N/A }
0N/A if (domain != 0) {
63N/A pDomain = JNU_GetStringPlatformChars(env, domain, &isCopy);
63N/A if (pDomain == NULL) {
63N/A if (pUser != NULL)
63N/A JNU_ReleaseStringPlatformChars(env, user, pUser);
63N/A return 0; // pending Exception
63N/A }
0N/A }
0N/A if (password != 0) {
63N/A pPassword = JNU_GetStringPlatformChars(env, password, &isCopy);
63N/A if (pPassword == NULL) {
63N/A if(pUser != NULL)
63N/A JNU_ReleaseStringPlatformChars(env, user, pUser);
63N/A if(pDomain != NULL)
63N/A JNU_ReleaseStringPlatformChars(env, domain, pDomain);
63N/A return 0; // pending Exception
63N/A }
0N/A }
0N/A pCred = (CredHandle *)malloc(sizeof (CredHandle));
0N/A
0N/A if ( ((pUser != NULL) || (pPassword != NULL)) || (pDomain != NULL)) {
0N/A pAuthId = &AuthId;
0N/A
0N/A memset( &AuthId, 0, sizeof( AuthId ));
0N/A
0N/A if ( pUser != NULL ) {
0N/A AuthId.User = (unsigned char *) pUser;
3877N/A AuthId.UserLength = (unsigned long) strlen( pUser );
0N/A }
0N/A
0N/A if ( pPassword != NULL ) {
0N/A AuthId.Password = (unsigned char *) pPassword;
3877N/A AuthId.PasswordLength = (unsigned long) strlen( pPassword );
0N/A }
0N/A
0N/A if ( pDomain != NULL ) {
0N/A AuthId.Domain = (unsigned char *) pDomain;
3877N/A AuthId.DomainLength = (unsigned long) strlen( pDomain );
0N/A }
0N/A
0N/A AuthId.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;
0N/A } else {
0N/A pAuthId = NULL;
0N/A }
0N/A
3877N/A ss = AcquireCredentialsHandleA(
0N/A NULL, "NTLM", SECPKG_CRED_OUTBOUND,
0N/A NULL, pAuthId, NULL, NULL,
0N/A pCred, &ltime
0N/A );
0N/A
63N/A /* Release resources held by JNU_GetStringPlatformChars */
63N/A if (pUser != NULL)
63N/A JNU_ReleaseStringPlatformChars(env, user, pUser);
63N/A if (pPassword != NULL)
63N/A JNU_ReleaseStringPlatformChars(env, password, pPassword);
63N/A if (pDomain != NULL)
63N/A JNU_ReleaseStringPlatformChars(env, domain, pDomain);
63N/A
0N/A if (ss == 0) {
0N/A return (jlong) pCred;
0N/A } else {
0N/A return 0;
0N/A }
0N/A}
0N/A
5542N/A
5542N/A/*
5542N/A * Class: sun_net_www_protocol_http_ntlm_NTLMAuthSequence
5542N/A * Method: getNextToken
5542N/A * Signature: (J[BLsun/net/www/protocol/http/ntlm/NTLMAuthSequence/Status;)[B
5542N/A */
1791N/AJNIEXPORT jbyteArray JNICALL Java_sun_net_www_protocol_http_ntlm_NTLMAuthSequence_getNextToken
5542N/A(JNIEnv *env, jobject this, jlong crdHandle, jbyteArray lastToken, jobject status)
0N/A{
0N/A
0N/A VOID *pInput = 0;
0N/A DWORD inputLen;
5160N/A CHAR buffOut[1024];
0N/A jboolean isCopy;
0N/A SECURITY_STATUS ss;
0N/A SecBufferDesc OutBuffDesc;
0N/A SecBuffer OutSecBuff;
0N/A SecBufferDesc InBuffDesc;
0N/A SecBuffer InSecBuff;
0N/A ULONG ContextAttributes;
0N/A CredHandle *pCred = (CredHandle *)crdHandle;
0N/A CtxtHandle *pCtx;
0N/A CtxtHandle *newContext;
0N/A TimeStamp ltime;
0N/A jbyteArray result;
0N/A
0N/A
0N/A pCtx = (CtxtHandle *) (*env)->GetLongField (env, this, ntlm_ctxHandleID);
0N/A if (pCtx == 0) { /* first call */
0N/A newContext = (CtxtHandle *)malloc(sizeof(CtxtHandle));
0N/A (*env)->SetLongField (env, this, ntlm_ctxHandleID, (jlong)newContext);
0N/A } else {
0N/A newContext = pCtx;
0N/A }
0N/A
0N/A OutBuffDesc.ulVersion = 0;
0N/A OutBuffDesc.cBuffers = 1;
0N/A OutBuffDesc.pBuffers = &OutSecBuff;
0N/A
5160N/A OutSecBuff.cbBuffer = 1024;
0N/A OutSecBuff.BufferType = SECBUFFER_TOKEN;
0N/A OutSecBuff.pvBuffer = buffOut;
0N/A
0N/A /*
0N/A * Prepare our Input buffer - Note the server is expecting the client's
0N/A * negotiation packet on the first call
0N/A */
0N/A
0N/A if (lastToken != 0)
0N/A {
0N/A pInput = (VOID *)(*env)->GetByteArrayElements(env, lastToken, &isCopy);
0N/A inputLen = (*env)->GetArrayLength(env, lastToken);
0N/A
0N/A InBuffDesc.ulVersion = 0;
0N/A InBuffDesc.cBuffers = 1;
0N/A InBuffDesc.pBuffers = &InSecBuff;
0N/A
0N/A InSecBuff.cbBuffer = inputLen;
0N/A InSecBuff.BufferType = SECBUFFER_TOKEN;
0N/A InSecBuff.pvBuffer = pInput;
0N/A }
0N/A
0N/A /*
0N/A * will return success when its done but we still
0N/A * need to send the out buffer if there are bytes to send
0N/A */
0N/A
3877N/A ss = InitializeSecurityContextA(
0N/A pCred, pCtx, NULL, 0, 0, SECURITY_NATIVE_DREP,
0N/A lastToken ? &InBuffDesc : NULL, 0, newContext, &OutBuffDesc,
0N/A &ContextAttributes, &ltime
0N/A );
0N/A
0N/A if (pInput != 0) {
0N/A (*env)->ReleaseByteArrayElements(env, lastToken, pInput, JNI_ABORT);
0N/A }
0N/A
0N/A if (ss < 0) {
5542N/A endSequence (pCred, pCtx, env, status);
0N/A return 0;
0N/A }
0N/A
0N/A if ((ss == SEC_I_COMPLETE_NEEDED) || (ss == SEC_I_COMPLETE_AND_CONTINUE) ) {
3877N/A ss = CompleteAuthToken( pCtx, &OutBuffDesc );
0N/A
0N/A if (ss < 0) {
5542N/A endSequence (pCred, pCtx, env, status);
0N/A return 0;
0N/A }
0N/A }
0N/A
0N/A if ( OutSecBuff.cbBuffer > 0 ) {
0N/A jbyteArray ret = (*env)->NewByteArray(env, OutSecBuff.cbBuffer);
0N/A (*env)->SetByteArrayRegion(env, ret, 0, OutSecBuff.cbBuffer,
0N/A OutSecBuff.pvBuffer);
0N/A if (lastToken != 0) // 2nd stage
5542N/A endSequence (pCred, pCtx, env, status);
0N/A result = ret;
0N/A }
0N/A
0N/A if ((ss != SEC_I_CONTINUE_NEEDED) && (ss == SEC_I_COMPLETE_AND_CONTINUE)) {
5542N/A endSequence (pCred, pCtx, env, status);
0N/A }
0N/A
0N/A return result;
0N/A}
0N/A
5542N/Astatic void endSequence (PCredHandle credHand, PCtxtHandle ctxHandle, JNIEnv *env, jobject status) {
0N/A if (credHand != 0) {
3877N/A FreeCredentialsHandle(credHand);
3877N/A free(credHand);
0N/A }
0N/A
0N/A if (ctxHandle != 0) {
3877N/A DeleteSecurityContext(ctxHandle);
3877N/A free(ctxHandle);
0N/A }
5542N/A
5542N/A /* Sequence is complete so set flag */
5542N/A (*env)->SetBooleanField(env, status, status_seqCompleteID, JNI_TRUE);
0N/A}