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, <ime 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, <ime 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 ---