├── .gitignore ├── .travis.yml ├── CMakeLists.txt ├── LICENSE.txt ├── README.md ├── cmake └── Modules │ └── FindPAM.cmake ├── include └── reattach.h ├── man ├── pam_reattach.8 ├── reattach-to-session-namespace.8 └── reattach_aqua.3 └── src ├── bootstrap.h ├── cli.c ├── pam.c ├── reattach.c └── xpc.h /.gitignore: -------------------------------------------------------------------------------- 1 | # ignore the .cproject and .project file generated by Eclipse. 2 | .cproject 3 | .project 4 | 5 | # ignore the output of the C compiler. 6 | Debug 7 | bin 8 | lib 9 | build 10 | 11 | # CMake Files 12 | Makefile 13 | CMakeCache.txt 14 | CMakeFiles 15 | cmake_install.cmake 16 | install_manifest.txt 17 | compile_commands.json 18 | 19 | .cache 20 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | os: osx 3 | 4 | # Build steps 5 | script: 6 | - mkdir build 7 | - cd build 8 | - cmake .. && make VERBOSE=1 9 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | project(reattach C) 3 | 4 | option(ENABLE_PAM "Build PAM module that reattaches on authentication" ON) 5 | option(ENABLE_CLI "Build CLI application that reattaches" OFF) 6 | 7 | 8 | add_library(reattach include/reattach.h src/reattach.c src/xpc.h src/bootstrap.h) 9 | target_include_directories(reattach PUBLIC include) 10 | target_compile_options(reattach PRIVATE -Wall -Werror) 11 | set_target_properties(reattach PROPERTIES 12 | PUBLIC_HEADER "include/reattach.h" 13 | C_STANDARD 90 14 | ) 15 | install( 16 | TARGETS reattach 17 | LIBRARY DESTINATION lib 18 | ARCHIVE DESTINATION lib 19 | PUBLIC_HEADER DESTINATION include/ 20 | ) 21 | install(FILES man/reattach_aqua.3 DESTINATION "share/man/man3") 22 | 23 | if (ENABLE_PAM) 24 | # Locate PAM dependency 25 | set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules) 26 | find_package(PAM REQUIRED) 27 | 28 | add_library(pam_reattach MODULE src/pam.c) 29 | target_compile_options(pam_reattach PRIVATE -Wall -Werror) 30 | set_target_properties(pam_reattach PROPERTIES PREFIX "") # Remove lib prefix 31 | target_link_libraries(pam_reattach reattach pam) 32 | install(TARGETS pam_reattach DESTINATION lib/pam) 33 | install(FILES man/pam_reattach.8 DESTINATION "share/man/man8") 34 | endif() 35 | 36 | if (ENABLE_CLI) 37 | add_executable(reattach-to-session-namespace src/cli.c) 38 | target_compile_options(reattach-to-session-namespace PRIVATE -Wall -Werror) 39 | target_link_libraries(reattach-to-session-namespace reattach) 40 | install(TARGETS reattach-to-session-namespace DESTINATION bin) 41 | install(FILES man/reattach-to-session-namespace.8 DESTINATION "share/man/man8") 42 | endif() 43 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018 Fabian Mastenbroek 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | pam\_reattach 2 | [![Build Status](https://travis-ci.org/fabianishere/pam_reattach.svg?branch=master)](https://travis-ci.org/fabianishere/pam_reattach) 3 | ============= 4 | This is a PAM module for reattaching to the authenticating user's per-session 5 | bootstrap namespace on macOS. 6 | This allows users to make use of the `pam_tid` module (Touch ID) from within tmux. 7 | 8 | ## Purpose 9 | Although in MacOS a user program may survive in the background across login sessions, several services (mostly related to the GUI, such as pasteboard and Touch ID) are 10 | strictly tied to the login session of a user and as such unavailable for programs in the background session. 11 | Users of programs such as [tmux](https://github.com/tmux/tmux) and [GNU Screen](https://www.gnu.org/software/screen/) that run in the background to survive across login sessions, 12 | will thus find that several services such as Touch ID are unavailable or do not work properly. 13 | 14 | This PAM module will attempt to move the current program (e.g. `sudo`) to the current active login session, 15 | after which the remaining PAM modules will have access to the per-session services like Touch ID. 16 | 17 | If you have installed the additional `reattach-to-session-namespace(8)` program, you may also execute arbitrary 18 | programs from the background in the login session of the user. 19 | 20 | See [TN2083](https://developer.apple.com/library/archive/technotes/tn2083/_index.html) for more details 21 | about bootstrap namespaces in MacOS. 22 | 23 | ## Usage 24 | This module should be invoked before the module that you want to put in the 25 | authenticating user's per-session bootstrap namespace. The module runs in the 26 | authentication phase and should be marked as either `optional` or `required` 27 | (I suggest using `optional` to prevent getting locked out in case of bugs) 28 | 29 | Modify the targeted service in `/etc/pam.d/` (such as `/etc/pam.d/sudo`) as explained: 30 | ``` 31 | auth optional pam_reattach.so 32 | auth sufficient pam_tid.so 33 | ... 34 | ``` 35 | 36 | Make sure you have the module installed. Note that when the module is not installed in `/usr/lib/pam` or `/usr/local/lib/pam` (e.g., on M1 Macs where Homebrew is installed in `/opt/homebrew`), you must specify the full path to the module in the PAM service file as shown below: 37 | ``` 38 | auth optional /opt/homebrew/lib/pam/pam_reattach.so 39 | auth sufficient pam_tid.so 40 | ... 41 | ``` 42 | 43 | The `pam_tid` module will try to avoid prompting for a touch when connected via SSH or another remote login method. However, there are situations (e.g. use of tmux and screen) where the current tty may be spawned by a remote session but not detected as such by `pam_tid`. To help mitigate this, the `ignore_ssh` option can be added to the configuration of `pam_reattach` as follows: 44 | ``` 45 | auth optional pam_reattach.so ignore_ssh 46 | auth sufficient pam_tid.so 47 | ... 48 | ``` 49 | This will detect the presence of any of `$SSH_CLIENT`, `$SSH_CONNECTION`, or `$SSH_TTY` in the environment, and cause this module to become a no-op. 50 | 51 | For further information, see `reattach_aqua(3)`, `pam_reattach(8)` and `reattach-to-session-namespace(8)`. 52 | 53 | ## Installation 54 | The module is available via Homebrew. Use the following command to install it: 55 | 56 | ```bash 57 | $ brew install pam-reattach 58 | ``` 59 | 60 | You can also install this module with MacPorts using the following command: 61 | 62 | ```bash 63 | $ sudo port install pam-reattach 64 | ``` 65 | 66 | ## Building 67 | Alternatively, you may manually build the module. The module is built using [CMake 3](https://cmake.org). Enter the following commands into your 68 | command prompt in the project directory: 69 | 70 | ```bash 71 | $ cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX:PATH=/usr/local 72 | $ cmake --build build 73 | ``` 74 | 75 | To create a universal binary for use with both Apple Silicon and x86 (e.g. for Rosetta support), use: 76 | 77 | ```bash 78 | $ cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX:PATH=/usr/local -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" 79 | $ cmake --build build 80 | ``` 81 | 82 | If CMake is not able to find `libpam` automatically (e.g., on Nix), you may need to specify the prefix path manually: 83 | ```bash 84 | $ cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX:PATH=/usr/local -DCMAKE_PREFIX_PATH="/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib/" 85 | $ cmake --build build 86 | ``` 87 | 88 | #### Manual Installation 89 | Then, to install the module, simply run the following command: 90 | ```bash 91 | $ cmake --install build 92 | ``` 93 | Make sure you **keep** the generated `install_manifest.txt` file in the build folder after installation. 94 | 95 | #### Manual Removal 96 | Run the following command in your command prompt to remove the installation from your system: 97 | 98 | ```bash 99 | $ xargs rm < build/install_manifest.txt 100 | ``` 101 | 102 | In case you lost `install_manifest.txt`, this is the list of files that are installed: 103 | ``` 104 | /usr/local/lib/libreattach.a 105 | /usr/local/include/reattach.h 106 | /usr/local/share/man/man3/reattach_aqua.3 107 | /usr/local/lib/pam/pam_reattach.so 108 | /usr/local/share/man/man8/pam_reattach.8 109 | /usr/local/bin/reattach-to-session-namespace 110 | /usr/local/share/man/man8/reattach-to-session-namespace.8 111 | ``` 112 | 113 | #### Additional Tools 114 | Additionally, you may build a `reattach-to-session-namespace` command line 115 | utility by specifying the `-DENABLE_CLI=ON` option when calling CMake. This command allows you to reattach to the user's session namespace from the 116 | command line. 117 | 118 | See `reattach-to-session-namespace(8)` for more information. 119 | 120 | 121 | ## Enabling Touch ID for sudo 122 | To enable Touch ID authorization for `sudo`, please see [this](https://derflounder.wordpress.com/2017/11/17/enabling-touch-id-authorization-for-sudo-on-macos-high-sierra/) 123 | article. 124 | 125 | ## License 126 | The code is released under the MIT license. See [LICENSE.txt](/LICENSE.txt). 127 | -------------------------------------------------------------------------------- /cmake/Modules/FindPAM.cmake: -------------------------------------------------------------------------------- 1 | # - Try to find the pam library 2 | # Once done this will define 3 | # PAM_FOUND - System has libpam 4 | # PAM_INCLUDE_DIRS - The libpam include directories 5 | # PAM_LIBRARIES - The libraries needed to use libpam 6 | 7 | find_path(PAM_INCLUDE_DIR security/pam_modules.h PATH_SUFFIXES ..) 8 | 9 | set(PAM_DEFINITIONS "-fPIC") 10 | 11 | find_library(PAM_LIBRARY NAMES pam) 12 | 13 | set(PAM_LIBRARIES ${PAM_LIBRARY}) 14 | set(PAM_INCLUDE_DIRS ${PAM_INCLUDE_DIR}) 15 | 16 | include(FindPackageHandleStandardArgs) 17 | 18 | # handle the QUIETLY and REQUIRED arguments and set PAM_FOUND to TRUE 19 | # if all listed variables are TRUE 20 | find_package_handle_standard_args(PAM DEFAULT_MSG PAM_LIBRARY PAM_INCLUDE_DIR) 21 | 22 | mark_as_advanced(PAM_INCLUDE_DIR PAM_LIBRARY) 23 | 24 | add_library(pam SHARED IMPORTED GLOBAL) 25 | set_property(TARGET pam PROPERTY IMPORTED_LOCATION ${PAM_LIBRARY}) 26 | set_property(TARGET pam PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${PAM_INCLUDE_DIRS}) 27 | 28 | -------------------------------------------------------------------------------- /include/reattach.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2018 Fabian Mastenbroek 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #ifndef REATTACH_H 26 | #define REATTACH_H 27 | 28 | /** 29 | * Reattach to the specified user's per-session bootstrap namespace (Aqua). 30 | * 31 | * @param[in] uid The user id of the user of the session to reattach to. 32 | * @return 0 on success, some other value on failure. See errno(3). 33 | */ 34 | int reattach_aqua(uid_t uid); 35 | 36 | #endif /* REATTACH_H */ 37 | -------------------------------------------------------------------------------- /man/pam_reattach.8: -------------------------------------------------------------------------------- 1 | .\" 2 | .\" The MIT License (MIT) 3 | .\" 4 | .\" Copyright (c) 2018 Fabian Mastenbroek 5 | .\" 6 | .\" Permission is hereby granted, free of charge, to any person obtaining a copy 7 | .\" of this software and associated documentation files (the "Software"), to deal 8 | .\" in the Software without restriction, including without limitation the rights 9 | .\" to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | .\" copies of the Software, and to permit persons to whom the Software is 11 | .\" furnished to do so, subject to the following conditions: 12 | .\" 13 | .\" The above copyright notice and this permission notice shall be included in 14 | .\" all copies or substantial portions of the Software. 15 | .\" 16 | .\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | .\" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | .\" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | .\" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | .\" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | .\" OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | .\" THE SOFTWARE. 23 | .Dd May 6, 2022 24 | .Dt pam_reattach 8 25 | .Os 26 | .Sh NAME 27 | .Nm pam_reattach 28 | .Nd PAM module to reattach to user's per-session bootstrap namespace 29 | .Sh SYNOPSIS 30 | .Op Ar service-name 31 | .Ar function-class 32 | .Ar control-flag 33 | pam_reattach 34 | .Op Ar options 35 | .Sh DESCRIPTION 36 | The reattach authentication module is used to move the next authentication 37 | modules to the correct, per-session, bootstrap namespace. 38 | 39 | The following options may be passed to this authentication module: 40 | .Bl -tag -width ".Cm default_principal" 41 | .It Cm ignore_ssh 42 | Detect and ignore probable SSH sessions. This helps prevent erroneously 43 | prompting for a touch when SSH and a terminal multiplexer like 44 | .Xr tmux 1 45 | is in use. This detection is based on the presence of 46 | .Dv $SSH_CLIENT , 47 | .Dv $SSH_CONNECTION , 48 | or 49 | .Dv $SSH_TTY 50 | in the environment. 51 | .Sh SEE ALSO 52 | .Xr pam.conf 5 , 53 | .Xr pam 8 54 | -------------------------------------------------------------------------------- /man/reattach-to-session-namespace.8: -------------------------------------------------------------------------------- 1 | .Dd October 31, 2018 2 | .Dt reattach-to-session-namespace 8 3 | .Os Mach 4 | .Sh NAME 5 | .Nm reattach-to-session-namespace 6 | .Nd utility to reattach to user's per-session bootstrap namespace 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl u 10 | 11 | .Op Fl args... 12 | .Sh DESCRIPTION 13 | A command line utility that will execute the specified command in the user's 14 | per-session bootstrap namespace. 15 | .Pp 16 | .Sh FLAGS 17 | .Bl -tag -width -indent 18 | .It Fl u | -uid 19 | The user id of the session to attach to. 20 | .El 21 | .Pp 22 | -------------------------------------------------------------------------------- /man/reattach_aqua.3: -------------------------------------------------------------------------------- 1 | .\" 2 | .\" The MIT License (MIT) 3 | .\" 4 | .\" Copyright (c) 2018 Fabian Mastenbroek 5 | .\" 6 | .\" Permission is hereby granted, free of charge, to any person obtaining a copy 7 | .\" of this software and associated documentation files (the "Software"), to deal 8 | .\" in the Software without restriction, including without limitation the rights 9 | .\" to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | .\" copies of the Software, and to permit persons to whom the Software is 11 | .\" furnished to do so, subject to the following conditions: 12 | .\" 13 | .\" The above copyright notice and this permission notice shall be included in 14 | .\" all copies or substantial portions of the Software. 15 | .\" 16 | .\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | .\" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | .\" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | .\" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | .\" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | .\" OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | .\" THE SOFTWARE. 23 | .Dd October 31, 2018 24 | .Dt reattach_aqua 3 25 | .Os Mach 26 | .Sh NAME 27 | .Nm reattach_aqua 28 | .Nd reattach to user's per-session bootstrap namespace 29 | .Sh SYNOPSIS 30 | .In reattach.h 31 | .Ft int 32 | .Fo reattach_aqua 33 | .Fa "uid_t uid" 34 | .Fc 35 | .Sh DESCRIPTION 36 | The 37 | .Fn reattach_aqua 38 | function reattaches the current running process to the per-session bootstrap 39 | namespace of the specified user. 40 | .Sh RETURN VALUE 41 | Upon successful completion, a value of 0 is returned. Otherwise some error code 42 | is returned in conformance to error codes listed in 43 | .Xr errno 2 . 44 | -------------------------------------------------------------------------------- /src/bootstrap.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2018 Fabian Mastenbroek 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #ifndef REATTACH_BOOTSTRAP_H 26 | #define REATTACH_BOOTSTRAP_H 27 | 28 | #include 29 | #include 30 | 31 | kern_return_t bootstrap_get_root(mach_port_t bp, mach_port_t *root); 32 | 33 | #endif /* REATTACH_BOOTSTRAP_H */ 34 | -------------------------------------------------------------------------------- /src/cli.c: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2018 Fabian Mastenbroek 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | 34 | /** 35 | * Print the usage message of this program. 36 | * 37 | * @param[in] name The name of this program (given by argv[0]). 38 | */ 39 | static void print_usage(char *name) { 40 | fprintf(stderr, "usage: %s [-u] [args...]\n", name); 41 | fprintf(stderr, "\t-u --uid\tthe user id of the session to attach to\n"); 42 | } 43 | 44 | /* Command line options */ 45 | static struct option long_options[] = { 46 | {"uid", required_argument, 0, 'u'}, 47 | {0, 0, 0, 0} 48 | }; 49 | 50 | /** 51 | * Main entry point of the command line interface. 52 | * 53 | * @param[in] argc The amount of arguments passed to the program. 54 | * @param[in] argv The command line arguments passed to the program. 55 | * @return EXIT_SUCCESS on success, EXIT_FAILURE 56 | * otherwise. 57 | */ 58 | int main(int argc, char **argv) 59 | { 60 | int err; 61 | uid_t uid = getuid(); 62 | 63 | while (1) { 64 | int option_index = 0; 65 | int option = getopt_long (argc, argv, "u:", 66 | long_options, &option_index); 67 | 68 | if (option == -1) { 69 | break; 70 | } 71 | 72 | switch (option) { 73 | case 0: 74 | if (long_options[option_index].flag != 0) 75 | break; 76 | break; 77 | case 'u': 78 | uid = atoi(optarg); 79 | break; 80 | case '?': 81 | print_usage(argv[0]); 82 | return EXIT_FAILURE; 83 | default: 84 | abort(); 85 | } 86 | } 87 | 88 | if (optind == argc) { 89 | print_usage(argv[0]); 90 | return EXIT_FAILURE; 91 | } 92 | 93 | if ((err = reattach_aqua(uid)) != 0) { 94 | fprintf(stderr, "reattach_aqua: %d %s\n", err, strerror(err)); 95 | return EXIT_FAILURE; 96 | } 97 | execvp(argv[optind], &argv[optind]); 98 | 99 | /* If we reach here, execv failed */ 100 | fprintf(stderr, "execv: %s\n", strerror(errno)); 101 | return EXIT_FAILURE; 102 | } 103 | -------------------------------------------------------------------------------- /src/pam.c: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2018 Fabian Mastenbroek 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #define PAM_SM_AUTH 32 | #include 33 | #include 34 | 35 | #include 36 | 37 | const char *ssh_env_vars[] = {"SSH_CLIENT", "SSH_CONNECTION", "SSH_TTY"}; 38 | 39 | PAM_EXTERN int 40 | pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) 41 | { 42 | int err, i; 43 | const char *env, *username; 44 | char buffer[2 * PATH_MAX]; 45 | struct passwd *pwd; 46 | struct passwd pwdbuf; 47 | uid_t uid; 48 | 49 | /* Ignore probable SSH sessions when configured */ 50 | if (openpam_get_option(pamh, "ignore_ssh")) { 51 | for (i = 0; i < sizeof(ssh_env_vars); i++) { 52 | if ((env = getenv(ssh_env_vars[i])) != NULL && strlen(env)) { 53 | openpam_log(PAM_LOG_ERROR, "Skipping pam_reattach because $%s is present", ssh_env_vars[i]); 54 | return PAM_IGNORE; 55 | } 56 | } 57 | } 58 | 59 | /* Get the username (and UID) */ 60 | if ((err = pam_get_user(pamh, &username, NULL)) != PAM_SUCCESS) { 61 | openpam_log(PAM_LOG_ERROR, "The username could not be obtained: %d %s", err, pam_strerror(pamh, err)); 62 | return PAM_USER_UNKNOWN; 63 | } 64 | if (getpwnam_r(username, &pwdbuf, buffer, sizeof(buffer), &pwd) != 0) { 65 | openpam_log(PAM_LOG_ERROR, "The password file entry for %s could not be obtained", username); 66 | return PAM_USER_UNKNOWN; 67 | } 68 | uid = pwd->pw_uid; 69 | 70 | openpam_log(PAM_LOG_DEBUG, "Going to switch to (%s) %u's Aqua bootstrap namespace", username, uid); 71 | 72 | /* Reattach to aqua session */ 73 | if ((err = reattach_aqua(uid)) != 0) { 74 | openpam_log(PAM_LOG_ERROR, "Failed to obtain Aqua bootstrap port: %d %s", err, strerror(err)); 75 | return PAM_SERVICE_ERR; 76 | } 77 | 78 | return PAM_SUCCESS; 79 | } 80 | 81 | PAM_EXTERN int 82 | pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv) 83 | { 84 | return PAM_IGNORE; 85 | } 86 | 87 | #ifdef PAM_MODULE_ENTRY 88 | PAM_MODULE_ENTRY("pam_reattach"); 89 | #endif 90 | -------------------------------------------------------------------------------- /src/reattach.c: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2018 Fabian Mastenbroek 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #include "bootstrap.h" 26 | #include "xpc.h" 27 | 28 | #include 29 | 30 | int reattach_aqua(uid_t uid) 31 | { 32 | int err; 33 | 34 | xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0); 35 | 36 | xpc_dictionary_set_uint64(dict, "subsystem", 0x3); 37 | xpc_dictionary_set_uint64(dict, "routine", 0x343); 38 | xpc_dictionary_set_uint64(dict, "handle", 0x0); 39 | xpc_dictionary_set_uint64(dict, "type", 0x1); 40 | xpc_dictionary_set_uint64(dict, "uid", uid); 41 | 42 | xpc_object_t reply; 43 | xpc_pipe_t pipe = xpc_pipe_create_from_port(bootstrap_port, 0); 44 | 45 | /* Obtain the user's Aqua bootstrap port */ 46 | if ((err = xpc_pipe_routine(pipe, dict, &reply)) != 0) { 47 | xpc_release(pipe); 48 | xpc_release(dict); 49 | 50 | return err; 51 | } else if ((err = xpc_dictionary_get_int64(reply, "error")) != 0) { 52 | xpc_release(dict); 53 | xpc_release(pipe); 54 | xpc_release(reply); 55 | 56 | return err; 57 | } 58 | 59 | mach_port_t puc = xpc_dictionary_copy_mach_send(reply, "bootstrap"); 60 | 61 | /* Attach to the user's per-session bootstrap port */ 62 | mach_port_mod_refs(mach_task_self(), bootstrap_port, MACH_PORT_RIGHT_SEND, -1); 63 | task_set_bootstrap_port(mach_task_self(), puc); 64 | mach_port_deallocate(mach_task_self(), bootstrap_port); 65 | bootstrap_port = puc; 66 | 67 | /* Release the XPC data structures */ 68 | xpc_release(dict); 69 | xpc_release(pipe); 70 | xpc_release(reply); 71 | 72 | return 0; 73 | } 74 | -------------------------------------------------------------------------------- /src/xpc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2018 Fabian Mastenbroek 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #ifndef REATTACH_XPC_H 26 | #define REATTACH_XPC_H 27 | 28 | #include 29 | #include 30 | 31 | typedef struct _xpc_pipe_s* xpc_pipe_t; 32 | 33 | xpc_pipe_t xpc_pipe_create_from_port(mach_port_t port, int flags); 34 | 35 | mach_port_t xpc_dictionary_copy_mach_send(xpc_object_t dict, const char *name); 36 | 37 | int xpc_pipe_routine(xpc_pipe_t pipe, 38 | xpc_object_t request, 39 | xpc_object_t *reply); 40 | 41 | #endif /* REATTACH_XPC_H */ 42 | --------------------------------------------------------------------------------