From 33ebf719a55fd601f9b01f21c367fbc60c4d0af5 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Tue, 12 Mar 2019 08:43:57 -0700 Subject: [PATCH] use cached grpc ssl credential --- include/grpc/grpc_security.h | 9 ++++++ .../private/GRPCSecureChannelFactory.h | 5 +++ .../private/GRPCSecureChannelFactory.m | 32 +++---------------- 3 files changed, 18 insertions(+), 28 deletions(-) diff --git a/include/grpc/grpc_security.h b/include/grpc/grpc_security.h index f0323eb16a1..9b7822627e0 100644 --- a/include/grpc/grpc_security.h +++ b/include/grpc/grpc_security.h @@ -191,6 +191,15 @@ typedef struct { try to get the roots set by grpc_override_ssl_default_roots. Eventually, if all these fail, it will try to get the roots from a well-known place on disk (in the grpc install directory). + + gRPC has implemented root cache if the underlying OpenSSL library supports + it. The gRPC root certificates cache is only applicable on the default + root certificates, which is used when this parameter is nullptr. If user + provides their own pem_root_certs, when creating an SSL credential object, + gRPC would not be able to cache it, and each subchannel will generate a + copy of the root store. So it is recommended to avoid providing large room + pem with pem_root_certs parameter to avoid excessive memory consumption, + particularly on mobile platforms such as iOS. - pem_key_cert_pair is a pointer on the object containing client's private key and certificate chain. This parameter can be NULL if the client does not have such a key/cert pair. diff --git a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.h b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.h index 588239b7064..572f20d341f 100644 --- a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.h +++ b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.h @@ -23,6 +23,11 @@ NS_ASSUME_NONNULL_BEGIN @interface GRPCSecureChannelFactory : NSObject +/** + * Creates a secure channel factory which uses provided root certificates and client authentication + * credentials. If rootCerts is nil, gRPC will use its default root certificates. If rootCerts is + * provided, it must only contain the server's CA to avoid memory issue. + */ + (nullable instancetype)factoryWithPEMRootCertificates:(nullable NSString *)rootCerts privateKey:(nullable NSString *)privateKey certChain:(nullable NSString *)certChain diff --git a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m index 96998895364..b1a6797b9e3 100644 --- a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m +++ b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m @@ -52,44 +52,20 @@ privateKey:(NSString *)privateKey certChain:(NSString *)certChain error:(NSError **)errorPtr { - static NSData *defaultRootsASCII; - static NSError *defaultRootsError; static dispatch_once_t loading; dispatch_once(&loading, ^{ NSString *defaultPath = @"gRPCCertificates.bundle/roots"; // .pem // Do not use NSBundle.mainBundle, as it's nil for tests of library projects. NSBundle *bundle = [NSBundle bundleForClass:[self class]]; NSString *path = [bundle pathForResource:defaultPath ofType:@"pem"]; - NSError *error; - // Files in PEM format can have non-ASCII characters in their comments (e.g. for the name of the - // issuer). Load them as UTF8 and produce an ASCII equivalent. - NSString *contentInUTF8 = - [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&error]; - if (contentInUTF8 == nil) { - defaultRootsError = error; - return; - } - defaultRootsASCII = [self nullTerminatedDataWithString:contentInUTF8]; + setenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR, + [path cStringUsingEncoding:NSUTF8StringEncoding], 1); }); - NSData *rootsASCII; + NSData *rootsASCII = nil; + // if rootCerts is not provided, gRPC will use its own default certs if (rootCerts != nil) { rootsASCII = [self nullTerminatedDataWithString:rootCerts]; - } else { - if (defaultRootsASCII == nil) { - if (errorPtr) { - *errorPtr = defaultRootsError; - } - NSAssert( - defaultRootsASCII, NSObjectNotAvailableException, - @"Could not read gRPCCertificates.bundle/roots.pem. This file, " - "with the root certificates, is needed to establish secure (TLS) connections. " - "Because the file is distributed with the gRPC library, this error is usually a sign " - "that the library wasn't configured correctly for your project. Error: %@", - defaultRootsError); - return nil; - } - rootsASCII = defaultRootsASCII; } grpc_channel_credentials *creds = NULL;