├── .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 | [](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 |
--------------------------------------------------------------------------------