@@ -144,7 +144,7 @@ bool verify_X509_cert_chain(const std::vector<std::string> &certChain, const std
144
144
// / Helper function to check return value and see if any exceptions
145
145
// / occurred when calling a JNI function.
146
146
// / <summary>
147
- // / <returns><c>true</c> if JNI call <c>failed </c>, false othewise.</returns>
147
+ // / <returns><c>true</c> if JNI call failed, <c>false </c> othewise.</returns>
148
148
bool jni_failed (JNIEnv *env)
149
149
{
150
150
if (env->ExceptionOccurred ())
@@ -158,18 +158,25 @@ bool jni_failed(JNIEnv *env)
158
158
return false ;
159
159
}
160
160
template <typename T>
161
- bool jni_failed (JNIEnv *env, const T &result)
161
+ bool jni_failed (JNIEnv *env, const java_local_ref<T> &result)
162
162
{
163
- if (jni_failed (env))
163
+ if (jni_failed (env) || !result )
164
164
{
165
165
return true ;
166
166
}
167
- else if (result == nullptr )
167
+ return false ;
168
+ }
169
+ bool jni_failed (JNIEnv *env, const jmethodID &result)
170
+ {
171
+ if (jni_failed (env) || result == nullptr )
168
172
{
169
173
return true ;
170
174
}
171
175
return false ;
172
176
}
177
+ #define CHECK_JREF (env, obj ) if (jni_failed<decltype (obj)::element_type>(env, obj)) return false ;
178
+ #define CHECK_JMID (env, mid ) if (jni_failed(env, mid)) return false ;
179
+ #define CHECK_JNI (env ) if (jni_failed(env)) return false ;
173
180
174
181
bool verify_X509_cert_chain (const std::vector<std::string> &certChain, const std::string &hostName)
175
182
{
@@ -183,136 +190,82 @@ bool verify_X509_cert_chain(const std::vector<std::string> &certChain, const std
183
190
184
191
// ByteArrayInputStream
185
192
java_local_ref<jclass> byteArrayInputStreamClass (env->FindClass (" java/io/ByteArrayInputStream" ));
186
- if (jni_failed (env, byteArrayInputStreamClass))
187
- {
188
- return false ;
189
- }
193
+ CHECK_JREF (env, byteArrayInputStreamClass);
190
194
jmethodID byteArrayInputStreamConstructorMethod = env->GetMethodID (
191
195
byteArrayInputStreamClass.get (),
192
196
" <init>" ,
193
197
" ([B)V" );
194
- if (jni_failed (env, byteArrayInputStreamConstructorMethod))
195
- {
196
- return false ;
197
- }
198
+ CHECK_JMID (env, byteArrayInputStreamConstructorMethod);
198
199
199
200
// CertificateFactory
200
201
java_local_ref<jclass> certificateFactoryClass (env->FindClass (" java/security/cert/CertificateFactory" ));
201
- if (jni_failed (env, certificateFactoryClass))
202
- {
203
- return false ;
204
- }
202
+ CHECK_JREF (env, certificateFactoryClass);
205
203
jmethodID certificateFactoryGetInstanceMethod = env->GetStaticMethodID (
206
204
certificateFactoryClass.get (),
207
205
" getInstance" ,
208
206
" (Ljava/lang/String;)Ljava/security/cert/CertificateFactory;" );
209
- if (jni_failed (env, certificateFactoryGetInstanceMethod))
210
- {
211
- return false ;
212
- }
207
+ CHECK_JMID (env, certificateFactoryGetInstanceMethod);
213
208
jmethodID generateCertificateMethod = env->GetMethodID (
214
209
certificateFactoryClass.get (),
215
210
" generateCertificate" ,
216
211
" (Ljava/io/InputStream;)Ljava/security/cert/Certificate;" );
217
- if (jni_failed (env, generateCertificateMethod))
218
- {
219
- return false ;
220
- }
212
+ CHECK_JMID (env, generateCertificateMethod);
221
213
222
214
// X509Certificate
223
215
java_local_ref<jclass> X509CertificateClass (env->FindClass (" java/security/cert/X509Certificate" ));
224
- if (jni_failed (env, X509CertificateClass))
225
- {
226
- return false ;
227
- }
216
+ CHECK_JREF (env, X509CertificateClass);
228
217
229
218
// TrustManagerFactory
230
219
java_local_ref<jclass> trustManagerFactoryClass (env->FindClass (" javax/net/ssl/TrustManagerFactory" ));
231
- if (jni_failed (env, trustManagerFactoryClass))
232
- {
233
- return false ;
234
- }
220
+ CHECK_JREF (env, trustManagerFactoryClass);
235
221
jmethodID trustManagerFactoryGetInstanceMethod = env->GetStaticMethodID (
236
222
trustManagerFactoryClass.get (),
237
223
" getInstance" ,
238
224
" (Ljava/lang/String;)Ljavax/net/ssl/TrustManagerFactory;" );
239
- if (jni_failed (env, trustManagerFactoryGetInstanceMethod))
240
- {
241
- return false ;
242
- }
225
+ CHECK_JMID (env, trustManagerFactoryGetInstanceMethod);
243
226
jmethodID trustManagerFactoryInitMethod = env->GetMethodID (
244
227
trustManagerFactoryClass.get (),
245
228
" init" ,
246
229
" (Ljava/security/KeyStore;)V" );
247
- if (jni_failed (env, trustManagerFactoryInitMethod))
248
- {
249
- return false ;
250
- }
230
+ CHECK_JMID (env, trustManagerFactoryInitMethod);
251
231
jmethodID trustManagerFactoryGetTrustManagersMethod = env->GetMethodID (
252
232
trustManagerFactoryClass.get (),
253
233
" getTrustManagers" ,
254
234
" ()[Ljavax/net/ssl/TrustManager;" );
255
- if (jni_failed (env, trustManagerFactoryGetTrustManagersMethod))
256
- {
257
- return false ;
258
- }
235
+ CHECK_JMID (env, trustManagerFactoryGetTrustManagersMethod);
259
236
260
237
// X509TrustManager
261
238
java_local_ref<jclass> X509TrustManagerClass (env->FindClass (" javax/net/ssl/X509TrustManager" ));
262
- if (jni_failed (env, X509TrustManagerClass))
263
- {
264
- return false ;
265
- }
239
+ CHECK_JREF (env, X509TrustManagerClass);
266
240
jmethodID X509TrustManagerCheckServerTrustedMethod = env->GetMethodID (
267
241
X509TrustManagerClass.get (),
268
242
" checkServerTrusted" ,
269
243
" ([Ljava/security/cert/X509Certificate;Ljava/lang/String;)V" );
270
- if (jni_failed (env, X509TrustManagerCheckServerTrustedMethod))
271
- {
272
- return false ;
273
- }
244
+ CHECK_JMID (env, X509TrustManagerCheckServerTrustedMethod);
274
245
275
246
// StrictHostnameVerifier
276
247
java_local_ref<jclass> strictHostnameVerifierClass (env->FindClass (" org/apache/http/conn/ssl/StrictHostnameVerifier" ));
277
- if (jni_failed (env, strictHostnameVerifierClass))
278
- {
279
- return false ;
280
- }
248
+ CHECK_JREF (env, strictHostnameVerifierClass);
281
249
jmethodID strictHostnameVerifierConstructorMethod = env->GetMethodID (strictHostnameVerifierClass.get (), " <init>" , " ()V" );
282
- if (jni_failed (env, strictHostnameVerifierConstructorMethod))
283
- {
284
- return false ;
285
- }
250
+ CHECK_JMID (env, strictHostnameVerifierConstructorMethod);
286
251
jmethodID strictHostnameVerifierVerifyMethod = env->GetMethodID (
287
252
strictHostnameVerifierClass.get (),
288
253
" verify" ,
289
254
" (Ljava/lang/String;Ljava/security/cert/X509Certificate;)V" );
290
- if (jni_failed (env, strictHostnameVerifierVerifyMethod))
291
- {
292
- return false ;
293
- }
255
+ CHECK_JMID (env, strictHostnameVerifierVerifyMethod);
294
256
295
257
// Create CertificateFactory
296
258
java_local_ref<jstring> XDot509String (env->NewStringUTF (" X.509" ));
297
- if (jni_failed (env, XDot509String))
298
- {
299
- return false ;
300
- }
259
+ CHECK_JREF (env, XDot509String);
301
260
java_local_ref<jobject> certificateFactory (env->CallStaticObjectMethod (
302
261
certificateFactoryClass.get (),
303
262
certificateFactoryGetInstanceMethod,
304
263
XDot509String.get ()));
305
- if (jni_failed (env, certificateFactory))
306
- {
307
- return false ;
308
- }
264
+ CHECK_JREF (env, certificateFactory);
309
265
310
266
// Create Java array to store all the certs in.
311
267
java_local_ref<jobjectArray> certsArray (env->NewObjectArray (certChain.size (), X509CertificateClass.get (), nullptr ));
312
- if (jni_failed (env, certsArray))
313
- {
314
- return false ;
315
- }
268
+ CHECK_JREF (env, certsArray);
316
269
317
270
// For each certificate perform the following steps:
318
271
// 1. Create ByteArrayInputStream backed by DER certificate bytes
@@ -322,116 +275,68 @@ bool verify_X509_cert_chain(const std::vector<std::string> &certChain, const std
322
275
for (const auto &certData : certChain)
323
276
{
324
277
java_local_ref<jbyteArray> byteArray (env->NewByteArray (certData.size ()));
325
- if (jni_failed (env, byteArray))
326
- {
327
- return false ;
328
- }
278
+ CHECK_JREF (env, byteArray);
329
279
env->SetByteArrayRegion (byteArray.get (), 0 , certData.size (), reinterpret_cast <const jbyte *>(certData.c_str ()));
330
- if (jni_failed (env))
331
- {
332
- return false ;
333
- }
280
+ CHECK_JNI (env);
334
281
java_local_ref<jobject> byteArrayInputStream (env->NewObject (
335
282
byteArrayInputStreamClass.get (),
336
283
byteArrayInputStreamConstructorMethod,
337
284
byteArray.get ()));
338
- if (jni_failed (env, byteArrayInputStream))
339
- {
340
- return false ;
341
- }
285
+ CHECK_JREF (env, byteArrayInputStream);
342
286
343
287
java_local_ref<jobject> cert (env->CallObjectMethod (
344
288
certificateFactory.get (),
345
289
generateCertificateMethod,
346
290
byteArrayInputStream.get ()));
347
- if (jni_failed (env, cert))
348
- {
349
- return false ;
350
- }
291
+ CHECK_JREF (env, cert);
351
292
352
293
env->SetObjectArrayElement (certsArray.get (), i, cert.get ());
353
- if (jni_failed (env))
354
- {
355
- return false ;
356
- }
294
+ CHECK_JNI (env);
357
295
++i;
358
296
}
359
297
360
298
// Create TrustManagerFactory, init with Android system certs
361
299
java_local_ref<jstring> X509String (env->NewStringUTF (" X509" ));
362
- if (jni_failed (env, X509String))
363
- {
364
- return false ;
365
- }
300
+ CHECK_JREF (env, X509String);
366
301
java_local_ref<jobject> trustFactoryManager (env->CallStaticObjectMethod (
367
302
trustManagerFactoryClass.get (),
368
303
trustManagerFactoryGetInstanceMethod,
369
304
X509String.get ()));
370
- if (jni_failed (env, trustFactoryManager))
371
- {
372
- return false ;
373
- }
305
+ CHECK_JREF (env, trustFactoryManager);
374
306
env->CallVoidMethod (trustFactoryManager.get (), trustManagerFactoryInitMethod, nullptr );
375
- if (jni_failed (env))
376
- {
377
- return false ;
378
- }
307
+ CHECK_JNI (env);
379
308
380
309
// Get TrustManager
381
310
java_local_ref<jobjectArray> trustManagerArray (static_cast <jobjectArray>(
382
311
env->CallObjectMethod (trustFactoryManager.get (), trustManagerFactoryGetTrustManagersMethod)));
383
- if (jni_failed (env, trustManagerArray))
384
- {
385
- return false ;
386
- }
312
+ CHECK_JREF (env, trustManagerArray);
387
313
java_local_ref<jobject> trustManager (env->GetObjectArrayElement (trustManagerArray.get (), 0 ));
388
- if (jni_failed (env, trustManager))
389
- {
390
- return false ;
391
- }
314
+ CHECK_JREF (env, trustManager);
392
315
393
316
// Validate certificate chain.
394
317
java_local_ref<jstring> RSAString (env->NewStringUTF (" RSA" ));
395
- if (jni_failed (env, RSAString))
396
- {
397
- return false ;
398
- }
318
+ CHECK_JREF (env, RSAString);
399
319
env->CallVoidMethod (
400
320
trustManager.get (),
401
321
X509TrustManagerCheckServerTrustedMethod,
402
322
certsArray.get (),
403
323
RSAString.get ());
404
- if (jni_failed (env))
405
- {
406
- return false ;
407
- }
324
+ CHECK_JNI (env);
408
325
409
326
// Verify hostname on certificate according to RFC 2818.
410
327
java_local_ref<jobject> hostnameVerifier (env->NewObject (
411
328
strictHostnameVerifierClass.get (), strictHostnameVerifierConstructorMethod));
412
- if (jni_failed (env, hostnameVerifier))
413
- {
414
- return false ;
415
- }
329
+ CHECK_JREF (env, hostnameVerifier);
416
330
java_local_ref<jstring> hostNameString (env->NewStringUTF (hostName.c_str ()));
417
- if (jni_failed (env, hostNameString))
418
- {
419
- return false ;
420
- }
331
+ CHECK_JREF (env, hostNameString);
421
332
java_local_ref<jobject> cert (env->GetObjectArrayElement (certsArray.get (), 0 ));
422
- if (jni_failed (env, cert))
423
- {
424
- return false ;
425
- }
333
+ CHECK_JREF (env, cert);
426
334
env->CallVoidMethod (
427
335
hostnameVerifier.get (),
428
336
strictHostnameVerifierVerifyMethod,
429
337
hostNameString.get (),
430
338
cert.get ());
431
- if (jni_failed (env))
432
- {
433
- return false ;
434
- }
339
+ CHECK_JNI (env);
435
340
436
341
return true ;
437
342
}
0 commit comments