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