@@ -42,11 +42,13 @@ using ncrypto::MarkPopErrorOnReturn;
42
42
using ncrypto::SSLPointer;
43
43
using ncrypto::StackOfX509;
44
44
using ncrypto::X509Pointer;
45
+ using ncrypto::X509View;
45
46
using v8::Array;
46
47
using v8::ArrayBufferView;
47
48
using v8::Boolean ;
48
49
using v8::Context;
49
50
using v8::DontDelete;
51
+ using v8::EscapableHandleScope;
50
52
using v8::Exception;
51
53
using v8::External;
52
54
using v8::FunctionCallbackInfo;
@@ -57,7 +59,9 @@ using v8::Integer;
57
59
using v8::Isolate;
58
60
using v8::JustVoid;
59
61
using v8::Local;
62
+ using v8::LocalVector;
60
63
using v8::Maybe;
64
+ using v8::MaybeLocal;
61
65
using v8::Nothing;
62
66
using v8::Object;
63
67
using v8::PropertyAttribute;
@@ -672,9 +676,6 @@ static void LoadCertsFromDir(std::vector<X509*>* certs,
672
676
return ;
673
677
}
674
678
675
- uv_fs_t stats_req;
676
- auto cleanup_stats =
677
- OnScopeLeave ([&stats_req]() { uv_fs_req_cleanup (&stats_req); });
678
679
for (;;) {
679
680
uv_dirent_t ent;
680
681
@@ -691,12 +692,14 @@ static void LoadCertsFromDir(std::vector<X509*>* certs,
691
692
return ;
692
693
}
693
694
695
+ uv_fs_t stats_req;
694
696
std::string file_path = std::string (cert_dir) + " /" + ent.name ;
695
697
int stats_r = uv_fs_stat (nullptr , &stats_req, file_path.c_str (), nullptr );
696
698
if (stats_r == 0 &&
697
699
(static_cast <uv_stat_t *>(stats_req.ptr )->st_mode & S_IFREG)) {
698
700
LoadCertsFromFile (certs, file_path.c_str ());
699
701
}
702
+ uv_fs_req_cleanup (&stats_req);
700
703
}
701
704
}
702
705
@@ -775,7 +778,7 @@ static std::vector<X509*> InitializeSystemStoreCertificates() {
775
778
return system_store_certs;
776
779
}
777
780
778
- static std::vector<X509*>& GetSystemStoreRootCertificates () {
781
+ static std::vector<X509*>& GetSystemStoreCACertificates () {
779
782
// Use function-local static to guarantee thread safety.
780
783
static std::vector<X509*> system_store_certs =
781
784
InitializeSystemStoreCertificates ();
@@ -847,7 +850,7 @@ X509_STORE* NewRootCertStore() {
847
850
CHECK_EQ (1 , X509_STORE_add_cert (store, cert));
848
851
}
849
852
if (per_process::cli_options->use_system_ca ) {
850
- for (X509* cert : GetSystemStoreRootCertificates ()) {
853
+ for (X509* cert : GetSystemStoreCACertificates ()) {
851
854
CHECK_EQ (1 , X509_STORE_add_cert (store, cert));
852
855
}
853
856
}
@@ -869,7 +872,7 @@ void CleanupCachedRootCertificates() {
869
872
}
870
873
}
871
874
if (has_cached_system_root_certs.load ()) {
872
- for (X509* cert : GetSystemStoreRootCertificates ()) {
875
+ for (X509* cert : GetSystemStoreCACertificates ()) {
873
876
X509_free (cert);
874
877
}
875
878
}
@@ -881,7 +884,7 @@ void CleanupCachedRootCertificates() {
881
884
}
882
885
}
883
886
884
- void GetRootCertificates (const FunctionCallbackInfo<Value>& args) {
887
+ void GetBundledRootCertificates (const FunctionCallbackInfo<Value>& args) {
885
888
Environment* env = Environment::GetCurrent (args);
886
889
Local<Value> result[arraysize (root_certs)];
887
890
@@ -898,6 +901,58 @@ void GetRootCertificates(const FunctionCallbackInfo<Value>& args) {
898
901
Array::New (env->isolate (), result, arraysize (root_certs)));
899
902
}
900
903
904
+ MaybeLocal<Array> X509sToArrayOfStrings (Environment* env,
905
+ const std::vector<X509*>& certs) {
906
+ ClearErrorOnReturn clear_error_on_return;
907
+ EscapableHandleScope scope (env->isolate ());
908
+
909
+ LocalVector<Value> result (env->isolate (), certs.size ());
910
+ for (size_t i = 0 ; i < certs.size (); ++i) {
911
+ X509View view (certs[i]);
912
+ auto pem_bio = view.toPEM ();
913
+ if (!pem_bio) {
914
+ ThrowCryptoError (env, ERR_get_error (), " X509 to PEM conversion" );
915
+ return MaybeLocal<Array>();
916
+ }
917
+
918
+ char * pem_data = nullptr ;
919
+ auto pem_size = BIO_get_mem_data (pem_bio.get (), &pem_data);
920
+ if (pem_size <= 0 || !pem_data) {
921
+ ThrowCryptoError (env, ERR_get_error (), " Reading PEM data" );
922
+ return MaybeLocal<Array>();
923
+ }
924
+ // PEM is base64-encoded, so it must be one-byte.
925
+ if (!String::NewFromOneByte (env->isolate (),
926
+ reinterpret_cast <uint8_t *>(pem_data),
927
+ v8::NewStringType::kNormal ,
928
+ pem_size)
929
+ .ToLocal (&result[i])) {
930
+ return MaybeLocal<Array>();
931
+ }
932
+ }
933
+ return scope.Escape (Array::New (env->isolate (), result.data (), result.size ()));
934
+ }
935
+
936
+ void GetSystemCACertificates (const FunctionCallbackInfo<Value>& args) {
937
+ Environment* env = Environment::GetCurrent (args);
938
+ Local<Array> results;
939
+ if (X509sToArrayOfStrings (env, GetSystemStoreCACertificates ())
940
+ .ToLocal (&results)) {
941
+ args.GetReturnValue ().Set (results);
942
+ }
943
+ }
944
+
945
+ void GetExtraCACertificates (const FunctionCallbackInfo<Value>& args) {
946
+ Environment* env = Environment::GetCurrent (args);
947
+ if (extra_root_certs_file.empty ()) {
948
+ return args.GetReturnValue ().Set (Array::New (env->isolate ()));
949
+ }
950
+ Local<Array> results;
951
+ if (X509sToArrayOfStrings (env, GetExtraCACertificates ()).ToLocal (&results)) {
952
+ args.GetReturnValue ().Set (results);
953
+ }
954
+ }
955
+
901
956
bool SecureContext::HasInstance (Environment* env, const Local<Value>& value) {
902
957
return GetConstructorTemplate (env)->HasInstance (value);
903
958
}
@@ -981,8 +1036,14 @@ void SecureContext::Initialize(Environment* env, Local<Object> target) {
981
1036
GetConstructorTemplate (env),
982
1037
SetConstructorFunctionFlag::NONE);
983
1038
1039
+ SetMethodNoSideEffect (context,
1040
+ target,
1041
+ " getBundledRootCertificates" ,
1042
+ GetBundledRootCertificates);
1043
+ SetMethodNoSideEffect (
1044
+ context, target, " getSystemCACertificates" , GetSystemCACertificates);
984
1045
SetMethodNoSideEffect (
985
- context, target, " getRootCertificates " , GetRootCertificates );
1046
+ context, target, " getExtraCACertificates " , GetExtraCACertificates );
986
1047
}
987
1048
988
1049
void SecureContext::RegisterExternalReferences (
@@ -1022,7 +1083,9 @@ void SecureContext::RegisterExternalReferences(
1022
1083
1023
1084
registry->Register (CtxGetter);
1024
1085
1025
- registry->Register (GetRootCertificates);
1086
+ registry->Register (GetBundledRootCertificates);
1087
+ registry->Register (GetSystemCACertificates);
1088
+ registry->Register (GetExtraCACertificates);
1026
1089
}
1027
1090
1028
1091
SecureContext* SecureContext::Create (Environment* env) {
0 commit comments