jdk/src/windows/native/sun/net/www/protocol/http/ntlm/NTLMAuthSequence.c
changeset 4157 558590fb3b49
parent 910 1f53246fb014
child 5506 202f599c92aa
equal deleted inserted replaced
4061:35a627ad2443 4157:558590fb3b49
       
     1 /*
       
     2  * Copyright 2002-2008 Sun Microsystems, Inc.  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.  Sun designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    23  * have any questions.
       
    24  */
       
    25 
       
    26 #include <jni.h>
       
    27 #include <windows.h>
       
    28 #include <rpc.h>
       
    29 #include <winsock.h>
       
    30 #include <lm.h>
       
    31 
       
    32 #include <stdio.h>
       
    33 #include <stdarg.h>
       
    34 #include <stdlib.h>
       
    35 #include <string.h>
       
    36 #include <tchar.h>
       
    37 #include <fcntl.h>
       
    38 
       
    39 #include "jni_util.h"
       
    40 
       
    41 #define SECURITY_WIN32
       
    42 #include "sspi.h"
       
    43 
       
    44 
       
    45 /*
       
    46  * OS calls loaded from DLL on intialization
       
    47  */
       
    48 
       
    49 static FREE_CREDENTIALS_HANDLE_FN pFreeCredentialsHandle;
       
    50 static ACQUIRE_CREDENTIALS_HANDLE_FN pAcquireCredentialsHandle;
       
    51 static FREE_CONTEXT_BUFFER_FN pFreeContextBuffer;
       
    52 static INITIALIZE_SECURITY_CONTEXT_FN pInitializeSecurityContext;
       
    53 static COMPLETE_AUTH_TOKEN_FN pCompleteAuthToken;
       
    54 static DELETE_SECURITY_CONTEXT_FN pDeleteSecurityContext;
       
    55 
       
    56 static void endSequence (PCredHandle credHand, PCtxtHandle ctxHandle);
       
    57 
       
    58 static jfieldID ntlm_ctxHandleID;
       
    59 static jfieldID ntlm_crdHandleID;
       
    60 
       
    61 static HINSTANCE lib = NULL;
       
    62 
       
    63 JNIEXPORT void JNICALL Java_sun_net_www_protocol_http_ntlm_NTLMAuthSequence_initFirst
       
    64 (JNIEnv *env, jclass clazz)
       
    65 {
       
    66     OSVERSIONINFO   version;
       
    67     UCHAR libName[MAX_PATH];
       
    68 
       
    69     ntlm_ctxHandleID = (*env)->GetFieldID(env, clazz, "ctxHandle", "J");
       
    70     ntlm_crdHandleID = (*env)->GetFieldID(env, clazz, "crdHandle", "J");
       
    71 
       
    72     version.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
       
    73     GetVersionEx (&version);
       
    74 
       
    75     if (version.dwPlatformId == VER_PLATFORM_WIN32_NT) {
       
    76         strcpy (libName, "security.dll" );
       
    77     }
       
    78     else if (version.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
       
    79         strcpy (libName, "secur32.dll" );
       
    80     }
       
    81 
       
    82     lib = LoadLibrary (libName);
       
    83 
       
    84     pFreeCredentialsHandle
       
    85         = (FREE_CREDENTIALS_HANDLE_FN) GetProcAddress(
       
    86         lib, "FreeCredentialsHandle" );
       
    87 
       
    88     pAcquireCredentialsHandle
       
    89         = (ACQUIRE_CREDENTIALS_HANDLE_FN) GetProcAddress(
       
    90         lib, "AcquireCredentialsHandleA" );
       
    91 
       
    92     pFreeContextBuffer
       
    93         = (FREE_CONTEXT_BUFFER_FN) GetProcAddress(
       
    94         lib, "FreeContextBuffer" );
       
    95 
       
    96     pInitializeSecurityContext
       
    97         = (INITIALIZE_SECURITY_CONTEXT_FN) GetProcAddress(
       
    98         lib, "InitializeSecurityContextA" );
       
    99 
       
   100     pCompleteAuthToken
       
   101         = (COMPLETE_AUTH_TOKEN_FN) GetProcAddress(
       
   102         lib, "CompleteAuthToken" );
       
   103 
       
   104     pDeleteSecurityContext
       
   105         = (DELETE_SECURITY_CONTEXT_FN) GetProcAddress(
       
   106         lib, "DeleteSecurityContext" );
       
   107 
       
   108 }
       
   109 
       
   110 /*
       
   111  * Class:     sun_net_www_protocol_http_NTLMAuthSequence
       
   112  * Method:    getCredentialsHandle
       
   113  * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)J
       
   114  */
       
   115 
       
   116 JNIEXPORT jlong JNICALL Java_sun_net_www_protocol_http_ntlm_NTLMAuthSequence_getCredentialsHandle
       
   117 (JNIEnv *env, jobject this, jstring user, jstring domain, jstring password)
       
   118 {
       
   119     SEC_WINNT_AUTH_IDENTITY   AuthId;
       
   120     SEC_WINNT_AUTH_IDENTITY * pAuthId;
       
   121     const CHAR        *pUser = 0;
       
   122     const CHAR        *pDomain = 0;
       
   123     const CHAR        *pPassword = 0;
       
   124     CredHandle      *pCred;
       
   125     TimeStamp            ltime;
       
   126     jboolean         isCopy;
       
   127     SECURITY_STATUS      ss;
       
   128 
       
   129     if (user != 0) {
       
   130         pUser = JNU_GetStringPlatformChars(env, user, &isCopy);
       
   131         if (pUser == NULL)
       
   132             return 0;  // pending Exception
       
   133     }
       
   134     if (domain != 0) {
       
   135         pDomain = JNU_GetStringPlatformChars(env, domain, &isCopy);
       
   136         if (pDomain == NULL) {
       
   137             if (pUser != NULL)
       
   138                 JNU_ReleaseStringPlatformChars(env, user, pUser);
       
   139             return 0;  // pending Exception
       
   140         }
       
   141     }
       
   142     if (password != 0) {
       
   143         pPassword = JNU_GetStringPlatformChars(env, password, &isCopy);
       
   144         if (pPassword == NULL) {
       
   145             if(pUser != NULL)
       
   146                 JNU_ReleaseStringPlatformChars(env, user, pUser);
       
   147             if(pDomain != NULL)
       
   148                 JNU_ReleaseStringPlatformChars(env, domain, pDomain);
       
   149             return 0;  // pending Exception
       
   150         }
       
   151     }
       
   152     pCred = (CredHandle *)malloc(sizeof (CredHandle));
       
   153 
       
   154     if ( ((pUser != NULL) || (pPassword != NULL)) || (pDomain != NULL)) {
       
   155         pAuthId = &AuthId;
       
   156 
       
   157         memset( &AuthId, 0, sizeof( AuthId ));
       
   158 
       
   159         if ( pUser != NULL ) {
       
   160             AuthId.User       = (unsigned char *) pUser;
       
   161             AuthId.UserLength = strlen( pUser );
       
   162         }
       
   163 
       
   164         if ( pPassword != NULL ) {
       
   165             AuthId.Password       = (unsigned char *) pPassword;
       
   166             AuthId.PasswordLength = strlen( pPassword );
       
   167         }
       
   168 
       
   169         if ( pDomain != NULL ) {
       
   170             AuthId.Domain       = (unsigned char *) pDomain;
       
   171             AuthId.DomainLength = strlen( pDomain );
       
   172         }
       
   173 
       
   174         AuthId.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;
       
   175     } else {
       
   176         pAuthId = NULL;
       
   177     }
       
   178 
       
   179     ss = pAcquireCredentialsHandle(
       
   180         NULL, "NTLM", SECPKG_CRED_OUTBOUND,
       
   181         NULL, pAuthId, NULL, NULL,
       
   182         pCred, &ltime
       
   183         );
       
   184 
       
   185     /* Release resources held by JNU_GetStringPlatformChars */
       
   186     if (pUser != NULL)
       
   187         JNU_ReleaseStringPlatformChars(env, user, pUser);
       
   188     if (pPassword != NULL)
       
   189         JNU_ReleaseStringPlatformChars(env, password, pPassword);
       
   190     if (pDomain != NULL)
       
   191         JNU_ReleaseStringPlatformChars(env, domain, pDomain);
       
   192 
       
   193     if (ss == 0) {
       
   194         return (jlong) pCred;
       
   195     } else {
       
   196         return 0;
       
   197     }
       
   198 }
       
   199 
       
   200 JNIEXPORT jbyteArray JNICALL Java_sun_net_www_protocol_http_ntlm_NTLMAuthSequence_getNextToken
       
   201 (JNIEnv *env, jobject this, jlong crdHandle, jbyteArray lastToken)
       
   202 {
       
   203 
       
   204     VOID        *pInput = 0;
       
   205     DWORD            inputLen;
       
   206     CHAR         buffOut[512];
       
   207     jboolean         isCopy;
       
   208     SECURITY_STATUS      ss;
       
   209     SecBufferDesc        OutBuffDesc;
       
   210     SecBuffer            OutSecBuff;
       
   211     SecBufferDesc        InBuffDesc;
       
   212     SecBuffer            InSecBuff;
       
   213     ULONG                ContextAttributes;
       
   214     CredHandle      *pCred = (CredHandle *)crdHandle;
       
   215     CtxtHandle      *pCtx;
       
   216     CtxtHandle      *newContext;
       
   217     TimeStamp            ltime;
       
   218     jbyteArray       result;
       
   219 
       
   220 
       
   221     pCtx = (CtxtHandle *) (*env)->GetLongField (env, this, ntlm_ctxHandleID);
       
   222     if (pCtx == 0) { /* first call */
       
   223         newContext = (CtxtHandle *)malloc(sizeof(CtxtHandle));
       
   224         (*env)->SetLongField (env, this, ntlm_ctxHandleID, (jlong)newContext);
       
   225     } else {
       
   226         newContext = pCtx;
       
   227     }
       
   228 
       
   229     OutBuffDesc.ulVersion = 0;
       
   230     OutBuffDesc.cBuffers  = 1;
       
   231     OutBuffDesc.pBuffers  = &OutSecBuff;
       
   232 
       
   233     OutSecBuff.cbBuffer   = 512;
       
   234     OutSecBuff.BufferType = SECBUFFER_TOKEN;
       
   235     OutSecBuff.pvBuffer   = buffOut;
       
   236 
       
   237     /*
       
   238      *  Prepare our Input buffer - Note the server is expecting the client's
       
   239      *  negotiation packet on the first call
       
   240      */
       
   241 
       
   242     if (lastToken != 0)
       
   243     {
       
   244         pInput = (VOID *)(*env)->GetByteArrayElements(env, lastToken, &isCopy);
       
   245         inputLen = (*env)->GetArrayLength(env, lastToken);
       
   246 
       
   247         InBuffDesc.ulVersion = 0;
       
   248         InBuffDesc.cBuffers  = 1;
       
   249         InBuffDesc.pBuffers  = &InSecBuff;
       
   250 
       
   251         InSecBuff.cbBuffer       = inputLen;
       
   252         InSecBuff.BufferType = SECBUFFER_TOKEN;
       
   253         InSecBuff.pvBuffer       = pInput;
       
   254     }
       
   255 
       
   256     /*
       
   257      *  will return success when its done but we still
       
   258      *  need to send the out buffer if there are bytes to send
       
   259      */
       
   260 
       
   261     ss = pInitializeSecurityContext(
       
   262         pCred, pCtx, NULL, 0, 0, SECURITY_NATIVE_DREP,
       
   263         lastToken ? &InBuffDesc : NULL, 0, newContext, &OutBuffDesc,
       
   264         &ContextAttributes, &ltime
       
   265     );
       
   266 
       
   267     if (pInput != 0) {
       
   268         (*env)->ReleaseByteArrayElements(env, lastToken, pInput, JNI_ABORT);
       
   269     }
       
   270 
       
   271     if (ss < 0) {
       
   272         endSequence (pCred, pCtx);
       
   273         return 0;
       
   274     }
       
   275 
       
   276     if ((ss == SEC_I_COMPLETE_NEEDED) || (ss == SEC_I_COMPLETE_AND_CONTINUE) ) {
       
   277         ss = pCompleteAuthToken( pCtx, &OutBuffDesc );
       
   278 
       
   279         if (ss < 0) {
       
   280             endSequence (pCred, pCtx);
       
   281             return 0;
       
   282         }
       
   283     }
       
   284 
       
   285     if ( OutSecBuff.cbBuffer > 0 ) {
       
   286         jbyteArray ret = (*env)->NewByteArray(env, OutSecBuff.cbBuffer);
       
   287         (*env)->SetByteArrayRegion(env, ret, 0, OutSecBuff.cbBuffer,
       
   288                 OutSecBuff.pvBuffer);
       
   289         if (lastToken != 0) // 2nd stage
       
   290             endSequence (pCred, pCtx);
       
   291         result = ret;
       
   292     }
       
   293 
       
   294     if ((ss != SEC_I_CONTINUE_NEEDED) && (ss == SEC_I_COMPLETE_AND_CONTINUE)) {
       
   295         endSequence (pCred, pCtx);
       
   296     }
       
   297 
       
   298     return result;
       
   299 }
       
   300 
       
   301 static void endSequence (PCredHandle credHand, PCtxtHandle ctxHandle) {
       
   302     if (credHand != 0) {
       
   303         pFreeCredentialsHandle (credHand);
       
   304         free (credHand);
       
   305     }
       
   306 
       
   307     if (ctxHandle != 0) {
       
   308         pDeleteSecurityContext(ctxHandle);
       
   309         free (ctxHandle);
       
   310     }
       
   311 }