Skip to content

Commit

Permalink
Sort certificates by most-recently issued (#20)
Browse files Browse the repository at this point in the history
This commit also adds a _very_ basic test that the filtering and sorting is working and updates the used apple_rules to the latest version, which requires bazel 4.0
  • Loading branch information
russellhancox authored May 3, 2021
1 parent f4ca54d commit fcd5ac9
Show file tree
Hide file tree
Showing 8 changed files with 216 additions and 36 deletions.
8 changes: 7 additions & 1 deletion BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,15 @@ objc_library(
testonly = 1,
srcs = [
"Source/MOLAuthenticatingURLSession/MOLDERDecoder.h",
"Tests/MOLAuthenticatingURLSessionTest.m",
"Tests/MOLDERDecoderTest.m",
],
data = ["Tests/dn.plist"],
data = [
"Tests/dn.plist",
"Tests/example_org_client_cert.pem",
"Tests/example_org_client_cert_old.pem",
"Tests/internet_widgits_client_cert.pem",
],
deps = [":MOLAuthenticatingURLSession"],
)

Expand Down
70 changes: 44 additions & 26 deletions Source/MOLAuthenticatingURLSession/MOLAuthenticatingURLSession.m
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,45 @@ - (SecIdentityRef)identityByFilteringArray:(NSArray *)array
issuerCountryName:(NSString *)issuerCountryName
issuerOrgName:(NSString *)issuerOrgName
issuerOrgUnit:(NSString *)issuerOrgUnit {
NSMutableArray *predicates = [NSMutableArray arrayWithCapacity:4];
NSArray<MOLCertificate *> *sortedCerts = [self filterAndSortArray:array
commonName:commonName
issuerCommonName:issuerCommonName
issuerCountryName:issuerCountryName
issuerOrgName:issuerOrgName
issuerOrgUnit:issuerOrgUnit];
for (MOLCertificate *cert in sortedCerts) {
SecIdentityRef identityRef = NULL;
OSStatus status = SecIdentityCreateWithCertificate(NULL, cert.certRef, &identityRef);
if (status == errSecSuccess) {
return identityRef;
} else {
// Avoid infinite recursion from self-signed certs
if ((!cert.commonName || [cert.commonName isEqual:cert.issuerCommonName]) &&
(!cert.countryName || [cert.countryName isEqual:cert.issuerCountryName]) &&
(!cert.orgName || [cert.orgName isEqual:cert.issuerOrgName]) &&
(!cert.orgUnit || [cert.orgUnit isEqual:cert.issuerOrgUnit])) {
continue;
}

// cert is an intermediate, recurse to find the leaf.
return [self identityByFilteringArray:array
commonName:nil
issuerCommonName:cert.commonName
issuerCountryName:cert.countryName
issuerOrgName:cert.orgName
issuerOrgUnit:cert.orgUnit];
}
}
return NULL;
}

- (NSArray<MOLCertificate *> *)filterAndSortArray:(NSArray<MOLCertificate *> *)array
commonName:(NSString *)commonName
issuerCommonName:(NSString *)issuerCommonName
issuerCountryName:(NSString *)issuerCountryName
issuerOrgName:(NSString *)issuerOrgName
issuerOrgUnit:(NSString *)issuerOrgUnit {
NSMutableArray *predicates = [NSMutableArray arrayWithCapacity:5];

if (commonName) {
[predicates addObject:[NSPredicate predicateWithFormat:@"SELF.commonName == %@",
Expand All @@ -361,32 +399,12 @@ - (SecIdentityRef)identityByFilteringArray:(NSArray *)array

NSCompoundPredicate *andPreds = [NSCompoundPredicate andPredicateWithSubpredicates:predicates];

NSArray *filteredCerts = [array filteredArrayUsingPredicate:andPreds];
if (!filteredCerts.count) return NULL;
NSArray<MOLCertificate *> *filteredCerts = [array filteredArrayUsingPredicate:andPreds];
if (!filteredCerts.count) return nil;

for (MOLCertificate *cert in filteredCerts) {
SecIdentityRef identityRef = NULL;
OSStatus status = SecIdentityCreateWithCertificate(NULL, cert.certRef, &identityRef);
if (status == errSecSuccess) {
return identityRef;
} else {
// Avoid infinite recursion from self-signed certs
if ((!cert.commonName || [cert.commonName isEqual:cert.issuerCommonName]) &&
(!cert.countryName || [cert.countryName isEqual:cert.issuerCountryName]) &&
(!cert.orgName || [cert.orgName isEqual:cert.issuerOrgName]) &&
(!cert.orgUnit || [cert.orgUnit isEqual:cert.issuerOrgUnit])) {
continue;
}

return [self identityByFilteringArray:array
commonName:nil
issuerCommonName:cert.commonName
issuerCountryName:cert.countryName
issuerOrgName:cert.orgName
issuerOrgUnit:cert.orgUnit];
}
}
return NULL;
return [filteredCerts sortedArrayUsingComparator:^(MOLCertificate *obj1, MOLCertificate *obj2) {
return [obj2.validFrom compare:obj1.validFrom];
}];
}

- (SecIdentityRef)identityFromFile:(NSString *)file password:(NSString *)password {
Expand Down
60 changes: 60 additions & 0 deletions Tests/MOLAuthenticatingURLSessionTest.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/// Copyright 2021 Google Inc. All rights reserved.
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.

#import <XCTest/XCTest.h>

#import <MOLCertificate/MOLCertificate.h>

#import "Source/MOLAuthenticatingURLSession/MOLAuthenticatingURLSession.h"

@interface MOLAuthenticatingURLSession (Testing)
- (NSArray<MOLCertificate *> *)filterAndSortArray:(NSArray<MOLCertificate *> *)array
commonName:(NSString *)commonName
issuerCommonName:(NSString *)issuerCommonName
issuerCountryName:(NSString *)issuerCountryName
issuerOrgName:(NSString *)issuerOrgName
issuerOrgUnit:(NSString *)issuerOrgUnit;
@end

@interface MOLAuthenticatingURLSessionTest : XCTestCase
@end

@implementation MOLAuthenticatingURLSessionTest

- (MOLCertificate *)certFromFilename:(NSString *)filename {
NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:filename ofType:@"pem"];
NSString *data = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:NULL];
return [[MOLCertificate alloc] initWithCertificateDataPEM:data];
}

- (void)testFilterAndSortArray {
MOLCertificate *c1 = [self certFromFilename:@"example_org_client_cert_old"];
MOLCertificate *c2 = [self certFromFilename:@"internet_widgits_client_cert"];
MOLCertificate *c3 = [self certFromFilename:@"example_org_client_cert"];

MOLAuthenticatingURLSession *s = [[MOLAuthenticatingURLSession alloc] init];

NSArray *got = [s filterAndSortArray:@[ c1, c2, c3 ]
commonName:@"Example Organization Client Certificate"
issuerCommonName:nil
issuerCountryName:nil
issuerOrgName:nil
issuerOrgUnit:nil];


NSArray *want = @[ c3, c1 ];
XCTAssertEqualObjects(got, want, @"");
}

@end
9 changes: 1 addition & 8 deletions Tests/MOLDERDecoderTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#import <XCTest/XCTest.h>

#import <MOLAuthenticatingURLSession/MOLDERDecoder.h>
#import <MOLCertificate/MOLCertificate.h>

@interface MOLDERDecoder (Testing)
+ (NSString *)decodeOIDWithBytes:(unsigned char *)bytes length:(NSUInteger)length;
Expand All @@ -25,14 +26,6 @@ @interface MOLDERDecoderTest : XCTestCase

@implementation MOLDERDecoderTest

- (void)setUp {
[super setUp];
}

- (void)tearDown {
[super tearDown];
}

- (void)testAllFields {
NSString *file = [[NSBundle bundleForClass:[self class]] pathForResource:@"dn" ofType:@"plist"];
NSArray *distinguishedNames = [NSArray arrayWithContentsOfFile:file];
Expand Down
33 changes: 33 additions & 0 deletions Tests/example_org_client_cert.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
-----BEGIN CERTIFICATE-----
MIIFwDCCA6gCCQD0lJTYOlYnGDANBgkqhkiG9w0BAQsFADCBoTELMAkGA1UEBhMC
VVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcx
HTAbBgNVBAoMFEV4YW1wbGUgT3JnYW5pemF0aW9uMRQwEgYDVQQLDAtFbmdpbmVl
cmluZzEwMC4GA1UEAwwnRXhhbXBsZSBPcmdhbml6YXRpb24gQ2xpZW50IENlcnRp
ZmljYXRlMB4XDTIxMDUwMzE2MDgxM1oXDTMyMDcyMDE2MDgxM1owgaExCzAJBgNV
BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBW
aWV3MR0wGwYDVQQKDBRFeGFtcGxlIE9yZ2FuaXphdGlvbjEUMBIGA1UECwwLRW5n
aW5lZXJpbmcxMDAuBgNVBAMMJ0V4YW1wbGUgT3JnYW5pemF0aW9uIENsaWVudCBD
ZXJ0aWZpY2F0ZTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAO7maT3z
hupTcFlm3sCJmPNCgn0LZqi0AWkht7ygYzxbWH1GI1A3chPTjM0gUNz0Q9RMdST8
aQ8CvpfLXuO+vWtny1s2MPtcnz7kfbB64ez03J1RLVVc8bIbwt5mfucU+fzF+Qvj
9Jkhvngz2GiLbkt8K9XJKeWOmLqBqTLuJhPrWXEU55tMTRwFeW48fJ5Av/Ls5FU1
lG5/gGc/ZfY9EZi4daTT/ePkwJa4OgM/ceY/E+MR+bqvYX91NQoAtjxdKRZ/c+JZ
JyHSpj36FjyPaQ5sEFZMdV2Guji162E4Nu3xXRoR4EpAe7BSBBZJMgUgzkmJgYOa
jqK3O9sw26Mcydk8o1yHKjRiM99QVWmM6LDvQLs4q0Oh80xkyezsnSwh8gMFTw0N
48DnvyxAuk1rYcIM7ytXZrmFZFqrXEaoiPJuvjFEyFsaXdY25PMIdvKP83dx/SDb
wpMlaEdg2yec9asqKwpBiFR9Pd0geFXvdXBhs0QyyTlyjz7xYbsJsl1JbK73zd8B
kH9A48pYHzYaR2xiCk/WRoMgtKif3DNZvmVHW3ux8QMTRQdPaIsUB21SNSd+7IBX
B25+w12guX0ozQ5/atPUkwNInC3QuLZH9+VFhJFDjhkcPhMAhRGEL0XMV2bWJBqg
cfF3i6aXUKMFVHGjnclYG75lHh6pdb28xqzhAgMBAAEwDQYJKoZIhvcNAQELBQAD
ggIBAKv27/iGhHwDS34Jq9qjBb4a63ZDYAwVNgepymqjGsYuL3sYyVMUTHdfboPw
a51Jabh+lG7YBJt6+PZzP8tcpjL0II4ysR7LWGnHii6Un6M0Ds1BtnDjiE0J6TwP
XJtsROPys6/aBEnUIiSPtF/TNHiDDcNgvZD9wi/3pv3zIRhoS/slOCf+AQhw5ccj
o2Sf113zuGtvvYvQVp1m1eo9+/P9r7CHdhFMJ1oVayzbIabQe8v0OnUTT0TyUbBR
9OrtuOx3fE02i2JfOVVEbtnIbQI3QK19joVqajjvIkvbiq4PNbfFkw7e4FO4XKmv
1P0wnwRMtHNWCkXLZefbv+PYQBnDcEzUj6tIlJCreuX0TTUlhV2LcH6XzY1Dw98t
wiB9clvzv3yjpIsZy6wY1/1iZ39AVSsKfE4nDA7ja2tqMXl8HI5kMpMOqaZi0AWw
LBheth0x1DC5nATp5HUh34ul2jZ4oAguzCGq8CxLXf8x5v00633ur7IpmDpe3bQx
oo8wia6rXjq4XAsCvtT36hEoxdL1GV3Q4Sp4z6DYqL7rc7lVecn5q//dyjBDGrSA
S6SZ8w850L87vp03QrXzxIbpQL++kIl45jalW+KU37/JvEm/fZ0GT3sqk4nKSexs
Ns3XBynypa52RZcmuFQkjdiUkkjWPZmkoVCv8satfdWimBsK
-----END CERTIFICATE-----
35 changes: 35 additions & 0 deletions Tests/example_org_client_cert_old.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
-----BEGIN CERTIFICATE-----
MIIGJTCCBA2gAwIBAgIUIEt2zigMYKVdwxwE4W5zDtB43k0wDQYJKoZIhvcNAQEL
BQAwgaExCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQH
DA1Nb3VudGFpbiBWaWV3MR0wGwYDVQQKDBRFeGFtcGxlIE9yZ2FuaXphdGlvbjEU
MBIGA1UECwwLRW5naW5lZXJpbmcxMDAuBgNVBAMMJ0V4YW1wbGUgT3JnYW5pemF0
aW9uIENsaWVudCBDZXJ0aWZpY2F0ZTAeFw0yMTA0MTkxNjM0MTBaFw0zMjA3MDYx
NjM0MTBaMIGhMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQG
A1UEBwwNTW91bnRhaW4gVmlldzEdMBsGA1UECgwURXhhbXBsZSBPcmdhbml6YXRp
b24xFDASBgNVBAsMC0VuZ2luZWVyaW5nMTAwLgYDVQQDDCdFeGFtcGxlIE9yZ2Fu
aXphdGlvbiBDbGllbnQgQ2VydGlmaWNhdGUwggIiMA0GCSqGSIb3DQEBAQUAA4IC
DwAwggIKAoICAQC72no9kT68zvguv3xv/BcFgHodpWlEueSSoSdPHVIvWR9QSO2J
FsUalWsfCa1rzCkl455PgOOmEs3zPIx9u8k2D1HVh7MvsP/QXDkSFrO+xtySXMSZ
/7FtHW5TOzDgHAj6AOycNUjTiLbjkOTjqay42gFZpynEnMlCXBeqljCn/ZserFYB
4Fh29oFuVTiRz/VnqKIku4QKI9SYN4trahX2D94jNXu/OoZWV4PODKLzU3yL8giv
GkjdLSHjIjXTpX37FIUvMfQ6/ra/Jg4QZ3GKBW+V8a/Y2isvyigNcOLJjAjSnmgz
34786YYdyY0tH6MmFaMFWrAerv+4NPNC2SCRy5t/gAPT6djZmyOrcvoUkotVyODL
WRXOQkzIWbAaAp0WoBqRVLr+2SImKLp92UHPLRSe8Y6uwK2/zM85RocjjNu0N7zC
paOdqBH6cZWEa5kU55S9G8Bm12c+HvPK8KOnLlT8mC0ixYNMb8+5/f9MQCEWUa4C
FWRxzk7/IKu0zAOcdyKoDkiDPVQ7YXrBVBZzeobW/cOYwsx3+RlFahMLnEFsw1Lo
WUCrNTi8wa77LeVFoiz2h/yNzpxhiK9wjkO2I/yxZFwYrFIS22lqmrXxVg9sPeqL
5koS9YUawF6HKHtQFcLl44OZv4wr8Y03Mj8STrujSFt2Cp4c3YYLackEywIDAQAB
o1MwUTAdBgNVHQ4EFgQUrpVGjLUBdpjszUQZsdpRkCNcZIIwHwYDVR0jBBgwFoAU
rpVGjLUBdpjszUQZsdpRkCNcZIIwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0B
AQsFAAOCAgEAUDkCqO2MInuUjk0LvhtK+yvBU5m4LGm/nqYY6jGzA7QLC1cxREPw
tEG1LVQ0fghPx1xzZKCCfAxObaNeVIgDkaekhLyvGwM1UBwpBJzGqiIOSv8MMD2L
9jMxawUdhLdH7EWZ1Oz+uR75pdAiBjCk8p0rcxSrlbH4/wpry+EdfQrKQlgCogi5
EA8Z2sznHi0vQh7awj7zq0/Tr6KOC/oW5hI8LE1IYenQf427oHqtDo1WRLTdHtgi
PJQswa8tYREmgvtMDAJZ4UV3wwcbrtSWiNJdmDwLfs4uoiEMzF+nlVA9p9pVYSBl
FmohyT61oNLq5kPZ6M0sjp32+HVnbjFUNqMEJneep350Y9j+HvH0La/Jj84pIWvD
/IrEXO/UqMBhUT6wBNLWcOFaSkjBLA0aQgdmZ+Dfd6iA+Sk8jLfnEew/5dDku6IY
s8Htwuu/zJKedsIK/ikG1BynFJwM26hwqza2OeEp8dZWUeq6LUKprFMgDrz1lqJH
YyrsWViZS3Lj0IkS1bvb9Un5Hq6ACFYpGtapHL9RMPUj3fZ2aaWnziO4jEGVf9AC
qePhthh2+O5sdP+8Y/EjYgNXfPI68AF8A42ZKx0JhfusbweH6sccrMm26Ng15+va
5Oy2LOm3iA71Taa6g1SRDy933sa8tsERqjNjUkm9s+8NNH7raKmhEpk=
-----END CERTIFICATE-----
35 changes: 35 additions & 0 deletions Tests/internet_widgits_client_cert.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
-----BEGIN CERTIFICATE-----
MIIGBzCCA++gAwIBAgIUUeR6m7gHvzGcU7UUoVnFMohnURYwDQYJKoZIhvcNAQEL
BQAwgZIxCzAJBgNVBAYTAkZSMRMwEQYDVQQIDApTb21lLVN0YXRlMQ4wDAYDVQQH
DAVQYXJpczEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRQwEgYD
VQQLDAtFbmdpbmVlcmluZzElMCMGA1UEAwwcSW50ZXJuZXQgV2lkZ2l0cyBDbGll
bnQgQ2VydDAeFw0yMTA0MTkxNjEzMjJaFw0zMjA3MDYxNjEzMjJaMIGSMQswCQYD
VQQGEwJGUjETMBEGA1UECAwKU29tZS1TdGF0ZTEOMAwGA1UEBwwFUGFyaXMxITAf
BgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEUMBIGA1UECwwLRW5naW5l
ZXJpbmcxJTAjBgNVBAMMHEludGVybmV0IFdpZGdpdHMgQ2xpZW50IENlcnQwggIi
MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCnjIiDnzosJi/70gUsW5UNlx+0
x5o1F69M68BjD6JPfjv2mMHbK1a5CkagwrCsjwFe1nBma+vvbhV51PxV/snteo/7
surEd+oJ1jbAGe2E1qURkEeM3Z915zg+CmDlWJsiIvfsYmKAwjfb0KCebioBUM9p
GR+sAKZiQq8w4dZahf7bsLevDettN426LmKnaAj+LCzOZb3ih00ecWN9/SQVh/S1
q2fDDIxkr5d7orjVdBr8ecoiYkXzGKVccOKwHtnL94tvp3vRSMdhNSuiabae9N+i
XVc4mnILRrvGE8hrEy9et4EJHbRKNvypz+yD1ktoLNYN5fVilB4Nxxe9Rdo3MfNx
SiA4r7HwYWUAxHlxX0U9TYiLHMk/4WSdCThLVXrxQHtfZ+se2ZDdmQhNn3Vf6L/C
Srj0eZjeCRGflwEyJnqVziJOVbcnKqX+hfYfsPdFdJrcVEcKRYK7Xog74inePPUl
WxrbIa19ZLS/wgXIEsVtSdoYTCwLLZtfJ02RtSojVr3FxS8/e0tOkCCRK00o54b9
d9qxvjSJI/0O+OcuVAwTFJl9jN0s0zmRjN6rFlxmjjYoF6nyBMvPhRsYcAq0Uk4u
Qi/3zPZvMwkqRneNYv9zsn1tcd4udcSp9gkmy+6oeGK6+LL/OMMGn9ZXVCd43gJy
UBEfJoN+ufCnnFdm2QIDAQABo1MwUTAdBgNVHQ4EFgQUNVH/caHIQb05OJKjWOn5
makZ4WYwHwYDVR0jBBgwFoAUNVH/caHIQb05OJKjWOn5makZ4WYwDwYDVR0TAQH/
BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEANAYHuXn8PGjY/0lj5tQltSpAiF1z
T/vurp/kVUt5HSCm3A/2OyxP4eFzAAlyfLvxTSx7nacqxHpZC0f+wCUpBU03zzmQ
UmMYVfu9wD6Kf9y6RBVcOc7mafHSTHhPu00vdbeZAtkB5qiZpZqmhNzZqQH3bBK5
g3K7akDk4cENwcoTIctSSHeuZzvqLWK3KfNHNmAvCfWZDb2WJKNP3Xt7imCoYtLF
0f89XmV3ygS7Sc/1B3Ji2uBT9Lxxb4vziOXMlB9KPrFu0K7IhGO8gVeMmi+OWAC4
aaiixFUVm6jhH/nn/IOnkjwKuNCaHZuCf9Lvn9aFEKfTLhgMBpQhBP8cpx/6/RIp
rzBRC1QU+K8LoKpue/5+U7soHIyLNPDYxWHyjxghHE/8bI9nnGf/wC6MnOhiRtFq
/HRK/EfyPkjOphQ+rv/O325b1E2A0HOf3NC3Ktgel729aKyzY5GCg2k/42dn9mkj
jivEMjcs4vl/wh6TIaTNDvvTqUhdIsjVP3ZtdFLNmVwble6LMKezMEzEp7GmiPcZ
kSIskyYjfoMpdbZGSinQ0Z2aaKvfM6HD7+7NN0vSu+L0KY7Kc/Cc3Xj61CSYgV1G
FJpNa5chaDM6+4XcWZuXo+jRghVi04dxd2r2l8GCESe/3B2OspcqSLHyVnH9IL+Y
+zF36y3iF/eBeAI=
-----END CERTIFICATE-----
2 changes: 1 addition & 1 deletion WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
git_repository(
name = "build_bazel_rules_apple",
remote = "https://github.com/bazelbuild/rules_apple.git",
tag = "0.17.2",
tag = "0.31.1",
)

load(
Expand Down

0 comments on commit fcd5ac9

Please sign in to comment.