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_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_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_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 }
--- EOF ---