File: | jdk/src/java.security.jgss/share/native/libj2gss/NativeUtil.c |
Warning: | line 510, column 3 Value stored to 'major' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* |
2 | * Copyright (c) 2005, 2018, Oracle and/or its affiliates. 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. Oracle designates this |
8 | * particular file as subject to the "Classpath" exception as provided |
9 | * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
22 | * or visit www.oracle.com if you need additional information or have any |
23 | * questions. |
24 | */ |
25 | |
26 | #include "NativeUtil.h" |
27 | #include "NativeFunc.h" |
28 | #include "jlong.h" |
29 | #include <jni.h> |
30 | #include "jni_util.h" |
31 | |
32 | const int JAVA_DUPLICATE_TOKEN_CODE = 19; /* DUPLICATE_TOKEN */ |
33 | const int JAVA_OLD_TOKEN_CODE = 20; /* OLD_TOKEN */ |
34 | const int JAVA_UNSEQ_TOKEN_CODE = 21; /* UNSEQ_TOKEN */ |
35 | const int JAVA_GAP_TOKEN_CODE = 22; /* GAP_TOKEN */ |
36 | const int JAVA_ERROR_CODE[] = { |
37 | 2, /* BAD_MECH */ |
38 | 3, /* BAD_NAME */ |
39 | 4, /* BAD_NAMETYPE */ |
40 | 1, /* BAD_BINDINGS */ |
41 | 5, /* BAD_STATUS */ |
42 | 6, /* BAD_MIC */ |
43 | 13, /* NO_CRED */ |
44 | 12, /* NO_CONTEXT */ |
45 | 10, /* DEFECTIVE_TOKEN */ |
46 | 9, /* DEFECTIVE_CREDENTIAL */ |
47 | 8, /* CREDENTIAL_EXPIRED */ |
48 | 7, /* CONTEXT_EXPIRED */ |
49 | 11, /* FAILURE */ |
50 | 14, /* BAD_QOP */ |
51 | 15, /* UNAUTHORIZED */ |
52 | 16, /* UNAVAILABLE */ |
53 | 17, /* DUPLICATE_ELEMENT */ |
54 | 18, /* NAME_NOT_MN */ |
55 | }; |
56 | const char SPNEGO_BYTES[] = { |
57 | 0x2b, 0x06, 0x01, 0x05, 0x05, 0x02 |
58 | }; |
59 | |
60 | jclass CLS_Object; |
61 | jclass CLS_String; |
62 | jclass CLS_Oid; |
63 | jclass CLS_GSSException; |
64 | jclass CLS_GSSNameElement; |
65 | jclass CLS_GSSCredElement; |
66 | jclass CLS_NativeGSSContext; |
67 | jclass CLS_SunNativeProvider; |
68 | jmethodID MID_String_ctor; |
69 | jmethodID MID_Oid_ctor1; |
70 | jmethodID MID_Oid_getDER; |
71 | jmethodID MID_MessageProp_getPrivacy; |
72 | jmethodID MID_MessageProp_getQOP; |
73 | jmethodID MID_MessageProp_setPrivacy; |
74 | jmethodID MID_MessageProp_setQOP; |
75 | jmethodID MID_MessageProp_setSupplementaryStates; |
76 | jmethodID MID_GSSException_ctor3; |
77 | jmethodID MID_ChannelBinding_getInitiatorAddr; |
78 | jmethodID MID_ChannelBinding_getAcceptorAddr; |
79 | jmethodID MID_ChannelBinding_getAppData; |
80 | jmethodID MID_InetAddress_getAddr; |
81 | jmethodID MID_GSSNameElement_ctor; |
82 | jmethodID MID_GSSCredElement_ctor; |
83 | jmethodID MID_NativeGSSContext_ctor; |
84 | jfieldID FID_GSSLibStub_pMech; |
85 | jfieldID FID_NativeGSSContext_pContext; |
86 | jfieldID FID_NativeGSSContext_srcName; |
87 | jfieldID FID_NativeGSSContext_targetName; |
88 | jfieldID FID_NativeGSSContext_isInitiator; |
89 | jfieldID FID_NativeGSSContext_isEstablished; |
90 | jfieldID FID_NativeGSSContext_delegatedCred; |
91 | jfieldID FID_NativeGSSContext_flags; |
92 | jfieldID FID_NativeGSSContext_lifetime; |
93 | jfieldID FID_NativeGSSContext_actualMech; |
94 | |
95 | int JGSS_DEBUG; |
96 | |
97 | JNIEXPORT__attribute__((visibility("default"))) jint JNICALL |
98 | DEF_JNI_OnLoadJNI_OnLoad(JavaVM *jvm, void *reserved) { |
99 | JNIEnv *env; |
100 | jclass cls; |
101 | |
102 | if ((*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_20x00010002)) { |
103 | return JNI_EVERSION(-3); /* JNI version not supported */ |
104 | } |
105 | /* Retrieve and store the classes in global ref */ |
106 | cls = (*env)->FindClass(env, "java/lang/Object"); |
107 | if (cls == NULL((void*)0)) { |
108 | printf("Couldn't find Object class\n")__printf_chk (2 - 1, "Couldn't find Object class\n"); |
109 | return JNI_ERR(-1); |
110 | } |
111 | CLS_Object = (*env)->NewGlobalRef(env, cls); |
112 | if (CLS_Object == NULL((void*)0)) { |
113 | return JNI_ERR(-1); |
114 | } |
115 | cls = (*env)->FindClass(env, "java/lang/String"); |
116 | if (cls == NULL((void*)0)) { |
117 | printf("Couldn't find String class\n")__printf_chk (2 - 1, "Couldn't find String class\n"); |
118 | return JNI_ERR(-1); |
119 | } |
120 | CLS_String = (*env)->NewGlobalRef(env, cls); |
121 | if (CLS_String == NULL((void*)0)) { |
122 | return JNI_ERR(-1); |
123 | } |
124 | cls = (*env)->FindClass(env, "org/ietf/jgss/Oid"); |
125 | if (cls == NULL((void*)0)) { |
126 | printf("Couldn't find org.ietf.jgss.Oid class\n")__printf_chk (2 - 1, "Couldn't find org.ietf.jgss.Oid class\n" ); |
127 | return JNI_ERR(-1); |
128 | } |
129 | CLS_Oid = (*env)->NewGlobalRef(env, cls); |
130 | if (CLS_Oid == NULL((void*)0)) { |
131 | return JNI_ERR(-1); |
132 | } |
133 | cls = (*env)->FindClass(env, "org/ietf/jgss/GSSException"); |
134 | if (cls == NULL((void*)0)) { |
135 | printf("Couldn't find org.ietf.jgss.GSSException class\n")__printf_chk (2 - 1, "Couldn't find org.ietf.jgss.GSSException class\n" ); |
136 | return JNI_ERR(-1); |
137 | } |
138 | CLS_GSSException = (*env)->NewGlobalRef(env, cls); |
139 | if (CLS_GSSException == NULL((void*)0)) { |
140 | return JNI_ERR(-1); |
141 | } |
142 | cls = (*env)->FindClass(env, "sun/security/jgss/wrapper/GSSNameElement"); |
143 | if (cls == NULL((void*)0)) { |
144 | printf("Couldn't find sun.security.jgss.wrapper.GSSNameElement class\n")__printf_chk (2 - 1, "Couldn't find sun.security.jgss.wrapper.GSSNameElement class\n" ); |
145 | return JNI_ERR(-1); |
146 | } |
147 | CLS_GSSNameElement = (*env)->NewGlobalRef(env, cls); |
148 | if (CLS_GSSNameElement == NULL((void*)0)) { |
149 | return JNI_ERR(-1); |
150 | } |
151 | cls = (*env)->FindClass(env, "sun/security/jgss/wrapper/GSSCredElement"); |
152 | if (cls == NULL((void*)0)) { |
153 | printf("Couldn't find sun.security.jgss.wrapper.GSSCredElement class\n")__printf_chk (2 - 1, "Couldn't find sun.security.jgss.wrapper.GSSCredElement class\n" ); |
154 | return JNI_ERR(-1); |
155 | } |
156 | CLS_GSSCredElement = (*env)->NewGlobalRef(env, cls); |
157 | if (CLS_GSSCredElement == NULL((void*)0)) { |
158 | return JNI_ERR(-1); |
159 | } |
160 | cls = (*env)->FindClass(env, "sun/security/jgss/wrapper/NativeGSSContext"); |
161 | if (cls == NULL((void*)0)) { |
162 | printf("Couldn't find sun.security.jgss.wrapper.NativeGSSContext class\n")__printf_chk (2 - 1, "Couldn't find sun.security.jgss.wrapper.NativeGSSContext class\n" ); |
163 | return JNI_ERR(-1); |
164 | } |
165 | CLS_NativeGSSContext = (*env)->NewGlobalRef(env, cls); |
166 | if (CLS_NativeGSSContext == NULL((void*)0)) { |
167 | return JNI_ERR(-1); |
168 | } |
169 | cls = (*env)->FindClass(env, "sun/security/jgss/wrapper/SunNativeProvider"); |
170 | if (cls == NULL((void*)0)) { |
171 | printf("Couldn't find sun.security.jgss.wrapper.SunNativeProvider class\n")__printf_chk (2 - 1, "Couldn't find sun.security.jgss.wrapper.SunNativeProvider class\n" ); |
172 | return JNI_ERR(-1); |
173 | } |
174 | CLS_SunNativeProvider = (*env)->NewGlobalRef(env, cls); |
175 | if (CLS_SunNativeProvider == NULL((void*)0)) { |
176 | return JNI_ERR(-1); |
177 | } |
178 | /* Compute and cache the method ID */ |
179 | MID_String_ctor = (*env)->GetMethodID(env, CLS_String, |
180 | "<init>", "([B)V"); |
181 | if (MID_String_ctor == NULL((void*)0)) { |
182 | printf("Couldn't find String(byte[]) constructor\n")__printf_chk (2 - 1, "Couldn't find String(byte[]) constructor\n" ); |
183 | return JNI_ERR(-1); |
184 | } |
185 | MID_Oid_ctor1 = |
186 | (*env)->GetMethodID(env, CLS_Oid, "<init>", "([B)V"); |
187 | if (MID_Oid_ctor1 == NULL((void*)0)) { |
188 | printf("Couldn't find Oid(byte[]) constructor\n")__printf_chk (2 - 1, "Couldn't find Oid(byte[]) constructor\n" ); |
189 | return JNI_ERR(-1); |
190 | } |
191 | MID_Oid_getDER = (*env)->GetMethodID(env, CLS_Oid, "getDER", "()[B"); |
192 | if (MID_Oid_getDER == NULL((void*)0)) { |
193 | printf("Couldn't find Oid.getDER() method\n")__printf_chk (2 - 1, "Couldn't find Oid.getDER() method\n"); |
194 | return JNI_ERR(-1); |
195 | } |
196 | cls = (*env)->FindClass(env, "org/ietf/jgss/MessageProp"); |
197 | if (cls == NULL((void*)0)) { |
198 | printf("Couldn't find org.ietf.jgss.MessageProp class\n")__printf_chk (2 - 1, "Couldn't find org.ietf.jgss.MessageProp class\n" ); |
199 | return JNI_ERR(-1); |
200 | } |
201 | MID_MessageProp_getPrivacy = |
202 | (*env)->GetMethodID(env, cls, "getPrivacy", "()Z"); |
203 | if (MID_MessageProp_getPrivacy == NULL((void*)0)) { |
204 | printf("Couldn't find MessageProp.getPrivacy() method\n")__printf_chk (2 - 1, "Couldn't find MessageProp.getPrivacy() method\n" ); |
205 | return JNI_ERR(-1); |
206 | } |
207 | MID_MessageProp_getQOP = (*env)->GetMethodID(env, cls, "getQOP", "()I"); |
208 | if (MID_MessageProp_getQOP == NULL((void*)0)) { |
209 | printf("Couldn't find MessageProp.getQOP() method\n")__printf_chk (2 - 1, "Couldn't find MessageProp.getQOP() method\n" ); |
210 | return JNI_ERR(-1); |
211 | } |
212 | MID_MessageProp_setPrivacy = |
213 | (*env)->GetMethodID(env, cls, "setPrivacy", "(Z)V"); |
214 | if (MID_MessageProp_setPrivacy == NULL((void*)0)) { |
215 | printf("Couldn't find MessageProp.setPrivacy(boolean) method\n")__printf_chk (2 - 1, "Couldn't find MessageProp.setPrivacy(boolean) method\n" ); |
216 | return JNI_ERR(-1); |
217 | } |
218 | MID_MessageProp_setQOP = (*env)->GetMethodID(env, cls, "setQOP", "(I)V"); |
219 | if (MID_MessageProp_setQOP == NULL((void*)0)) { |
220 | printf("Couldn't find MessageProp.setQOP(int) method\n")__printf_chk (2 - 1, "Couldn't find MessageProp.setQOP(int) method\n" ); |
221 | return JNI_ERR(-1); |
222 | } |
223 | MID_MessageProp_setSupplementaryStates = |
224 | (*env)->GetMethodID(env, cls, "setSupplementaryStates", |
225 | "(ZZZZILjava/lang/String;)V"); |
226 | if (MID_MessageProp_setSupplementaryStates == NULL((void*)0)) { |
227 | printf("Couldn't find MessageProp.setSupplementaryStates(...) method\n")__printf_chk (2 - 1, "Couldn't find MessageProp.setSupplementaryStates(...) method\n" ); |
228 | return JNI_ERR(-1); |
229 | } |
230 | MID_GSSException_ctor3 = (*env)->GetMethodID |
231 | (env, CLS_GSSException, "<init>", "(IILjava/lang/String;)V"); |
232 | if (MID_GSSException_ctor3 == NULL((void*)0)) { |
233 | printf("Couldn't find GSSException(int, int, String) constructor\n")__printf_chk (2 - 1, "Couldn't find GSSException(int, int, String) constructor\n" ); |
234 | return JNI_ERR(-1); |
235 | } |
236 | cls = (*env)->FindClass(env, "org/ietf/jgss/ChannelBinding"); |
237 | if (cls == NULL((void*)0)) { |
238 | printf("Couldn't find org.ietf.jgss.ChannelBinding class\n")__printf_chk (2 - 1, "Couldn't find org.ietf.jgss.ChannelBinding class\n" ); |
239 | return JNI_ERR(-1); |
240 | } |
241 | MID_ChannelBinding_getInitiatorAddr = |
242 | (*env)->GetMethodID(env, cls, "getInitiatorAddress", |
243 | "()Ljava/net/InetAddress;"); |
244 | if (MID_ChannelBinding_getInitiatorAddr == NULL((void*)0)) { |
245 | printf("Couldn't find ChannelBinding.getInitiatorAddress() method\n")__printf_chk (2 - 1, "Couldn't find ChannelBinding.getInitiatorAddress() method\n" ); |
246 | return JNI_ERR(-1); |
247 | } |
248 | MID_ChannelBinding_getAcceptorAddr = |
249 | (*env)->GetMethodID(env, cls, "getAcceptorAddress", |
250 | "()Ljava/net/InetAddress;"); |
251 | if (MID_ChannelBinding_getAcceptorAddr == NULL((void*)0)) { |
252 | printf("Couldn't find ChannelBinding.getAcceptorAddress() method\n")__printf_chk (2 - 1, "Couldn't find ChannelBinding.getAcceptorAddress() method\n" ); |
253 | return JNI_ERR(-1); |
254 | } |
255 | MID_ChannelBinding_getAppData = |
256 | (*env)->GetMethodID(env, cls, "getApplicationData", "()[B"); |
257 | if (MID_ChannelBinding_getAppData == NULL((void*)0)) { |
258 | printf("Couldn't find ChannelBinding.getApplicationData() method\n")__printf_chk (2 - 1, "Couldn't find ChannelBinding.getApplicationData() method\n" ); |
259 | return JNI_ERR(-1); |
260 | } |
261 | cls = (*env)->FindClass(env, "java/net/InetAddress"); |
262 | if (cls == NULL((void*)0)) { |
263 | printf("Couldn't find java.net.InetAddress class\n")__printf_chk (2 - 1, "Couldn't find java.net.InetAddress class\n" ); |
264 | return JNI_ERR(-1); |
265 | } |
266 | MID_InetAddress_getAddr = (*env)->GetMethodID(env, cls, "getAddress", |
267 | "()[B"); |
268 | if (MID_InetAddress_getAddr == NULL((void*)0)) { |
269 | printf("Couldn't find InetAddress.getAddress() method\n")__printf_chk (2 - 1, "Couldn't find InetAddress.getAddress() method\n" ); |
270 | return JNI_ERR(-1); |
271 | } |
272 | MID_GSSNameElement_ctor = |
273 | (*env)->GetMethodID(env, CLS_GSSNameElement, |
274 | "<init>", "(JLsun/security/jgss/wrapper/GSSLibStub;)V"); |
275 | if (MID_GSSNameElement_ctor == NULL((void*)0)) { |
276 | printf("Couldn't find GSSNameElement(long, GSSLibStub) constructor\n")__printf_chk (2 - 1, "Couldn't find GSSNameElement(long, GSSLibStub) constructor\n" ); |
277 | return JNI_ERR(-1); |
278 | } |
279 | MID_GSSCredElement_ctor = |
280 | (*env)->GetMethodID(env, CLS_GSSCredElement, "<init>", |
281 | "(JLsun/security/jgss/wrapper/GSSNameElement;Lorg/ietf/jgss/Oid;)V"); |
282 | if (MID_GSSCredElement_ctor == NULL((void*)0)) { |
283 | printf("Couldn't find GSSCredElement(long, GSSLibStub) constructor\n")__printf_chk (2 - 1, "Couldn't find GSSCredElement(long, GSSLibStub) constructor\n" ); |
284 | return JNI_ERR(-1); |
285 | } |
286 | MID_NativeGSSContext_ctor = |
287 | (*env)->GetMethodID(env, CLS_NativeGSSContext, "<init>", |
288 | "(JLsun/security/jgss/wrapper/GSSLibStub;)V"); |
289 | if (MID_NativeGSSContext_ctor == NULL((void*)0)) { |
290 | printf("Couldn't find NativeGSSContext(long, GSSLibStub) constructor\n")__printf_chk (2 - 1, "Couldn't find NativeGSSContext(long, GSSLibStub) constructor\n" ); |
291 | return JNI_ERR(-1); |
292 | } |
293 | /* Compute and cache the field ID */ |
294 | cls = (*env)->FindClass(env, "sun/security/jgss/wrapper/GSSLibStub"); |
295 | if (cls == NULL((void*)0)) { |
296 | printf("Couldn't find sun.security.jgss.wrapper.GSSLibStub class\n")__printf_chk (2 - 1, "Couldn't find sun.security.jgss.wrapper.GSSLibStub class\n" ); |
297 | return JNI_ERR(-1); |
298 | } |
299 | FID_GSSLibStub_pMech = |
300 | (*env)->GetFieldID(env, cls, "pMech", "J"); |
301 | if (FID_GSSLibStub_pMech == NULL((void*)0)) { |
302 | printf("Couldn't find GSSLibStub.pMech field\n")__printf_chk (2 - 1, "Couldn't find GSSLibStub.pMech field\n" ); |
303 | return JNI_ERR(-1); |
304 | } |
305 | FID_NativeGSSContext_pContext = |
306 | (*env)->GetFieldID(env, CLS_NativeGSSContext, "pContext", "J"); |
307 | if (FID_NativeGSSContext_pContext == NULL((void*)0)) { |
308 | printf("Couldn't find NativeGSSContext.pContext field\n")__printf_chk (2 - 1, "Couldn't find NativeGSSContext.pContext field\n" ); |
309 | return JNI_ERR(-1); |
310 | } |
311 | FID_NativeGSSContext_srcName = |
312 | (*env)->GetFieldID(env, CLS_NativeGSSContext, "srcName", |
313 | "Lsun/security/jgss/wrapper/GSSNameElement;"); |
314 | if (FID_NativeGSSContext_srcName == NULL((void*)0)) { |
315 | printf("Couldn't find NativeGSSContext.srcName field\n")__printf_chk (2 - 1, "Couldn't find NativeGSSContext.srcName field\n" ); |
316 | return JNI_ERR(-1); |
317 | } |
318 | FID_NativeGSSContext_targetName = |
319 | (*env)->GetFieldID(env, CLS_NativeGSSContext, "targetName", |
320 | "Lsun/security/jgss/wrapper/GSSNameElement;"); |
321 | if (FID_NativeGSSContext_targetName == NULL((void*)0)) { |
322 | printf("Couldn't find NativeGSSContext.targetName field\n")__printf_chk (2 - 1, "Couldn't find NativeGSSContext.targetName field\n" ); |
323 | return JNI_ERR(-1); |
324 | } |
325 | FID_NativeGSSContext_isInitiator = |
326 | (*env)->GetFieldID(env, CLS_NativeGSSContext, "isInitiator", "Z"); |
327 | if (FID_NativeGSSContext_isInitiator == NULL((void*)0)) { |
328 | printf("Couldn't find NativeGSSContext.isInitiator field\n")__printf_chk (2 - 1, "Couldn't find NativeGSSContext.isInitiator field\n" ); |
329 | return JNI_ERR(-1); |
330 | } |
331 | FID_NativeGSSContext_isEstablished = |
332 | (*env)->GetFieldID(env, CLS_NativeGSSContext, "isEstablished", "Z"); |
333 | if (FID_NativeGSSContext_isEstablished == NULL((void*)0)) { |
334 | printf("Couldn't find NativeGSSContext.isEstablished field\n")__printf_chk (2 - 1, "Couldn't find NativeGSSContext.isEstablished field\n" ); |
335 | return JNI_ERR(-1); |
336 | } |
337 | FID_NativeGSSContext_delegatedCred = |
338 | (*env)->GetFieldID(env, CLS_NativeGSSContext, "delegatedCred", |
339 | "Lsun/security/jgss/wrapper/GSSCredElement;"); |
340 | if (FID_NativeGSSContext_delegatedCred == NULL((void*)0)) { |
341 | printf("Couldn't find NativeGSSContext.delegatedCred field\n")__printf_chk (2 - 1, "Couldn't find NativeGSSContext.delegatedCred field\n" ); |
342 | return JNI_ERR(-1); |
343 | } |
344 | FID_NativeGSSContext_flags = |
345 | (*env)->GetFieldID(env, CLS_NativeGSSContext, "flags", "I"); |
346 | if (FID_NativeGSSContext_flags == NULL((void*)0)) { |
347 | printf("Couldn't find NativeGSSContext.flags field\n")__printf_chk (2 - 1, "Couldn't find NativeGSSContext.flags field\n" ); |
348 | return JNI_ERR(-1); |
349 | } |
350 | FID_NativeGSSContext_lifetime = |
351 | (*env)->GetFieldID(env, CLS_NativeGSSContext, "lifetime", "I"); |
352 | if (FID_NativeGSSContext_lifetime == NULL((void*)0)) { |
353 | printf("Couldn't find NativeGSSContext.lifetime field\n")__printf_chk (2 - 1, "Couldn't find NativeGSSContext.lifetime field\n" ); |
354 | return JNI_ERR(-1); |
355 | } |
356 | FID_NativeGSSContext_actualMech = |
357 | (*env)->GetFieldID(env, CLS_NativeGSSContext, "actualMech", |
358 | "Lorg/ietf/jgss/Oid;"); |
359 | if (FID_NativeGSSContext_actualMech == NULL((void*)0)) { |
360 | printf("Couldn't find NativeGSSContext.actualMech field\n")__printf_chk (2 - 1, "Couldn't find NativeGSSContext.actualMech field\n" ); |
361 | return JNI_ERR(-1); |
362 | } |
363 | return JNI_VERSION_1_20x00010002; |
364 | } |
365 | |
366 | JNIEXPORT__attribute__((visibility("default"))) void JNICALL |
367 | DEF_JNI_OnUnloadJNI_OnUnload(JavaVM *jvm, void *reserved) { |
368 | JNIEnv *env; |
369 | |
370 | if ((*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_20x00010002)) { |
371 | return; |
372 | } |
373 | /* Delete the global refs */ |
374 | (*env)->DeleteGlobalRef(env, CLS_Object); |
375 | (*env)->DeleteGlobalRef(env, CLS_String); |
376 | (*env)->DeleteGlobalRef(env, CLS_Oid); |
377 | (*env)->DeleteGlobalRef(env, CLS_GSSException); |
378 | (*env)->DeleteGlobalRef(env, CLS_GSSNameElement); |
379 | (*env)->DeleteGlobalRef(env, CLS_GSSCredElement); |
380 | (*env)->DeleteGlobalRef(env, CLS_SunNativeProvider); |
381 | return; |
382 | } |
383 | |
384 | const OM_uint32 JAVA_MAX = GSS_C_INDEFINITE((OM_uint32) 0xfffffffful)/2; |
385 | |
386 | /* |
387 | * Utility routine for converting the C unsigned integer time |
388 | * to Java signed integer time. |
389 | */ |
390 | jint getJavaTime(OM_uint32 ctime) { |
391 | jint result; |
392 | |
393 | /* special handle values equals or more than JAVA_MAX */ |
394 | if (ctime == GSS_C_INDEFINITE((OM_uint32) 0xfffffffful)) { |
395 | result = JAVA_MAX; |
396 | } else if (ctime >= JAVA_MAX) { |
397 | result = JAVA_MAX-1; |
398 | } else { |
399 | result = ctime; |
400 | } |
401 | return result; |
402 | } |
403 | /* |
404 | * Utility routine for converting the Java signed integer time |
405 | * to C unsigned integer time. |
406 | */ |
407 | OM_uint32 getGSSTime(jint jtime) { |
408 | OM_uint32 result; |
409 | |
410 | /* special handle values equal to JAVA_MAX */ |
411 | if (jtime == (jint)JAVA_MAX) { |
412 | result = GSS_C_INDEFINITE((OM_uint32) 0xfffffffful); |
413 | } else { |
414 | result = jtime; |
415 | } |
416 | return result; |
417 | } |
418 | /* |
419 | * Utility routine for mapping the C error code to the |
420 | * Java one. The routine errors really should have |
421 | * shared the same values but unfortunately don't. |
422 | */ |
423 | jint getJavaErrorCode(int cNonCallingErr) { |
424 | int cRoutineErr, cSuppStatus; |
425 | /* map the routine errors */ |
426 | cRoutineErr = GSS_ROUTINE_ERROR(cNonCallingErr)((cNonCallingErr) & (((OM_uint32) 0377ul) << 16)) >> 16; |
427 | if (cRoutineErr != GSS_S_COMPLETE0) { |
428 | return JAVA_ERROR_CODE[cRoutineErr-1]; |
429 | } |
430 | /* map the supplementary infos */ |
431 | cSuppStatus = GSS_SUPPLEMENTARY_INFO(cNonCallingErr)((cNonCallingErr) & (((OM_uint32) 0177777ul) << 0)); |
432 | if (cSuppStatus & GSS_S_DUPLICATE_TOKEN(1 << (0 + 1))) { |
433 | return JAVA_DUPLICATE_TOKEN_CODE; |
434 | } else if (cSuppStatus & GSS_S_OLD_TOKEN(1 << (0 + 2))) { |
435 | return JAVA_OLD_TOKEN_CODE; |
436 | } else if (cSuppStatus & GSS_S_UNSEQ_TOKEN(1 << (0 + 3))) { |
437 | return JAVA_UNSEQ_TOKEN_CODE; |
438 | } else if (cSuppStatus & GSS_S_GAP_TOKEN(1 << (0 + 4))) { |
439 | return JAVA_GAP_TOKEN_CODE; |
440 | } |
441 | return GSS_S_COMPLETE0; |
442 | } |
443 | |
444 | |
445 | /* Throws a Java Exception by name */ |
446 | void throwByName(JNIEnv *env, const char *name, const char *msg) { |
447 | jclass cls = (*env)->FindClass(env, name); |
448 | |
449 | if (cls != NULL((void*)0)) { |
450 | (*env)->ThrowNew(env, cls, msg); |
451 | } |
452 | } |
453 | |
454 | void throwOutOfMemoryError(JNIEnv *env, const char *message) { |
455 | throwByName(env, "java/lang/OutOfMemoryError", message); |
456 | } |
457 | |
458 | /* |
459 | * Utility routine for creating a java.lang.String object |
460 | * using the specified gss_buffer_t structure. The specified |
461 | * gss_buffer_t structure is always released. |
462 | */ |
463 | jstring getJavaString(JNIEnv *env, gss_buffer_t bytes) { |
464 | jstring result = NULL((void*)0); |
465 | OM_uint32 minor; |
466 | int len; |
467 | jbyteArray jbytes; |
468 | |
469 | if (bytes != NULL((void*)0)) { |
470 | /* constructs the String object with new String(byte[]) |
471 | NOTE: do NOT include the trailing NULL */ |
472 | len = (int) bytes->length; |
473 | jbytes = (*env)->NewByteArray(env, len); |
474 | if (jbytes == NULL((void*)0)) { |
475 | goto finish; |
476 | } |
477 | |
478 | (*env)->SetByteArrayRegion(env, jbytes, 0, len, (jbyte *) bytes->value); |
479 | if ((*env)->ExceptionCheck(env)) { |
480 | goto finish; |
481 | } |
482 | |
483 | result = (*env)->NewObject(env, CLS_String, MID_String_ctor, |
484 | jbytes); |
485 | finish: |
486 | (*env)->DeleteLocalRef(env, jbytes); |
487 | (*ftab->releaseBuffer)(&minor, bytes); |
488 | return result; |
489 | } /* else fall through */ |
490 | return NULL((void*)0); |
491 | } |
492 | /* |
493 | * Utility routine for generate message for the specified minor |
494 | * status code. |
495 | */ |
496 | jstring getMinorMessage(JNIEnv *env, jobject jstub, OM_uint32 statusValue) { |
497 | OM_uint32 messageContext, minor, major; |
498 | gss_buffer_desc statusString; |
499 | gss_OID mech; |
500 | |
501 | messageContext = 0; |
502 | if (jstub != NULL((void*)0)) { |
503 | mech = (gss_OID) jlong_to_ptr((*env)->GetLongField(env, jstub, FID_GSSLibStub_pMech))((void*)((*env)->GetLongField(env, jstub, FID_GSSLibStub_pMech ))); |
504 | } else { |
505 | mech = GSS_C_NO_OID((gss_OID) 0); |
506 | } |
507 | |
508 | /* gss_display_status(...) => GSS_S_BAD_MECH, GSS_S_BAD_STATUS */ |
509 | // TBD: check messageContext value and repeat the call if necessary |
510 | major = (*ftab->displayStatus)(&minor, statusValue, GSS_C_MECH_CODE2, mech, |
Value stored to 'major' is never read | |
511 | &messageContext, &statusString); |
512 | |
513 | return getJavaString(env, &statusString); |
514 | } |
515 | |
516 | /* |
517 | * Utility routine checking the specified major and minor |
518 | * status codes. GSSExceptions will be thrown if they are |
519 | * not GSS_S_COMPLETE (i.e. 0). |
520 | */ |
521 | void checkStatus(JNIEnv *env, jobject jstub, OM_uint32 major, |
522 | OM_uint32 minor, char* methodName) { |
523 | int callingErr, routineErr, supplementaryInfo; |
524 | jint jmajor, jminor; |
525 | char* msg; |
526 | jstring jmsg; |
527 | jthrowable gssEx; |
528 | |
529 | if (major == GSS_S_COMPLETE0) return; |
530 | |
531 | callingErr = GSS_CALLING_ERROR(major)((major) & (((OM_uint32) 0377ul) << 24)); |
532 | routineErr = GSS_ROUTINE_ERROR(major)((major) & (((OM_uint32) 0377ul) << 16)); |
533 | supplementaryInfo = GSS_SUPPLEMENTARY_INFO(major)((major) & (((OM_uint32) 0177777ul) << 0)); |
534 | |
535 | TRACE3("%s Status major/minor = %x/%d", methodName, major, minor){ if (JGSS_DEBUG) { __printf_chk (2 - 1, "[GSSLibStub:%d] ""%s Status major/minor = %x/%d" "\n", 535, methodName, major, minor); fflush(stdout); }}; |
536 | TRACE3("c/r/s = %d/%d/%d ", callingErr>>24, routineErr>>16,{ if (JGSS_DEBUG) { __printf_chk (2 - 1, "[GSSLibStub:%d] ""c/r/s = %d/%d/%d " "\n", 537, callingErr>>24, routineErr>>16, supplementaryInfo ); fflush(stdout); }} |
537 | supplementaryInfo){ if (JGSS_DEBUG) { __printf_chk (2 - 1, "[GSSLibStub:%d] ""c/r/s = %d/%d/%d " "\n", 537, callingErr>>24, routineErr>>16, supplementaryInfo ); fflush(stdout); }}; |
538 | |
539 | jmajor = getJavaErrorCode(routineErr | supplementaryInfo); |
540 | jminor = minor; |
541 | if (jmajor != GSS_S_COMPLETE0) { |
542 | jmsg = NULL((void*)0); |
543 | if (minor != 0) { |
544 | jmsg = getMinorMessage(env, jstub, minor); |
545 | if ((*env)->ExceptionCheck(env)) { |
546 | return; |
547 | } |
548 | } |
549 | |
550 | gssEx = (*env)->NewObject(env, CLS_GSSException, |
551 | MID_GSSException_ctor3, |
552 | jmajor, jminor, jmsg); |
553 | if (gssEx != NULL((void*)0)) { |
554 | (*env)->Throw(env, gssEx); |
555 | } |
556 | } else { |
557 | /* Error in calling the GSS api */ |
558 | if (callingErr == GSS_S_CALL_INACCESSIBLE_READ(((OM_uint32) 1ul) << 24)) { |
559 | msg = "A required input parameter cannot be read"; |
560 | } else if (callingErr == GSS_S_CALL_INACCESSIBLE_WRITE(((OM_uint32) 2ul) << 24)) { |
561 | msg = "A required output parameter cannot be write"; |
562 | } else { |
563 | msg = "A parameter was malformed"; |
564 | } |
565 | jmajor = 13; /* use GSSException.FAILURE for now */ |
566 | jmsg = (*env)->NewStringUTF(env, msg); |
567 | if (jmsg == NULL((void*)0)) { |
568 | return; |
569 | } |
570 | gssEx = (*env)->NewObject(env, CLS_GSSException, |
571 | MID_GSSException_ctor3, |
572 | jmajor, jminor, jmsg); |
573 | if (gssEx != NULL((void*)0)) { |
574 | (*env)->Throw(env, gssEx); |
575 | } |
576 | } |
577 | } |
578 | |
579 | /* |
580 | * Utility routine for initializing gss_buffer_t structure |
581 | * with the byte[] in the specified jbyteArray object. |
582 | * NOTE: must call resetGSSBuffer() to free up the resources |
583 | * inside the gss_buffer_t structure. |
584 | */ |
585 | void initGSSBuffer(JNIEnv *env, jbyteArray jbytes, |
586 | gss_buffer_t cbytes) { |
587 | |
588 | int len; |
589 | void* value; |
590 | |
591 | if (jbytes != NULL((void*)0)) { |
592 | len = (*env)->GetArrayLength(env, jbytes); |
593 | value = malloc(len); |
594 | if (value == NULL((void*)0)) { |
595 | throwOutOfMemoryError(env, NULL((void*)0)); |
596 | return; |
597 | } else { |
598 | (*env)->GetByteArrayRegion(env, jbytes, 0, len, value); |
599 | if ((*env)->ExceptionCheck(env)) { |
600 | free(value); |
601 | return; |
602 | } else { |
603 | cbytes->length = len; |
604 | cbytes->value = value; |
605 | } |
606 | } |
607 | } else { |
608 | cbytes->length = 0; |
609 | cbytes->value = NULL((void*)0); |
610 | } |
611 | } |
612 | |
613 | /* |
614 | * Utility routine for freeing the bytes malloc'ed |
615 | * in initGSSBuffer() method. |
616 | * NOTE: used in conjunction with initGSSBuffer(...). |
617 | */ |
618 | void resetGSSBuffer(gss_buffer_t cbytes) { |
619 | if ((cbytes != NULL((void*)0)) && (cbytes != GSS_C_NO_BUFFER((gss_buffer_t) 0))) { |
620 | free(cbytes->value); |
621 | cbytes->length = 0; |
622 | cbytes->value = NULL((void*)0); |
623 | } |
624 | } |
625 | |
626 | /* |
627 | * Utility routine for creating a jbyteArray object using |
628 | * the byte[] value in specified gss_buffer_t structure. |
629 | * NOTE: the specified gss_buffer_t structure is always |
630 | * released. |
631 | */ |
632 | jbyteArray getJavaBuffer(JNIEnv *env, gss_buffer_t cbytes) { |
633 | jbyteArray result = NULL((void*)0); |
634 | OM_uint32 minor; // don't care, just so it compiles |
635 | |
636 | if (cbytes != NULL((void*)0)) { |
637 | if ((cbytes != GSS_C_NO_BUFFER((gss_buffer_t) 0)) && (cbytes->length != 0)) { |
638 | result = (*env)->NewByteArray(env, (int) cbytes->length); |
639 | if (result == NULL((void*)0)) { |
640 | goto finish; |
641 | } |
642 | (*env)->SetByteArrayRegion(env, result, 0, (int) cbytes->length, |
643 | cbytes->value); |
644 | if ((*env)->ExceptionCheck(env)) { |
645 | result = NULL((void*)0); |
646 | } |
647 | } |
648 | finish: |
649 | (*ftab->releaseBuffer)(&minor, cbytes); |
650 | return result; |
651 | } |
652 | return NULL((void*)0); |
653 | } |
654 | |
655 | /* |
656 | * Utility routine for creating a non-mech gss_OID using |
657 | * the specified org.ietf.jgss.Oid object. |
658 | * NOTE: must call deleteGSSOID(...) to free up the gss_OID. |
659 | */ |
660 | gss_OID newGSSOID(JNIEnv *env, jobject jOid) { |
661 | jbyteArray jbytes; |
662 | gss_OID cOid; |
663 | if (jOid != NULL((void*)0)) { |
664 | jbytes = (*env)->CallObjectMethod(env, jOid, MID_Oid_getDER); |
665 | if ((*env)->ExceptionCheck(env)) { |
666 | return GSS_C_NO_OID((gss_OID) 0); |
667 | } |
668 | cOid = malloc(sizeof(struct gss_OID_desc_struct)); |
669 | if (cOid == NULL((void*)0)) { |
670 | throwOutOfMemoryError(env,NULL((void*)0)); |
671 | return GSS_C_NO_OID((gss_OID) 0); |
672 | } |
673 | cOid->length = (*env)->GetArrayLength(env, jbytes) - 2; |
674 | cOid->elements = malloc(cOid->length); |
675 | if (cOid->elements == NULL((void*)0)) { |
676 | throwOutOfMemoryError(env,NULL((void*)0)); |
677 | goto cleanup; |
678 | } |
679 | (*env)->GetByteArrayRegion(env, jbytes, 2, cOid->length, |
680 | cOid->elements); |
681 | if ((*env)->ExceptionCheck(env)) { |
682 | goto cleanup; |
683 | } |
684 | return cOid; |
685 | } else { |
686 | return GSS_C_NO_OID((gss_OID) 0); |
687 | } |
688 | cleanup: |
689 | (*env)->DeleteLocalRef(env, jbytes); |
690 | free(cOid->elements); |
691 | free(cOid); |
692 | return GSS_C_NO_OID((gss_OID) 0); |
693 | } |
694 | |
695 | /* |
696 | * Utility routine for releasing the specified gss_OID |
697 | * structure. |
698 | * NOTE: used in conjunction with newGSSOID(...). |
699 | */ |
700 | void deleteGSSOID(gss_OID oid) { |
701 | if (oid != GSS_C_NO_OID((gss_OID) 0)) { |
702 | free(oid->elements); |
703 | free(oid); |
704 | } |
705 | } |
706 | |
707 | /* |
708 | * Utility routine for creating a org.ietf.jgss.Oid |
709 | * object using the specified gss_OID structure. |
710 | */ |
711 | jobject getJavaOID(JNIEnv *env, gss_OID cOid) { |
712 | int cLen; |
713 | char oidHdr[2]; |
714 | jbyteArray jbytes; |
715 | jobject result = NULL((void*)0); |
716 | |
717 | if ((cOid == NULL((void*)0)) || (cOid == GSS_C_NO_OID((gss_OID) 0))) { |
718 | return NULL((void*)0); |
719 | } |
720 | cLen = cOid->length; |
721 | oidHdr[0] = 6; |
722 | oidHdr[1] = cLen; |
723 | jbytes = (*env)->NewByteArray(env, cLen+2); |
724 | if (jbytes == NULL((void*)0)) { |
725 | return NULL((void*)0); |
726 | } |
727 | if (!(*env)->ExceptionCheck(env)) { |
728 | (*env)->SetByteArrayRegion(env, jbytes, 0, 2, (jbyte *) oidHdr); |
729 | } |
730 | if (!(*env)->ExceptionCheck(env)) { |
731 | (*env)->SetByteArrayRegion(env, jbytes, 2, cLen, (jbyte *) cOid->elements); |
732 | } |
733 | if (!(*env)->ExceptionCheck(env)) { |
734 | result = (*env)->NewObject(env, CLS_Oid, MID_Oid_ctor1, jbytes); |
735 | } |
736 | (*env)->DeleteLocalRef(env, jbytes); |
737 | return result; |
738 | } |
739 | /* |
740 | * Utility routine for creating a gss_OID_set structure |
741 | * using the specified gss_OID. |
742 | * NOTE: need to call deleteGSSOIDSet(...) afterwards |
743 | * to release the created gss_OID_set structure. |
744 | */ |
745 | gss_OID_set newGSSOIDSet(gss_OID oid) { |
746 | gss_OID_set oidSet; |
747 | OM_uint32 minor; // don't care; just so it compiles |
748 | |
749 | if (oid->length != 6 || |
750 | memcmp(oid->elements, SPNEGO_BYTES, 6) != 0) { |
751 | (*ftab->createEmptyOidSet)(&minor, &oidSet); |
752 | (*ftab->addOidSetMember)(&minor, oid, &oidSet); |
753 | return oidSet; |
754 | } else { |
755 | // Use all mechs for SPNEGO in order to work with |
756 | // various native GSS impls |
757 | return (ftab->mechs); |
758 | } |
759 | } |
760 | /* |
761 | * Utility routine for releasing a gss_OID_set structure. |
762 | * NOTE: used in conjunction with newGSSOIDSet(...). |
763 | */ |
764 | void deleteGSSOIDSet(gss_OID_set oidSet) { |
765 | OM_uint32 minor; /* don't care; just so it compiles */ |
766 | |
767 | if ((oidSet != ftab->mechs) && |
768 | (oidSet != NULL((void*)0)) && (oidSet != GSS_C_NO_OID_SET((gss_OID_set) 0))) { |
769 | (*ftab->releaseOidSet)(&minor, &oidSet); |
770 | } |
771 | } |
772 | /* |
773 | * Utility routine for creating a org.ietf.jgss.Oid[] |
774 | * using the specified gss_OID_set structure. |
775 | */ |
776 | jobjectArray getJavaOIDArray(JNIEnv *env, gss_OID_set cOidSet) { |
777 | int numOfOids = 0; |
778 | jobjectArray jOidSet; |
779 | jobject jOid; |
780 | int i; |
781 | |
782 | if (cOidSet != NULL((void*)0) && cOidSet != GSS_C_NO_OID_SET((gss_OID_set) 0)) { |
783 | numOfOids = (int) cOidSet->count; |
784 | jOidSet = (*env)->NewObjectArray(env, numOfOids, CLS_Oid, NULL((void*)0)); |
785 | if ((*env)->ExceptionCheck(env)) { |
786 | return NULL((void*)0); |
787 | } |
788 | for (i = 0; i < numOfOids; i++) { |
789 | jOid = getJavaOID(env, &(cOidSet->elements[i])); |
790 | if ((*env)->ExceptionCheck(env)) { |
791 | return NULL((void*)0); |
792 | } |
793 | (*env)->SetObjectArrayElement(env, jOidSet, i, jOid); |
794 | if ((*env)->ExceptionCheck(env)) { |
795 | return NULL((void*)0); |
796 | } |
797 | (*env)->DeleteLocalRef(env, jOid); |
798 | } |
799 | return jOidSet; |
800 | } |
801 | return NULL((void*)0); |
802 | } |
803 | |
804 | int sameMech(gss_OID mech, gss_OID mech2) { |
805 | int result = JNI_FALSE0; // default to not equal |
806 | |
807 | if (mech->length == mech2->length) { |
808 | result = (memcmp(mech->elements, mech2->elements, mech->length) == 0); |
809 | } |
810 | return result; |
811 | } |