From bc29777f24e9529c56505a20e56ababc5f41bd8c Mon Sep 17 00:00:00 2001 From: Matt Rajca Date: Mon, 28 Nov 2016 11:08:32 -0600 Subject: [PATCH 1/5] Restore the security warning --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 20eae67..1af2aa6 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,8 @@ ## Warning -Only tested under the MacBook Pro with Touch Bar, macOS 10.12.1. +- I am not a security expert. While I am using this as a fun experiment on my personal computer, your security needs may vary. +- Only tested under the MacBook Pro with Touch Bar, macOS 10.12.1. ## Building From 8d020875d438ca1462c5c9f2deb43aec01093bd0 Mon Sep 17 00:00:00 2001 From: Matt Rajca Date: Mon, 28 Nov 2016 11:09:29 -0600 Subject: [PATCH 2/5] Better re-phrase the hardware testing note --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1af2aa6..056c8b6 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ ## Warning - I am not a security expert. While I am using this as a fun experiment on my personal computer, your security needs may vary. -- Only tested under the MacBook Pro with Touch Bar, macOS 10.12.1. +- This has only been tested on the 2016 15" MacBook Pro with Touch Bar running macOS 10.12.1. ## Building From b31d28edcfbd811cdc44b847e4a45978ec553f27 Mon Sep 17 00:00:00 2001 From: Matt Rajca Date: Mon, 28 Nov 2016 11:16:37 -0600 Subject: [PATCH 3/5] Restore info on testing with LAPolicyDeviceOwnerAuthentication --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 056c8b6..4728548 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,12 @@ Now if we try running our copy of `sudo`, it should work: > ./sudo -s +If you don't have a Mac with a biometric sensor, `sudo-touchid` will fail. If you'd still like to test whether the `LocalAuthentication` framework is working correctly, you can change the `kAuthPolicy` constant to `LAPolicyDeviceOwnerAuthentication` in `sudo/plugins/sudoers/auth/sudo_auth.m`. This will present a dialog box asking the user for his or her password: + + + +While not useful in practice, you can use this to verify that the `LocalAuthentication` code does in fact work. + ## Installing Replacing the system's `sudo` program is quite risky (can prevent your Mac from booting) and requires disabling System Integrity Protection (aka "Rootless"). From 39e5ea3c874cdd3f18f4b245edc835d13997cb0a Mon Sep 17 00:00:00 2001 From: Matt Rajca Date: Mon, 28 Nov 2016 11:17:57 -0600 Subject: [PATCH 4/5] Display the screenshot at nominal resolution --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4728548..29f6a71 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ ## Screenshot -![Screenshot](images/Screenshot.png) + ## Warning From 7d6c51706460d04a3766514d9105a8607f21e63e Mon Sep 17 00:00:00 2001 From: Cee Date: Wed, 4 Oct 2017 00:19:13 -0400 Subject: [PATCH 5/5] Support High Sierra, upgrading sudo to version 86. --- pam.d/sudo | 1 + sudo-entitlements.plist | 10 ++++ sudo.xcodeproj/project.pbxproj | 0 .../contents.xcworkspacedata | 2 +- sudo/plugins/sudoers/auth/sudo_auth.m | 52 ++++++++++++++----- sudo/plugins/sudoers/pwutil.c | 21 ++++++++ 6 files changed, 72 insertions(+), 14 deletions(-) create mode 100644 sudo-entitlements.plist mode change 100644 => 100755 sudo.xcodeproj/project.pbxproj mode change 100644 => 100755 sudo.xcodeproj/project.xcworkspace/contents.xcworkspacedata diff --git a/pam.d/sudo b/pam.d/sudo index 87551fb..1869df8 100644 --- a/pam.d/sudo +++ b/pam.d/sudo @@ -1,4 +1,5 @@ # sudo: auth account password session +auth sufficient pam_smartcard.so auth required pam_opendirectory.so account required pam_permit.so password required pam_deny.so diff --git a/sudo-entitlements.plist b/sudo-entitlements.plist new file mode 100644 index 0000000..c5bf520 --- /dev/null +++ b/sudo-entitlements.plist @@ -0,0 +1,10 @@ + + + + + com.apple.private.AuthorizationServices + + com.apple.security.sudo + + + diff --git a/sudo.xcodeproj/project.pbxproj b/sudo.xcodeproj/project.pbxproj old mode 100644 new mode 100755 diff --git a/sudo.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/sudo.xcodeproj/project.xcworkspace/contents.xcworkspacedata old mode 100644 new mode 100755 index f437590..919434a --- a/sudo.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ b/sudo.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -2,6 +2,6 @@ + location = "self:"> diff --git a/sudo/plugins/sudoers/auth/sudo_auth.m b/sudo/plugins/sudoers/auth/sudo_auth.m index a058d15..57cb383 100644 --- a/sudo/plugins/sudoers/auth/sudo_auth.m +++ b/sudo/plugins/sudoers/auth/sudo_auth.m @@ -458,39 +458,65 @@ typedef enum { kTouchIDResultNone, kTouchIDResultAllowed, + kTouchIDResultFallback, + kTouchIDResultCancel, kTouchIDResultFailed } TouchIDResult; static const LAPolicy kAuthPolicy = 0x3f0; +static const LAPolicy kAuthPolicyFallback = LAPolicyDeviceOwnerAuthentication; int touchid_setup(struct passwd *pw, char **prompt, sudo_auth *auth) { @try { LAContext *context = [[LAContext alloc] init]; - BOOL canAuthenticate = [context canEvaluatePolicy:kAuthPolicy error:nil]; + BOOL canAuthenticate = [context canEvaluatePolicy:kAuthPolicy error:nil] + || [context canEvaluatePolicy:kAuthPolicyFallback error:nil]; [context release]; - return canAuthenticate ? AUTH_SUCCESS : AUTH_FAILURE; + return canAuthenticate ? AUTH_SUCCESS : AUTH_FATAL; } @catch(NSException *) { // LAPolicyDeviceOwnerAuthenticationWithBiometrics may not be available on builds older than 10.12.1! sudo_printf(SUDO_CONV_INFO_MSG, _("2")); - return AUTH_FAILURE; + return AUTH_FATAL; } } int touchid_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_conv_callback *callback) { - LAContext *context = [[LAContext alloc] init]; __block TouchIDResult result = kTouchIDResultNone; - [context evaluatePolicy:kAuthPolicy localizedReason:@"authenticate a privileged operation" reply:^(BOOL success, NSError *error) { - result = success ? kTouchIDResultAllowed : kTouchIDResultFailed; - CFRunLoopWakeUp(CFRunLoopGetCurrent()); - }]; - - while (result == kTouchIDResultNone) - CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true); + while (result == kTouchIDResultFallback || result == kTouchIDResultNone) { + LAContext *context = [[LAContext alloc] init]; + [context evaluatePolicy:(result != kTouchIDResultFallback ? kAuthPolicy : kAuthPolicyFallback) localizedReason:@"authenticate a privileged operation" reply:^(BOOL success, NSError *error) { + result = success ? kTouchIDResultAllowed : kTouchIDResultFailed; + switch (error.code) { + case LAErrorBiometryNotAvailable: + case LAErrorUserFallback: + result = kTouchIDResultFallback; + break; + case LAErrorUserCancel: + result = kTouchIDResultCancel; + break; + } + CFRunLoopWakeUp(CFRunLoopGetCurrent()); + }]; + + result = kTouchIDResultNone; + + while (result == kTouchIDResultNone) { + CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true); + } + + [context release]; + } - [context release]; - return result == kTouchIDResultAllowed ? AUTH_SUCCESS : AUTH_FAILURE; + switch (result) { + case kTouchIDResultCancel: + return AUTH_FATAL; + case kTouchIDResultAllowed: + return AUTH_SUCCESS; + default: + return AUTH_FAILURE; + } } diff --git a/sudo/plugins/sudoers/pwutil.c b/sudo/plugins/sudoers/pwutil.c index 354866a..c115878 100644 --- a/sudo/plugins/sudoers/pwutil.c +++ b/sudo/plugins/sudoers/pwutil.c @@ -800,6 +800,8 @@ sudo_set_grlist(struct passwd *pw, char * const *groups, char * const *gids) debug_return_int(0); } +#ifndef __APPLE_MEMBERSHIP__ + bool user_in_group(const struct passwd *pw, const char *group) { @@ -860,3 +862,22 @@ user_in_group(const struct passwd *pw, const char *group) __func__, pw->pw_name, matched ? "" : "NOT ", group); debug_return_bool(matched); } + +#else + +#include + +int mbr_check_membership_ext(int, const void *, size_t, int, const void *, int, int *); + +bool +user_in_group(const struct passwd *pw, const char *group) +{ + debug_decl(user_in_group, SUDOERS_DEBUG_NSS) + int is_member = 0; + int ret = mbr_check_membership_ext(ID_TYPE_UID, &pw->pw_uid, sizeof(pw->pw_uid), ID_TYPE_GROUPNAME, group, 0, &is_member); + sudo_debug_printf(SUDO_DEBUG_DEBUG, "%s: user %s %sin group %s (mbr_check: %d)", __func__, pw->pw_name, is_member ? "" : "NOT ", group, ret); + + debug_return_bool((bool)is_member); +} + +#endif