Path: blob/master/src/java.base/windows/native/libnet/NTLMAuthSequence.c
41119 views
/*1* Copyright (c) 2002, 2012, 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#include <jni.h>26#include <windows.h>27#include <rpc.h>28#include <winsock.h>29#include <lm.h>3031#include <stdio.h>32#include <stdarg.h>33#include <stdlib.h>34#include <string.h>35#include <tchar.h>36#include <fcntl.h>3738#include "jni_util.h"3940#define SECURITY_WIN3241#include "sspi.h"4243static void endSequence (PCredHandle credHand, PCtxtHandle ctxHandle, JNIEnv *env, jobject status);4445static jfieldID ntlm_ctxHandleID;46static jfieldID ntlm_crdHandleID;47static jfieldID status_seqCompleteID;4849static HINSTANCE lib = NULL;5051JNIEXPORT void JNICALL Java_sun_net_www_protocol_http_ntlm_NTLMAuthSequence_initFirst52(JNIEnv *env, jclass authseq_clazz, jclass status_clazz)53{54ntlm_ctxHandleID = (*env)->GetFieldID(env, authseq_clazz, "ctxHandle", "J");55CHECK_NULL(ntlm_ctxHandleID);56ntlm_crdHandleID = (*env)->GetFieldID(env, authseq_clazz, "crdHandle", "J");57CHECK_NULL(ntlm_crdHandleID);58status_seqCompleteID = (*env)->GetFieldID(env, status_clazz, "sequenceComplete", "Z");59}6061/*62* Class: sun_net_www_protocol_http_NTLMAuthSequence63* Method: getCredentialsHandle64* Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)J65*/6667JNIEXPORT jlong JNICALL Java_sun_net_www_protocol_http_ntlm_NTLMAuthSequence_getCredentialsHandle68(JNIEnv *env, jobject this, jstring user, jstring domain, jstring password)69{70SEC_WINNT_AUTH_IDENTITY AuthId;71SEC_WINNT_AUTH_IDENTITY * pAuthId;72const CHAR *pUser = 0;73const CHAR *pDomain = 0;74const CHAR *pPassword = 0;75CredHandle *pCred;76TimeStamp ltime;77jboolean isCopy;78SECURITY_STATUS ss;7980if (user != 0) {81pUser = JNU_GetStringPlatformChars(env, user, &isCopy);82if (pUser == NULL)83return 0; // pending Exception84}85if (domain != 0) {86pDomain = JNU_GetStringPlatformChars(env, domain, &isCopy);87if (pDomain == NULL) {88if (pUser != NULL)89JNU_ReleaseStringPlatformChars(env, user, pUser);90return 0; // pending Exception91}92}93if (password != 0) {94pPassword = JNU_GetStringPlatformChars(env, password, &isCopy);95if (pPassword == NULL) {96if(pUser != NULL)97JNU_ReleaseStringPlatformChars(env, user, pUser);98if(pDomain != NULL)99JNU_ReleaseStringPlatformChars(env, domain, pDomain);100return 0; // pending Exception101}102}103pCred = (CredHandle *)malloc(sizeof (CredHandle));104if (pCred == NULL) {105JNU_ThrowOutOfMemoryError(env, "native memory allocation failed");106if (pUser != NULL)107JNU_ReleaseStringPlatformChars(env, user, pUser);108if (pPassword != NULL)109JNU_ReleaseStringPlatformChars(env, password, pPassword);110if (pDomain != NULL)111JNU_ReleaseStringPlatformChars(env, domain, pDomain);112return NULL;113}114115if ( ((pUser != NULL) || (pPassword != NULL)) || (pDomain != NULL)) {116pAuthId = &AuthId;117118memset( &AuthId, 0, sizeof( AuthId ));119120if ( pUser != NULL ) {121AuthId.User = (unsigned char *) pUser;122AuthId.UserLength = (unsigned long) strlen( pUser );123}124125if ( pPassword != NULL ) {126AuthId.Password = (unsigned char *) pPassword;127AuthId.PasswordLength = (unsigned long) strlen( pPassword );128}129130if ( pDomain != NULL ) {131AuthId.Domain = (unsigned char *) pDomain;132AuthId.DomainLength = (unsigned long) strlen( pDomain );133}134135AuthId.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;136} else {137pAuthId = NULL;138}139140ss = AcquireCredentialsHandleA(141NULL, "NTLM", SECPKG_CRED_OUTBOUND,142NULL, pAuthId, NULL, NULL,143pCred, <ime144);145146/* Release resources held by JNU_GetStringPlatformChars */147if (pUser != NULL)148JNU_ReleaseStringPlatformChars(env, user, pUser);149if (pPassword != NULL)150JNU_ReleaseStringPlatformChars(env, password, pPassword);151if (pDomain != NULL)152JNU_ReleaseStringPlatformChars(env, domain, pDomain);153154if (ss == 0) {155return (jlong) pCred;156} else {157return 0;158}159}160161162/*163* Class: sun_net_www_protocol_http_ntlm_NTLMAuthSequence164* Method: getNextToken165* Signature: (J[BLsun/net/www/protocol/http/ntlm/NTLMAuthSequence/Status;)[B166*/167JNIEXPORT jbyteArray JNICALL Java_sun_net_www_protocol_http_ntlm_NTLMAuthSequence_getNextToken168(JNIEnv *env, jobject this, jlong crdHandle, jbyteArray lastToken, jobject status)169{170171VOID *pInput = 0;172DWORD inputLen;173CHAR buffOut[1024];174jboolean isCopy;175SECURITY_STATUS ss;176SecBufferDesc OutBuffDesc;177SecBuffer OutSecBuff;178SecBufferDesc InBuffDesc;179SecBuffer InSecBuff;180ULONG ContextAttributes;181CredHandle *pCred = (CredHandle *)crdHandle;182CtxtHandle *pCtx;183CtxtHandle *newContext;184TimeStamp ltime;185jbyteArray result;186187188pCtx = (CtxtHandle *) (*env)->GetLongField (env, this, ntlm_ctxHandleID);189if (pCtx == 0) { /* first call */190newContext = (CtxtHandle *)malloc(sizeof(CtxtHandle));191if (newContext != NULL) {192(*env)->SetLongField (env, this, ntlm_ctxHandleID, (jlong)newContext);193} else {194JNU_ThrowOutOfMemoryError(env, "native memory allocation failed");195return NULL;196}197} else {198newContext = pCtx;199}200201OutBuffDesc.ulVersion = 0;202OutBuffDesc.cBuffers = 1;203OutBuffDesc.pBuffers = &OutSecBuff;204205OutSecBuff.cbBuffer = 1024;206OutSecBuff.BufferType = SECBUFFER_TOKEN;207OutSecBuff.pvBuffer = buffOut;208209/*210* Prepare our Input buffer - Note the server is expecting the client's211* negotiation packet on the first call212*/213214if (lastToken != 0)215{216pInput = (VOID *)(*env)->GetByteArrayElements(env, lastToken, &isCopy);217CHECK_NULL_RETURN(pInput, NULL);218inputLen = (*env)->GetArrayLength(env, lastToken);219220InBuffDesc.ulVersion = 0;221InBuffDesc.cBuffers = 1;222InBuffDesc.pBuffers = &InSecBuff;223224InSecBuff.cbBuffer = inputLen;225InSecBuff.BufferType = SECBUFFER_TOKEN;226InSecBuff.pvBuffer = pInput;227}228229/*230* will return success when its done but we still231* need to send the out buffer if there are bytes to send232*/233234ss = InitializeSecurityContextA(235pCred, pCtx, NULL, 0, 0, SECURITY_NATIVE_DREP,236lastToken ? &InBuffDesc : NULL, 0, newContext, &OutBuffDesc,237&ContextAttributes, <ime238);239240if (pInput != 0) {241(*env)->ReleaseByteArrayElements(env, lastToken, pInput, JNI_ABORT);242}243244if (ss < 0) {245endSequence (pCred, pCtx, env, status);246return 0;247}248249if ((ss == SEC_I_COMPLETE_NEEDED) || (ss == SEC_I_COMPLETE_AND_CONTINUE) ) {250ss = CompleteAuthToken( pCtx, &OutBuffDesc );251252if (ss < 0) {253endSequence (pCred, pCtx, env, status);254return 0;255}256}257258if ( OutSecBuff.cbBuffer > 0 ) {259jbyteArray ret = (*env)->NewByteArray(env, OutSecBuff.cbBuffer);260if (ret != NULL) {261(*env)->SetByteArrayRegion(env, ret, 0, OutSecBuff.cbBuffer,262OutSecBuff.pvBuffer);263}264if (lastToken != 0) // 2nd stage265endSequence (pCred, pCtx, env, status);266result = ret;267}268269if ((ss != SEC_I_CONTINUE_NEEDED) && (ss == SEC_I_COMPLETE_AND_CONTINUE)) {270endSequence (pCred, pCtx, env, status);271}272273return result;274}275276static void endSequence (PCredHandle credHand, PCtxtHandle ctxHandle, JNIEnv *env, jobject status) {277if (credHand != 0) {278FreeCredentialsHandle(credHand);279free(credHand);280}281282if (ctxHandle != 0) {283DeleteSecurityContext(ctxHandle);284free(ctxHandle);285}286287/* Sequence is complete so set flag */288(*env)->SetBooleanField(env, status, status_seqCompleteID, JNI_TRUE);289}290291292