diff --git a/ADAL.podspec b/ADAL.podspec
index 4fbbc2686..ba80b8115 100644
--- a/ADAL.podspec
+++ b/ADAL.podspec
@@ -1,7 +1,7 @@
Pod::Spec.new do |s|
s.name = "ADAL"
s.module_name = "ADAL"
- s.version = "2.7.8"
+ s.version = "2.7.9"
s.summary = "The ADAL SDK for iOS gives you the ability to add Azure Identity authentication to your application"
s.description = <<-DESC
diff --git a/ADAL/resources/ios/Framework/Info.plist b/ADAL/resources/ios/Framework/Info.plist
index e998d0697..911df6ec1 100644
--- a/ADAL/resources/ios/Framework/Info.plist
+++ b/ADAL/resources/ios/Framework/Info.plist
@@ -15,7 +15,7 @@
CFBundlePackageType
FMWK
CFBundleShortVersionString
- 2.7.8
+ 2.7.9
CFBundleSignature
????
CFBundleVersion
diff --git a/ADAL/resources/mac/Info.plist b/ADAL/resources/mac/Info.plist
index c280a3c30..1c2978e30 100644
--- a/ADAL/resources/mac/Info.plist
+++ b/ADAL/resources/mac/Info.plist
@@ -15,7 +15,7 @@
CFBundlePackageType
FMWK
CFBundleShortVersionString
- 2.7.8
+ 2.7.9
CFBundleSignature
????
CFBundleVersion
diff --git a/ADAL/src/ADAL_Internal.h b/ADAL/src/ADAL_Internal.h
index bc4b3b3a2..63ee4eeb1 100644
--- a/ADAL/src/ADAL_Internal.h
+++ b/ADAL/src/ADAL_Internal.h
@@ -27,7 +27,7 @@
// through build script. Don't change its format unless changing build script as well.)
#define ADAL_VER_HIGH 2
#define ADAL_VER_LOW 7
-#define ADAL_VER_PATCH 8
+#define ADAL_VER_PATCH 9
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
diff --git a/ADAL/src/workplacejoin/ADPkeyAuthHelper.m b/ADAL/src/workplacejoin/ADPkeyAuthHelper.m
index 84edbf663..dd968b515 100644
--- a/ADAL/src/workplacejoin/ADPkeyAuthHelper.m
+++ b/ADAL/src/workplacejoin/ADPkeyAuthHelper.m
@@ -71,8 +71,7 @@ + (nullable NSString*)createDeviceAuthResponse:(nonnull NSString*)authorizationS
{
ADAuthenticationError* adError = nil;
ADRegistrationInformation *info =
- [ADWorkPlaceJoinUtil getRegistrationInformation:context
- error:&adError];
+ [ADWorkPlaceJoinUtil getRegistrationInformation:context urlChallenge:nil error:&adError];
if (!info && adError)
{
diff --git a/ADAL/src/workplacejoin/ADWorkPlaceJoinUtil.h b/ADAL/src/workplacejoin/ADWorkPlaceJoinUtil.h
index 39b356e90..652c7ad81 100644
--- a/ADAL/src/workplacejoin/ADWorkPlaceJoinUtil.h
+++ b/ADAL/src/workplacejoin/ADWorkPlaceJoinUtil.h
@@ -27,7 +27,8 @@
@interface ADWorkPlaceJoinUtil : NSObject
-+ (ADRegistrationInformation*)getRegistrationInformation:(id)context
- error:(ADAuthenticationError * __autoreleasing *)error;
++ (ADRegistrationInformation *)getRegistrationInformation:(id)context
+ urlChallenge:(NSURLAuthenticationChallenge *)challenge
+ error:(ADAuthenticationError * __autoreleasing *)error;
@end
diff --git a/ADAL/src/workplacejoin/ios/ADWorkPlaceJoinUtil.m b/ADAL/src/workplacejoin/ios/ADWorkPlaceJoinUtil.m
index 657724e33..cae94dd68 100644
--- a/ADAL/src/workplacejoin/ios/ADWorkPlaceJoinUtil.m
+++ b/ADAL/src/workplacejoin/ios/ADWorkPlaceJoinUtil.m
@@ -51,8 +51,9 @@ @implementation ADWorkPlaceJoinUtil
}
-+ (ADRegistrationInformation*)getRegistrationInformation:(id)context
- error:(ADAuthenticationError * __autoreleasing *)error
++ (ADRegistrationInformation *)getRegistrationInformation:(id)context
+ urlChallenge:(NSURLAuthenticationChallenge *)challenge
+ error:(ADAuthenticationError * __autoreleasing *)error
{
NSString* teamId = [ADKeychainUtil keychainTeamId:error];
diff --git a/ADAL/src/workplacejoin/mac/ADClientCertAuthHandler.m b/ADAL/src/workplacejoin/mac/ADClientCertAuthHandler.m
index 31b4714bc..227a3c137 100644
--- a/ADAL/src/workplacejoin/mac/ADClientCertAuthHandler.m
+++ b/ADAL/src/workplacejoin/mac/ADClientCertAuthHandler.m
@@ -54,10 +54,9 @@ + (void)resetHandler
+ (BOOL)isWPJChallenge:(NSArray *)distinguishedNames
{
-
for (NSData *distinguishedName in distinguishedNames)
{
- NSString *distinguishedNameString = [[[NSString alloc] initWithData:distinguishedName encoding:NSISOLatin1StringEncoding] lowercaseString];
+ NSString *distinguishedNameString = [[[NSString alloc] initWithData:distinguishedName encoding:NSASCIIStringEncoding] lowercaseString];
if ([distinguishedNameString containsString:[kADALProtectionSpaceDistinguishedName lowercaseString]])
{
return YES;
@@ -72,7 +71,7 @@ + (BOOL)handleWPJChallenge:(NSURLAuthenticationChallenge *)challenge
completionHandler:(ChallengeCompletionHandler)completionHandler
{
ADAuthenticationError *adError = nil;
- ADRegistrationInformation *info = [ADWorkPlaceJoinUtil getRegistrationInformation:protocol.context error:&adError];
+ ADRegistrationInformation *info = [ADWorkPlaceJoinUtil getRegistrationInformation:protocol.context urlChallenge:challenge error:&adError];
if (!info || ![info isWorkPlaceJoined])
{
MSID_LOG_INFO(protocol.context, @"Device is not workplace joined");
diff --git a/ADAL/src/workplacejoin/mac/ADWorkPlaceJoinUtil.m b/ADAL/src/workplacejoin/mac/ADWorkPlaceJoinUtil.m
index 273d84077..388131a82 100644
--- a/ADAL/src/workplacejoin/mac/ADWorkPlaceJoinUtil.m
+++ b/ADAL/src/workplacejoin/mac/ADWorkPlaceJoinUtil.m
@@ -37,11 +37,10 @@
} \
}
-static const UInt8 certificateIdentifier[] = "WorkPlaceJoin-Access\0";
-
@implementation ADWorkPlaceJoinUtil
+ (ADRegistrationInformation *)getRegistrationInformation:(id)context
+ urlChallenge:(NSURLAuthenticationChallenge *)challenge
error:(ADAuthenticationError * __autoreleasing *)error
{
ADRegistrationInformation *info = nil;
@@ -51,58 +50,50 @@ + (ADRegistrationInformation *)getRegistrationInformation:(id)context
+ issuer:(NSString **)issuer
+ certificateAuthorities:(NSArray *)authorities
-+ (void)copyCertificate:(SecCertificateRef __nullable * __nonnull)certificate
- identity:(SecIdentityRef __nullable * __nonnull)identity
- issuer:(NSString * __nullable * __nonnull)issuer
- context:(id)context
- error:(ADAuthenticationError * __nullable __autoreleasing * __nullable)error
{
- OSStatus status = noErr;
- ADAuthenticationError *adError = nil;
- NSData *issuerData = nil;
- NSDictionary *identityQuery = nil;
- CFDictionaryRef result = NULL;
-
- *identity = nil;
- *certificate = nil;
- if (error)
- {
- *error = nil;
- }
-
- *certificate = [self copyWPJCertificateRef:context error:&adError];
-
- if (adError)
- {
- if (error)
- {
- *error = adError;
- }
-
- MSID_LOG_ERROR(context, @"Failed to retrieve WPJ client certificate from keychain. Error code: %ld", (long)adError.code);
- goto _error;
- }
-
- // If there's no certificate in the keychain, adError won't be set since this isn't an error condition.
- if (!*certificate)
+ if (![authorities count])
{
- return;
+ return NULL;
}
- // In OS X the shared access group cannot be set, so the search needs to be more
- // specific. The code below searches the identity by passing the WPJ cert as reference.
- identityQuery = @{ (__bridge id)kSecClass : (__bridge id)kSecClassIdentity,
- (__bridge id)kSecReturnRef : (__bridge id)kCFBooleanTrue,
- (__bridge id)kSecReturnAttributes : (__bridge id)kCFBooleanTrue,
- (__bridge id)kSecAttrKeyClass : (__bridge id)kSecAttrKeyClassPrivate,
- (__bridge id)kSecValueRef : (__bridge id)*certificate
- };
+ NSDictionary *query = @{ (__bridge id)kSecClass : (__bridge id)kSecClassIdentity,
+ (__bridge id)kSecReturnAttributes:(__bridge id)kCFBooleanTrue,
+ (__bridge id)kSecReturnRef : (__bridge id)kCFBooleanTrue,
+ (__bridge id)kSecMatchLimit : (__bridge id)kSecMatchLimitAll,
+ (__bridge id)kSecMatchIssuers : authorities
+ };
- status = SecItemCopyMatching((__bridge CFDictionaryRef)identityQuery, (CFTypeRef*)&result);
- CHECK_KEYCHAIN_STATUS(@"Failed to retrieve WPJ identity from keychain.");
+ CFArrayRef identityList = NULL;
+ SecIdentityRef identityRef = NULL;
+ NSDictionary *identityDict = nil;
+ NSData *currentIssuer = nil;
+ NSString *currentIssuerName = nil;
- issuerData = [(__bridge NSDictionary*)result objectForKey:(__bridge id)kSecAttrIssuer];
- if (issuerData)
- {
- *issuer = [[NSString alloc] initWithData:issuerData encoding:NSISOLatin1StringEncoding];
- }
+ OSStatus status = SecItemCopyMatching((CFDictionaryRef)query, (CFTypeRef *)&identityList);
- *identity = (__bridge SecIdentityRef)([(__bridge NSDictionary*)result objectForKey:(__bridge id)kSecValueRef]);
- if (*identity)
+ if (status != errSecSuccess)
{
- CFRetain(*identity);
+ return NULL;
}
- CFRelease(result);
-
- return;
+ CFIndex identityCount = CFArrayGetCount(identityList);
+ NSString *challengeIssuerName = [[NSString alloc] initWithData:authorities[0] encoding:NSASCIIStringEncoding];
-_error:
-
- if (*identity)
+ for (int resultIndex = 0; resultIndex < identityCount; resultIndex++)
{
- CFRelease(*identity);
+ identityDict = (NSDictionary *)CFArrayGetValueAtIndex(identityList, resultIndex);
+
+ if ([identityDict isKindOfClass:[NSDictionary class]])
+ {
+ currentIssuer = [identityDict objectForKey:(__bridge NSString*)kSecAttrIssuer];
+ currentIssuerName = [[NSString alloc] initWithData:currentIssuer encoding:NSASCIIStringEncoding];
+
+ /* The issuer name returned from the certificate in keychain is capitalized but the issuer name returned from the TLS challenge is not.
+ Hence we need to do a caseInsenstitive compare to match the issuer.
+ */
+ if ([challengeIssuerName caseInsensitiveCompare:currentIssuerName] == NSOrderedSame)
+ {
+ identityRef = (__bridge_retained SecIdentityRef)[identityDict objectForKey:(__bridge NSString*)kSecValueRef];
+
+ if (issuer)
+ {
+ *issuer = currentIssuerName;
+ }
+
+ break;
+ }
+ }
}
- *identity = nil;
- if (*certificate)
+ if (identityList)
{
- CFRelease(*certificate);
+ CFRelease(identityList);
+ identityList = NULL;
}
- *certificate = nil;
- *issuer = nil;
-}
-
-
-+ (SecCertificateRef)copyWPJCertificateRef:(id)context
- error:(ADAuthenticationError * __nullable __autoreleasing * __nullable)error
-{
- OSStatus status= noErr;
- SecCertificateRef certRef = NULL;
- NSData *issuerTag = [self wpjCertIssuerTag];
-
- // Set the private key query dictionary.
- NSDictionary *queryCert = @{ (__bridge id)kSecClass : (__bridge id)kSecClassCertificate,
- (__bridge id)kSecAttrLabel : issuerTag
- };
-
- // Get the certificate. If the certificate is not found, this is not considered an error.
- status = SecItemCopyMatching((__bridge CFDictionaryRef)queryCert, (CFTypeRef*)&certRef);
- if (status == errSecItemNotFound)
- {
- return NULL;
- }
-
- CHECK_KEYCHAIN_STATUS(@"Failed to read WPJ certificate.");
-
- return certRef;
-
-_error:
- return NULL;
-}
-
-+ (NSData *)wpjCertIssuerTag
-{
- return [NSData dataWithBytes:certificateIdentifier length:strlen((const char *)certificateIdentifier)];
-}
-
-+ (SecKeyRef)copyPrivateKeyRefForIdentifier:(NSString *)identifier
- context:(id)context
- error:(ADAuthenticationError* __nullable __autoreleasing * __nullable)error
-{
- OSStatus status= noErr;
- SecKeyRef privateKeyReference = NULL;
-
- NSData *privateKeyTag = [NSData dataWithBytes:[identifier UTF8String] length:identifier.length];
-
- // Set the private key query dictionary.
- NSDictionary *privateKeyQuery = @{ (__bridge id)kSecClass : (__bridge id)kSecClassKey,
- (__bridge id)kSecAttrApplicationTag : privateKeyTag,
- (__bridge id)kSecAttrKeyType : (__bridge id)kSecAttrKeyTypeRSA,
- (__bridge id)kSecReturnRef : (__bridge id)kCFBooleanTrue
- };
-
- // Get the key.
- status = SecItemCopyMatching((__bridge CFDictionaryRef)privateKeyQuery, (CFTypeRef*)&privateKeyReference);
- CHECK_KEYCHAIN_STATUS(@"Failed to read WPJ private key for identifier.");
-
- return privateKeyReference;
-
-_error:
- return nil;
+ return identityRef; //Caller must call CFRelease
}
@end
diff --git a/ADAL/tests/app/src/ios/ADTestAppSettingsViewController.m b/ADAL/tests/app/src/ios/ADTestAppSettingsViewController.m
index e555511c2..56090b7b9 100644
--- a/ADAL/tests/app/src/ios/ADTestAppSettingsViewController.m
+++ b/ADAL/tests/app/src/ios/ADTestAppSettingsViewController.m
@@ -136,7 +136,7 @@ - (void)viewDidLoad
- (void)viewWillAppear:(BOOL)animated
{
ADRegistrationInformation* regInfo =
- [ADWorkPlaceJoinUtil getRegistrationInformation:nil error:nil];
+ [ADWorkPlaceJoinUtil getRegistrationInformation:nil urlChallenge:nil error:nil];
NSString* wpjLabel = @"No WPJ Registration Found";
diff --git a/changelog.txt b/changelog.txt
index 0960c1d44..a4ab5557e 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,3 +1,7 @@
+Version 2.7.9 (03.06.2018)
+-----------
+* Hotfix for Mac OS to query WPJ cert using issuers from authentication challenge.
+
Version 2.7.8
-----------
* Hotfix to skip user Id matching check for an acquire token silent call.