Skip to content

Commit

Permalink
added 802.1x support; added support for pref key for finding password…
Browse files Browse the repository at this point in the history
… based on type=password
  • Loading branch information
twocanoes committed Mar 27, 2023
1 parent 9ef8493 commit 38ddeff
Show file tree
Hide file tree
Showing 19 changed files with 896 additions and 80 deletions.
12 changes: 12 additions & 0 deletions Profile Manifest/com.twocanoes.xcreds.plist
Original file line number Diff line number Diff line change
Expand Up @@ -648,6 +648,18 @@ A profile can consist of payloads with different version numbers. For example, c
<key>pfm_type</key>
<string>string</string>
</dict>
<dict>
<key>pfm_description</key>
<string>Selects the password element field in the web page by finding a form element that has bullets (input is password)</string>
<key>pfm_documentation_url</key>
<string>https://github.com/twocanoes/xcreds/wiki/AdminGuide#shouldfindpasswordelement</string>
<key>pfm_name</key>
<string>shouldFindPasswordElement</string>
<key>pfm_title</key>
<string>shouldFindPasswordElement</string>
<key>pfm_type</key>
<string>boolean</string>
</dict>
<dict>
<key>pfm_default</key>
<string>given_name</string>
Expand Down
2 changes: 1 addition & 1 deletion XCreds/MainController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ class MainController: NSObject {
}
}
//delay startup to give network time to settle.
Timer.scheduledTimer(withTimeInterval: 15, repeats: false) { timer in
Timer.scheduledTimer(withTimeInterval: 1, repeats: false) { timer in
ScheduleManager.shared.startCredentialCheck()
}

Expand Down
2 changes: 1 addition & 1 deletion XCreds/PrefKeys.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import Foundation

enum PrefKeys: String {
case clientID, clientSecret, password="local password",discoveryURL, redirectURI, scopes, accessToken, idToken, refreshToken, tokenEndpoint, expirationDate, invalidToken, refreshRateHours, showDebug, verifyPassword, shouldShowQuitMenu, shouldShowPreferencesOnStart, shouldSetGoogleAccessTypeToOffline, passwordChangeURL, shouldShowAboutMenu, username, idpHostName, passwordElementID, shouldShowVersionInfo, shouldShowSupportStatus,shouldShowConfigureWifiButton,shouldShowMacLoginButton, loginWindowBackgroundImageURL, shouldShowCloudLoginByDefault,idpHostNames,autoRefreshLoginTimer, loginWindowWidth, loginWindowHeight, shouldShowRefreshBanner
case clientID, clientSecret, password="local password",discoveryURL, redirectURI, scopes, accessToken, idToken, refreshToken, tokenEndpoint, expirationDate, invalidToken, refreshRateHours, showDebug, verifyPassword, shouldShowQuitMenu, shouldShowPreferencesOnStart, shouldSetGoogleAccessTypeToOffline, passwordChangeURL, shouldShowAboutMenu, username, idpHostName, passwordElementID, shouldFindPasswordElement, shouldShowVersionInfo, shouldShowSupportStatus,shouldShowConfigureWifiButton,shouldShowMacLoginButton, loginWindowBackgroundImageURL, shouldShowCloudLoginByDefault,idpHostNames,autoRefreshLoginTimer, loginWindowWidth, loginWindowHeight, shouldShowRefreshBanner
}
func getManagedPreference(key: Preferences) -> Any? {

Expand Down
56 changes: 39 additions & 17 deletions XCreds/WebView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -187,25 +187,47 @@ extension WebViewController: WKNavigationDelegate {
idpHostNames=[idpHostName]
}
let passwordElementID:String? = UserDefaults.standard.value(forKey: PrefKeys.passwordElementID.rawValue) as? String
if let idpHostNames = idpHostNames as? Array<String?>, idpHostNames.contains(navigationAction.request.url?.host), let passwordElementID = passwordElementID {
let shouldFindPasswordElement:Bool? = UserDefaults.standard.bool(forKey: PrefKeys.shouldFindPasswordElement.rawValue)

if let idpHostNames = idpHostNames as? Array<String?>, idpHostNames.contains(navigationAction.request.url?.host) {
TCSLogWithMark("host matches custom idpHostName")
TCSLogWithMark("passwordElementID is \(passwordElementID)")

TCSLogWithMark("inserting javascript to get password")
let javaScript = "document.getElementById('\(passwordElementID.sanitized())').value"
webView.evaluateJavaScript(javaScript, completionHandler: { response, error in
if error != nil {
TCSLogWithMark(error?.localizedDescription ?? "unknown error")
}
if let rawPass = response as? String, rawPass != "" {
TCSLogWithMark("========= password set===========")
self.password=rawPass
}
else {
TCSLogWithMark("password not captured")
return
}
})
var javaScript = "" //document.getElementsByName('password')[0].value

if let passwordElementID = passwordElementID {
TCSLogWithMark("passwordElementID is \(passwordElementID)")
javaScript = "document.getElementById('\(passwordElementID.sanitized())').value"
}
else if shouldFindPasswordElement == true {
TCSLogWithMark("finding with bulleted text")

javaScript="document.querySelectorAll('input[type=password]')[0].value"
}
else {
TCSLogWithMark("no password element id set or find password element")
}
if javaScript.count>0{
TCSLogWithMark("using javascript to get password")
webView.evaluateJavaScript(javaScript, completionHandler: { response, error in
if error != nil {
TCSLogWithMark(error?.localizedDescription ?? "unknown error")
}
if let rawPass = response as? String, rawPass != "" {
TCSLogWithMark("========= password set===========")
self.password=rawPass
}
else {

if let password = self.password, password.count>0{
TCSLogWithMark("password already captured")
}
else {
TCSLogWithMark("password not captured")
}
return
}
})
}

}
// Azure snarfing
Expand Down
2 changes: 1 addition & 1 deletion XCreds/XCreds-Bridging-Header.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@
#define XCreds_Bridging_Header_h
#import "SecurityPrivateAPI.h"
#import "XCredsLoginPlugin.h"

#import "TCSKeychain.h"
#import "TCSUnifiedLogger.h"
#endif /* XCreds_Bridging_Header_h */
1 change: 1 addition & 0 deletions XCreds/XCredsLoginPlugin-Bridging-Header.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
#import "XCredsLoginPlugin.h"
#import "TCSUnifiedLogger.h"
#import "TCSReturnWindow.h"
#import "TCSKeychain.h"
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,10 @@ class LoginWindowControlsWindowController: NSWindowController {
let refreshTimerSecs = UserDefaults.standard.integer(forKey: PrefKeys.autoRefreshLoginTimer.rawValue)

if refreshTimerSecs > 0 {
TCSLogWithMark("Setting refresh timer")

refreshTimer = Timer.scheduledTimer(withTimeInterval: TimeInterval(refreshTimerSecs), repeats: true, block: { [self] timer in
TCSLogWithMark("refreshing in timer")
delegate?.reload()
})
}
Expand Down
20 changes: 20 additions & 0 deletions XCredsLoginPlugIn/NSData+HexString.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//
// NSData+HexString.h
// Identity Manager
//
// Created by Timothy Perfitt on 12/29/19.
// Copyright © 2020 Twocanoes Software, Inc. All rights reserved.
//



#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface NSData (HexString)
+(id)dataWithHexString:(NSString *)hex;
- (NSString *)hexString;
@end

NS_ASSUME_NONNULL_END
53 changes: 53 additions & 0 deletions XCredsLoginPlugIn/NSData+HexString.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
//
// NSData+HexString.m
// Identity Manager
//
// Created by Timothy Perfitt on 12/29/19.
// Copyright © 2019 Twocanoes Software, Inc. All rights reserved.
//

#import "NSData+HexString.h"

@implementation NSData (HexString)
- (NSString *)hexString {

NSUInteger capacity = self.length * 2;
NSMutableString *stringBuffer = [NSMutableString stringWithCapacity:capacity];
const unsigned char *dataBuffer = self.bytes;

for (NSInteger i = 0; i < self.length; i++) {
[stringBuffer appendFormat:@"%02lX", (unsigned long)dataBuffer[i]];
}

return stringBuffer;
}
+(id)dataWithHexString:(NSString *)hex
{
char buf[3];
buf[2] = '\0';

NSString *currHex=hex;
if ([hex hasPrefix:@"0x"] || [hex hasPrefix:@"0X"] ) {
currHex=[hex substringFromIndex:2];
}
if ([currHex length] % 2 !=0) {
return nil;
}

unsigned char *bytes = malloc([currHex length]/2);
unsigned char *bp = bytes;
for (CFIndex i = 0; i < [currHex length]; i += 2) {
buf[0] = [currHex characterAtIndex:i];
buf[1] = [currHex characterAtIndex:i+1];
char *b2 = NULL;
*bp++ = strtol(buf, &b2, 16);
if (b2 != buf + 2) {
NSLog(@"String should be all hex digits: %@ (bad digit around %ld)", currHex, i);
return nil;
}
}

return [NSData dataWithBytesNoCopy:bytes length:[currHex length]/2 freeWhenDone:YES];
}

@end
20 changes: 20 additions & 0 deletions XCredsLoginPlugIn/NSData+SHA1.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//
// NSData+SHA1.h
// TCSToken
//
// Created by Timothy Perfitt on 12/29/19.
// Copyright © 2019 Twocanoes Software, Inc. All rights reserved.
//



#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN


@interface NSData (SHA1)
- (NSData *)sha1;
@end

NS_ASSUME_NONNULL_END
41 changes: 41 additions & 0 deletions XCredsLoginPlugIn/NSData+SHA1.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//
// NSData+SHA1.m
// TCSToken
//
// Created by Timothy Perfitt on 12/29/19.
// Copyright © 2019 Twocanoes Software, Inc. All rights reserved.
//

#import "NSData+SHA1.h"
#import <Security/Security.h>
#import <CommonCrypto/CommonDigest.h>
#import <CommonCrypto/CommonCryptor.h>


@implementation NSData (SHA1)
- (NSData *)sha1
{
CC_SHA1_CTX ctx;
uint8_t *hashBytes = NULL;
NSData *hash = nil;

// Malloc a buffer to hold hash.
hashBytes = malloc(CC_SHA1_DIGEST_LENGTH * sizeof(uint8_t));
memset((void *)hashBytes, 0x0, CC_SHA1_DIGEST_LENGTH);

// Initialize the context.
CC_SHA1_Init(&ctx);
// Perform the hash.
CC_SHA1_Update(&ctx, (void *)[self bytes], (CC_LONG)[self length]);
// Finalize the output.
CC_SHA1_Final(hashBytes, &ctx);

// Build up the SHA1 blob.
hash = [NSData dataWithBytes:(const void *)hashBytes length:(NSUInteger)CC_SHA1_DIGEST_LENGTH];

if (hashBytes) free(hashBytes);

return hash;
}

@end
35 changes: 35 additions & 0 deletions XCredsLoginPlugIn/TCSKeychain.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//
//
// Copyright (c) 2014 Twocanoes. All rights reserved.
//

#import <Foundation/Foundation.h>


@interface TCSKeychain : NSObject
+ (NSArray *)keychainIdentities;
+ (SecIdentityRef)findIdentityWithSubject:(NSString *)inSubject;
+ (NSString *)randomPasswordLength:(NSUInteger)length;
+ (NSString *)randomPassword;

+ (NSDictionary *)attributesForService:(NSString *)service account:(NSString *)account accessGroup:(NSString *)accessGroup error:(NSError **)err;
+ (NSString *)passwordForService:(NSString *)service account:(NSString *)account accessGroup:(NSString *)accessGroup error:(NSError **)err;

+ (BOOL)setPassword:(NSString *)password forService:(NSString *)service account:(NSString *)account accessGroup:(NSString *)accessGroup;
+ (BOOL)setPassword:(NSString *)password forAccount:(NSString *)account accessGroup:(NSString *)accessGroup;
+ (NSString *)passwordForAccount:(NSString *)account accessGroup:(NSString *)accessGroup error:(NSError **)err;
+ (void)findIdentityWithSHA1Hash:(NSData *)inHash returnIdentity:(SecIdentityRef *)returnIdentity;
+ (NSArray *)availableIdentityInfo;
+ (NSArray *)smartcardCertificateArrayFromKeychain;
@end


@interface TCSPassword : NSObject

@property (nonatomic, copy) NSString *service;
@property (nonatomic, copy) NSString *accessGroup;
@property (nonatomic, copy) NSString *password;

- (instancetype)initWithService:(NSString *)service account:(NSString *)account group:(NSString *)group;

@end
Loading

0 comments on commit 38ddeff

Please sign in to comment.