├── tscrot.png ├── Makefile ├── pam_touchid.m ├── .gitignore └── README.md /tscrot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spaghetti-/pam-touchid/HEAD/tscrot.png -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | euid=$(shell id -u) 2 | egid=$(shell id -g) 3 | 4 | all: 5 | clang -fPIC -DPIC -fmodules -shared -rdynamic -DCURRENT_EUID=$(euid) -DCURRENT_EGID=$(egid) -o pam_touchid.so pam_touchid.m 6 | 7 | -------------------------------------------------------------------------------- /pam_touchid.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | #define PAM_SM_AUTH 5 | 6 | #include 7 | #include 8 | 9 | 10 | typedef enum { 11 | RESULT_NONE, 12 | RESULT_ALLOWED, 13 | RESULT_FAILED 14 | } TouchIdResult; 15 | 16 | 17 | int pam_sm_authenticate(pam_handle_t* pamh, int flags, 18 | int argc, const char** argv) 19 | { 20 | uid_t _uid = geteuid(); 21 | gid_t _gid = getegid(); 22 | seteuid(CURRENT_EUID); 23 | setegid(CURRENT_EGID); 24 | 25 | LAContext* ctx = [[LAContext alloc] init]; 26 | const bool can_auth = [ctx 27 | canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:nil]; 28 | if (!can_auth) return PAM_AUTH_ERR; 29 | 30 | __block TouchIdResult result = RESULT_NONE; 31 | 32 | [ctx evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics 33 | localizedReason:@"sudo" reply:^(BOOL success, NSError * _Nullable error) { 34 | result = success ? RESULT_ALLOWED : RESULT_FAILED; 35 | CFRunLoopWakeUp(CFRunLoopGetCurrent()); 36 | }]; 37 | 38 | while (result == RESULT_NONE) { 39 | CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true); 40 | } 41 | 42 | seteuid(_uid); 43 | setegid(_gid); 44 | 45 | return result == RESULT_ALLOWED ? PAM_SUCCESS : PAM_AUTH_ERR; 46 | } 47 | 48 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ### https://raw.github.com/github/gitignore/7af8eea00b37b330af2b9de94170f1d6aeafb1f0/c.gitignore 2 | 3 | # Prerequisites 4 | *.d 5 | 6 | # Object files 7 | *.o 8 | *.ko 9 | *.obj 10 | *.elf 11 | 12 | # Linker output 13 | *.ilk 14 | *.map 15 | *.exp 16 | 17 | # Precompiled Headers 18 | *.gch 19 | *.pch 20 | 21 | # Libraries 22 | *.lib 23 | *.a 24 | *.la 25 | *.lo 26 | 27 | # Shared objects (inc. Windows DLLs) 28 | *.dll 29 | *.so 30 | *.so.* 31 | *.dylib 32 | 33 | # Executables 34 | *.exe 35 | *.out 36 | *.app 37 | *.i*86 38 | *.x86_64 39 | *.hex 40 | 41 | # Debug files 42 | *.dSYM/ 43 | *.su 44 | *.idb 45 | *.pdb 46 | 47 | # Kernel Module Compile Results 48 | *.mod* 49 | *.cmd 50 | .tmp_versions/ 51 | modules.order 52 | Module.symvers 53 | Mkfile.old 54 | dkms.conf 55 | 56 | 57 | ### https://raw.github.com/github/gitignore/7af8eea00b37b330af2b9de94170f1d6aeafb1f0/Global/macos.gitignore 58 | 59 | # General 60 | *.DS_Store 61 | .AppleDouble 62 | .LSOverride 63 | 64 | # Icon must end with two \r 65 | Icon 66 | 67 | # Thumbnails 68 | ._* 69 | 70 | # Files that might appear in the root of a volume 71 | .DocumentRevisions-V100 72 | .fseventsd 73 | .Spotlight-V100 74 | .TemporaryItems 75 | .Trashes 76 | .VolumeIcon.icns 77 | .com.apple.timemachine.donotpresent 78 | 79 | # Directories potentially created on remote AFP share 80 | .AppleDB 81 | .AppleDesktop 82 | Network Trash Folder 83 | Temporary Items 84 | .apdisk 85 | 86 | 87 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Pluggable Authentication Module using Touch-ID 2 | ---------------------------------------------- 3 | 4 | This module allows us to authenticate services via touch-id using Apple's 5 | `LocalAuthentication` API. I am using the module to authenticate `sudo` as it's 6 | something we run frequently. The module can be dropped in to authenticate any 7 | other PAM enabled service as well. 8 | 9 | NOTE: Apple has added its own pam touch-id module to the OS and you should 10 | use that. Please see: https://news.ycombinator.com/item?id=26302139 11 | 12 | 13 | Compilation 14 | ----------- 15 | 16 | Compile this module as the user who has touchid active. Otherwise manually edit 17 | the user id's inside the .m file. 18 | 19 | 20 | `make all` 21 | 22 | Caveats 23 | ------- 24 | 25 | The compiled module must be installed to `/usr/lib/pam` which is a system 26 | directory protected by System Integrity Protection (SIP). To install the module 27 | you have to disable this (no worries, it can be enabled later). 28 | 29 | Reboot while holding Command-R, go into the recovery mode and spawn a new shell. 30 | In the shell run 31 | 32 | ``` 33 | csrutil disable 34 | ``` 35 | 36 | Reboot, copy the module over by doing `sudo cp pam_touchid.so /usr/lib/pam/` 37 | 38 | Next, add this line to the top of `/etc/pam.d/sudo` 39 | 40 | ``` 41 | auth sufficient pam_touchid.so 42 | ``` 43 | 44 | This also allows fallback to standard password authentication if your finger 45 | fails. 46 | 47 | Reboot back into recovery to enable SIP again 48 | 49 | ``` 50 | csrutil enable 51 | ``` 52 | 53 | Screenshot 54 | ---------- 55 | 56 | 57 | Here's what shows on the touchbar when you try to `sudo` with the module 58 | installed 59 | 60 | ![Touchbar screenshot](tscrot.png) 61 | 62 | --------------------------------------------------------------------------------