blob: 29c0a2b3b70e31e0cf8c937df6f3a5d473efd778 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2002-2005 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#define SECURITY_WIN32
40#include "sspi.h"
41#include "issperr.h"
42
43
44/*
45 * OS calls loaded from DLL on intialization
46 */
47
48static FREE_CREDENTIALS_HANDLE_FN pFreeCredentialsHandle;
49static ACQUIRE_CREDENTIALS_HANDLE_FN pAcquireCredentialsHandle;
50static FREE_CONTEXT_BUFFER_FN pFreeContextBuffer;
51static INITIALIZE_SECURITY_CONTEXT_FN pInitializeSecurityContext;
52static COMPLETE_AUTH_TOKEN_FN pCompleteAuthToken;
53static DELETE_SECURITY_CONTEXT_FN pDeleteSecurityContext;
54
55static void endSequence (PCredHandle credHand, PCtxtHandle ctxHandle, SecBufferDesc OutBuffDesc);
56
57static jfieldID ntlm_ctxHandleID;
58static jfieldID ntlm_crdHandleID;
59
60static HINSTANCE lib = NULL;
61
62JNIEXPORT void JNICALL Java_sun_net_www_protocol_http_NTLMAuthSequence_initFirst
63(JNIEnv *env, jclass clazz)
64{
65 OSVERSIONINFO version;
66 UCHAR libName[MAX_PATH];
67
68 ntlm_ctxHandleID = (*env)->GetFieldID(env, clazz, "ctxHandle", "J");
69 ntlm_crdHandleID = (*env)->GetFieldID(env, clazz, "crdHandle", "J");
70
71 version.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
72 GetVersionEx (&version);
73
74 if (version.dwPlatformId == VER_PLATFORM_WIN32_NT) {
75 strcpy (libName, "security.dll" );
76 }
77 else if (version.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
78 strcpy (libName, "secur32.dll" );
79 }
80
81 lib = LoadLibrary (libName);
82
83 pFreeCredentialsHandle
84 = (FREE_CREDENTIALS_HANDLE_FN) GetProcAddress(
85 lib, "FreeCredentialsHandle" );
86
87 pAcquireCredentialsHandle
88 = (ACQUIRE_CREDENTIALS_HANDLE_FN) GetProcAddress(
89 lib, "AcquireCredentialsHandleA" );
90
91 pFreeContextBuffer
92 = (FREE_CONTEXT_BUFFER_FN) GetProcAddress(
93 lib, "FreeContextBuffer" );
94
95 pInitializeSecurityContext
96 = (INITIALIZE_SECURITY_CONTEXT_FN) GetProcAddress(
97 lib, "InitializeSecurityContextA" );
98
99 pCompleteAuthToken
100 = (COMPLETE_AUTH_TOKEN_FN) GetProcAddress(
101 lib, "CompleteAuthToken" );
102
103 pDeleteSecurityContext
104 = (DELETE_SECURITY_CONTEXT_FN) GetProcAddress(
105 lib, "DeleteSecurityContext" );
106
107}
108
109/*
110 * Class: sun_net_www_protocol_http_NTLMAuthSequence
111 * Method: getCredentialsHandle
112 * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)J
113 */
114
115JNIEXPORT jlong JNICALL Java_sun_net_www_protocol_http_NTLMAuthSequence_getCredentialsHandle
116(JNIEnv *env, jobject this, jstring user, jstring domain, jstring password)
117{
118 SEC_WINNT_AUTH_IDENTITY AuthId;
119 SEC_WINNT_AUTH_IDENTITY * pAuthId;
120 CHAR *pUser = 0;
121 CHAR *pDomain = 0;
122 CHAR *pPassword = 0;
123 CredHandle *pCred;
124 TimeStamp ltime;
125 jboolean isCopy;
126 SECURITY_STATUS ss;
127
128 if (user != 0) {
129 pUser = (CHAR *)(*env)->GetStringUTFChars(env, user, &isCopy);
130 }
131 if (domain != 0) {
132 pDomain = (CHAR *)(*env)->GetStringUTFChars(env, domain, &isCopy);
133 }
134 if (password != 0) {
135 pPassword = (CHAR *)(*env)->GetStringUTFChars(env, password, &isCopy);
136 }
137 pCred = (CredHandle *)malloc(sizeof (CredHandle));
138
139 if ( ((pUser != NULL) || (pPassword != NULL)) || (pDomain != NULL)) {
140 pAuthId = &AuthId;
141
142 memset( &AuthId, 0, sizeof( AuthId ));
143
144 if ( pUser != NULL ) {
145 AuthId.User = (unsigned char *) pUser;
146 AuthId.UserLength = strlen( pUser );
147 }
148
149 if ( pPassword != NULL ) {
150 AuthId.Password = (unsigned char *) pPassword;
151 AuthId.PasswordLength = strlen( pPassword );
152 }
153
154 if ( pDomain != NULL ) {
155 AuthId.Domain = (unsigned char *) pDomain;
156 AuthId.DomainLength = strlen( pDomain );
157 }
158
159 AuthId.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;
160 } else {
161 pAuthId = NULL;
162 }
163
164 ss = pAcquireCredentialsHandle(
165 NULL, "NTLM", SECPKG_CRED_OUTBOUND,
166 NULL, pAuthId, NULL, NULL,
167 pCred, &ltime
168 );
169
170 if (ss == 0) {
171 return (jlong) pCred;
172 } else {
173 return 0;
174 }
175}
176
177JNIEXPORT jbyteArray JNICALL Java_sun_net_www_protocol_http_NTLMAuthSequence_getNextToken
178(JNIEnv *env, jobject this, jlong crdHandle, jbyteArray lastToken)
179{
180
181 VOID *pInput = 0;
182 DWORD inputLen;
183 CHAR buffOut[512];
184 DWORD pcbBuffOut;
185 jboolean isCopy;
186 SECURITY_STATUS ss;
187 SecBufferDesc OutBuffDesc;
188 SecBuffer OutSecBuff;
189 SecBufferDesc InBuffDesc;
190 SecBuffer InSecBuff;
191 ULONG ContextAttributes;
192 CredHandle *pCred = (CredHandle *)crdHandle;
193 CtxtHandle *pCtx;
194 CtxtHandle *newContext;
195 TimeStamp ltime;
196 jbyteArray result;
197
198
199 pCtx = (CtxtHandle *) (*env)->GetLongField (env, this, ntlm_ctxHandleID);
200 if (pCtx == 0) { /* first call */
201 newContext = (CtxtHandle *)malloc(sizeof(CtxtHandle));
202 (*env)->SetLongField (env, this, ntlm_ctxHandleID, (jlong)newContext);
203 } else {
204 newContext = pCtx;
205 }
206
207 OutBuffDesc.ulVersion = 0;
208 OutBuffDesc.cBuffers = 1;
209 OutBuffDesc.pBuffers = &OutSecBuff;
210
211 OutSecBuff.cbBuffer = 512;
212 OutSecBuff.BufferType = SECBUFFER_TOKEN;
213 OutSecBuff.pvBuffer = buffOut;
214
215 /*
216 * Prepare our Input buffer - Note the server is expecting the client's
217 * negotiation packet on the first call
218 */
219
220 if (lastToken != 0)
221 {
222 pInput = (VOID *)(*env)->GetByteArrayElements(env, lastToken, &isCopy);
223 inputLen = (*env)->GetArrayLength(env, lastToken);
224
225 InBuffDesc.ulVersion = 0;
226 InBuffDesc.cBuffers = 1;
227 InBuffDesc.pBuffers = &InSecBuff;
228
229 InSecBuff.cbBuffer = inputLen;
230 InSecBuff.BufferType = SECBUFFER_TOKEN;
231 InSecBuff.pvBuffer = pInput;
232 }
233
234 /*
235 * will return success when its done but we still
236 * need to send the out buffer if there are bytes to send
237 */
238
239 ss = pInitializeSecurityContext(
240 pCred, pCtx, NULL, 0, 0, SECURITY_NATIVE_DREP,
241 lastToken ? &InBuffDesc : NULL, 0, newContext, &OutBuffDesc,
242 &ContextAttributes, &ltime
243 );
244
245 if (pInput != 0) {
246 (*env)->ReleaseByteArrayElements(env, lastToken, pInput, JNI_ABORT);
247 }
248
249 if (ss < 0) {
250 endSequence (pCred, pCtx, OutBuffDesc);
251 return 0;
252 }
253
254 if ((ss == SEC_I_COMPLETE_NEEDED) || (ss == SEC_I_COMPLETE_AND_CONTINUE) ) {
255 ss = pCompleteAuthToken( pCtx, &OutBuffDesc );
256
257 if (ss < 0) {
258 endSequence (pCred, pCtx, OutBuffDesc);
259 return 0;
260 }
261 }
262
263 if ( OutSecBuff.cbBuffer > 0 ) {
264 jbyteArray ret = (*env)->NewByteArray(env, OutSecBuff.cbBuffer);
265 (*env)->SetByteArrayRegion(env, ret, 0, OutSecBuff.cbBuffer,
266 OutSecBuff.pvBuffer);
267 if (lastToken != 0) // 2nd stage
268 endSequence (pCred, pCtx, OutBuffDesc);
269 result = ret;
270 }
271
272 if ((ss != SEC_I_CONTINUE_NEEDED) && (ss == SEC_I_COMPLETE_AND_CONTINUE)) {
273 endSequence (pCred, pCtx, OutBuffDesc);
274 }
275
276 return result;
277}
278
279static void endSequence (PCredHandle credHand, PCtxtHandle ctxHandle, SecBufferDesc OutBuffDesc) {
280 if (credHand != 0) {
281 pFreeCredentialsHandle (credHand);
282 free (credHand);
283 }
284
285 pFreeContextBuffer (&OutBuffDesc);
286
287 if (ctxHandle != 0) {
288 pDeleteSecurityContext(ctxHandle);
289 free (ctxHandle);
290 }
291}